怎么使fullcalendar日程事件源严格按照eventOrder传进来的顺序排序?

时间: 作者:admin 浏览:
关于fullcalendar的日程事件,在2.4.0之前的版本是默认按照title属性来排序的,2.4.0版本之后增加了eventOrder参数来自定义排序;但是其实就算你传了顺序进去,插件页并非严格按照我们给出的顺序来排序的,比如像我们填写了这个参数:

1、先看懂原来的排序逻辑
$('.person-schedule-box-js').empty().fullCalendar({
        header: {
            left: 'prev',
            center:'title',
            right: 'next'
        },
        firstDay:0,
        editable: false,
        titleFormat:'YYYY年MM月',
        dayNamesShort:['日','一','二','三','四','五','六'],
        fixedWeekCount:false,
        weekNumberTitle:'W',
        timeFormat: 'H:mm',
        slotLabelFormat: 'H:mm',
        buttonText: {
            prev: '<',
            next: '>'
        },
        events:[],
        eventOrder:'index',
        height:'auto',
        
    });
//自定义index为排序的参考值;但在实际排序中,
//插件会判断如果同一行里面的事件时间起始点不会交叉就会将事件跟在这个事件的后面,并非另起一行;如下图:



//上图中这个日程事件线条的顺序index是8,应该排在最后才对,但是第一段线条却排在了24号的第二行,
//这里其实体现了一个事件插进来的规则是:如果跟前面的日程事件不冲突,就直接跟在有空缺的日程事件后面。
//这个插件的代码也是这样体现的(可以在2.4.0版本里搜索出这个函数):



// Computes whether two segments' columns collide. They are assumed to be in the same row.
function isDaySegCollision(seg, otherSegs) {
	var i, otherSeg;

	for (i = 0; i < otherSegs.length; i++) {
		otherSeg = otherSegs[i];

		if (
			otherSeg.leftCol <= seg.rightCol && 
			otherSeg.rightCol >= seg.leftCol
		) {
			return true;
		}
	}

	return false;
}

//otherSeg.leftCol <= seg.rightCol && otherSeg.rightCol >= seg.leftCol 

//上面的条件说明,如果将要插入的日程事件跟已经存在的日程事件的起始列冲突(重叠),则返回true;
//然后再看isDaySegCollision()方法用在了哪里:

buildSegLevels: function(segs) {
	var levels = [];
	var i, seg;
	var j;

	// Give preference to elements with certain criteria, so they have
	// a chance to be closer to the top.
	this.sortSegs(segs);
	for (i = 0; i < segs.length; i++) {
		seg = segs[i];

		// loop through levels, starting with the topmost, until the segment doesn't collide with other segments
		for (j = 0; j < levels.length; j++) {
			if (!isDaySegCollision(seg, levels[j])) {
				break;
			}
		}
		// `j` now holds the desired subrow index
		seg.level = j;
		// create new level array if needed and append segment
		(levels[j] || (levels[j] = [])).push(seg);
	}
	// order segments left-to-right. very important if calendar is RTL
	for (j = 0; j < levels.length; j++) {
		levels[j].sort(compareDaySegCols);
	}
	return levels;
}
/*
   说明:

   1、上面的函数 if条件语句里 如果isDaySegCollision(seg, levels[j])返回true则说明日程事件重叠;
      重叠则不执行break(即不结束for循环);j的值就会继续往下加;
      这样levels数组就会多插入(push(seg))一个日程事件,这个日程事件会另起一行;

   2、如果isDaySegCollision(seg, levels[j])返回false则说明日程不重叠,
      执行break跳出for循环,j的值不往下加,新插入的日程事件就跟在第j个日程事件后面开始;
      所以同一行里面就会有两个不相连的线条(上图21日-24日的第二行两条线条就是这么来的)
*/

2、如何修改?

