计算div jquery中的左侧定位

几天前,我在webapps.stackexchange.com上问了以下问题:
https://webapps.stackexchange.com/questions/54130/is-there-a-way-to-remove-overlaying-events-in-google-calendar

到目前为止我还没有得到任何好的答案,所以我决定写一个我自己的小脚本,根据重叠事件的数量来改变事件的宽度。

我想避免重叠的框,并希望他们堆叠。

这是最初的测试:

以下是一个包​​含说明的基本脚本:

    $('[class^="tg-col"]').each(function(){ // each day column 
                                           //(Mon, Tue, etc. has class tg-col or tg-col-weekend.
    var ItemArray = [];
    $(this).find(".chip").each(function(){ //each event box has chip class.

    var top = $$(this).position().top;  //Get top pixels
    var bottom = $$(this).height() + top;  //get end of the event.
    var arr = ItemArray.push({
        class: $$(this).attr("class").split(" ")[0], 
        start : top, 
        end:bottom
         }); 
    });
    var result = getOverlaps(ItemArray); //get overlaps counts number of overlapping events.
    $$.each(result, function(index, value){ 
      var ec = result[index].eventCount;
      var w = 100/result[index].eventCount-1 + "%";
    var el = $$("."+result[index].class);
      el.width(w);
    //el.css("left",w);
        });
    });
function getOverlaps(events) {
    // sort events
    events.sort(function (a, b) {
        return a.start - b.start;
    });

    var results = [];
    for (var i = 0, l = events.length; i < l; i++) {
        var oEvent = events[i];
        var nOverlaps = 0;
        for (var j = 0; j < l; j++) {
            var oCompareEvent = events[j];
            if (oCompareEvent.start <= oEvent.end && oCompareEvent.end > oEvent.start || oCompareEvent.end <= oEvent.start && oCompareEvent.start > oEvent.end) {
                nOverlaps++;
            }
        }
        if (nOverlaps > 1) {
            results.push({
                class: oEvent.class,
                eventCount: nOverlaps
            });
        }

    }
    return results;
}

此解决方案仅适用于简单事件(左侧):

对于更复杂的重叠,我们不能简单地计算重叠数量和潜水100%/重叠数量。 我们必须考虑其他方面。

另外,在Google日历中的每次操作后,重绘事件和脚本更改都会丢失。 有更简单的方法来解决这个问题吗?
(也许有可能修改从谷歌直接收到的JS?(但它被缩小:()。


你已经有了正确的左边位置,所以你只需要设置正确的宽度。

在伪代码中:

foreach chip
  chips_siblings = this.parent
                       .allchilds(chip)
                       .filter(this.top <= child.top <= this.bottom
                               && child.left > this.left)
  this.width = min(chips_siblings.left) - this.left

在JavaScript中:

function placeChipsCorrectly() {
    "use strict"
    Array.prototype.forEach.call(
        document.getElementsByClassName('chip'),
        function(self) {
            var siblings = Array.prototype.filter.call(
                self.parentElement.getElementsByClassName('chip'),
                function(child) {
                  return child.offsetTop >= self.offsetTop-2 &&
                         child.offsetTop <= self.offsetTop+self.offsetHeight-3 &&
                         child.offsetLeft > self.offsetLeft;
                });
            if (siblings.length > 0) {
                var minLeft = Math.min.apply(null, Array.prototype.map.call(
                    siblings,
                    function(el) {
                        return el.offsetLeft;
                    }));
                self.style.width = (minLeft - self.offsetLeft - 2) + "px";
            }
        });
}
placeChipsCorrectly();

至于跟踪修改事件:

在每次数据更改后,您可以在右上角看到“正在加载...”。 在检查它的工作原理之后,你可以看到它改变了id为lo-c的容器的style属性。
所以你可以跟踪它的出现和消失,如下所示:

(new MutationObserver(placeChipsCorrectly)).observe(document.getElementById('lo-c'),{attributes: true});

如果只修改视图而不修改数据(例如选择另一天或一周),则不会显示“正在加载...”。 对于这些事件,您可以跟踪全局click事件:

document.body.addEventListener('click', placeChipsCorrectly);

请记住,这两种方法都需要一些开销。 如果您想改进它们,请首先修改观察者,使其仅在消失时正确调用placeChipsCorrectly ,并将点击跟踪限制为特定控件。


你可以使用你的元素的边界框,并尝试通过使用(纯JavaScript)来避免重叠

document.getElementById("elemID").getBoundingClientRect();

我认为在jQuery中的等价物是类似的

elemID.offset()

有了这个,你可以拥有所有的Top,Bottom,Right和Left属性。 有了它,你可以更轻松地检测出你是否重叠。 一旦检测到,就从叠加的盒子边界进行调整。


我认为你应该从另一个角度来处理这个问题。 你有一个事件清单,包括开始时间和结束时间。 我相信Google日历会在网格上以15分钟的精度显示事件。 此外,请注意,我们无需知道某个事件在整个时间段内与某个事件发生冲突的次数,而是需要知道在每个时间间隔内冲突的事件数量。

所以...如果你做了一些准备工作,并确定每个15分钟的时间范围内有多少事件。 首先你准备一个数组:

var timespans = Array();
//24*4 quarters
for( var i = 0; i < 96; i++ ) {
  timespans[i] = 0;
}

然后我们填充这一天:

for( var i = 0, l = events.length; i < l; i++) {
  var oEvent = events[i];
  //Assuming that .start and .end is 'minutes since midnight'
  var firstQuarter = Math.floor( oEvent.start / 15 );
  var lastQuarter = Math.ceil( oEvent.end / 15 );
  for( var j = firstQuarter; j < lastQuarter; j++ ) {
    timespans[j] += 1;
  }
}

然后如果我们再次循环所有事件,我们只需要检查我们准备好的数组。

for( var i = 0, l = events.length; i < l; i++) {
  var oEvent = events[i];
  //Assuming that .start and .end is 'minutes since midnight'
  var firstQuarter = Math.floor( oEvent.start / 15 );
  var lastQuarter = Math.ceil( oEvent.end / 15 );
  var conflictingTimespans = timespans.slice( firstQuarter, lastQuarter );
  //http://stackoverflow.com/a/1669222/2209007
  var maxConflicting = Math.max.apply( null, conflictingTimespans );
  //Set width of said element to columnWidth / maxConflicting
}

除了它应该摆脱你的问题,你只会检查2n事件,而不是n^2事件,这应该会提高性能。

至于你的第二个问题,我不确定如何帮助你。

链接地址: http://www.djcxy.com/p/18545.html

上一篇: Calculate left positioning in div jquery

下一篇: C# Add days to a given date