From 1b68e49a2ad7aa15cef861ba7da2a65ba7e382ad Mon Sep 17 00:00:00 2001 From: rolux Date: Thu, 3 Mar 2011 22:02:35 +0100 Subject: [PATCH] splitpanel rewrite --- build/css/ox.ui.css | 57 +++++++++++ build/js/ox.js | 36 +++++-- build/js/ox.ui.js | 243 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 322 insertions(+), 14 deletions(-) diff --git a/build/css/ox.ui.css b/build/css/ox.ui.css index 1912e56c..a2662d22 100644 --- a/build/css/ox.ui.css +++ b/build/css/ox.ui.css @@ -1240,6 +1240,63 @@ Panels position: absolute; } +.OxSplitPanel2 { + display: box; + display: -moz-box; + display: -webkit-box; + overflow: hidden; + box-flex: 0; + -mox-box-flex: 0; + -webkit-box-flex: 0; +} +.OxSplitPanel2.OxHorizontal { + box-orient: horizontal; + -moz-box-orient: horizontal; + -webkit-box-orient: horizontal; +} +.OxSplitPanel2.OxVertical { + box-orient: vertical; + -moz-box-orient: vertical; + -webkit-box-orient: vertical; +} +.OxSplitPanel2 > * { + box-flex: 0; + -mox-box-flex: 0; + -webkit-box-flex: 0; +} +.OxSplitPanel2 > .OxSeparator { + display: -webkit-box; + position: relative; + z-index: 2; +} +.OxSplitPanel2 > .OxSeparator > * { + -webkit-box-flex: 0; +} +.OxSplitPanel2 > .OxSeparator > .OxLine { + background-color: black; +} +.OxSplitPanel2.OxHorizontal > .OxSeparator { + width: 5px; + margin: 0 -2px 0 -2px; + cursor: ew-resize; +} +.OxSplitPanel2.OxHorizontal > .OxSeparator > .OxLine { + width: 1px; +} +.OxSplitPanel2.OxHorizontal > .OxSeparator > .OxSpace { + width: 2px; +} +.OxSplitPanel2.OxVertical > .OxSeparator { + height: 5px; + margin: -2px 0 -2px 0; + cursor: ns-resize; +} +.OxSplitPanel2.OxVertical > .OxSeparator > .OxLine { + height: 1px; +} +.OxSplitPanel2.OxVertical > .OxSeparator > .OxSpace { + height: 2px; +} /* ================================================================================ Requests diff --git a/build/js/ox.js b/build/js/ox.js index 0fcc9218..539cb8e0 100644 --- a/build/js/ox.js +++ b/build/js/ox.js @@ -1,8 +1,29 @@ // todo: check http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ -var Ox = { - version: '0.1.2' -}; +/* +(function() { + var methods = { + 'array': ['pop', 'push', 'shift', 'unshift'], + 'string': [ + 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', + 'match', 'replace', 'search', 'slice', 'split', + 'substr', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', + 'toString', 'toUpperCase', 'trim', 'trimLeft, 'trimRight', + 'valueOf' + ] + }, + global = this; + return function Ox(val) { + var ret, + type = Ox.typeof(val); + if (type == 'array') { + + } + } +})(); +*/ + +Ox = {}; /* ================================================================================ @@ -74,6 +95,7 @@ Ox.TYPES = [ 'Arguments', 'Array', 'Boolean', 'Date', 'Element', 'Function', 'Infinity', 'NaN', 'Null', 'Number', 'Object', 'RegExp', 'String', 'Undefined' ]; +Ox.VERSION = '0.1.2'; Ox.WEEKDAYS = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]; @@ -99,7 +121,7 @@ Ox.getset = function(obj, args, callback, context) { Ox.getset(obj, [key, val], callback, context) Ox.getset(obj, [{key: val, ...}], callback, context) sets obj.key to val, calls callback(key, val) - for any changed value, + for each changed value, returns context (for chaining) @@ -2310,7 +2332,7 @@ Ox.endsWith = function(str, sub) { >>> Ox.endsWith("foobar", "bar") true */ - return str.substr(-sub.length) === sub; + return str.toString().substr(-sub.length) === sub; }; Ox.highlight = function(txt, str) { @@ -2371,7 +2393,7 @@ Ox.reverse = function(str) { Ox.reverse("foo") oof */ - return str.split('').reverse().join(''); + return str.toString().split('').reverse().join(''); }; Ox.startsWith = function(str, sub) { @@ -2379,7 +2401,7 @@ Ox.startsWith = function(str, sub) { >>> Ox.startsWith("foobar", "foo") true */ - return str.substr(0, sub.length) === sub; + return str.toString().substr(0, sub.length) === sub; }; Ox.stripTags = function(str) { diff --git a/build/js/ox.ui.js b/build/js/ox.ui.js index bb5c7fd7..5cadb0b5 100644 --- a/build/js/ox.ui.js +++ b/build/js/ox.ui.js @@ -772,20 +772,42 @@ requires }; Ox.UI = (function() { + /* + $(function() { + Ox.extend(Ox.UI, { + $body: $('body'), + $document: $(document), + $window: $(window) + }); + }); + */ return { - $body: $('body'), - $document: $(document), - $window: $(window), - path: function() { - return oxui.path; + getDimensions: function(orientation) { + return orientation == 'horizontal' ? + ['width', 'height'] : ['height', 'width']; }, + getEdges: function(orientation) { + return orientation == 'horizontal' ? + ['left', 'right', 'top', 'bottom'] : + ['top', 'bottom', 'left', 'right']; + }, + DIMENSIONS: { + horizontal: ['width', 'height'], + vertical: ['height', 'width'] + }, + EDGES: { + horizontal: [['left', 'right'], ['top', 'bottom']], + vertical: [['top', 'bottom'], ['left', 'right']] + }, + PATH: $('script[src*="ox.ui.js"]') + .attr('src').replace('js/ox.ui.js', ''), theme: function() { }, themePath: function() { } - } + }; }()); /*** @@ -881,7 +903,7 @@ requires element: self.options }; } - that.ox = Ox.version; + that.ox = Ox.VERSION; that.id = Ox.uid(); that.$element = $('<' + (self.options.element || 'div') + '/>', { data: { @@ -11142,6 +11164,213 @@ requires return that; }; + Ox.SplitPanel2 = function(options, self) { + + var self = self || {}, + that = new Ox.Element('div', self) + .defaults({ + elements: [], + orientation: 'horizontal' + }) + .options(options) + .addClass( + 'OxSplitPanel2 Ox' + Ox.toTitleCase(self.options.orientation) + ); + + Ox.extend(self, { + $separators: [], + clientXY: self.options.orientation == 'horizontal' ? 'clientX' : 'clientY', + dimensions: Ox.UI.DIMENSIONS[self.options.orientation], + edges: Ox.UI.EDGES[self.options.orientation] + }); + + self.options.elements.forEach(function(element, i) { + self.options.elements[i] = Ox.extend({ + collapsible: false, + collapsed: false, + resizable: false, + resize: [], + size: 'auto' + }, element); + }); + + self.autoPercent = (100 - self.options.elements.reduce(function(val, element) { + return val + (Ox.endsWith(element.size, '%') ? parseFloat(element.size) : 0); + }, 0)) / self.options.elements.filter(function(element) { + return element.size == 'auto'; + }).length + '%'; + + self.options.elements.forEach(function(element, i) { + var flex, index = i == 0 ? 0 : 1; + if (Ox.isNumber(element.size)) { + element.element.css(self.dimensions[0], element.size + 'px'); + } else { + flex = ( + element.size == 'auto' ? self.autoPercent : element.size + ).replace('%', ''); + element.element.css({ + boxFlex: flex, + MozBoxFlex: flex, + WebkitBoxFlex: flex + }); + } + element.element.appendTo(that); + if (element.collapsible || element.resizable) { + self.$separators.push( + Ox.Element() + .addClass('OxSeparator') + .bindEvent({ + anyclick: function() { + that.toggle(i); + }, + dragstart: function(event, e) { + dragstart(i, e); + }, + drag: function(event, e) { + drag(i, e); + }, + dragend: function(event, e) { + dragend(i, e); + }, + }) + .append($('
').addClass('OxSpace')) + .append($('
').addClass('OxLine')) + .append($('
').addClass('OxSpace')) + ['insert' + (index ? 'Before' : 'After')](element.element) + ); + } + + }); + + function dragstart(pos, e) { + var element = self.options.elements[pos], + size = element.element[self.dimensions[0]](); + if (element.resizable && !element.collapsed) { + Ox.isString(element.size) && setPixels(pos); + self.drag = { + resize: Ox.isNumber(element.size) ? + element.resize : element.resize.map(function(v) { + return getPixelsByPercent(v); + }), + size: size, + startPos: e[self.clientXY], + startSize: size + }; + Ox.print('self.drag', self.drag) + } + } + + function drag(pos, e) { + var data = {}, + element = self.options.elements[pos], + index = pos == 0 ? 0 : 1; + if (element.resizable && !element.collapsed) { + var d = e[self.clientXY] - self.drag.startPos, + size = Ox.limit( + self.drag.startSize + d * (index ? -1 : 1), + self.drag.resize[0], + self.drag.resize[element.resize.length - 1] + ); + self.drag.resize.forEach(function(v) { + if (size >= v - 8 && size <= v + 8) { + size = v; + return false; + } + }); + if (size != self.drag.size) { + self.drag.size = size; + data[self.dimensions[0]] = size; + element.element + .css(self.dimensions[0], size + 'px') + .triggerEvent('resize', data); + triggerEvents('resize', pos); + } + } + + } + + function dragend(pos, e) { + var data = {}, + element = self.options.elements[pos]; + if (element.resizable && !element.collapsed) { + Ox.isString(element.size) && setPercent(pos); + data[self.dimensions[0]] = self.drag.size + element.element.triggerEvent('resizeend', data); + triggerEvents('resizeend', pos); + } + } + + function getPixelsByPercent(percent) { + return Math.round(( + that[self.dimensions[0]]() - + self.options.elements.reduce(function(val, element) { + return val + Ox.isNumber(element.size) ? + element.element[self.dimensions[0]]() : 0; + }, 0) - self.$separators.length + ) * parseFloat(percent) / 100); + } + + function setPercent(pos) { + var element = self.options.elements[pos], + flex = element.size.replace('%', ''), + css = { + boxFlex: flex, + MozBoxFlex: flex, + WebkitBoxFlex: flex + }; + css[self.dimensions[0]] = ''; + element.element.css(css); + } + + function setPixels(pos) { + var css = { + boxFlex: '', + MozBoxFlex: '', + WebkitBoxFlex: '' + }, + element = self.options.elements[pos]; + css[self.dimensions[0]] = element.element[self.dimensions[0]]() + 'px'; + element.element.css(css); + } + + function triggerEvents(event, pos) { + var data = {}; + self.options.elements.forEach(function(element, i) { + if (i != pos && Ox.isString(element.size)) { + data[self.dimensions[0]] = element.element[self.dimensions[0]](); + element.element.triggerEvent(event, data); + } + }); + } + + that.toggle = function(pos) { + var css = {}, + element = self.options.elements[pos], + flex, + index = pos == 0 ? 0 : 1, + size = element.element[self.dimensions[0]](); + if (element.collapsible) { + element.collapsed = !element.collapsed; + if (Ox.isString(element.size) && element.collapsed) { + setPixels(pos); + } + css['margin' + Ox.toTitleCase(self.edges[0][index])] = + element.collapsed ? -size : 0; + Ox.print('css', css); + that.animate(css, 250, function() { + if (Ox.isString(element.size) && !element.collapsed) { + setPercent(pos); + } + element.element.triggerEvent('toggle', {collapsed: element.collapsed}); + triggerEvents('resize', pos); + }); + } + } + + return that; + + }; + /** options: elements: [{ array of one, two or three elements