但是,插件所给的结果不是我想要的,我想要的是所有线条严格按照我给的顺序来排序;
那么可以加多一个参数strictMode; 2.4.0版本里找到eventOrderSpecs这个参数的位置;
跟着在后面加上strictMode:false;参数,默认为false,即:
eventOrderSpecs: null, // criteria for ordering events when they have same date/time
strictMode:false,
然后将上面所说的函数buildSegLevels里面的if条件改为:
!isDaySegCollision(seg, levels[j]) && !this.view.opt('strictMode')
即:
buildSegLevels: function(segs) {
	var levels = [];
	var i, seg;
	var j;

	// Give preference to elements with certain criteria, so they have
	// a chance to be closer to the top.
	this.sortSegs(segs);
	for (i = 0; i < segs.length; i++) {
		seg = segs[i];

		// loop through levels, starting with the topmost, until the segment doesn't collide with other segments
		for (j = 0; j < levels.length; j++) {
			if (!isDaySegCollision(seg, levels[j]) && !this.view.opt('strictMode')) {
				break;
			}
		}
		// `j` now holds the desired subrow index
		seg.level = j;
		// create new level array if needed and append segment
		(levels[j] || (levels[j] = [])).push(seg);
	}
	// order segments left-to-right. very important if calendar is RTL
	for (j = 0; j < levels.length; j++) {
		levels[j].sort(compareDaySegCols);
	}
	return levels;
}	
然后在调用的fullcalendar里面加上这个参数设置为true;即:
$('.person-schedule-box-js').empty().fullCalendar({
    header: {
        left: 'prev',
        center:'title',
        right: 'next'
    },
    firstDay:0,
    editable: false,
    titleFormat:'YYYY年MM月',
    dayNamesShort:['日','一','二','三','四','五','六'],
    fixedWeekCount:false,
    weekNumberTitle:'W',
    timeFormat: 'H:mm',
    slotLabelFormat: 'H:mm',
    buttonText: {
        prev: '<',
        next: '>'
    },
    events:[],
    eventOrder:'index',
    height:'auto',
    strictMode:true //2018/04/02改插件2.4.0新加的严格模式//严格按照传进去的eventOrder的顺序来排序,目前只支持数字顺序,比如本例的index的值0、1、2、3、4……
    
});
//最后,还有一步很重要的修改,就是将排序的依据函数优先级放到最高级, 即修改compareSegs方法,将compareByFieldSpecs提到第一位:
        //原方法
        // A cmp function for determining which segments should take visual priority
	// DOES NOT WORK ON INVERTED BACKGROUND EVENTS because they have no eventStartMS/eventDurationMS
	compareSegs: function(seg1, seg2) {
		return seg1.eventStartMS - seg2.eventStartMS || // earlier events go first
			seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first
			seg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1)
			compareByFieldSpecs(seg1.event, seg2.event, this.view.eventOrderSpecs);
	}

        //修改后
        // A cmp function for determining which segments should take visual priority
	// DOES NOT WORK ON INVERTED BACKGROUND EVENTS because they have no eventStartMS/eventDurationMS
	compareSegs: function(seg1, seg2) {
		return compareByFieldSpecs(seg1.event, seg2.event, this.view.eventOrderSpecs) ||
			seg1.eventStartMS - seg2.eventStartMS || // earlier events go first
			seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first
			seg2.event.allDay - seg1.event.allDay; // tie? put all-day events first (booleans cast to 0/1)
	}
//这种改法小编只是测试了数字顺序,其他类型值的顺序并未测试,您可以自己试试,改完之后的最终效果是这样的:


可以看到所有日程事件都各占一行,这样就不会顺序错乱了。


关于如何应用日程事件可以看我的另外一篇文章:
http://www.seozhijia.net/javascript/146.html
微信公众号
微信公众号:
  • 前端全栈之路(微信群)
前端QQ交流群
前端QQ交流群:
  • 794324979
  • 734802480(已满)

更多文章

栏目文章


Copyright © 2014-2023 seozhijia.net 版权所有-粤ICP备13087626号-4