Oops #2
[redakcja.git] / project / static / js / views / split.js
index 84f48ea..48f0de7 100644 (file)
-/*globals Class*/
+/*globals View*/
 
-var SplitView = Class.extend({
-  leftPanelClass: 'splitview-left-panel',
-  rightPanelClass: 'splitview-right-panel',
-  splitterClass: 'splitview-splitter',
+// Split view inspired by jQuery Splitter Plugin http://methvin.com/splitter/
+var SplitView = View.extend({
+  _className: 'SplitView',
+  splitbarClass: 'splitview-splitbar',
+  activeClass: 'splitview-active',
   overlayClass: 'splitview-overlay',
   element: null,
+  model: null,
+  zombie: null,
+  leftViewOffset: 0,
   
-  init: function(element) {
-    this.element = $(element);
-    this.leftPanel = $(this.leftPanelClass, element);
-    this.rightPanel = $(this.rightPanelClass, element);
-    this.splitter = $(this.splitterClass, element);
-    this.overlay = this._createOverlay(this.overlayClass);
-    
-    this.splitter.bind('mousedown.splitview', this.beginResize.bind(this));
-  },
+  // Cache
+  _splitbarWidth: 0,
   
-  _createOverlay: function(cssClass) {
-    var pos = this.root.position();
-    return $('<div />')
-      .addClass(cssClass)
+  init: function(element, model) {
+    this._super(element, model, null);
+    this.element.css('position', 'relative');
+    this._resizingSubviews = false;
+    
+    this.views = $(">*", this.element[0]).css({
+       position: 'absolute',                     // positioned inside splitter container
+       'z-index': 1,                                           // splitbar is positioned above
+       '-moz-outline-style': 'none',   // don't show dotted outline
+      overflow: 'auto'
+    });
+    
+    this.leftView = $(this.views[0]);
+    this.rightView = $(this.views[1]);
+    this.splitbar = $(this.views[2] || '<div></div>')
+      .insertAfter(this.leftView)
       .css({
         position: 'absolute',
-        left: pos.left,
-        top: pos.top,
-        width: this.root.width(),
-        height: this.root.height()
+        'user-select': 'none',
+        '-webkit-user-select': 'none',
+        '-khtml-user-select': 'none',
+        '-moz-user-select': 'none',
+        'z-index': 100
       })
-      .hide()
-      .appendTo(this.element);
+      .attr('unselectable', 'on')
+      .addClass(this.splitbarClass)
+      .bind('mousedown.splitview', this.beginResize.bind(this));
+    
+    this._splitbarWidth = this.splitbar.outerWidth();
+    
+    // Solomon's algorithm ;-)
+    this.resplit(this.element.width() / 2);
   },
-  
+    
   beginResize: function(event) {
-    this.hotspotX = event.pageX - this.splitter.position().left;
+    this.zombie = this.zombie || this.splitbar.clone(false).insertAfter(this.leftView);
+    this.overlay = this.overlay || $('<div></div>').addClass(this.overlayClass).css({
+        position: 'absolute',
+        width: this.element.width(),
+        height: this.element.height(),
+        top: this.element.position().top,
+        left: this.element.position().left
+      }).appendTo(this.element);
+    this.views.css("-webkit-user-select", "none"); // Safari selects A/B text on a move
+    this.splitbar.addClass(this.activeClass);
+    this.leftViewOffset = this.leftView[0].offsetWidth - event.pageX;
     
     $(document)
       .bind('mousemove.splitview', this.resizeChanged.bind(this))
       .bind('mouseup.splitview', this.endResize.bind(this));
-
-    this.overlay.show();
-    return false;
   },
   
   resizeChanged: function(event) {
-    var old_width = this.overlay.width();
-    var delta = event.pageX + this.hotspotX - old_width;
-
-    if(old_width + delta < 12) delta = 12 - old_width;
-    if(old_width + delta > $(window).width()) {
-      delta = $(window).width() - old_width;
-    }
-    
-    this.overlay.css({'width': old_width + delta});
-    
-    if(this.overlay.next) {
-        var left = parseInt(this.overlay.next.css('left'), 10);
-        this.overlay.next.css('left', left+delta);
-    }
-    return false;
+    var newPosition = event.pageX + this.leftViewOffset;
+    newPosition = Math.max(0, Math.min(newPosition, this.element.width() - this._splitbarWidth));
+    this.splitbar.css('left', newPosition);
   },
 
   endResize: function(event) {
+    var newPosition = event.pageX + this.leftViewOffset;
+    this.zombie.remove();
+    this.zombie = null;
+    this.overlay.remove();
+    this.overlay = null;
+    this.resplit(newPosition);
+
     $(document)
       .unbind('mousemove.splitview')
       .unbind('mouseup.splitview');
-    
-    this.leftPanel.css({
+  },
+
+  resized: function(event) {
+    if (!this._resizingSubviews) {
+      this.resplit(Math.min(this.leftView.width(), this.element.width() - this._splitbarWidth));
+    }
+  },
+  
+  resplit: function(newPosition) {
+    newPosition = Math.max(0, Math.min(newPosition, this.element.width() - this._splitbarWidth));
+    this.splitbar.css('left', newPosition);
+    this.leftView.css({
       left: 0,
-      right: this.hotspotX
+      width: newPosition
     });
-
-    this.rightPanel.css({
-      left: this.hotspotX,
-      right: 0
+    this.rightView.css({
+      left: newPosition + this._splitbarWidth,
+      width: this.element.width() - newPosition - this._splitbarWidth
     });
-
-    this.overlay.hide();
+    if (!$.browser.msie) {
+      this._resizingSubviews = true;
+                 $(window).trigger('resize');
+                 this._resizingSubviews = false;
+               }
   },
   
   dispose: function() {
     this.splitter.unbind('mousedown.splitview');
+    this._super();
   }
 });