Update wcDocker to enable properly translation of the context menu options.
							parent
							
								
									cd059aaea3
								
							
						
					
					
						commit
						527620d34e
					
				| 
						 | 
				
			
			@ -17,14 +17,13 @@ $(window).bind('unload', function() {
 | 
			
		|||
// Build a regular dock panel
 | 
			
		||||
function buildPanel(docker, name, title, width, height, showTitle, isCloseable, isPrivate, content) {
 | 
			
		||||
    docker.registerPanelType(name, {
 | 
			
		||||
        title: title,
 | 
			
		||||
        isPrivate: isPrivate,
 | 
			
		||||
        onCreate: function(myPanel) {
 | 
			
		||||
            myPanel.initSize(width, height);
 | 
			
		||||
            
 | 
			
		||||
            if (showTitle == false) 
 | 
			
		||||
                myPanel.title(false);
 | 
			
		||||
            else
 | 
			
		||||
                myPanel.title(title);
 | 
			
		||||
 | 
			
		||||
            myPanel.closeable(isCloseable);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,15 +35,14 @@ function buildPanel(docker, name, title, width, height, showTitle, isCloseable,
 | 
			
		|||
// Build an iFrame dock panel
 | 
			
		||||
function buildIFramePanel(docker, name, title, width, height, showTitle, isCloseable, isPrivate, url) {
 | 
			
		||||
    docker.registerPanelType(name, {
 | 
			
		||||
        title: title,
 | 
			
		||||
        isPrivate: isPrivate,
 | 
			
		||||
        onCreate: function(myPanel) {
 | 
			
		||||
            myPanel.initSize(width, height);
 | 
			
		||||
            
 | 
			
		||||
            if (showTitle == false) 
 | 
			
		||||
                myPanel.title(false);
 | 
			
		||||
            else
 | 
			
		||||
                myPanel.title(title);
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
            myPanel.closeable(isCloseable);
 | 
			
		||||
 | 
			
		||||
            var $frameArea = $('<div style="width:100%;height:100%;position:relative;">');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,7 +51,12 @@ def index():
 | 
			
		|||
        
 | 
			
		||||
    # Add browser stylesheets
 | 
			
		||||
    stylesheets.append(url_for('static', filename='css/codemirror/codemirror.css'))
 | 
			
		||||
    stylesheets.append(url_for('static', filename='css/wcDocker/style.css'))
 | 
			
		||||
    
 | 
			
		||||
    if config.DEBUG:
 | 
			
		||||
        stylesheets.append(url_for('static', filename='css/wcDocker/wcDocker.css'))
 | 
			
		||||
    else:
 | 
			
		||||
        stylesheets.append(url_for('static', filename='css/wcDocker/wcDocker.min.css'))
 | 
			
		||||
        
 | 
			
		||||
    stylesheets.append(url_for('static', filename='css/wcDocker/theme.css'))
 | 
			
		||||
    stylesheets.append(url_for('browser.static', filename='css/browser.css'))
 | 
			
		||||
    stylesheets.append(url_for('browser.static', filename='css/aciTree/css/aciTree.css'))
 | 
			
		||||
| 
						 | 
				
			
			@ -61,14 +66,12 @@ def index():
 | 
			
		|||
    # Add browser scripts
 | 
			
		||||
    scripts.append(url_for('static', filename='js/codemirror/codemirror.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/codemirror/mode/sql.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/docker.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/splitter.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/frame.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/panel.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/layout.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/ghost.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/tabframe.js'))
 | 
			
		||||
    scripts.append(url_for('static', filename='js/wcDocker/iframe.js'))
 | 
			
		||||
    
 | 
			
		||||
    if config.DEBUG:
 | 
			
		||||
        scripts.append(url_for('static', filename='js/wcDocker/wcDocker.js'))
 | 
			
		||||
    else:
 | 
			
		||||
        scripts.append(url_for('static', filename='js/wcDocker/wcDocker.min.js'))
 | 
			
		||||
 | 
			
		||||
    scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciPlugin.min.js'))
 | 
			
		||||
    scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciTree.dom.js'))
 | 
			
		||||
    scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciTree.min.js'))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								web/pgadmin/static/css/wcDocker/style.css → web/pgadmin/static/css/wcDocker/wcDocker.css
								
								
								
								
									
									
									Executable file → Normal file
								
							
							
						
						
									
										20
									
								
								web/pgadmin/static/css/wcDocker/style.css → web/pgadmin/static/css/wcDocker/wcDocker.css
								
								
								
								
									
									
									Executable file → Normal file
								
							| 
						 | 
				
			
			@ -461,6 +461,26 @@ html, body {
 | 
			
		|||
  border-radius: 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar {
 | 
			
		||||
  width: 12px;
 | 
			
		||||
  height: 12px;
 | 
			
		||||
  background-color: #888;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar-corner {
 | 
			
		||||
  background-color: #888;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar-track {
 | 
			
		||||
  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar-thumb {
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.7);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wcMenuList, .context-menu-list {
 | 
			
		||||
  border: 1px solid #111;
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,843 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
  The frame is a container for a panel, and can contain multiple panels inside it, each appearing
 | 
			
		||||
  as a tabbed item.  All docking panels have a frame, but the frame can change any time the panel
 | 
			
		||||
  is moved.
 | 
			
		||||
*/
 | 
			
		||||
function wcFrame(container, parent, isFloating) {
 | 
			
		||||
  this.$container = $(container);
 | 
			
		||||
  this._parent = parent;
 | 
			
		||||
  this._isFloating = isFloating;
 | 
			
		||||
 | 
			
		||||
  this.$frame     = null;
 | 
			
		||||
  this.$title     = null;
 | 
			
		||||
  this.$tabScroll = null;
 | 
			
		||||
  this.$center    = null;
 | 
			
		||||
  this.$tabLeft   = null;
 | 
			
		||||
  this.$tabRight  = null;
 | 
			
		||||
  this.$close     = null;
 | 
			
		||||
  this.$top       = null;
 | 
			
		||||
  this.$bottom    = null;
 | 
			
		||||
  this.$left      = null;
 | 
			
		||||
  this.$right     = null;
 | 
			
		||||
  this.$corner1   = null;
 | 
			
		||||
  this.$corner2   = null;
 | 
			
		||||
  this.$corner3   = null;
 | 
			
		||||
  this.$corner4   = null;
 | 
			
		||||
 | 
			
		||||
  this.$shadower  = null;
 | 
			
		||||
  this.$modalBlocker = null;
 | 
			
		||||
 | 
			
		||||
  this._canScrollTabs = false;
 | 
			
		||||
  this._tabScrollPos = 0;
 | 
			
		||||
  this._curTab = -1;
 | 
			
		||||
  this._panelList = [];
 | 
			
		||||
  this._buttonList = [];
 | 
			
		||||
 | 
			
		||||
  this._resizeData = {
 | 
			
		||||
    time: -1,
 | 
			
		||||
    timeout: false,
 | 
			
		||||
    delta: 150,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._pos = {
 | 
			
		||||
    x: 0.5,
 | 
			
		||||
    y: 0.5,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._size = {
 | 
			
		||||
    x: 400,
 | 
			
		||||
    y: 400,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._lastSize = {
 | 
			
		||||
    x: 400,
 | 
			
		||||
    y: 400,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._anchorMouse = {
 | 
			
		||||
    x: 0,
 | 
			
		||||
    y: 0,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this.__init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wcFrame.prototype = {
 | 
			
		||||
  LEFT_TAB_BUFFER: 15,
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Public Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the position of the frame.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y    If supplied, assigns the new position.
 | 
			
		||||
  //    pixels  If true, the coordinates given will be treated as a
 | 
			
		||||
  //            pixel position rather than a percentage.
 | 
			
		||||
  pos: function(x, y, pixels) {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    if (typeof x === 'undefined') {
 | 
			
		||||
      if (pixels) {
 | 
			
		||||
        return {x: this._pos.x*width, y: this._pos.y*height};
 | 
			
		||||
      } else {
 | 
			
		||||
        return {x: this._pos.x, y: this._pos.y};
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (pixels) {
 | 
			
		||||
      this._pos.x = x/width;
 | 
			
		||||
      this._pos.y = y/height;
 | 
			
		||||
    } else {
 | 
			
		||||
      this._pos.x = x;
 | 
			
		||||
      this._pos.y = y;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the desired size of the panel.
 | 
			
		||||
  initSize: function() {
 | 
			
		||||
    var size = {
 | 
			
		||||
      x: -1,
 | 
			
		||||
      y: -1,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      if (size.x < this._panelList[i].initSize().x) {
 | 
			
		||||
        size.x = this._panelList[i].initSize().x;
 | 
			
		||||
      }
 | 
			
		||||
      if (size.y < this._panelList[i].initSize().y) {
 | 
			
		||||
        size.y = this._panelList[i].initSize().y;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (size.x < 0 || size.y < 0) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    return size;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the minimum size of the panel.
 | 
			
		||||
  minSize: function() {
 | 
			
		||||
    var size = {
 | 
			
		||||
      x: 0,
 | 
			
		||||
      y: 0,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      size.x = Math.max(size.x, this._panelList[i].minSize().x);
 | 
			
		||||
      size.y = Math.max(size.y, this._panelList[i].minSize().y);
 | 
			
		||||
    }
 | 
			
		||||
    return size;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the minimum size of the panel.
 | 
			
		||||
  maxSize: function() {
 | 
			
		||||
    var size = {
 | 
			
		||||
      x: Infinity,
 | 
			
		||||
      y: Infinity,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      size.x = Math.min(size.x, this._panelList[i].maxSize().x);
 | 
			
		||||
      size.y = Math.min(size.y, this._panelList[i].maxSize().y);
 | 
			
		||||
    }
 | 
			
		||||
    return size;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Adds a given panel as a new tab item.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    panel    The panel to add.
 | 
			
		||||
  //    index     An optional index to insert the tab at.
 | 
			
		||||
  addPanel: function(panel, index) {
 | 
			
		||||
    var found = this._panelList.indexOf(panel);
 | 
			
		||||
    if (found !== -1) {
 | 
			
		||||
      this._panelList.splice(found, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof index === 'undefined') {
 | 
			
		||||
      this._panelList.push(panel);
 | 
			
		||||
    } else {
 | 
			
		||||
      this._panelList.splice(index, 0, panel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._curTab === -1 && this._panelList.length) {
 | 
			
		||||
      this._curTab = 0;
 | 
			
		||||
      this._size = this.initSize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__updateTabs();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Removes a given panel from the tab item.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    panel       The panel to remove.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    bool        Returns whether or not any panels still remain.
 | 
			
		||||
  removePanel: function(panel) {
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      if (this._panelList[i] === panel) {
 | 
			
		||||
        if (this._curTab >= i) {
 | 
			
		||||
          this._curTab--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._panelList[i].__container(null);
 | 
			
		||||
        this._panelList[i]._parent = null;
 | 
			
		||||
 | 
			
		||||
        this._panelList.splice(i, 1);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._curTab === -1 && this._panelList.length) {
 | 
			
		||||
      this._curTab = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__updateTabs();
 | 
			
		||||
    return this._panelList.length > 0;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the currently visible panel.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    tabIndex      If supplied, sets the current tab.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    wcPanel       The currently visible panel.
 | 
			
		||||
  panel: function(tabIndex, autoFocus) {
 | 
			
		||||
    if (typeof tabIndex !== 'undefined') {
 | 
			
		||||
      if (tabIndex > -1 && tabIndex < this._panelList.length) {
 | 
			
		||||
        this.$title.find('> .wcTabScroller > .wcPanelTab[id="' + this._curTab + '"]').removeClass('wcPanelTabActive');
 | 
			
		||||
        this.$center.children('.wcPanelTabContent[id="' + this._curTab + '"]').addClass('wcPanelTabContentHidden');
 | 
			
		||||
        this._curTab = tabIndex;
 | 
			
		||||
        this.$title.find('> .wcTabScroller > .wcPanelTab[id="' + tabIndex + '"]').addClass('wcPanelTabActive');
 | 
			
		||||
        this.$center.children('.wcPanelTabContent[id="' + tabIndex + '"]').removeClass('wcPanelTabContentHidden');
 | 
			
		||||
        this.__updateTabs(autoFocus);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._curTab > -1 && this._curTab < this._panelList.length) {
 | 
			
		||||
      return this._panelList[this._curTab];
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Private Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Initialize
 | 
			
		||||
  __init: function() {
 | 
			
		||||
    this.$frame     = $('<div class="wcFrame wcWide wcTall wcPanelBackground">');
 | 
			
		||||
    this.$title     = $('<div class="wcFrameTitle">');
 | 
			
		||||
    this.$tabScroll = $('<div class="wcTabScroller">');
 | 
			
		||||
    this.$center    = $('<div class="wcFrameCenter wcWide">');
 | 
			
		||||
    this.$tabLeft   = $('<div class="wcFrameButton" title="Scroll tabs to the left."><span class="fa fa-arrow-left"></span><</div>');
 | 
			
		||||
    this.$tabRight  = $('<div class="wcFrameButton" title="Scroll tabs to the right."><span class="fa fa-arrow-right"></span>></div>');
 | 
			
		||||
    this.$close     = $('<div class="wcFrameButton" title="Close the currently active panel tab"><div class="fa fa-close"></div>X</div>');
 | 
			
		||||
    // this.$frame.append(this.$title);
 | 
			
		||||
    this.$title.append(this.$tabScroll);
 | 
			
		||||
    this.$frame.append(this.$close);
 | 
			
		||||
 | 
			
		||||
    if (this._isFloating) {
 | 
			
		||||
      this.$top     = $('<div class="wcFrameEdgeH wcFrameEdge"></div>').css('top', '-6px').css('left', '0px').css('right', '0px');
 | 
			
		||||
      this.$bottom  = $('<div class="wcFrameEdgeH wcFrameEdge"></div>').css('bottom', '-6px').css('left', '0px').css('right', '0px');
 | 
			
		||||
      this.$left    = $('<div class="wcFrameEdgeV wcFrameEdge"></div>').css('left', '-6px').css('top', '0px').css('bottom', '0px');
 | 
			
		||||
      this.$right   = $('<div class="wcFrameEdgeV wcFrameEdge"></div>').css('right', '-6px').css('top', '0px').css('bottom', '0px');
 | 
			
		||||
      this.$corner1 = $('<div class="wcFrameCornerNW wcFrameEdge"></div>').css('top', '-6px').css('left', '-6px');
 | 
			
		||||
      this.$corner2 = $('<div class="wcFrameCornerNE wcFrameEdge"></div>').css('top', '-6px').css('right', '-6px');
 | 
			
		||||
      this.$corner3 = $('<div class="wcFrameCornerNW wcFrameEdge"></div>').css('bottom', '-6px').css('right', '-6px');
 | 
			
		||||
      this.$corner4 = $('<div class="wcFrameCornerNE wcFrameEdge"></div>').css('bottom', '-6px').css('left', '-6px');
 | 
			
		||||
 | 
			
		||||
      this.$frame.append(this.$top);
 | 
			
		||||
      this.$frame.append(this.$bottom);
 | 
			
		||||
      this.$frame.append(this.$left);
 | 
			
		||||
      this.$frame.append(this.$right);
 | 
			
		||||
      this.$frame.append(this.$corner1);
 | 
			
		||||
      this.$frame.append(this.$corner2);
 | 
			
		||||
      this.$frame.append(this.$corner3);
 | 
			
		||||
      this.$frame.append(this.$corner4);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$frame.append(this.$center);
 | 
			
		||||
 | 
			
		||||
    // Floating windows have no container.
 | 
			
		||||
    this.__container(this.$container);
 | 
			
		||||
 | 
			
		||||
    if (this._isFloating) {
 | 
			
		||||
      this.$frame.addClass('wcFloating');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$center.scroll(this.__scrolled.bind(this));
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Updates the size of the frame.
 | 
			
		||||
  __update: function() {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    // Floating windows manage their own sizing.
 | 
			
		||||
    if (this._isFloating) {
 | 
			
		||||
      var left = (this._pos.x * width) - this._size.x/2;
 | 
			
		||||
      var top = (this._pos.y * height) - this._size.y/2;
 | 
			
		||||
 | 
			
		||||
      if (top < 0) {
 | 
			
		||||
        top = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (left + this._size.x/2 < 0) {
 | 
			
		||||
        left = -this._size.x/2;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (left + this._size.x/2 > width) {
 | 
			
		||||
        left = width - this._size.x/2;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (top + parseInt(this.$center.css('top')) > height) {
 | 
			
		||||
        top = height - parseInt(this.$center.css('top'));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.$frame.css('left', left + 'px');
 | 
			
		||||
      this.$frame.css('top', top + 'px');
 | 
			
		||||
      this.$frame.css('width', this._size.x + 'px');
 | 
			
		||||
      this.$frame.css('height', this._size.y + 'px');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (width !== this._lastSize.x || height !== this._lastSize.y) {
 | 
			
		||||
      this._lastSize.x = width;
 | 
			
		||||
      this._lastSize.y = height;
 | 
			
		||||
 | 
			
		||||
      this._resizeData.time = new Date();
 | 
			
		||||
      if (!this._resizeData.timeout) {
 | 
			
		||||
        this._resizeData.timeout = true;
 | 
			
		||||
        setTimeout(this.__resizeEnd.bind(this), this._resizeData.delta);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // this.__updateTabs();
 | 
			
		||||
    this.__onTabChange();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __resizeEnd: function() {
 | 
			
		||||
    this.__updateTabs();
 | 
			
		||||
    if (new Date() - this._resizeData.time < this._resizeData.delta) {
 | 
			
		||||
      setTimeout(this.__resizeEnd.bind(this), this._resizeData.delta);
 | 
			
		||||
    } else {
 | 
			
		||||
      this._resizeData.timeout = false;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Triggers an event exclusively on the docker and none of its panels.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    eventName   The name of the event.
 | 
			
		||||
  //    data        A custom data parameter to pass to all handlers.
 | 
			
		||||
  __trigger: function(eventName, data) {
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      this._panelList[i].__trigger(eventName, data);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Saves the current panel configuration into a meta
 | 
			
		||||
  // object that can be used later to restore it.
 | 
			
		||||
  __save: function() {
 | 
			
		||||
    var data = {};
 | 
			
		||||
    data.type = 'wcFrame';
 | 
			
		||||
    data.floating = this._isFloating;
 | 
			
		||||
    data.isFocus = this.$frame.hasClass('wcFloatingFocus')
 | 
			
		||||
    data.pos = {
 | 
			
		||||
      x: this._pos.x,
 | 
			
		||||
      y: this._pos.y,
 | 
			
		||||
    };
 | 
			
		||||
    data.size = {
 | 
			
		||||
      x: this._size.x,
 | 
			
		||||
      y: this._size.y,
 | 
			
		||||
    };
 | 
			
		||||
    data.tab = this._curTab;
 | 
			
		||||
    data.panels = [];
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      data.panels.push(this._panelList[i].__save());
 | 
			
		||||
    }
 | 
			
		||||
    return data;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Restores a previously saved configuration.
 | 
			
		||||
  __restore: function(data, docker) {
 | 
			
		||||
    this._isFloating = data.floating;
 | 
			
		||||
    this._pos.x = data.pos.x;
 | 
			
		||||
    this._pos.y = data.pos.y;
 | 
			
		||||
    this._size.x = data.size.x;
 | 
			
		||||
    this._size.y = data.size.y;
 | 
			
		||||
    this._curTab = data.tab;
 | 
			
		||||
    for (var i = 0; i < data.panels.length; ++i) {
 | 
			
		||||
      var panel = docker.__create(data.panels[i], this, this.$center);
 | 
			
		||||
      panel.__restore(data.panels[i], docker);
 | 
			
		||||
      this._panelList.push(panel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__update();
 | 
			
		||||
 | 
			
		||||
    if (data.isFocus) {
 | 
			
		||||
      this.$frame.addClass('wcFloatingFocus');
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __updateTabs: function(autoFocus) {
 | 
			
		||||
    this.$tabScroll.empty();
 | 
			
		||||
 | 
			
		||||
    // Move all tabbed panels to a temporary element to preserve event handlers on them.
 | 
			
		||||
    // var $tempCenter = $('<div>');
 | 
			
		||||
    // this.$frame.append($tempCenter);
 | 
			
		||||
    // this.$center.children().appendTo($tempCenter);
 | 
			
		||||
 | 
			
		||||
    var visibilityChanged = [];
 | 
			
		||||
    var tabPositions = [];
 | 
			
		||||
    var totalWidth = 0;
 | 
			
		||||
    var parentLeft = this.$tabScroll.offset().left;
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    this.$title.removeClass('wcNotMoveable');
 | 
			
		||||
 | 
			
		||||
    this.$center.children('.wcPanelTabContent').each(function() {
 | 
			
		||||
      $(this).addClass('wcPanelTabContentHidden wcPanelTabUnused');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    var titleVisible = true;
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      var panel = this._panelList[i];
 | 
			
		||||
 | 
			
		||||
      var $tab = $('<div id="' + i + '" class="wcPanelTab">' + panel.title() + '</div>');
 | 
			
		||||
      this.$tabScroll.append($tab);
 | 
			
		||||
      if (panel.$icon) {
 | 
			
		||||
        $tab.prepend(panel.$icon);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $tab.toggleClass('wcNotMoveable', !panel.moveable());
 | 
			
		||||
      if (!panel.moveable()) {
 | 
			
		||||
        this.$title.addClass('wcNotMoveable');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 
 | 
			
		||||
      if (!panel._titleVisible) {
 | 
			
		||||
        titleVisible = false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var $tabContent = this.$center.children('.wcPanelTabContent[id="' + i + '"]');
 | 
			
		||||
      if (!$tabContent.length) {
 | 
			
		||||
        $tabContent = $('<div class="wcPanelTabContent wcPanelBackground wcPanelTabContentHidden" id="' + i + '">');
 | 
			
		||||
        this.$center.append($tabContent);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      panel.__container($tabContent);
 | 
			
		||||
      panel._parent = this;
 | 
			
		||||
 | 
			
		||||
      var isVisible = this._curTab === i;
 | 
			
		||||
      if (panel.isVisible() !== isVisible) {
 | 
			
		||||
        visibilityChanged.push({
 | 
			
		||||
          panel: panel,
 | 
			
		||||
          isVisible: isVisible,
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $tabContent.removeClass('wcPanelTabUnused');
 | 
			
		||||
 | 
			
		||||
      if (isVisible) {
 | 
			
		||||
        $tab.addClass('wcPanelTabActive');
 | 
			
		||||
        $tabContent.removeClass('wcPanelTabContentHidden');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      totalWidth = $tab.offset().left - parentLeft;
 | 
			
		||||
      tabPositions.push(totalWidth);
 | 
			
		||||
 | 
			
		||||
      totalWidth += $tab.outerWidth();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (titleVisible) {
 | 
			
		||||
      this.$frame.prepend(this.$title);
 | 
			
		||||
      if (!this.$frame.parent()) {
 | 
			
		||||
        this.$center.css('top', '');
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$title.remove();
 | 
			
		||||
      this.$center.css('top', '0px');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Now remove all unused panel tabs.
 | 
			
		||||
    this.$center.children('.wcPanelTabUnused').each(function() {
 | 
			
		||||
      $(this).remove();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // $tempCenter.remove();
 | 
			
		||||
    if (titleVisible) {
 | 
			
		||||
      var buttonSize = this.__onTabChange();
 | 
			
		||||
 | 
			
		||||
      if (autoFocus) {
 | 
			
		||||
        for (var i = 0; i < tabPositions.length; ++i) {
 | 
			
		||||
          if (i === this._curTab) {
 | 
			
		||||
            var left = tabPositions[i];
 | 
			
		||||
            var right = totalWidth;
 | 
			
		||||
            if (i+1 < tabPositions.length) {
 | 
			
		||||
              right = tabPositions[i+1];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var scrollPos = -parseInt(this.$tabScroll.css('left'));
 | 
			
		||||
            var titleWidth = this.$title.width() - buttonSize;
 | 
			
		||||
 | 
			
		||||
            // If the tab is behind the current scroll position.
 | 
			
		||||
            if (left < scrollPos) {
 | 
			
		||||
              this._tabScrollPos = left - this.LEFT_TAB_BUFFER;
 | 
			
		||||
              if (this._tabScrollPos < 0) {
 | 
			
		||||
                this._tabScrollPos = 0;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            // If the tab is beyond the current scroll position.
 | 
			
		||||
            else if (right - scrollPos > titleWidth) {
 | 
			
		||||
              this._tabScrollPos = right - titleWidth + this.LEFT_TAB_BUFFER;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this._canScrollTabs = false;
 | 
			
		||||
      if (totalWidth > this.$title.width() - buttonSize) {
 | 
			
		||||
        this._canScrollTabs = titleVisible;
 | 
			
		||||
        this.$frame.append(this.$tabRight);
 | 
			
		||||
        this.$frame.append(this.$tabLeft);
 | 
			
		||||
        var scrollLimit = totalWidth - (this.$title.width() - buttonSize)/2;
 | 
			
		||||
        // If we are beyond our scroll limit, clamp it.
 | 
			
		||||
        if (this._tabScrollPos > scrollLimit) {
 | 
			
		||||
          var children = this.$tabScroll.children();
 | 
			
		||||
          for (var i = 0; i < children.length; ++i) {
 | 
			
		||||
            var $tab = $(children[i]);
 | 
			
		||||
 | 
			
		||||
            totalWidth = $tab.offset().left - parentLeft;
 | 
			
		||||
            if (totalWidth + $tab.outerWidth() > scrollLimit) {
 | 
			
		||||
              this._tabScrollPos = totalWidth - this.LEFT_TAB_BUFFER;
 | 
			
		||||
              if (this._tabScrollPos < 0) {
 | 
			
		||||
                this._tabScrollPos = 0;
 | 
			
		||||
              }
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        this._tabScrollPos = 0;
 | 
			
		||||
        this.$tabLeft.remove();
 | 
			
		||||
        this.$tabRight.remove();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.$tabScroll.stop().animate({left: -this._tabScrollPos + 'px'}, 'fast');
 | 
			
		||||
 | 
			
		||||
      // Update visibility on panels.
 | 
			
		||||
      for (var i = 0; i < visibilityChanged.length; ++i) {
 | 
			
		||||
        visibilityChanged[i].panel.__isVisible(visibilityChanged[i].isVisible);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __onTabChange: function() {
 | 
			
		||||
    var buttonSize = 0;
 | 
			
		||||
    var panel = this.panel();
 | 
			
		||||
    if (panel) {
 | 
			
		||||
      var scrollable = panel.scrollable();
 | 
			
		||||
      this.$center.toggleClass('wcScrollableX', scrollable.x);
 | 
			
		||||
      this.$center.toggleClass('wcScrollableY', scrollable.y);
 | 
			
		||||
 | 
			
		||||
      var overflowVisible = panel.overflowVisible();
 | 
			
		||||
      this.$center.toggleClass('wcOverflowVisible', overflowVisible);
 | 
			
		||||
 | 
			
		||||
      this.$tabLeft.remove();
 | 
			
		||||
      this.$tabRight.remove();
 | 
			
		||||
 | 
			
		||||
      while (this._buttonList.length) {
 | 
			
		||||
        this._buttonList.pop().remove();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (panel.closeable()) {
 | 
			
		||||
        this.$close.show();
 | 
			
		||||
        buttonSize += this.$close.outerWidth();
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$close.hide();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (var i = 0; i < panel._buttonList.length; ++i) {
 | 
			
		||||
        var buttonData = panel._buttonList[i];
 | 
			
		||||
        var $button = $('<div>');
 | 
			
		||||
        var buttonClass = buttonData.className;
 | 
			
		||||
        $button.addClass('wcFrameButton');
 | 
			
		||||
        if (buttonData.isTogglable) {
 | 
			
		||||
          $button.addClass('wcFrameButtonToggler');
 | 
			
		||||
 | 
			
		||||
          if (buttonData.isToggled) {
 | 
			
		||||
            $button.addClass('wcFrameButtonToggled');
 | 
			
		||||
            buttonClass = buttonData.toggleClassName || buttonClass;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        $button.attr('title', buttonData.tip);
 | 
			
		||||
        $button.data('name', buttonData.name);
 | 
			
		||||
        $button.text(buttonData.text);
 | 
			
		||||
        if (buttonClass) {
 | 
			
		||||
          $button.prepend($('<div class="' + buttonClass + '">'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._buttonList.push($button);
 | 
			
		||||
        this.$frame.append($button);
 | 
			
		||||
        buttonSize += $button.outerWidth();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this._canScrollTabs) {
 | 
			
		||||
        this.$frame.append(this.$tabRight);
 | 
			
		||||
        this.$frame.append(this.$tabLeft);
 | 
			
		||||
 | 
			
		||||
        buttonSize += this.$tabRight.outerWidth() + this.$tabLeft.outerWidth();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      panel.__update();
 | 
			
		||||
 | 
			
		||||
      this.$center.scrollLeft(panel._scroll.x);
 | 
			
		||||
      this.$center.scrollTop(panel._scroll.y);
 | 
			
		||||
    }
 | 
			
		||||
    return buttonSize;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Handles scroll notifications.
 | 
			
		||||
  __scrolled: function() {
 | 
			
		||||
    var panel = this.panel();
 | 
			
		||||
    panel._scroll.x = this.$center.scrollLeft();
 | 
			
		||||
    panel._scroll.y = this.$center.scrollTop();
 | 
			
		||||
 | 
			
		||||
    panel.__trigger(wcDocker.EVENT_SCROLLED);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Brings the frame into focus.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    flash     Optional, if true will flash the window.
 | 
			
		||||
  __focus: function(flash) {
 | 
			
		||||
    if (flash) {
 | 
			
		||||
      var $flasher = $('<div class="wcFrameFlasher">');
 | 
			
		||||
      this.$frame.append($flasher);
 | 
			
		||||
      $flasher.animate({
 | 
			
		||||
        opacity: 0.25,
 | 
			
		||||
      },100)
 | 
			
		||||
      .animate({
 | 
			
		||||
        opacity: 0.0,
 | 
			
		||||
      },100)
 | 
			
		||||
      .animate({
 | 
			
		||||
        opacity: 0.1,
 | 
			
		||||
      },50)
 | 
			
		||||
      .animate({
 | 
			
		||||
        opacity: 0.0,
 | 
			
		||||
      },50)
 | 
			
		||||
      .queue(function(next) {
 | 
			
		||||
        $flasher.remove();
 | 
			
		||||
        next();
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Moves the panel based on mouse dragging.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    mouse     The current mouse position.
 | 
			
		||||
  __move: function(mouse) {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    this._pos.x = (mouse.x + this._anchorMouse.x) / width;
 | 
			
		||||
    this._pos.y = (mouse.y + this._anchorMouse.y) / height;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Sets the anchor position for moving the panel.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    mouse     The current mouse position.
 | 
			
		||||
  __anchorMove: function(mouse) {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    this._anchorMouse.x = (this._pos.x * width) - mouse.x;
 | 
			
		||||
    this._anchorMouse.y = (this._pos.y * height) - mouse.y;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Moves a tab from a given index to another index.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    fromIndex     The current tab index to move.
 | 
			
		||||
  //    toIndex       The new index to move to.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    element       The new element of the moved tab.
 | 
			
		||||
  //    false         If an error occurred.
 | 
			
		||||
  __tabMove: function(fromIndex, toIndex) {
 | 
			
		||||
    if (fromIndex >= 0 && fromIndex < this._panelList.length &&
 | 
			
		||||
        toIndex >= 0 && toIndex < this._panelList.length) {
 | 
			
		||||
      var panel = this._panelList.splice(fromIndex, 1);
 | 
			
		||||
      this._panelList.splice(toIndex, 0, panel[0]);
 | 
			
		||||
 | 
			
		||||
      // Preserve the currently active tab.
 | 
			
		||||
      if (this._curTab === fromIndex) {
 | 
			
		||||
        this._curTab = toIndex;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.__updateTabs();
 | 
			
		||||
 | 
			
		||||
      return this.$title.find('> .wcTabScroller > .wcPanelTab[id="' + toIndex + '"]')[0];
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Checks if the mouse is in a valid anchor position for docking a panel.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    mouse     The current mouse position.
 | 
			
		||||
  //    same      Whether the moving frame and this one are the same.
 | 
			
		||||
  __checkAnchorDrop: function(mouse, same, ghost, canSplit) {
 | 
			
		||||
    var panel = this.panel();
 | 
			
		||||
    if (panel && panel.moveable()) {
 | 
			
		||||
      return panel.layout().__checkAnchorDrop(mouse, same, ghost, (!this._isFloating && canSplit), this.$frame, panel.moveable() && panel.title());
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Resizes the panel based on mouse dragging.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    edges     A list of edges being moved.
 | 
			
		||||
  //    mouse     The current mouse position.
 | 
			
		||||
  __resize: function(edges, mouse) {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
    var offset = this.$container.offset();
 | 
			
		||||
 | 
			
		||||
    mouse.x -= offset.left;
 | 
			
		||||
    mouse.y -= offset.top;
 | 
			
		||||
 | 
			
		||||
    var minSize = this.minSize();
 | 
			
		||||
    var maxSize = this.maxSize();
 | 
			
		||||
 | 
			
		||||
    var pos = {
 | 
			
		||||
      x: (this._pos.x * width) - this._size.x/2,
 | 
			
		||||
      y: (this._pos.y * height) - this._size.y/2,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < edges.length; ++i) {
 | 
			
		||||
      switch (edges[i]) {
 | 
			
		||||
        case 'top':
 | 
			
		||||
          this._size.y += pos.y - mouse.y-2;
 | 
			
		||||
          pos.y = mouse.y+2;
 | 
			
		||||
          if (this._size.y < minSize.y) {
 | 
			
		||||
            pos.y += this._size.y - minSize.y;
 | 
			
		||||
            this._size.y = minSize.y;
 | 
			
		||||
          }
 | 
			
		||||
          if (this._size.y > maxSize.y) {
 | 
			
		||||
            pos.y += this._size.y - maxSize.y;
 | 
			
		||||
            this._size.y = maxSize.y;
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case 'bottom':
 | 
			
		||||
          this._size.y = mouse.y-4 - pos.y;
 | 
			
		||||
          if (this._size.y < minSize.y) {
 | 
			
		||||
            this._size.y = minSize.y;
 | 
			
		||||
          }
 | 
			
		||||
          if (this._size.y > maxSize.y) {
 | 
			
		||||
            this._size.y = maxSize.y;
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case 'left':
 | 
			
		||||
          this._size.x += pos.x - mouse.x-2;
 | 
			
		||||
          pos.x = mouse.x+2;
 | 
			
		||||
          if (this._size.x < minSize.x) {
 | 
			
		||||
            pos.x += this._size.x - minSize.x;
 | 
			
		||||
            this._size.x = minSize.x;
 | 
			
		||||
          }
 | 
			
		||||
          if (this._size.x > maxSize.x) {
 | 
			
		||||
            pos.x += this._size.x - maxSize.x;
 | 
			
		||||
            this._size.x = maxSize.x;
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case 'right':
 | 
			
		||||
          this._size.x = mouse.x-4 - pos.x;
 | 
			
		||||
          if (this._size.x < minSize.x) {
 | 
			
		||||
            this._size.x = minSize.x;
 | 
			
		||||
          }
 | 
			
		||||
          if (this._size.x > maxSize.x) {
 | 
			
		||||
            this._size.x = maxSize.x;
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this._pos.x = (pos.x + this._size.x/2) / width;
 | 
			
		||||
      this._pos.y = (pos.y + this._size.y/2) / height;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Turn off or on a shadowing effect to signify this widget is being moved.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    enabled       Whether to enable __shadow mode.
 | 
			
		||||
  __shadow: function(enabled) {
 | 
			
		||||
    if (enabled) {
 | 
			
		||||
      if (!this.$shadower) {
 | 
			
		||||
        this.$shadower = $('<div class="wcFrameShadower">');
 | 
			
		||||
        this.$frame.append(this.$shadower);
 | 
			
		||||
        this.$shadower.animate({
 | 
			
		||||
          opacity: 0.5,
 | 
			
		||||
        }, 300);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (this.$shadower) {
 | 
			
		||||
        var self = this;
 | 
			
		||||
        this.$shadower.animate({
 | 
			
		||||
          opacity: 0.0,
 | 
			
		||||
        }, 300)
 | 
			
		||||
        .queue(function(next) {
 | 
			
		||||
          self.$shadower.remove();
 | 
			
		||||
          self.$shadower = null;
 | 
			
		||||
          next();
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the bounding rect for this frame.
 | 
			
		||||
  __rect: function() {
 | 
			
		||||
    var offset = this.$frame.offset();
 | 
			
		||||
    var width = this.$frame.width();
 | 
			
		||||
    var height = this.$frame.height();
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      x: offset.left,
 | 
			
		||||
      y: offset.top,
 | 
			
		||||
      w: width,
 | 
			
		||||
      h: height,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets a new container for this layout.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    $container          If supplied, sets a new container for this layout.
 | 
			
		||||
  //    parent              If supplied, sets a new parent for this layout.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    JQuery collection   The current container.
 | 
			
		||||
  __container: function($container) {
 | 
			
		||||
    if (typeof $container === 'undefined') {
 | 
			
		||||
      return this.$container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$container = $container;
 | 
			
		||||
    if (this.$container) {
 | 
			
		||||
      this.$container.append(this.$frame);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$frame.remove();
 | 
			
		||||
    }
 | 
			
		||||
    return this.$container;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Disconnects and prepares this widget for destruction.
 | 
			
		||||
  __destroy: function() {
 | 
			
		||||
    this._curTab = -1;
 | 
			
		||||
    for (var i = 0; i < this._panelList.length; ++i) {
 | 
			
		||||
      this._panelList[i].__destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (this._panelList.length) this._panelList.pop();
 | 
			
		||||
    if (this.$modalBlocker) {
 | 
			
		||||
      this.$modalBlocker.remove();
 | 
			
		||||
      this.$modalBlocker = null;
 | 
			
		||||
    }
 | 
			
		||||
    this.__container(null);
 | 
			
		||||
    this._parent = null;
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,196 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
  A ghost object that follows the mouse around during dock movement.
 | 
			
		||||
*/
 | 
			
		||||
function wcGhost(rect, mouse, docker) {
 | 
			
		||||
  this.$ghost = null;
 | 
			
		||||
  this._rect;
 | 
			
		||||
  this._anchorMouse = false;
 | 
			
		||||
  this._anchor = null;
 | 
			
		||||
  this._docker = docker;
 | 
			
		||||
 | 
			
		||||
  this.__init(rect, mouse);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wcGhost.prototype = {
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Public Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  // Updates the ghost based on the given screen position.
 | 
			
		||||
  update: function(position) {
 | 
			
		||||
    this.__move(position);
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._docker._floatingList.length; ++i) {
 | 
			
		||||
      var rect = this._docker._floatingList[i].__rect();
 | 
			
		||||
      if (position.x > rect.x && position.y > rect.y 
 | 
			
		||||
        && position.x < rect.x + rect.w && position.y < rect.y + rect.h) {
 | 
			
		||||
 | 
			
		||||
        if (!this._docker._floatingList[i].__checkAnchorDrop(position, false, this, true)) {
 | 
			
		||||
          this.anchor(position, null);
 | 
			
		||||
        } else {
 | 
			
		||||
          this._anchor.panel = this._docker._floatingList[i].panel();
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._docker._frameList.length; ++i) {
 | 
			
		||||
      var rect = this._docker._frameList[i].__rect();
 | 
			
		||||
      if (position.x > rect.x && position.y > rect.y 
 | 
			
		||||
        && position.x < rect.x + rect.w && position.y < rect.y + rect.h) {
 | 
			
		||||
 | 
			
		||||
        if (!this._docker._frameList[i].__checkAnchorDrop(position, false, this, true)) {
 | 
			
		||||
          this.anchor(position, null);
 | 
			
		||||
        } else {
 | 
			
		||||
          this._anchor.panel = this._docker._frameList[i].panel();
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  // Get, or Sets the ghost's anchor.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    mouse     The current mouse position.
 | 
			
		||||
  //    anchor    If supplied, assigns a new anchor.
 | 
			
		||||
  anchor: function(mouse, anchor) {
 | 
			
		||||
    if (typeof mouse === 'undefined') {
 | 
			
		||||
      return this._anchor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (anchor && this._anchor && anchor.loc === this._anchor.loc && anchor.item === this._anchor.item) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var rect = {
 | 
			
		||||
      x: parseInt(this.$ghost.css('left')),
 | 
			
		||||
      y: parseInt(this.$ghost.css('top')),
 | 
			
		||||
      w: parseInt(this.$ghost.css('width')),
 | 
			
		||||
      h: parseInt(this.$ghost.css('height')),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this._anchorMouse = {
 | 
			
		||||
      x: rect.x - mouse.x,
 | 
			
		||||
      y: rect.y - mouse.y,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this._rect.x = -this._anchorMouse.x;
 | 
			
		||||
    this._rect.y = -this._anchorMouse.y;
 | 
			
		||||
 | 
			
		||||
    if (!anchor) {
 | 
			
		||||
      if (!this._anchor) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this._anchor = null;
 | 
			
		||||
      this.$ghost.show();
 | 
			
		||||
      this.$ghost.stop().animate({
 | 
			
		||||
        opacity: 0.3,
 | 
			
		||||
        'margin-left': this._rect.x - this._rect.w/2 + 'px',
 | 
			
		||||
        'margin-top': this._rect.y - 10 + 'px',
 | 
			
		||||
        width: this._rect.w + 'px',
 | 
			
		||||
        height: this._rect.h + 'px',
 | 
			
		||||
      }, 150);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this._anchor = anchor;
 | 
			
		||||
    var opacity = 0.8;
 | 
			
		||||
    if (anchor.self && anchor.loc === wcDocker.DOCK_STACKED) {
 | 
			
		||||
      opacity = 0;
 | 
			
		||||
      this.$ghost.hide();
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$ghost.show();
 | 
			
		||||
    }
 | 
			
		||||
    this.$ghost.stop().animate({
 | 
			
		||||
      opacity: opacity,
 | 
			
		||||
      'margin-left': '2px',
 | 
			
		||||
      'margin-top': '2px',
 | 
			
		||||
      border: '0px',
 | 
			
		||||
      left: anchor.x + 'px',
 | 
			
		||||
      top: anchor.y + 'px',
 | 
			
		||||
      width: anchor.w + 'px',
 | 
			
		||||
      height: anchor.h + 'px',
 | 
			
		||||
    }, 150);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  rect: function() {
 | 
			
		||||
    return {
 | 
			
		||||
      x: this.$ghost.offset().left,
 | 
			
		||||
      y: this.$ghost.offset().top,
 | 
			
		||||
      w: parseInt(this.$ghost.css('width')),
 | 
			
		||||
      h: parseInt(this.$ghost.css('height')),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  destroy: function() {
 | 
			
		||||
    this.__destroy();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Private Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Initialize
 | 
			
		||||
  __init: function(rect, mouse) {
 | 
			
		||||
    this.$ghost = $('<div class="wcGhost">')
 | 
			
		||||
      .css('opacity', 0)
 | 
			
		||||
      .css('top', rect.y + 'px')
 | 
			
		||||
      .css('left', rect.x + 'px')
 | 
			
		||||
      .css('width', rect.w + 'px')
 | 
			
		||||
      .css('height', rect.h + 'px');
 | 
			
		||||
 | 
			
		||||
    this._anchorMouse = {
 | 
			
		||||
      x: rect.x - mouse.x,
 | 
			
		||||
      y: rect.y - mouse.y,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this._rect = {
 | 
			
		||||
      x: -this._anchorMouse.x,
 | 
			
		||||
      y: -this._anchorMouse.y,
 | 
			
		||||
      w: rect.w,
 | 
			
		||||
      h: rect.h,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $('body').append(this.$ghost);
 | 
			
		||||
 | 
			
		||||
    this.anchor(mouse, rect);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Updates the size of the layout.
 | 
			
		||||
  __move: function(mouse) {
 | 
			
		||||
    if (this._anchor) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var x = parseInt(this.$ghost.css('left'));
 | 
			
		||||
    var y = parseInt(this.$ghost.css('top'));
 | 
			
		||||
 | 
			
		||||
    x = mouse.x + this._anchorMouse.x;
 | 
			
		||||
    y = mouse.y + this._anchorMouse.y;
 | 
			
		||||
 | 
			
		||||
    this.$ghost.css('left', x + 'px');
 | 
			
		||||
    this.$ghost.css('top',  y + 'px');
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the original size of the moving widget.
 | 
			
		||||
  __rect: function() {
 | 
			
		||||
    return this._rect;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Exorcise the ghost.
 | 
			
		||||
  __destroy: function() {
 | 
			
		||||
    this.$ghost.stop().animate({
 | 
			
		||||
      opacity: 0.0,
 | 
			
		||||
    }, {
 | 
			
		||||
      duration: 175,
 | 
			
		||||
      complete: function() {
 | 
			
		||||
        $(this).remove();
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,213 +0,0 @@
 | 
			
		|||
function wcIFrame(container, panel) {
 | 
			
		||||
 | 
			
		||||
  this._panel = panel;
 | 
			
		||||
  this._layout = panel.layout();
 | 
			
		||||
 | 
			
		||||
  this.$container = $(container);
 | 
			
		||||
  this.$frame = null;
 | 
			
		||||
 | 
			
		||||
  this._window = null;
 | 
			
		||||
  this._isAttached = true;
 | 
			
		||||
  this._hasFocus = false;
 | 
			
		||||
 | 
			
		||||
  this._boundEvents = [];
 | 
			
		||||
 | 
			
		||||
  this.__init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wcIFrame.prototype = {
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  docker: function() {
 | 
			
		||||
    var parent = this._panel;
 | 
			
		||||
    while (parent && !(parent instanceof wcDocker)) {
 | 
			
		||||
      parent = parent._parent;
 | 
			
		||||
    }
 | 
			
		||||
    return parent;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  openURL: function(url) {
 | 
			
		||||
    this.__clearFrame();
 | 
			
		||||
 | 
			
		||||
    this.$frame = $('<iframe class="wcIFrame">');
 | 
			
		||||
    this._panel.docker().$container.append(this.$frame);
 | 
			
		||||
    this.onMoved();
 | 
			
		||||
    this._window = this.$frame[0].contentWindow || this.$frame[0];
 | 
			
		||||
    this.__updateFrame();
 | 
			
		||||
    this._window.location.replace(url);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  openHTML: function(html) {
 | 
			
		||||
    this.__clearFrame();
 | 
			
		||||
 | 
			
		||||
    this.$frame = $('<iframe class="wcIFrame">');
 | 
			
		||||
    this._panel.docker().$container.append(this.$frame);
 | 
			
		||||
    this.onMoved();
 | 
			
		||||
    this._window = this.$frame[0].contentWindow || this.$frame[0];
 | 
			
		||||
    this.__updateFrame();
 | 
			
		||||
 | 
			
		||||
    this._boundEvents = [];
 | 
			
		||||
 | 
			
		||||
    // Write the frame source.
 | 
			
		||||
    this._window.document.open();
 | 
			
		||||
    this._window.document.write(html);
 | 
			
		||||
    this._window.document.close();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  show: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      this.$frame.removeClass('wcIFrameHidden');
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  hide: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      this.$frame.addClass('wcIFrameHidden');
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  window: function() {
 | 
			
		||||
    return this._window;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  destroy: function() {
 | 
			
		||||
    // Remove all registered events.
 | 
			
		||||
    while (this._boundEvents.length){
 | 
			
		||||
      this._panel.off(this._boundEvents[0].event, this._boundEvents[0].handler);
 | 
			
		||||
      this._boundEvents.pop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__clearFrame();
 | 
			
		||||
    this._panel = null;
 | 
			
		||||
    this._layout = null;
 | 
			
		||||
    this.$container = null;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onVisibilityChanged: function() {
 | 
			
		||||
    this.__updateFrame();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onBeginDock: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      this.$frame.addClass('wcIFrameMoving');
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onEndDock: function() {
 | 
			
		||||
    if (this.$frame && this._hasFocus) {
 | 
			
		||||
      this.$frame.removeClass('wcIFrameMoving');
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onMoveStarted: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      // Hide the frame while it is moving.
 | 
			
		||||
      this.$frame.addClass('wcIFrameMoving');
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onMoveFinished: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      this.$frame.removeClass('wcIFrameMoving');
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  onMoved: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      // Size, position, and show the frame once the move is finished.
 | 
			
		||||
      var pos = this.$container.offset();
 | 
			
		||||
      var width = this.$container.width();
 | 
			
		||||
      var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
      this.$frame.css('left', pos.left);
 | 
			
		||||
      this.$frame.css('top', pos.top);
 | 
			
		||||
      this.$frame.css('width', width);
 | 
			
		||||
      this.$frame.css('height', height);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onAttached: function() {
 | 
			
		||||
    this._isAttached = true;
 | 
			
		||||
    this.__updateFrame();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onDetached: function() {
 | 
			
		||||
    this._isAttached = false;
 | 
			
		||||
    this.__updateFrame();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onGainFocus: function() {
 | 
			
		||||
    this._hasFocus = true;
 | 
			
		||||
    this.__updateFrame();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
  onLostFocus: function() {
 | 
			
		||||
    this._hasFocus = false;
 | 
			
		||||
    this.__updateFrame();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  onClosed: function() {
 | 
			
		||||
    this.destroy();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  __clearFrame: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      this.$frame[0].srcdoc = '';
 | 
			
		||||
      this.$frame.remove();
 | 
			
		||||
      this.$frame = null;
 | 
			
		||||
      this._window = null;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  __updateFrame: function() {
 | 
			
		||||
    if (this.$frame) {
 | 
			
		||||
      this.$frame.toggleClass('wcIFrameFloating', !this._isAttached);
 | 
			
		||||
      if (!this._isAttached) {
 | 
			
		||||
        this.$frame.toggleClass('wcIFrameFloatingFocus', this._hasFocus);
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$frame.removeClass('wcIFrameFloatingFocus');
 | 
			
		||||
      }
 | 
			
		||||
      this.$frame.toggleClass('wcIFramePanelHidden', !this._panel.isVisible());
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // --------------------------------------------------------------------------------
 | 
			
		||||
  __init: function() {
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_VISIBILITY_CHANGED, handler: this.onVisibilityChanged.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_BEGIN_DOCK,         handler: this.onBeginDock.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_END_DOCK,           handler: this.onEndDock.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_MOVE_STARTED,       handler: this.onMoveStarted.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_RESIZE_STARTED,     handler: this.onMoveStarted.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_MOVE_ENDED,         handler: this.onMoveFinished.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_RESIZE_ENDED,       handler: this.onMoveFinished.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_MOVED,              handler: this.onMoved.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_RESIZED,            handler: this.onMoved.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_ATTACHED,           handler: this.onAttached.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_DETACHED,           handler: this.onDetached.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_GAIN_FOCUS,         handler: this.onGainFocus.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_LOST_FOCUS,         handler: this.onLostFocus.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_CLOSED,             handler: this.onClosed.bind(this)});
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._boundEvents.length; ++i) {
 | 
			
		||||
      this._panel.on(this._boundEvents[i].event, this._boundEvents[i].handler);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,434 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
  Handles the contents of a panel.
 | 
			
		||||
*/
 | 
			
		||||
function wcLayout(container, parent) {
 | 
			
		||||
  this.$container = $(container);
 | 
			
		||||
  this._parent = parent;
 | 
			
		||||
 | 
			
		||||
  this._batchProcess = false;
 | 
			
		||||
  this._grid = [];
 | 
			
		||||
  this.$table = null;
 | 
			
		||||
 | 
			
		||||
  this.__init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wcLayout.prototype = {
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Public Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Adds an item into the layout, expanding the grid
 | 
			
		||||
  // size if necessary.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    item        The DOM element to add.
 | 
			
		||||
  //    x, y        The grid coordinates to place the item.
 | 
			
		||||
  //    w, h        If supplied, will stretch the item among
 | 
			
		||||
  //                multiple grid elements.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    <td>        On success, returns the jquery <td> dom element.
 | 
			
		||||
  //    false       A failure happened, most likely cells could not be merged.
 | 
			
		||||
  addItem: function(item, x, y, w, h) {
 | 
			
		||||
    if (typeof x === 'undefined' || x < 0) {
 | 
			
		||||
      x = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof y === 'undefined' || y < 0) {
 | 
			
		||||
      y = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof w === 'undefined' || w <= 0) {
 | 
			
		||||
      w = 1;
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof h === 'undefined' || h <= 0) {
 | 
			
		||||
      h = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__resizeGrid(x + w - 1, y + h - 1);
 | 
			
		||||
    if (w > 1 || h > 1) {
 | 
			
		||||
      if (!this.__mergeGrid(x, y, w, h)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this._grid[y][x].$el.append($(item));
 | 
			
		||||
    return this._grid[y][x].$el;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the table item at a given grid position, if it exists.
 | 
			
		||||
  // Note, if an element spans multiple cells, only the top-left
 | 
			
		||||
  // cell will retrieve the item.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y        The grid position.
 | 
			
		||||
  // Return:
 | 
			
		||||
  //    <td>        On success, returns the found jquery <td> dom element.
 | 
			
		||||
  //    null        If no element was found.
 | 
			
		||||
  item: function(x, y) {
 | 
			
		||||
    if (y >= this._grid.length) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (x >= this._grid[y].length) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._grid[y][x].$el;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Clears the layout.
 | 
			
		||||
  clear: function() {
 | 
			
		||||
    var showGrid = this.showGrid();
 | 
			
		||||
    var spacing = this.gridSpacing();
 | 
			
		||||
    var alternate = this.gridAlternate();
 | 
			
		||||
 | 
			
		||||
    this.$table.remove();
 | 
			
		||||
    this.__init();
 | 
			
		||||
 | 
			
		||||
    this.showGrid(showGrid);
 | 
			
		||||
    this.gridSpacing(spacing);
 | 
			
		||||
    this.gridAlternate(alternate);
 | 
			
		||||
 | 
			
		||||
    this._grid = [];
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Begins a batch operation.  Basically it refrains from constructing
 | 
			
		||||
  // the layout grid, which causes a reflow, on each item added.  Instead,
 | 
			
		||||
  // The grid is only generated at the end once FinishBatch() is called.
 | 
			
		||||
  startBatch: function() {
 | 
			
		||||
    this._batchProcess = true;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Ends a batch operation. See startBatch() for information.
 | 
			
		||||
  finishBatch: function() {
 | 
			
		||||
    this._batchProcess = false;
 | 
			
		||||
    this.__resizeGrid(0, 0);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the visible status of the layout grid.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    enabled     If supplied, will set the grid shown or hidden.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    bool        The current visibility of the grid.
 | 
			
		||||
  showGrid: function(enabled) {
 | 
			
		||||
    if (typeof enabled !== 'undefined') {
 | 
			
		||||
      this.$table.toggleClass('wcLayoutGrid', enabled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this.$table.hasClass('wcLayoutGrid');
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Version 1.0.1
 | 
			
		||||
  // Gets, or Sets the spacing between cell borders.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    size      If supplied, sets the pixel size of the border spacing.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    int       The current border spacing size.
 | 
			
		||||
  gridSpacing: function(size) {
 | 
			
		||||
    if (typeof size !== 'undefined') {
 | 
			
		||||
      this.$table.css('border-spacing', size + 'px');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return parseInt(this.$table.css('border-spacing'));
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Version 1.0.1
 | 
			
		||||
  // Gets, or Sets whether the table rows alternate in color.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    enabled     If supplied, will set whether the grid alternates in color.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    bool        Whether the grid alternates in color.
 | 
			
		||||
  gridAlternate: function(enabled) {
 | 
			
		||||
    if (typeof enabled !== 'undefined') {
 | 
			
		||||
      this.$table.toggleClass('wcLayoutGridAlternate', enabled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this.$table.hasClass('wcLayoutGridAlternate');
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the main scene DOM element.
 | 
			
		||||
  scene: function() {
 | 
			
		||||
    return this.$table;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Private Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Initialize
 | 
			
		||||
  __init: function() {
 | 
			
		||||
    this.$table = $('<table class="wcLayout wcWide wcTall"></table>');
 | 
			
		||||
    this.$table.append($('<tbody></tbody>'));
 | 
			
		||||
    this.__container(this.$container);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Updates the size of the layout.
 | 
			
		||||
  __update: function() {
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Resizes the grid to fit a given position.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    width     The width to expand to.
 | 
			
		||||
  //    height    The height to expand to.
 | 
			
		||||
  __resizeGrid: function(width, height) {
 | 
			
		||||
    for (var y = 0; y <= height; ++y) {
 | 
			
		||||
      if (this._grid.length <= y) {
 | 
			
		||||
        this._grid.push([]);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (var x = 0; x <= width; ++x) {
 | 
			
		||||
        if (this._grid[y].length <= x) {
 | 
			
		||||
          this._grid[y].push({
 | 
			
		||||
            $el: $('<td>'),
 | 
			
		||||
            x: 0,
 | 
			
		||||
            y: 0,
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!this._batchProcess) {
 | 
			
		||||
      var $oldBody = this.$table.find('tbody');
 | 
			
		||||
      $('.wcDockerTransition').append($oldBody);
 | 
			
		||||
 | 
			
		||||
      var $newBody = $('<tbody>');
 | 
			
		||||
      for (var y = 0; y < this._grid.length; ++y) {
 | 
			
		||||
        var $row = null;
 | 
			
		||||
 | 
			
		||||
        for (var x = 0; x < this._grid[y].length; ++x) {
 | 
			
		||||
          var item = this._grid[y][x];
 | 
			
		||||
          if (item.$el) {
 | 
			
		||||
            if (!$row) {
 | 
			
		||||
              $row = $('<tr>');
 | 
			
		||||
              $newBody.append($row);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $row.append(item.$el);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.$table.append($newBody);
 | 
			
		||||
      $oldBody.remove();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Merges cells in the layout.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y      Cell position to begin merge.
 | 
			
		||||
  //    w, h      The width and height to merge.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    true      Cells were merged succesfully.
 | 
			
		||||
  //    false     Merge failed, either because the grid position was out of bounds
 | 
			
		||||
  //              or some of the cells were already merged.
 | 
			
		||||
  __mergeGrid: function(x, y, w, h) {
 | 
			
		||||
    // Make sure each cell to be merged is not already merged somewhere else.
 | 
			
		||||
    for (var yy = 0; yy < h; ++yy) {
 | 
			
		||||
      for (var xx = 0; xx < w; ++xx) {
 | 
			
		||||
        var item = this._grid[y + yy][x + xx];
 | 
			
		||||
        if (!item.$el || item.x !== 0 || item.y !== 0) {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Now merge the cells here.
 | 
			
		||||
    var item = this._grid[y][x];
 | 
			
		||||
    if (w > 1) {
 | 
			
		||||
      item.$el.attr('colspan', '' + w);
 | 
			
		||||
      item.x = w-1;
 | 
			
		||||
    }
 | 
			
		||||
    if (h > 1) {
 | 
			
		||||
      item.$el.attr('rowspan', '' + h);
 | 
			
		||||
      item.y = h-1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (var yy = 0; yy < h; ++yy) {
 | 
			
		||||
      for (var xx = 0; xx < w; ++xx) {
 | 
			
		||||
        if (yy !== 0 || xx !== 0) {
 | 
			
		||||
          var item = this._grid[y + yy][x + xx];
 | 
			
		||||
          item.$el.remove();
 | 
			
		||||
          item.$el = null;
 | 
			
		||||
          item.x = -xx;
 | 
			
		||||
          item.y = -yy;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Checks if the mouse is in a valid anchor position for nesting another widget.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    mouse     The current mouse position.
 | 
			
		||||
  //    same      Whether the moving frame and this one are the same.
 | 
			
		||||
  __checkAnchorDrop: function(mouse, same, ghost, canSplit, $elem, title) {
 | 
			
		||||
    var width = $elem.width();
 | 
			
		||||
    var height = $elem.height();
 | 
			
		||||
    var offset = $elem.offset();
 | 
			
		||||
    var top = $elem.find('.wcFrameTitle').height();
 | 
			
		||||
    // var top = this.$table.offset().top - offset.top;
 | 
			
		||||
    if (!title) {
 | 
			
		||||
      top = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (same) {
 | 
			
		||||
      // Same tabs
 | 
			
		||||
      if (mouse.y >= offset.top && mouse.y <= offset.top + top &&
 | 
			
		||||
          mouse.x >= offset.left && mouse.x <= offset.left + width) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left,
 | 
			
		||||
          y: offset.top,
 | 
			
		||||
          w: width,
 | 
			
		||||
          h: top-2,
 | 
			
		||||
          loc: wcDocker.DOCK_STACKED,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: true,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Tab ordering or adding.
 | 
			
		||||
    if (title) {
 | 
			
		||||
      if (mouse.y >= offset.top && mouse.y <= offset.top + top &&
 | 
			
		||||
          mouse.x >= offset.left && mouse.x <= offset.left + width) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left,
 | 
			
		||||
          y: offset.top,
 | 
			
		||||
          w: width,
 | 
			
		||||
          h: top-2,
 | 
			
		||||
          loc: wcDocker.DOCK_STACKED,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: false,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!canSplit) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (width < height) {
 | 
			
		||||
      // Top docking.
 | 
			
		||||
      if (mouse.y >= offset.top && mouse.y <= offset.top + height*0.25 &&
 | 
			
		||||
          mouse.x >= offset.left && mouse.x <= offset.left + width) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left,
 | 
			
		||||
          y: offset.top,
 | 
			
		||||
          w: width,
 | 
			
		||||
          h: height*0.5,
 | 
			
		||||
          loc: wcDocker.DOCK_TOP,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: false,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Bottom side docking.
 | 
			
		||||
      if (mouse.y >= offset.top + height*0.75 && mouse.y <= offset.top + height &&
 | 
			
		||||
          mouse.x >= offset.left && mouse.x <= offset.left + width) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left,
 | 
			
		||||
          y: offset.top + (height - height*0.5),
 | 
			
		||||
          w: width,
 | 
			
		||||
          h: height*0.5,
 | 
			
		||||
          loc: wcDocker.DOCK_BOTTOM,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: false,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Left side docking
 | 
			
		||||
    if (mouse.y >= offset.top && mouse.y <= offset.top + height) {
 | 
			
		||||
      if (mouse.x >= offset.left && mouse.x <= offset.left + width*0.25) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left,
 | 
			
		||||
          y: offset.top,
 | 
			
		||||
          w: width*0.5,
 | 
			
		||||
          h: height,
 | 
			
		||||
          loc: wcDocker.DOCK_LEFT,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: false,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Right side docking
 | 
			
		||||
      if (mouse.x >= offset.left + width*0.75 && mouse.x <= offset.left + width) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left + width*0.5,
 | 
			
		||||
          y: offset.top,
 | 
			
		||||
          w: width*0.5,
 | 
			
		||||
          h: height,
 | 
			
		||||
          loc: wcDocker.DOCK_RIGHT,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: false,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (width >= height) {
 | 
			
		||||
      // Top docking.
 | 
			
		||||
      if (mouse.y >= offset.top && mouse.y <= offset.top + height*0.25 &&
 | 
			
		||||
          mouse.x >= offset.left && mouse.x <= offset.left + width) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left,
 | 
			
		||||
          y: offset.top,
 | 
			
		||||
          w: width,
 | 
			
		||||
          h: height*0.5,
 | 
			
		||||
          loc: wcDocker.DOCK_TOP,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: false,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Bottom side docking.
 | 
			
		||||
      if (mouse.y >= offset.top + height*0.75 && mouse.y <= offset.top + height &&
 | 
			
		||||
          mouse.x >= offset.left && mouse.x <= offset.left + width) {
 | 
			
		||||
        ghost.anchor(mouse, {
 | 
			
		||||
          x: offset.left,
 | 
			
		||||
          y: offset.top + (height - height*0.5),
 | 
			
		||||
          w: width,
 | 
			
		||||
          h: height*0.5,
 | 
			
		||||
          loc: wcDocker.DOCK_BOTTOM,
 | 
			
		||||
          item: this,
 | 
			
		||||
          self: false,
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets a new container for this layout.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    $container          If supplied, sets a new container for this layout.
 | 
			
		||||
  //    parent              If supplied, sets a new parent for this layout.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    JQuery collection   The current container.
 | 
			
		||||
  __container: function($container) {
 | 
			
		||||
    if (typeof $container === 'undefined') {
 | 
			
		||||
      return this.$container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$container = $container;
 | 
			
		||||
    if (this.$container) {
 | 
			
		||||
      this.$container.append(this.$table);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$table.remove();
 | 
			
		||||
    }
 | 
			
		||||
    return this.$container;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Destroys the layout.
 | 
			
		||||
  __destroy: function() {
 | 
			
		||||
    this.__container(null);
 | 
			
		||||
    this._parent = null;
 | 
			
		||||
    this.clear();
 | 
			
		||||
 | 
			
		||||
    this.$table.remove();
 | 
			
		||||
    this.$table = null;
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,728 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
  The public interface for the docking panel, it contains a layout that can be filled with custom
 | 
			
		||||
  elements and a number of convenience functions for use.
 | 
			
		||||
*/
 | 
			
		||||
function wcPanel(type, options) {
 | 
			
		||||
  this.$container = null;
 | 
			
		||||
  this._parent = null;
 | 
			
		||||
  this.$icon = null;
 | 
			
		||||
 | 
			
		||||
  if (options.icon) {
 | 
			
		||||
    this.icon(options.icon);
 | 
			
		||||
  }
 | 
			
		||||
  if (options.faicon) {
 | 
			
		||||
    this.faicon(options.faicon);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this._panelObject = null;
 | 
			
		||||
  this._initialized = false;
 | 
			
		||||
 | 
			
		||||
  this._type = type;
 | 
			
		||||
  this._title = type;
 | 
			
		||||
  this._titleVisible = true;
 | 
			
		||||
 | 
			
		||||
  this._layout = null;
 | 
			
		||||
 | 
			
		||||
  this._buttonList = [];
 | 
			
		||||
 | 
			
		||||
  this._actualPos = {
 | 
			
		||||
    x: 0.5,
 | 
			
		||||
    y: 0.5,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._actualSize = {
 | 
			
		||||
    x: 0,
 | 
			
		||||
    y: 0,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._resizeData = {
 | 
			
		||||
    time: -1,
 | 
			
		||||
    timeout: false,
 | 
			
		||||
    delta: 150,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._pos = {
 | 
			
		||||
    x: 0.5,
 | 
			
		||||
    y: 0.5,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._moveData = {
 | 
			
		||||
    time: -1,
 | 
			
		||||
    timeout: false,
 | 
			
		||||
    delta: 150,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._size = {
 | 
			
		||||
    x: -1,
 | 
			
		||||
    y: -1,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._minSize = {
 | 
			
		||||
    x: 100,
 | 
			
		||||
    y: 100,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._maxSize = {
 | 
			
		||||
    x: Infinity,
 | 
			
		||||
    y: Infinity,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._scroll = {
 | 
			
		||||
    x: 0,
 | 
			
		||||
    y: 0,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._scrollable = {
 | 
			
		||||
    x: true,
 | 
			
		||||
    y: true,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  this._overflowVisible = false;
 | 
			
		||||
  this._moveable = true;
 | 
			
		||||
  this._closeable = true;
 | 
			
		||||
  this._resizeVisible = true;
 | 
			
		||||
  this._isVisible = false;
 | 
			
		||||
 | 
			
		||||
  this._events = {};
 | 
			
		||||
 | 
			
		||||
  this.__init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wcPanel.prototype = {
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Public Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Finds the main Docker window.
 | 
			
		||||
  docker: function() {
 | 
			
		||||
    var parent = this._parent;
 | 
			
		||||
    while (parent && !(parent instanceof wcDocker)) {
 | 
			
		||||
      parent = parent._parent;
 | 
			
		||||
    }
 | 
			
		||||
    return parent;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the title for this dock widget.
 | 
			
		||||
  title: function(title) {
 | 
			
		||||
    if (typeof title !== 'undefined') {
 | 
			
		||||
      if (title === false) {
 | 
			
		||||
        this._titleVisible = false;
 | 
			
		||||
      } else {
 | 
			
		||||
        this._title = title;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this._parent instanceof wcFrame) {
 | 
			
		||||
        this._parent.__updateTabs();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._title;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the registration info of the panel.
 | 
			
		||||
  info: function() {
 | 
			
		||||
    return this.docker().panelTypeInfo(this._type);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the main widget container for this dock widget.
 | 
			
		||||
  layout: function() {
 | 
			
		||||
    return this._layout;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Brings this widget into focus.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    flash     Optional, if true will flash the window.
 | 
			
		||||
  focus: function(flash) {
 | 
			
		||||
    var docker = this.docker();
 | 
			
		||||
    if (docker) {
 | 
			
		||||
      docker.__focus(this._parent, flash);
 | 
			
		||||
      for (var i = 0; i < this._parent._panelList.length; ++i) {
 | 
			
		||||
        if (this._parent._panelList[i] === this) {
 | 
			
		||||
          this._parent.panel(i);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves whether this panel is within view.
 | 
			
		||||
  isVisible: function() {
 | 
			
		||||
    return this._isVisible;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Creates a new custom button that will appear in the title bar of the panel.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    name              The name of the button, to identify it.
 | 
			
		||||
  //    className         A class name to apply to the button.
 | 
			
		||||
  //    text              Text to apply to the button.
 | 
			
		||||
  //    tip               Tooltip text.
 | 
			
		||||
  //    isTogglable       If true, will make the button toggle on and off per click.
 | 
			
		||||
  //    toggleClassName   If this button is toggleable, you can designate an
 | 
			
		||||
  //                      optional class name that will replace the original class name.
 | 
			
		||||
  addButton: function(name, className, text, tip, isTogglable, toggleClassName) {
 | 
			
		||||
    this._buttonList.push({
 | 
			
		||||
      name: name,
 | 
			
		||||
      className: className,
 | 
			
		||||
      toggleClassName: toggleClassName,
 | 
			
		||||
      text: text,
 | 
			
		||||
      tip: tip,
 | 
			
		||||
      isTogglable: isTogglable,
 | 
			
		||||
      isToggled: false,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (this._parent instanceof wcFrame) {
 | 
			
		||||
      this._parent.__update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._buttonList.length-1;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Removes a button from the panel.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    name        The name identifier for this button.
 | 
			
		||||
  removeButton: function(name) {
 | 
			
		||||
    for (var i = 0; i < this._buttonList.length; ++i) {
 | 
			
		||||
      if (this._buttonList[i].name === name) {
 | 
			
		||||
        this._buttonList.splice(i, 1);
 | 
			
		||||
        if (this._parent instanceof wcFrame) {
 | 
			
		||||
          this._parent.__onTabChange();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._parent instanceof wcFrame) {
 | 
			
		||||
          this._parent.__update();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the current toggle state of a custom button that was
 | 
			
		||||
  // added using addButton().
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    name          The name identifier of the button.
 | 
			
		||||
  //    isToggled     If supplied, will assign a new toggle state to the button.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    Boolean       The current toggle state of the button.
 | 
			
		||||
  buttonState: function(name, isToggled) {
 | 
			
		||||
    for (var i = 0; i < this._buttonList.length; ++i) {
 | 
			
		||||
      if (this._buttonList[i].name === name) {
 | 
			
		||||
        if (typeof isToggled !== 'undefined') {
 | 
			
		||||
          this._buttonList[i].isToggled = isToggled;
 | 
			
		||||
          if (this._parent instanceof wcFrame) {
 | 
			
		||||
            this._parent.__onTabChange();
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._parent instanceof wcFrame) {
 | 
			
		||||
          this._parent.__update();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this._buttonList[i].isToggled;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the default position of the widget if it is floating.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y    If supplied, sets the position of the floating panel.
 | 
			
		||||
  //            Can be a pixel position, or a string with a 'px' or '%' suffix.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //            An object with the current percentage position is returned.
 | 
			
		||||
  initPos: function(x, y) {
 | 
			
		||||
    if (typeof x !== 'undefined') {
 | 
			
		||||
      var docker = this.docker();
 | 
			
		||||
      if (docker) {
 | 
			
		||||
        this._pos.x = this.__stringToPercent(x, docker.$container.width());
 | 
			
		||||
        this._pos.y = this.__stringToPercent(y, docker.$container.height());
 | 
			
		||||
      } else {
 | 
			
		||||
        this._pos.x = x;
 | 
			
		||||
        this._pos.y = y;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {x: this._pos.x, y: this._pos.y};
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the desired size of the widget.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y    If supplied, sets the desired initial size of the panel.
 | 
			
		||||
  //            Can be a pixel position, or a string with a 'px' or '%' suffix.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //            An object with the current pixel size is returned.
 | 
			
		||||
  initSize: function(x, y) {
 | 
			
		||||
    if (typeof x !== 'undefined') {
 | 
			
		||||
      var docker = this.docker();
 | 
			
		||||
      if (docker) {
 | 
			
		||||
        this._size.x = this.__stringToPixel(x, docker.$container.width());
 | 
			
		||||
        this._size.y = this.__stringToPixel(y, docker.$container.height());
 | 
			
		||||
      } else {
 | 
			
		||||
        this._size.x = x;
 | 
			
		||||
        this._size.y = y;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return {x: this._size.x, y: this._size.y};
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the minimum size of the widget.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y    If supplied, sets the desired minimum size of the panel.
 | 
			
		||||
  //            Can be a pixel position, or a string with a 'px' or '%' suffix.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //            An object with the current minimum pixel size is returned.
 | 
			
		||||
  minSize: function(x, y) {
 | 
			
		||||
    if (typeof x !== 'undefined') {
 | 
			
		||||
      var docker = this.docker();
 | 
			
		||||
      if (docker) {
 | 
			
		||||
        this._minSize.x = this.__stringToPixel(x, docker.$container.width());
 | 
			
		||||
        this._minSize.y = this.__stringToPixel(y, docker.$container.height());
 | 
			
		||||
      } else {
 | 
			
		||||
        this._minSize.x = x;
 | 
			
		||||
        this._minSize.y = y;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return this._minSize;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the maximum size of the widget.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y    If supplied, sets the desired maximum size of the panel.
 | 
			
		||||
  //            Can be a pixel position, or a string with a 'px' or '%' suffix.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //            An object with the current maximum pixel size is returned.
 | 
			
		||||
  maxSize: function(x, y) {
 | 
			
		||||
    if (typeof x !== 'undefined') {
 | 
			
		||||
      var docker = this.docker();
 | 
			
		||||
      if (docker) {
 | 
			
		||||
        this._maxSize.x = this.__stringToPixel(x, docker.$container.width());
 | 
			
		||||
        this._maxSize.y = this.__stringToPixel(y, docker.$container.height());
 | 
			
		||||
      } else {
 | 
			
		||||
        this._maxSize.x = x;
 | 
			
		||||
        this._maxSize.y = y;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return this._maxSize;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the width of the panel contents.
 | 
			
		||||
  width: function() {
 | 
			
		||||
    if (this.$container) {
 | 
			
		||||
      return this.$container.width();
 | 
			
		||||
    }
 | 
			
		||||
    return 0.0;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the height of the panel contents.
 | 
			
		||||
  height: function() {
 | 
			
		||||
    if (this.$container) {
 | 
			
		||||
      return this.$container.height();
 | 
			
		||||
    }
 | 
			
		||||
    return 0.0;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Sets the icon for the panel, shown in the panels tab widget.
 | 
			
		||||
  // Must be a css class name that contains the image.
 | 
			
		||||
  icon: function(icon) {
 | 
			
		||||
    if (!this.$icon) {
 | 
			
		||||
      this.$icon = $('<div>');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$icon.removeClass();
 | 
			
		||||
    this.$icon.addClass('wcTabIcon ' + icon);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Sets the icon for the panel, shown in the panels tab widget,
 | 
			
		||||
  // to an icon defined from the font-awesome library.
 | 
			
		||||
  faicon: function(icon) {
 | 
			
		||||
    if (!this.$icon) {
 | 
			
		||||
      this.$icon = $('<div>');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$icon.removeClass();
 | 
			
		||||
    this.$icon.addClass('fa fa-fw fa-' + icon);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the scroll position of the window (if it is scrollable).
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y      If supplied, sets the scroll position of the window.
 | 
			
		||||
  //    duration  If setting a scroll position, you can supply a time duration
 | 
			
		||||
  //              to animate the scroll (in milliseconds).
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    object    The scroll position of the window.
 | 
			
		||||
  scroll: function(x, y, duration) {
 | 
			
		||||
    if (!this.$container) {
 | 
			
		||||
      return {x: 0, y: 0};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof x !== 'undefined') {
 | 
			
		||||
      if (duration) {
 | 
			
		||||
        this.$container.parent().stop().animate({
 | 
			
		||||
          scrollLeft: x,
 | 
			
		||||
          scrollTop: y,
 | 
			
		||||
        }, duration);
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$container.parent().scrollLeft(x);
 | 
			
		||||
        this.$container.parent().scrollTop(y);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      x: this.$container.parent().scrollLeft(),
 | 
			
		||||
      y: this.$container.parent().scrollTop(),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether overflow on this panel is visible.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    visible   If supplied, assigns whether overflow is visible.
 | 
			
		||||
  //
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    boolean   The current overflow visibility.
 | 
			
		||||
  overflowVisible: function(visible) {
 | 
			
		||||
    if (typeof visible !== 'undefined') {
 | 
			
		||||
      this._overflowVisible = visible? true: false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._overflowVisible;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether the contents of the panel are visible on resize.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    visible   If supplied, assigns whether panel contents are visible.
 | 
			
		||||
  //
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    boolean   The current resize visibility.
 | 
			
		||||
  resizeVisible: function(visible) {
 | 
			
		||||
    if (typeof visible !== 'undefined') {
 | 
			
		||||
      this._resizeVisible = visible? true: false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._resizeVisible;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether the window is scrollable.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    x, y      If supplied, assigns whether the window is scrollable
 | 
			
		||||
  //              for each axis.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    object    The current scrollable status.
 | 
			
		||||
  scrollable: function(x, y) {
 | 
			
		||||
    if (typeof x !== 'undefined') {
 | 
			
		||||
      this._scrollable.x = x? true: false;
 | 
			
		||||
      this._scrollable.y = y? true: false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {x: this._scrollable.x, y: this._scrollable.y};
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Sets, or Gets the moveable status of the window.
 | 
			
		||||
  moveable: function(enabled) {
 | 
			
		||||
    if (typeof enabled !== 'undefined') {
 | 
			
		||||
      this._moveable = enabled? true: false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._moveable;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether this dock window can be closed.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    enabled     If supplied, toggles whether it can be closed.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    bool        The current closeable status.
 | 
			
		||||
  closeable: function(enabled) {
 | 
			
		||||
    if (typeof enabled !== 'undefined') {
 | 
			
		||||
      this._closeable = enabled? true: false;
 | 
			
		||||
      if (this._parent) {
 | 
			
		||||
        this._parent.__update();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._closeable;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Forces the window to close.
 | 
			
		||||
  close: function() {
 | 
			
		||||
    if (this._parent) {
 | 
			
		||||
      this._parent.$close.click();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Registers an event.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    eventType     The event type, as defined by wcDocker.EVENT_...
 | 
			
		||||
  //    handler       A handler function to be called for the event.
 | 
			
		||||
  //                  Params:
 | 
			
		||||
  //                    panel   The panel invoking the event.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    true          The event was added.
 | 
			
		||||
  //    false         The event failed to add.
 | 
			
		||||
  on: function(eventType, handler) {
 | 
			
		||||
    if (!eventType) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!this._events[eventType]) {
 | 
			
		||||
      this._events[eventType] = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._events[eventType].indexOf(handler) !== -1) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this._events[eventType].push(handler);
 | 
			
		||||
    return true;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Unregisters an event.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    eventType     The event type to remove, if omitted, all events are removed.
 | 
			
		||||
  //    handler       The handler function to remove, if omitted, all events of
 | 
			
		||||
  //                  the above type are removed.
 | 
			
		||||
  off: function(eventType, handler) {
 | 
			
		||||
    if (typeof eventType === 'undefined') {
 | 
			
		||||
      this._events = {};
 | 
			
		||||
      return;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (this._events[eventType]) {
 | 
			
		||||
        if (typeof handler === 'undefined') {
 | 
			
		||||
          this._events[eventType] = [];
 | 
			
		||||
        } else {
 | 
			
		||||
          for (var i = 0; i < this._events[eventType].length; ++i) {
 | 
			
		||||
            if (this._events[eventType][i] === handler) {
 | 
			
		||||
              this._events[eventType].splice(i, 1);
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Triggers an event of a given type to all panels.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    eventType     The event to trigger.
 | 
			
		||||
  //    data          A custom data object to pass into all handlers.
 | 
			
		||||
  trigger: function(eventType, data) {
 | 
			
		||||
    var docker = this.docker();
 | 
			
		||||
    if (docker) {
 | 
			
		||||
      docker.trigger(eventType, data);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Private Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Initialize
 | 
			
		||||
  __init: function() {
 | 
			
		||||
    this._layout = new wcLayout(this.$container, this);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Updates the size of the layout.
 | 
			
		||||
  __update: function() {
 | 
			
		||||
    this._layout.__update();
 | 
			
		||||
    if (!this.$container) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ( this._resizeVisible ) {
 | 
			
		||||
      this._parent.$frame.removeClass('wcHideOnResize');
 | 
			
		||||
    } else {
 | 
			
		||||
      this._parent.$frame.addClass('wcHideOnResize');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!this._initialized) {
 | 
			
		||||
      this._initialized = true;
 | 
			
		||||
      var self = this;
 | 
			
		||||
      setTimeout(function() {
 | 
			
		||||
        self.__trigger(wcDocker.EVENT_INIT);
 | 
			
		||||
      }, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__trigger(wcDocker.EVENT_UPDATED);
 | 
			
		||||
 | 
			
		||||
    var width   = this.$container.width();
 | 
			
		||||
    var height  = this.$container.height();
 | 
			
		||||
    if (this._actualSize.x !== width || this._actualSize.y !== height) {
 | 
			
		||||
      this._actualSize.x = width;
 | 
			
		||||
      this._actualSize.y = height;
 | 
			
		||||
 | 
			
		||||
      this._resizeData.time = new Date();
 | 
			
		||||
      if (!this._resizeData.timeout) {
 | 
			
		||||
        this._resizeData.timeout = true;
 | 
			
		||||
        setTimeout(this.__resizeEnd.bind(this), this._resizeData.delta);
 | 
			
		||||
        this.__trigger(wcDocker.EVENT_RESIZE_STARTED);
 | 
			
		||||
      }
 | 
			
		||||
      this.__trigger(wcDocker.EVENT_RESIZED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var offset  = this.$container.offset();
 | 
			
		||||
    if (this._actualPos.x !== offset.left || this._actualPos.y !== offset.top) {
 | 
			
		||||
      this._actualPos.x = offset.left;
 | 
			
		||||
      this._actualPos.y = offset.top;
 | 
			
		||||
 | 
			
		||||
      this._moveData.time = new Date();
 | 
			
		||||
      if (!this._moveData.timeout) {
 | 
			
		||||
        this._moveData.timeout = true;
 | 
			
		||||
        setTimeout(this.__moveEnd.bind(this), this._moveData.delta);
 | 
			
		||||
        this.__trigger(wcDocker.EVENT_MOVE_STARTED);
 | 
			
		||||
      }
 | 
			
		||||
      this.__trigger(wcDocker.EVENT_MOVED);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __resizeEnd: function() {
 | 
			
		||||
    if (new Date() - this._resizeData.time < this._resizeData.delta) {
 | 
			
		||||
      setTimeout(this.__resizeEnd.bind(this), this._resizeData.delta);
 | 
			
		||||
    } else {
 | 
			
		||||
      this._resizeData.timeout = false;
 | 
			
		||||
      this.__trigger(wcDocker.EVENT_RESIZE_ENDED);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __moveEnd: function() {
 | 
			
		||||
    if (new Date() - this._moveData.time < this._moveData.delta) {
 | 
			
		||||
      setTimeout(this.__moveEnd.bind(this), this._moveData.delta);
 | 
			
		||||
    } else {
 | 
			
		||||
      this._moveData.timeout = false;
 | 
			
		||||
      this.__trigger(wcDocker.EVENT_MOVE_ENDED);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __isVisible: function(inView) {
 | 
			
		||||
    if (this._isVisible !== inView) {
 | 
			
		||||
      this._isVisible = inView;
 | 
			
		||||
 | 
			
		||||
      this.__trigger(wcDocker.EVENT_VISIBILITY_CHANGED);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Saves the current panel configuration into a meta
 | 
			
		||||
  // object that can be used later to restore it.
 | 
			
		||||
  __save: function() {
 | 
			
		||||
    var data = {};
 | 
			
		||||
    data.type = 'wcPanel';
 | 
			
		||||
    data.panelType = this._type;
 | 
			
		||||
    // data.title = this._title;
 | 
			
		||||
    // data.minSize = {
 | 
			
		||||
    //   x: this._minSize.x,
 | 
			
		||||
    //   y: this._minSize.y,
 | 
			
		||||
    // };
 | 
			
		||||
    // data.maxSize = {
 | 
			
		||||
    //   x: this._maxSize.x,
 | 
			
		||||
    //   y: this._maxSize.y,
 | 
			
		||||
    // };
 | 
			
		||||
    // data.scrollable = {
 | 
			
		||||
    //   x: this._scrollable.x,
 | 
			
		||||
    //   y: this._scrollable.y,
 | 
			
		||||
    // };
 | 
			
		||||
    // data.moveable = this._moveable;
 | 
			
		||||
    // data.closeable = this._closeable;
 | 
			
		||||
    // data.resizeVisible = this.resizeVisible();
 | 
			
		||||
    data.customData = {};
 | 
			
		||||
    this.__trigger(wcDocker.EVENT_SAVE_LAYOUT, data.customData);
 | 
			
		||||
    return data;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Restores a previously saved configuration.
 | 
			
		||||
  __restore: function(data, docker) {
 | 
			
		||||
    // this._title = data.title;
 | 
			
		||||
    // this._minSize.x = data.minSize.x;
 | 
			
		||||
    // this._minSize.y = data.minSize.y;
 | 
			
		||||
    // this._maxSize.x = data.maxSize.x;
 | 
			
		||||
    // this._maxSize.y = data.maxSize.y;
 | 
			
		||||
    // this._scrollable.x = data.scrollable.x;
 | 
			
		||||
    // this._scrollable.y = data.scrollable.y;
 | 
			
		||||
    // this._moveable = data.moveable;
 | 
			
		||||
    // this._closeable = data.closeable;
 | 
			
		||||
    // this.resizeVisible(data.resizeVisible)
 | 
			
		||||
    this.__trigger(wcDocker.EVENT_RESTORE_LAYOUT, data.customData);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Triggers an event of a given type onto this current panel.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    eventType     The event to trigger.
 | 
			
		||||
  //    data          A custom data object to pass into all handlers.
 | 
			
		||||
  __trigger: function(eventType, data) {
 | 
			
		||||
    if (!eventType) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._events[eventType]) {
 | 
			
		||||
      for (var i = 0; i < this._events[eventType].length; ++i) {
 | 
			
		||||
        this._events[eventType][i].call(this, data);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Converts a potential string value to a percentage.
 | 
			
		||||
  __stringToPercent: function(value, size) {
 | 
			
		||||
    if (typeof value === 'string') {
 | 
			
		||||
      if (value.indexOf('%', value.length - 1) !== -1) {
 | 
			
		||||
        return parseFloat(value)/100;
 | 
			
		||||
      } else if (value.indexOf('px', value.length - 2) !== -1) {
 | 
			
		||||
        return parseFloat(value) / size;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return parseFloat(value);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Converts a potential string value to a pixel value.
 | 
			
		||||
  __stringToPixel: function(value, size) {
 | 
			
		||||
    if (typeof value === 'string') {
 | 
			
		||||
      if (value.indexOf('%', value.length - 1) !== -1) {
 | 
			
		||||
        return (parseFloat(value)/100) * size;
 | 
			
		||||
      } else if (value.indexOf('px', value.length - 2) !== -1) {
 | 
			
		||||
        return parseFloat(value);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return parseFloat(value);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the bounding rect for this widget.
 | 
			
		||||
  __rect: function() {
 | 
			
		||||
    var offset = this.$container.offset();
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      x: offset.left,
 | 
			
		||||
      y: offset.top,
 | 
			
		||||
      w: width,
 | 
			
		||||
      h: height,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets a new container for this layout.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    $container          If supplied, sets a new container for this layout.
 | 
			
		||||
  //    parent              If supplied, sets a new parent for this layout.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    JQuery collection   The current container.
 | 
			
		||||
  __container: function($container) {
 | 
			
		||||
    if (typeof $container === 'undefined') {
 | 
			
		||||
      return this.$container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$container = $container;
 | 
			
		||||
    
 | 
			
		||||
    if (this.$container) {
 | 
			
		||||
      this._layout.__container(this.$container);
 | 
			
		||||
    } else {
 | 
			
		||||
      this._layout.__container(null);
 | 
			
		||||
    }
 | 
			
		||||
    return this.$container;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Destroys this panel.
 | 
			
		||||
  __destroy: function() {
 | 
			
		||||
    this._panelObject = null;
 | 
			
		||||
    this.off();
 | 
			
		||||
 | 
			
		||||
    this.__container(null);
 | 
			
		||||
    this._parent = null;
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,552 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
  Splits an area in two, dividing it with a resize splitter bar
 | 
			
		||||
*/
 | 
			
		||||
function wcSplitter(container, parent, orientation) {
 | 
			
		||||
  this.$container = $(container);
 | 
			
		||||
  this._parent = parent;
 | 
			
		||||
  this._orientation = orientation;
 | 
			
		||||
 | 
			
		||||
  this._pane = [false, false];
 | 
			
		||||
  this.$pane = [];
 | 
			
		||||
  this.$bar = null;
 | 
			
		||||
  this._pos = 0.5;
 | 
			
		||||
  this._findBestPos = false;
 | 
			
		||||
 | 
			
		||||
  this._boundEvents = [];
 | 
			
		||||
 | 
			
		||||
  this.__init();
 | 
			
		||||
 | 
			
		||||
  this.docker()._splitterList.push(this);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wcSplitter.prototype = {
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Public Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Initializes the splitter with its own layouts.
 | 
			
		||||
  initLayouts: function() {
 | 
			
		||||
    var layout0 = new wcLayout(this.$pane[0], this);
 | 
			
		||||
    var layout1 = new wcLayout(this.$pane[1], this);
 | 
			
		||||
    this.pane(0, layout0);
 | 
			
		||||
    this.pane(1, layout1);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Finds the main Docker window.
 | 
			
		||||
  docker: function() {
 | 
			
		||||
    var parent = this._parent;
 | 
			
		||||
    while (parent && !(parent instanceof wcDocker)) {
 | 
			
		||||
      parent = parent._parent;
 | 
			
		||||
    }
 | 
			
		||||
    return parent;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the orientation of the splitter.
 | 
			
		||||
  orientation: function(value) {
 | 
			
		||||
    if (typeof value === 'undefined') {
 | 
			
		||||
      return this._orientation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._orientation != value) {
 | 
			
		||||
      this._orientation = value;
 | 
			
		||||
 | 
			
		||||
      if (this._orientation) {
 | 
			
		||||
        this.$pane[0].removeClass('wcWide').addClass('wcTall');
 | 
			
		||||
        this.$pane[1].removeClass('wcWide').addClass('wcTall');
 | 
			
		||||
        this.$bar.removeClass('wcWide').removeClass('wcSplitterBarH').addClass('wcTall').addClass('wcSplitterBarV');
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$pane[0].removeClass('wcTall').addClass('wcWide');
 | 
			
		||||
        this.$pane[1].removeClass('wcTall').addClass('wcWide');
 | 
			
		||||
        this.$bar.removeClass('wcTall').removeClass('wcSplitterBarV').addClass('wcWide').addClass('wcSplitterBarH');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.$pane[0].css('top', '').css('left', '').css('width', '').css('height', '');
 | 
			
		||||
      this.$pane[1].css('top', '').css('left', '').css('width', '').css('height', '');
 | 
			
		||||
      this.$bar.css('top', '').css('left', '').css('width', '').css('height', '');
 | 
			
		||||
      this.__update();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the minimum size of the widget.
 | 
			
		||||
  minSize: function() {
 | 
			
		||||
    var minSize1;
 | 
			
		||||
    var minSize2;
 | 
			
		||||
    if (this._pane[0] && typeof this._pane[0].minSize === 'function') {
 | 
			
		||||
      minSize1 = this._pane[0].minSize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._pane[1] && typeof this._pane[1].minSize === 'function') {
 | 
			
		||||
      minSize2 = this._pane[1].minSize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (minSize1 && minSize2) {
 | 
			
		||||
      if (this._orientation) {
 | 
			
		||||
        minSize1.x += minSize2.x;
 | 
			
		||||
        minSize1.y = Math.max(minSize1.y, minSize2.y);
 | 
			
		||||
      } else {
 | 
			
		||||
        minSize1.y += minSize2.y;
 | 
			
		||||
        minSize1.x = Math.max(minSize1.x, minSize2.x);
 | 
			
		||||
      }
 | 
			
		||||
      return minSize1;
 | 
			
		||||
      return {
 | 
			
		||||
        x: Math.min(minSize1.x, minSize2.x),
 | 
			
		||||
        y: Math.min(minSize1.y, minSize2.y),
 | 
			
		||||
      };
 | 
			
		||||
    } else if (minSize1) {
 | 
			
		||||
      return minSize1;
 | 
			
		||||
    } else if (minSize2) {
 | 
			
		||||
      return minSize2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the minimum size of the widget.
 | 
			
		||||
  maxSize: function() {
 | 
			
		||||
    var maxSize1;
 | 
			
		||||
    var maxSize2;
 | 
			
		||||
    if (this._pane[0] && typeof this._pane[0].maxSize === 'function') {
 | 
			
		||||
      maxSize1 = this._pane[0].maxSize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._pane[1] && typeof this._pane[1].maxSize === 'function') {
 | 
			
		||||
      maxSize2 = this._pane[1].maxSize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (maxSize1 && maxSize2) {
 | 
			
		||||
      if (this._orientation) {
 | 
			
		||||
        maxSize1.x += maxSize2.x;
 | 
			
		||||
        maxSize1.y = Math.min(maxSize1.y, maxSize2.y);
 | 
			
		||||
      } else {
 | 
			
		||||
        maxSize1.y += maxSize2.y;
 | 
			
		||||
        maxSize1.x = Math.min(maxSize1.x, maxSize2.x);
 | 
			
		||||
      }
 | 
			
		||||
      return maxSize1;
 | 
			
		||||
      return {
 | 
			
		||||
        x: Math.min(maxSize1.x, maxSize2.x),
 | 
			
		||||
        y: Math.min(maxSize1.y, maxSize2.y),
 | 
			
		||||
      };
 | 
			
		||||
    } else if (maxSize1) {
 | 
			
		||||
      return maxSize1;
 | 
			
		||||
    } else if (maxSize2) {
 | 
			
		||||
      return maxSize2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Get, or Set a splitter position.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    value         If supplied, assigns a new splitter percentage (0-1).
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    number        The current position.
 | 
			
		||||
  pos: function(value) {
 | 
			
		||||
    if (typeof value === 'undefined') {
 | 
			
		||||
      return this._pos;
 | 
			
		||||
    }
 | 
			
		||||
    this._pos = value;
 | 
			
		||||
    this.__update();
 | 
			
		||||
 | 
			
		||||
    if (this._parent instanceof wcPanel) {
 | 
			
		||||
      this._parent.__trigger(wcDocker.EVENT_UPDATED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._pos;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Sets, or Gets the widget at a given pane
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index       The pane index, only 0 or 1 are valid.
 | 
			
		||||
  //    item        If supplied, assigns the item to the pane.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    wcPanel     The panel that exists in the pane.
 | 
			
		||||
  //    wcSplitter  
 | 
			
		||||
  //    false       If no pane exists.
 | 
			
		||||
  pane: function(index, item) {
 | 
			
		||||
    if (index >= 0 && index < 2) {
 | 
			
		||||
      if (typeof item === 'undefined') {
 | 
			
		||||
        return this._pane[index];
 | 
			
		||||
      } else {
 | 
			
		||||
        if (item) {
 | 
			
		||||
          this._pane[index] = item;
 | 
			
		||||
          item._parent = this;
 | 
			
		||||
          item.__container(this.$pane[index]);
 | 
			
		||||
 | 
			
		||||
          if (this._pane[0] && this._pane[1]) {
 | 
			
		||||
            this.__update();
 | 
			
		||||
          }
 | 
			
		||||
          return item;
 | 
			
		||||
        } else if (this._pane[index]) {
 | 
			
		||||
          this._pane[index].__container(null);
 | 
			
		||||
          this._pane[index] = false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.__update();
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Toggles whether a pane can contain scroll bars.
 | 
			
		||||
  // By default, scrolling is enabled.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     The pane index, only 0 or 1 are valid.
 | 
			
		||||
  //    x         Whether to allow scrolling in the horizontal direction.
 | 
			
		||||
  //    y         Whether to allow scrolling in the vertical direction.
 | 
			
		||||
  scrollable: function(index, x, y) {
 | 
			
		||||
    if (typeof x !== 'undefined') {
 | 
			
		||||
      this.$pane[index].toggleClass('wcScrollableX', x);
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof y !== 'undefined') {
 | 
			
		||||
      this.$pane[index].toggleClass('wcScrollableY', y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      x: this.$pane[index].hasClass('wcScrollableX'),
 | 
			
		||||
      y: this.$pane[index].hasClass('wcScrollableY'),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Destroys the splitter.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    destroyPanes    If true, or omitted, both panes attached will be destroyed as well.
 | 
			
		||||
  destroy: function(destroyPanes) {
 | 
			
		||||
    var docker = this.docker();
 | 
			
		||||
    if (docker) {
 | 
			
		||||
      var index = this.docker()._splitterList.indexOf(this);
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        this.docker()._splitterList.splice(index, 1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof destroyPanes === 'undefined' || destroyPanes) {
 | 
			
		||||
      this.__destroy();
 | 
			
		||||
    } else {
 | 
			
		||||
      this.__container(null);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Reaction to the panels update event.
 | 
			
		||||
  onUpdate: function() {
 | 
			
		||||
    this.__update();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Reaction to the panels close event.
 | 
			
		||||
  onClosed: function() {
 | 
			
		||||
    this.destroy();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Private Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Initialize
 | 
			
		||||
  __init: function() {
 | 
			
		||||
    this.$pane.push($('<div class="wcLayoutPane wcScrollableX wcScrollableY">'));
 | 
			
		||||
    this.$pane.push($('<div class="wcLayoutPane wcScrollableX wcScrollableY">'));
 | 
			
		||||
    this.$bar = $('<div class="wcSplitterBar">');
 | 
			
		||||
 | 
			
		||||
    if (this._orientation) {
 | 
			
		||||
      this.$pane[0].addClass('wcTall');
 | 
			
		||||
      this.$pane[1].addClass('wcTall');
 | 
			
		||||
      this.$bar.addClass('wcTall').addClass('wcSplitterBarV');
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$pane[0].addClass('wcWide');
 | 
			
		||||
      this.$pane[1].addClass('wcWide');
 | 
			
		||||
      this.$bar.addClass('wcWide').addClass('wcSplitterBarH');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__container(this.$container);
 | 
			
		||||
 | 
			
		||||
    if (this._parent instanceof wcPanel) {
 | 
			
		||||
      this._boundEvents.push({event: wcDocker.EVENT_UPDATED, handler: this.onUpdate.bind(this)});
 | 
			
		||||
      this._boundEvents.push({event: wcDocker.EVENT_CLOSED,  handler: this.onClosed.bind(this)});
 | 
			
		||||
 | 
			
		||||
      for (var i = 0; i < this._boundEvents.length; ++i) {
 | 
			
		||||
        this._parent.on(this._boundEvents[i].event, this._boundEvents[i].handler);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Updates the size of the splitter.
 | 
			
		||||
  __update: function() {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    var minSize = this.__minPos();
 | 
			
		||||
    var maxSize = this.__maxPos();
 | 
			
		||||
 | 
			
		||||
    if (this._findBestPos) {
 | 
			
		||||
      this._findBestPos = false;
 | 
			
		||||
 | 
			
		||||
      var size1;
 | 
			
		||||
      var size2;
 | 
			
		||||
      if (this._pane[0] && typeof this._pane[0].initSize === 'function') {
 | 
			
		||||
        size1 = this._pane[0].initSize();
 | 
			
		||||
        if (size1) {
 | 
			
		||||
          if (size1.x < 0) {
 | 
			
		||||
            size1.x = width/2;
 | 
			
		||||
          }
 | 
			
		||||
          if (size1.y < 0) {
 | 
			
		||||
            size1.y = height/2;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this._pane[1] && typeof this._pane[1].initSize === 'function') {
 | 
			
		||||
        size2 = this._pane[1].initSize();
 | 
			
		||||
        if (size2) {
 | 
			
		||||
          if (size2.x < 0) {
 | 
			
		||||
            size2.x = width/2;
 | 
			
		||||
          }
 | 
			
		||||
          if (size2.y < 0) {
 | 
			
		||||
            size2.y = height/2;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          size2.x = width  - size2.x;
 | 
			
		||||
          size2.y = height - size2.y;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var size;
 | 
			
		||||
      if (size1 && size2) {
 | 
			
		||||
        size = {
 | 
			
		||||
          x: Math.min(size1.x, size2.x),
 | 
			
		||||
          y: Math.min(size1.y, size2.y),
 | 
			
		||||
        };
 | 
			
		||||
      } else if (size1) {
 | 
			
		||||
        size = size1;
 | 
			
		||||
      } else if (size2) {
 | 
			
		||||
        size = size2;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (size) {
 | 
			
		||||
        if (this._orientation) {
 | 
			
		||||
          this._pos = size.x / width;
 | 
			
		||||
        } else {
 | 
			
		||||
          this._pos = size.y / height;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._orientation) {
 | 
			
		||||
      var size = width * this._pos;
 | 
			
		||||
 | 
			
		||||
      if (minSize) {
 | 
			
		||||
        size = Math.max(minSize.x, size);
 | 
			
		||||
      }
 | 
			
		||||
      if (maxSize) {
 | 
			
		||||
        size = Math.min(maxSize.x, size);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Bar is top to bottom
 | 
			
		||||
 | 
			
		||||
      this.$bar.css('left', size+2);
 | 
			
		||||
      this.$bar.css('top', '0px');
 | 
			
		||||
      this.$bar.css('height', height-2);
 | 
			
		||||
      this.$pane[0].css('width', size+2);
 | 
			
		||||
      this.$pane[0].css('left',  '0px');
 | 
			
		||||
      this.$pane[0].css('right', '');
 | 
			
		||||
      this.$pane[1].css('left',  '');
 | 
			
		||||
      this.$pane[1].css('right', '0px');
 | 
			
		||||
      this.$pane[1].css('width', width - size - 6);
 | 
			
		||||
    } else {
 | 
			
		||||
      var size = height * this._pos;
 | 
			
		||||
 | 
			
		||||
      if (minSize) {
 | 
			
		||||
        size = Math.max(minSize.y, size);
 | 
			
		||||
      }
 | 
			
		||||
      if (maxSize) {
 | 
			
		||||
        size = Math.min(maxSize.y, size);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Bar is left to right
 | 
			
		||||
 | 
			
		||||
      this.$bar.css('top', size+2);
 | 
			
		||||
      this.$bar.css('left', '0px');
 | 
			
		||||
      this.$bar.css('width', width-2);
 | 
			
		||||
      this.$pane[0].css('height', size+2);
 | 
			
		||||
      this.$pane[0].css('top',    '0px');
 | 
			
		||||
      this.$pane[0].css('bottom', '');
 | 
			
		||||
      this.$pane[1].css('top',    '');
 | 
			
		||||
      this.$pane[1].css('bottom', '0px');
 | 
			
		||||
      this.$pane[1].css('height', height - size - 6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._pane[0]) {
 | 
			
		||||
      this._pane[0].__update();
 | 
			
		||||
    }
 | 
			
		||||
    if (this._pane[1]) {
 | 
			
		||||
      this._pane[1].__update();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Saves the current panel configuration into a meta
 | 
			
		||||
  // object that can be used later to restore it.
 | 
			
		||||
  __save: function() {
 | 
			
		||||
    var data = {};
 | 
			
		||||
    data.type       = 'wcSplitter';
 | 
			
		||||
    data.horizontal = this._orientation;
 | 
			
		||||
    data.pane0      = this._pane[0]? this._pane[0].__save(): null;
 | 
			
		||||
    data.pane1      = this._pane[1]? this._pane[1].__save(): null;
 | 
			
		||||
    data.pos        = this._pos;
 | 
			
		||||
    return data;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Restores a previously saved configuration.
 | 
			
		||||
  __restore: function(data, docker) {
 | 
			
		||||
    this._pos  = data.pos;
 | 
			
		||||
    if (data.pane0) {
 | 
			
		||||
      this._pane[0] = docker.__create(data.pane0, this, this.$pane[0]);
 | 
			
		||||
      this._pane[0].__restore(data.pane0, docker);
 | 
			
		||||
    }
 | 
			
		||||
    if (data.pane1) {
 | 
			
		||||
      this._pane[1] = docker.__create(data.pane1, this, this.$pane[1]);
 | 
			
		||||
      this._pane[1].__restore(data.pane1, docker);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Attempts to find the best splitter position based on
 | 
			
		||||
  // the contents of each pane.
 | 
			
		||||
  __findBestPos: function() {
 | 
			
		||||
    this._findBestPos = true;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Moves the slider bar based on a mouse position.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    mouse       The mouse offset position.
 | 
			
		||||
  __moveBar: function(mouse) {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
    var offset = this.$container.offset();
 | 
			
		||||
 | 
			
		||||
    mouse.x -= offset.left;
 | 
			
		||||
    mouse.y -= offset.top;
 | 
			
		||||
 | 
			
		||||
    var minSize = this.__minPos();
 | 
			
		||||
    var maxSize = this.__maxPos();
 | 
			
		||||
 | 
			
		||||
    if (this._orientation) {
 | 
			
		||||
      this.pos((mouse.x-3) / width);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.pos((mouse.y-3) / height);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the minimum position of the splitter divider.
 | 
			
		||||
  __minPos: function() {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    var minSize;
 | 
			
		||||
    if (this._pane[0] && typeof this._pane[0].minSize === 'function') {
 | 
			
		||||
      minSize = this._pane[0].minSize();
 | 
			
		||||
    } else {
 | 
			
		||||
      minSize = {x:50,y:50};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var maxSize;
 | 
			
		||||
    if (this._pane[1] && typeof this._pane[1].maxSize === 'function') {
 | 
			
		||||
      maxSize = this._pane[1].maxSize();
 | 
			
		||||
    } else {
 | 
			
		||||
      maxSize = {x:width,y:height};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    maxSize.x = width  - Math.min(maxSize.x, width);
 | 
			
		||||
    maxSize.y = height - Math.min(maxSize.y, height);
 | 
			
		||||
 | 
			
		||||
    minSize.x = Math.max(minSize.x, maxSize.x);
 | 
			
		||||
    minSize.y = Math.max(minSize.y, maxSize.y);
 | 
			
		||||
    return minSize;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets the maximum position of the splitter divider.
 | 
			
		||||
  __maxPos: function() {
 | 
			
		||||
    var width = this.$container.width();
 | 
			
		||||
    var height = this.$container.height();
 | 
			
		||||
 | 
			
		||||
    var maxSize;
 | 
			
		||||
    if (this._pane[0] && typeof this._pane[0].maxSize === 'function') {
 | 
			
		||||
      maxSize = this._pane[0].maxSize();
 | 
			
		||||
    } else {
 | 
			
		||||
      maxSize = {x:width,y:height};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var minSize;
 | 
			
		||||
    if (this._pane[1] && typeof this._pane[1].minSize === 'function') {
 | 
			
		||||
      minSize = this._pane[1].minSize();
 | 
			
		||||
    } else {
 | 
			
		||||
      minSize = {x:50,y:50};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    minSize.x = width  - minSize.x;
 | 
			
		||||
    minSize.y = height - minSize.y;
 | 
			
		||||
 | 
			
		||||
    maxSize.x = Math.min(minSize.x, maxSize.x);
 | 
			
		||||
    maxSize.y = Math.min(minSize.y, maxSize.y);
 | 
			
		||||
    return maxSize;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets a new container for this layout.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    $container          If supplied, sets a new container for this layout.
 | 
			
		||||
  //    parent              If supplied, sets a new parent for this layout.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    JQuery collection   The current container.
 | 
			
		||||
  __container: function($container) {
 | 
			
		||||
    if (typeof $container === 'undefined') {
 | 
			
		||||
      return this.$container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$container = $container;
 | 
			
		||||
 | 
			
		||||
    if (this.$container) {
 | 
			
		||||
      this.$container.append(this.$pane[0]);
 | 
			
		||||
      this.$container.append(this.$pane[1]);
 | 
			
		||||
      this.$container.append(this.$bar);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$pane[0].remove();
 | 
			
		||||
      this.$pane[1].remove();
 | 
			
		||||
      this.$bar.remove();
 | 
			
		||||
    }
 | 
			
		||||
    return this.$container;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Removes a child from this splitter.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    child         The child to remove.
 | 
			
		||||
  __removeChild: function(child) {
 | 
			
		||||
    if (this._pane[0] === child) {
 | 
			
		||||
      this._pane[0] = false;
 | 
			
		||||
    } else if (this._pane[1] === child) {
 | 
			
		||||
      this._pane[1] = false;
 | 
			
		||||
    } else {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
    if (child) {
 | 
			
		||||
      child.__container(null);
 | 
			
		||||
      child._parent = null;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Disconnects and prepares this widget for destruction.
 | 
			
		||||
  __destroy: function() {
 | 
			
		||||
    // Remove all registered events.
 | 
			
		||||
    while (this._boundEvents.length){
 | 
			
		||||
      this._parent.off(this._boundEvents[0].event, this._boundEvents[0].handler);
 | 
			
		||||
      this._boundEvents.pop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._pane[0]) {
 | 
			
		||||
      this._pane[0].__destroy();
 | 
			
		||||
      this._pane[0] = null;
 | 
			
		||||
    }
 | 
			
		||||
    if (this._pane[1]) {
 | 
			
		||||
      this._pane[1].__destroy();
 | 
			
		||||
      this._pane[1] = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__container(null);
 | 
			
		||||
    this._parent = false;
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,533 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
  A tab widget container, to break up multiple elements into separate tabs.
 | 
			
		||||
*/
 | 
			
		||||
function wcTabFrame(container, parent) {
 | 
			
		||||
  this.$container = $(container);
 | 
			
		||||
  this._parent = parent;
 | 
			
		||||
 | 
			
		||||
  this.$frame     = null;
 | 
			
		||||
  this.$title     = null;
 | 
			
		||||
  this.$tabScroll = null;
 | 
			
		||||
  this.$center    = null;
 | 
			
		||||
  this.$tabLeft   = null;
 | 
			
		||||
  this.$tabRight  = null;
 | 
			
		||||
  this.$close     = null;
 | 
			
		||||
 | 
			
		||||
  this._canScrollTabs = false;
 | 
			
		||||
  this._tabScrollPos = 0;
 | 
			
		||||
  this._curTab = -1;
 | 
			
		||||
  this._layoutList = [];
 | 
			
		||||
  this._moveable = true;
 | 
			
		||||
 | 
			
		||||
  this._boundEvents = [];
 | 
			
		||||
 | 
			
		||||
  this.__init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wcTabFrame.prototype = {
 | 
			
		||||
  LEFT_TAB_BUFFER: 15,
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Public Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Finds the main Docker window.
 | 
			
		||||
  docker: function() {
 | 
			
		||||
    var parent = this._parent;
 | 
			
		||||
    while (parent && !(parent instanceof wcDocker)) {
 | 
			
		||||
      parent = parent._parent;
 | 
			
		||||
    }
 | 
			
		||||
    return parent;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Destroys the tab area.
 | 
			
		||||
  destroy: function() {
 | 
			
		||||
    this.__destroy();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Adds a new tab item at a given index
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    name      The name of the tab.
 | 
			
		||||
  //    index     An optional index to insert the tab at.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    wcLayout  The layout of the newly created tab.
 | 
			
		||||
  addTab: function(name, index) {
 | 
			
		||||
    var newLayout = new wcLayout('.wcDockerTransition', this._parent);
 | 
			
		||||
    newLayout.name = name;
 | 
			
		||||
    newLayout._scrollable = {
 | 
			
		||||
      x: true,
 | 
			
		||||
      y: true,
 | 
			
		||||
    };
 | 
			
		||||
    newLayout._scroll = {
 | 
			
		||||
      x: 0,
 | 
			
		||||
      y: 0,
 | 
			
		||||
    };
 | 
			
		||||
    newLayout._closeable = false;
 | 
			
		||||
    newLayout._overflowVisible = false;
 | 
			
		||||
 | 
			
		||||
    if (typeof index === 'undefined') {
 | 
			
		||||
      this._layoutList.push(newLayout);
 | 
			
		||||
    } else {
 | 
			
		||||
      this._layoutList.splice(index, 0, newLayout);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._curTab === -1 && this._layoutList.length) {
 | 
			
		||||
      this._curTab = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.__updateTabs();
 | 
			
		||||
 | 
			
		||||
    return newLayout;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Removes a tab item.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index       The tab index to remove.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    bool        Returns whether or not the tab was removed.
 | 
			
		||||
  removeTab: function(index) {
 | 
			
		||||
    if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
      var name = this._layoutList[index].name;
 | 
			
		||||
      this._layoutList[index].__destroy();
 | 
			
		||||
      this._layoutList.splice(index, 1);
 | 
			
		||||
 | 
			
		||||
      if (this._curTab >= index) {
 | 
			
		||||
        this._curTab--;
 | 
			
		||||
 | 
			
		||||
        if (this._curTab < 0) {
 | 
			
		||||
          this._curTab = 0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.__updateTabs();
 | 
			
		||||
      this._parent.__trigger(wcDocker.EVENT_CUSTOM_TAB_CLOSED, {obj: this, name: name, index: index});
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets the currently visible tab.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     If supplied, sets the current tab index.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    number    The currently visible tab index.
 | 
			
		||||
  tab: function(index, autoFocus) {
 | 
			
		||||
    if (typeof index !== 'undefined') {
 | 
			
		||||
      if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
        this.$title.find('> .wcTabScroller > .wcPanelTab[id="' + this._curTab + '"]').removeClass('wcPanelTabActive');
 | 
			
		||||
        this.$center.children('.wcPanelTabContent[id="' + this._curTab + '"]').addClass('wcPanelTabContentHidden');
 | 
			
		||||
        this._curTab = index;
 | 
			
		||||
        this.$title.find('> .wcTabScroller > .wcPanelTab[id="' + index + '"]').addClass('wcPanelTabActive');
 | 
			
		||||
        this.$center.children('.wcPanelTabContent[id="' + index + '"]').removeClass('wcPanelTabContentHidden');
 | 
			
		||||
        this.__updateTabs(autoFocus);
 | 
			
		||||
 | 
			
		||||
        var name = this._layoutList[this._curTab].name;
 | 
			
		||||
        this._parent.__trigger(wcDocker.EVENT_CUSTOM_TAB_CHANGED, {obj: this, name: name, index: index});
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this._curTab;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Retrieves the layout for a given tab.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     The tab index.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    wcLayout  The layout found.
 | 
			
		||||
  //    false     The layout was not found.
 | 
			
		||||
  layout: function(index) {
 | 
			
		||||
    if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
      return this._layoutList[index];
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Moves a tab from a given index to another index.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    fromIndex     The current tab index to move.
 | 
			
		||||
  //    toIndex       The new index to move to.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    element       The new element of the moved tab.
 | 
			
		||||
  //    false         If an error occurred.
 | 
			
		||||
  moveTab: function(fromIndex, toIndex) {
 | 
			
		||||
    if (fromIndex >= 0 && fromIndex < this._layoutList.length &&
 | 
			
		||||
        toIndex >= 0 && toIndex < this._layoutList.length) {
 | 
			
		||||
      var panel = this._layoutList.splice(fromIndex, 1);
 | 
			
		||||
      this._layoutList.splice(toIndex, 0, panel[0]);
 | 
			
		||||
 | 
			
		||||
      // Preserve the currently active tab.
 | 
			
		||||
      if (this._curTab === fromIndex) {
 | 
			
		||||
        this._curTab = toIndex;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.__updateTabs();
 | 
			
		||||
 | 
			
		||||
      return this.$title.find('> .wcTabScroller > .wcPanelTab[id="' + toIndex + '"]')[0];
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether the tabs can be reordered by the user.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    moveable  If supplied, assigns whether tabs are moveable.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    boolean   Whether tabs are currently moveable.
 | 
			
		||||
  moveable: function(moveable) {
 | 
			
		||||
    if (typeof moveable !== 'undefined') {
 | 
			
		||||
      this._moveable = moveable;
 | 
			
		||||
    }
 | 
			
		||||
    return this._moveable;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether a tab can be closed (removed) by the user.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     The index of the tab.
 | 
			
		||||
  //    closeable If supplied, assigns whether the tab can be closed.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    boolean   Whether the tab can be closed.
 | 
			
		||||
  closeable: function(index, closeable) {
 | 
			
		||||
    if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
      var layout = this._layoutList[index];
 | 
			
		||||
 | 
			
		||||
      if (typeof closeable !== 'undefined') {
 | 
			
		||||
        layout._closeable = closeable;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return layout._closeable;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether a tab area is scrollable.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     The index of the tab.
 | 
			
		||||
  //    x, y      If supplied, assigns whether the tab pane
 | 
			
		||||
  //              is scrollable for each axis.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    Object    An object with boolean values x and y
 | 
			
		||||
  //              that tell whether each axis is scrollable.
 | 
			
		||||
  scrollable: function(index, x, y) {
 | 
			
		||||
    if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
      var layout = this._layoutList[index];
 | 
			
		||||
 | 
			
		||||
      var changed = false;
 | 
			
		||||
      if (typeof x !== 'undefined') {
 | 
			
		||||
        layout._scrollable.x = x;
 | 
			
		||||
        changed = true;
 | 
			
		||||
      }
 | 
			
		||||
      if (typeof y !== 'undefined') {
 | 
			
		||||
        layout._scrollable.y = y;
 | 
			
		||||
        changed = true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (changed) {
 | 
			
		||||
        this.__onTabChange();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        x: layout._scrollable.x,
 | 
			
		||||
        y: layout._scrollable.y,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets whether overflow on a tab area is visible.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     The index of the tab.
 | 
			
		||||
  //    visible   If supplied, assigns whether overflow is visible.
 | 
			
		||||
  //
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    boolean   The current overflow visibility.
 | 
			
		||||
  overflowVisible: function(index, visible) {
 | 
			
		||||
    if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
      var layout = this._layoutList[index];
 | 
			
		||||
 | 
			
		||||
      if (typeof overflow !== 'undefined') {
 | 
			
		||||
        layout._overflowVisible = overflow;
 | 
			
		||||
        this.__onTabChange();
 | 
			
		||||
      }
 | 
			
		||||
      return layout._overflowVisible;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Sets the icon for a tab.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     The index of the tab to alter.
 | 
			
		||||
  //    icon      A CSS class name that represents the icon.
 | 
			
		||||
  icon: function(index, icon) {
 | 
			
		||||
    if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
      var layout = this._layoutList[index];
 | 
			
		||||
 | 
			
		||||
      if (!layout.$icon) {
 | 
			
		||||
        layout.$icon = $('<div>');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      layout.$icon.removeClass();
 | 
			
		||||
      layout.$icon.addClass('wcTabIcon ' + icon);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Sets the icon for a tab.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    index     The index of the tab to alter.
 | 
			
		||||
  //    icon      A font-awesome icon name (without the 'fa fa-' prefix).
 | 
			
		||||
  faicon: function(index, icon) {
 | 
			
		||||
    if (index > -1 && index < this._layoutList.length) {
 | 
			
		||||
      var layout = this._layoutList[index];
 | 
			
		||||
 | 
			
		||||
      if (!layout.$icon) {
 | 
			
		||||
        layout.$icon = $('<div>');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      layout.$icon.removeClass();
 | 
			
		||||
      layout.$icon.addClass('fa fa-fw fa-' + icon);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Reaction to the panels update event.
 | 
			
		||||
  onUpdate: function() {
 | 
			
		||||
    this.__update();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Reaction to the panels close event.
 | 
			
		||||
  onClosed: function() {
 | 
			
		||||
    this.destroy();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Private Functions
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Initialize
 | 
			
		||||
  __init: function() {
 | 
			
		||||
    this.$frame     = $('<div class="wcCustomTab wcWide wcTall wcPanelBackground">');
 | 
			
		||||
    this.$title     = $('<div class="wcFrameTitle wcCustomTabTitle">');
 | 
			
		||||
    this.$tabScroll = $('<div class="wcTabScroller">');
 | 
			
		||||
    this.$center    = $('<div class="wcFrameCenter wcWide">');
 | 
			
		||||
    this.$tabLeft   = $('<div class="wcFrameButton" title="Scroll tabs to the left."><span class="fa fa-arrow-left"></span><</div>');
 | 
			
		||||
    this.$tabRight  = $('<div class="wcFrameButton" title="Scroll tabs to the right."><span class="fa fa-arrow-right"></span>></div>');
 | 
			
		||||
    this.$close     = $('<div class="wcFrameButton" title="Close the currently active panel tab"><span class="fa fa-close"></span>X</div>');
 | 
			
		||||
    this.$frame.append(this.$title);
 | 
			
		||||
    this.$title.append(this.$tabScroll);
 | 
			
		||||
    this.$frame.append(this.$center);
 | 
			
		||||
 | 
			
		||||
    this.__container(this.$container);
 | 
			
		||||
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_UPDATED, handler: this.onUpdate.bind(this)});
 | 
			
		||||
    this._boundEvents.push({event: wcDocker.EVENT_CLOSED,  handler: this.onClosed.bind(this)});
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._boundEvents.length; ++i) {
 | 
			
		||||
      this._parent.on(this._boundEvents[i].event, this._boundEvents[i].handler);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var docker = this.docker();
 | 
			
		||||
    if (docker) {
 | 
			
		||||
      docker._tabList.push(this);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Updates the size of the frame.
 | 
			
		||||
  __update: function() {
 | 
			
		||||
    this.__updateTabs();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __updateTabs: function(autoFocus) {
 | 
			
		||||
    this.$tabScroll.empty();
 | 
			
		||||
 | 
			
		||||
    var tabPositions = [];
 | 
			
		||||
    var totalWidth = 0;
 | 
			
		||||
    var parentLeft = this.$tabScroll.offset().left;
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    this.$center.children('.wcPanelTabContent').each(function() {
 | 
			
		||||
      $(this).addClass('wcPanelTabContentHidden wcPanelTabUnused');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < this._layoutList.length; ++i) {
 | 
			
		||||
      var $tab = $('<div id="' + i + '" class="wcPanelTab">' + this._layoutList[i].name + '</div>');
 | 
			
		||||
      if (this._moveable) {
 | 
			
		||||
        $tab.addClass('wcCustomTabMoveable');
 | 
			
		||||
      }
 | 
			
		||||
      this.$tabScroll.append($tab);
 | 
			
		||||
      if (this._layoutList[i].$icon) {
 | 
			
		||||
        $tab.prepend(this._layoutList[i].$icon);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var $tabContent = this.$center.children('.wcPanelTabContent[id="' + i + '"]');
 | 
			
		||||
      if (!$tabContent.length) {
 | 
			
		||||
        $tabContent = $('<div class="wcPanelTabContent wcPanelTabContentHidden" id="' + i + '">');
 | 
			
		||||
        this.$center.append($tabContent);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this._layoutList[i].__container($tabContent);
 | 
			
		||||
      this._layoutList[i]._parent = this;
 | 
			
		||||
 | 
			
		||||
      var isVisible = this._curTab === i;
 | 
			
		||||
 | 
			
		||||
      $tabContent.removeClass('wcPanelTabUnused');
 | 
			
		||||
 | 
			
		||||
      if (isVisible) {
 | 
			
		||||
        $tab.addClass('wcPanelTabActive');
 | 
			
		||||
        $tabContent.removeClass('wcPanelTabContentHidden');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      totalWidth = $tab.offset().left - parentLeft;
 | 
			
		||||
      tabPositions.push(totalWidth);
 | 
			
		||||
 | 
			
		||||
      totalWidth += $tab.outerWidth();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Now remove all unused panel tabs.
 | 
			
		||||
    this.$center.children('.wcPanelTabUnused').each(function() {
 | 
			
		||||
      $(this).remove();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // $tempCenter.remove();
 | 
			
		||||
    var buttonSize = this.__onTabChange();
 | 
			
		||||
 | 
			
		||||
    if (autoFocus) {
 | 
			
		||||
      for (var i = 0; i < tabPositions.length; ++i) {
 | 
			
		||||
        if (i === this._curTab) {
 | 
			
		||||
          var left = tabPositions[i];
 | 
			
		||||
          var right = totalWidth;
 | 
			
		||||
          if (i+1 < tabPositions.length) {
 | 
			
		||||
            right = tabPositions[i+1];
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          var scrollPos = -parseInt(this.$tabScroll.css('left'));
 | 
			
		||||
          var titleWidth = this.$title.width() - buttonSize;
 | 
			
		||||
 | 
			
		||||
          // If the tab is behind the current scroll position.
 | 
			
		||||
          if (left < scrollPos) {
 | 
			
		||||
            this._tabScrollPos = left - this.LEFT_TAB_BUFFER;
 | 
			
		||||
            if (this._tabScrollPos < 0) {
 | 
			
		||||
              this._tabScrollPos = 0;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          // If the tab is beyond the current scroll position.
 | 
			
		||||
          else if (right - scrollPos > titleWidth) {
 | 
			
		||||
            this._tabScrollPos = right - titleWidth + this.LEFT_TAB_BUFFER;
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this._canScrollTabs = false;
 | 
			
		||||
    if (totalWidth > this.$title.width() - buttonSize) {
 | 
			
		||||
      this._canScrollTabs = true;
 | 
			
		||||
      this.$frame.append(this.$tabRight);
 | 
			
		||||
      this.$frame.append(this.$tabLeft);
 | 
			
		||||
      var scrollLimit = totalWidth - (this.$title.width() - buttonSize)/2;
 | 
			
		||||
      // If we are beyond our scroll limit, clamp it.
 | 
			
		||||
      if (this._tabScrollPos > scrollLimit) {
 | 
			
		||||
        var children = this.$tabScroll.children();
 | 
			
		||||
        for (var i = 0; i < children.length; ++i) {
 | 
			
		||||
          var $tab = $(children[i]);
 | 
			
		||||
 | 
			
		||||
          totalWidth = $tab.offset().left - parentLeft;
 | 
			
		||||
          if (totalWidth + $tab.outerWidth() > scrollLimit) {
 | 
			
		||||
            this._tabScrollPos = totalWidth - this.LEFT_TAB_BUFFER;
 | 
			
		||||
            if (this._tabScrollPos < 0) {
 | 
			
		||||
              this._tabScrollPos = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      this._tabScrollPos = 0;
 | 
			
		||||
      this.$tabLeft.remove();
 | 
			
		||||
      this.$tabRight.remove();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$tabScroll.stop().animate({left: -this._tabScrollPos + 'px'}, 'fast');
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  __onTabChange: function() {
 | 
			
		||||
    var buttonSize = 0;
 | 
			
		||||
    var layout = this.layout(this._curTab);
 | 
			
		||||
    if (layout) {
 | 
			
		||||
      this.$center.toggleClass('wcScrollableX', layout._scrollable.x);
 | 
			
		||||
      this.$center.toggleClass('wcScrollableY', layout._scrollable.y);
 | 
			
		||||
      this.$center.toggleClass('wcOverflowVisible', layout._overflowVisible);
 | 
			
		||||
 | 
			
		||||
      this.$tabLeft.remove();
 | 
			
		||||
      this.$tabRight.remove();
 | 
			
		||||
 | 
			
		||||
      if (layout._closeable) {
 | 
			
		||||
        this.$frame.append(this.$close);
 | 
			
		||||
        buttonSize += this.$close.outerWidth();
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$close.remove();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this._canScrollTabs) {
 | 
			
		||||
        this.$frame.append(this.$tabRight);
 | 
			
		||||
        this.$frame.append(this.$tabLeft);
 | 
			
		||||
 | 
			
		||||
        buttonSize += this.$tabRight.outerWidth() + this.$tabLeft.outerWidth();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.$center.scrollLeft(layout._scroll.x);
 | 
			
		||||
      this.$center.scrollTop(layout._scroll.y);
 | 
			
		||||
    }
 | 
			
		||||
    return buttonSize;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Handles scroll notifications.
 | 
			
		||||
  __scrolled: function() {
 | 
			
		||||
    var layout = this.layout(this._curTab);
 | 
			
		||||
    layout._scroll.x = this.$center.scrollLeft();
 | 
			
		||||
    layout._scroll.y = this.$center.scrollTop();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Gets, or Sets a new container for this layout.
 | 
			
		||||
  // Params:
 | 
			
		||||
  //    $container          If supplied, sets a new container for this layout.
 | 
			
		||||
  //    parent              If supplied, sets a new parent for this layout.
 | 
			
		||||
  // Returns:
 | 
			
		||||
  //    JQuery collection   The current container.
 | 
			
		||||
  __container: function($container) {
 | 
			
		||||
    if (typeof $container === 'undefined') {
 | 
			
		||||
      return this.$container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.$container = $container;
 | 
			
		||||
    if (this.$container) {
 | 
			
		||||
      this.$container.append(this.$frame);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$frame.remove();
 | 
			
		||||
    }
 | 
			
		||||
    return this.$container;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // Disconnects and prepares this widget for destruction.
 | 
			
		||||
  __destroy: function() {
 | 
			
		||||
    var docker = this.docker();
 | 
			
		||||
    if (docker) {
 | 
			
		||||
      var index = docker._tabList.indexOf(this);
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        docker._tabList.splice(index, 1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Remove all registered events.
 | 
			
		||||
    while (this._boundEvents.length){
 | 
			
		||||
      this._parent.off(this._boundEvents[0].event, this._boundEvents[0].handler);
 | 
			
		||||
      this._boundEvents.pop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this._curTab = -1;
 | 
			
		||||
    for (var i = 0; i < this._layoutList.length; ++i) {
 | 
			
		||||
      this._layoutList[i].__destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (this._layoutList.length) this._layoutList.pop();
 | 
			
		||||
    this.__container(null);
 | 
			
		||||
    this._parent = null;
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
		Reference in New Issue