2014-01-18 19 views
7

数日前、私はwebapps.stackexchange.com上、次の質問尋ねたのdivのjQueryの位置決め左:私は今のところ何か良い答えを取得していないので、私がすることに決めました
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; 
} 

このソリューションは、(左側)のみの単純なイベントに動作します:以下enter image description here

は説明の基本的なスクリプトです:

は、ここで最初のテストです enter image description here

より複雑なオーバーラップについては、単純にオーバーラップの数をカウントしたり、100%/オーバーラップの数をダイビングすることはできません。我々は他の次元を考慮に入れなければならない。

また、Googleカレンダーの各操作後に、イベントが再描画され、スクリプトの変更が失われます。この問題を解決する簡単な方法はありますか?
(多分それはGoogleの直接?(から受け取ったJSを変更することが可能である。しかし、それは):(縮小されます。

+4

誰がそれをいじるしたい場合は、ここではカレンダーのフィドルだ[ここ](http://jsfiddle.net/JfRU9/) – Olumide

+0

それは幅と各イベントのボックスの高さを変更することは可能ですか?そうでない場合、イベントボックスを保持する各コンテナの幅や高さを変更することは可能ですか? –

+0

Googleカレンダーでチェックすると、各イベントの幅と位置のみを変更できます。右? –

答えて

3

あなたが唯一の正しい幅を設定する必要があるので、あなたはすでに正しい左のポジションを持っています。擬似コードで

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を呼び出すように、オブザーバを変更することによって開始します。

+0

ありがとうございました。それは素晴らしい作品です。あなたのアドバイスを求めていたかったことがいくつかあります。 1)2つの重複イベントがある場合、チップを正しく配置しません.1つは午後5時から6時に設定され、もう1つは5-5.30pmに設定されます。 2)addEventListeberは動作を変更せず、すべてがリセットされます。私はDomAttrModified以外の何かを使うべきですか? – user194076

+0

また、幅が正しく計算されません。 2つと3つのアイテムのペアがあります。 http://tinypic.com/r/s5bclz/5 – user194076

+0

@ user194076私は自分の答えを更新しました。 DOMAttrModifiedはブラウザ間のMutationObserverに置き換えられました。関数にピクセル調整を追加しましたので、あなたが示したケースで正しく機能します。 – user

0

あなたの要素のバウンディングボックスを使用して、純粋なJavaScriptで(使用して重複を避けるために試みることができる)

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

私はjqueryのの等価はこれで

elemID.offset() 

のようなもので、あなたはすべての上、下、右と左の性質を持つことができると思います。あなたがある場合はそれを使用すると、あなたが道より簡単に検出することができます重なり合うかどうか。あなたが検出している場合は、重なり合うボックスの境界から調整を行います。

+0

'.offset()!= .getBoundingClientRect()' –

+0

おかげであなたの答えのために、私は私の例にgetBoundingClientRectを適用するかどうかはわかりません。 getBoundingClientRectから取得した情報では不十分です。 – user194076

0

私はあなたが別の角度から問題に近づくべきだと思います。開始時刻と終了時刻を含むイベントのリストがあります。 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 
} 

それはあなたの問題を取り除く必要があることに加えて、あなただけの代わりに、パフォーマンスを向上させる必要がありますn^2イベントの2nイベントを、チェックします。あなたの2番目の質問については

、私はそれのお手伝いをする方法がわからないと思います。