From a1ed6a44c5bee47177218075d9d9c500ef53a994 Mon Sep 17 00:00:00 2001 From: rolux Date: Sat, 7 May 2011 23:07:53 +0200 Subject: [PATCH] better layout for documentation pages, use syntax highlighter --- source/Ox.UI/css/Ox.UI.css | 12 +-- source/Ox.UI/js/Core/Ox.DocPage.js | 65 ++++++----- source/Ox.UI/js/Core/Ox.Element.js | 108 +++++++++---------- source/Ox.UI/js/Core/Ox.SyntaxHighlighter.js | 29 +++-- source/Ox.UI/js/List/Ox.TreeList.js | 2 + source/Ox.UI/themes/classic/css/classic.css | 2 +- source/Ox.js | 18 ++-- 7 files changed, 121 insertions(+), 115 deletions(-) diff --git a/source/Ox.UI/css/Ox.UI.css b/source/Ox.UI/css/Ox.UI.css index 228f3469..c18c9e50 100644 --- a/source/Ox.UI/css/Ox.UI.css +++ b/source/Ox.UI/css/Ox.UI.css @@ -1442,20 +1442,18 @@ SyntaxHightlighter ================================================================================ */ -.OxSyntaxHighlighter { - position: absolute; - overflow: auto; -} .OxSyntaxHighlighter > div { - position: absolute; font-family: Menlo, Monaco, DejaVu Sans Mono, Bitstream Vera Sans Mono, Consolas, Lucida Console; - line-height: 14px; + //line-height: 14px; } .OxSyntaxHighlighter > .OxLineNumbers { + padding: 4px; text-align: right; + -moz-user-select: none; + -webkit-user-select: none; } .OxSyntaxHighlighter > .OxSourceCode { - //display: table-cell; + padding: 4px; -moz-user-select: text; -webkit-user-select: text; } diff --git a/source/Ox.UI/js/Core/Ox.DocPage.js b/source/Ox.UI/js/Core/Ox.DocPage.js index 642e9611..681cd9b8 100644 --- a/source/Ox.UI/js/Core/Ox.DocPage.js +++ b/source/Ox.UI/js/Core/Ox.DocPage.js @@ -11,12 +11,14 @@ Ox.DocPage = function(options, self) { overflow: 'auto' }); - that.append($('

') - .css({ - marginTop: 0, - WebkitMarginBefore: 0 - }) - .append('' + self.options.item.name + '')); + that.append( + $('

') + .css({ + marginTop: 0, + WebkitMarginBefore: 0 + }) + .html('' + self.options.item.name + '') + ); getItem(self.options.item, 0).forEach(function($element) { that.append($element); @@ -24,7 +26,7 @@ Ox.DocPage = function(options, self) { function getItem(item, level, name) { var $elements = [$('
') - .css({paddingLeft: ((level * 32) + 'px')}) + .css({paddingLeft: (level ? level * 32 - 16 : 0) + 'px'}) .html( '' + (name || item.name) + ' ' + '<' + item.types.join('> or <') + '> ' + @@ -33,18 +35,24 @@ Ox.DocPage = function(options, self) { ) ]; [ - 'description', 'usage', 'arguments', 'properties', 'events', 'examples', 'source' + 'description', 'usage', 'arguments', 'properties', + 'events', 'examples', 'source' ].forEach(function(section) { var className = 'OxLine' + Ox.uid(); if (item[section]) { if (section == 'description') { $elements.push($('
') - .css({paddingLeft: ((level * 32 + 16) + 'px')}) + .css({paddingLeft: (level * 32) + 'px'}) .html(item.description) ); } else { $elements.push($('
') - .css({paddingLeft: ((level * 32 + 16) + 'px')}) + .css({ + paddingTop: (level ? 0 : 8) + 'px', + borderTop: level ? '': '1px solid rgb(192, 192, 192)', + marginTop: (level ? 0 : 8) + 'px', + marginLeft: (level * 32) + 'px', + }) .append( $('') .attr({src: Ox.UI.getImagePath('symbolDown.svg')}) @@ -87,7 +95,7 @@ Ox.DocPage = function(options, self) { item.examples.forEach(function(example) { $elements.push($('
') .addClass(className) - .css({marginLeft: ((level * 32 + 32) + 'px')}) + .css({marginLeft: (level * 32 + 16) + 'px'}) .html( '> ' + Ox.encodeHTML(example.statement) @@ -98,26 +106,35 @@ Ox.DocPage = function(options, self) { ); example.result && $elements.push($('
') .addClass(className) - .css({marginLeft: ((level * 32 + 32) + 'px')}) + .css({marginLeft: (level * 32 + 16) + 'px'}) .html( '' + Ox.parseHTML(example.result) + '' ) ) }); } else if (section == 'source') { - var html = ''; - item.source.forEach(function(token) { - html += '' + - Ox.encodeHTML(token.source) - .replace(/ /g, ' ') - .replace(/\n/g, '
') + - '
'; - }); + // fixme: not the right place to fix path $elements.push($('
') - .addClass('OxSourceCode ' + className) - .css({background: 'rgb(255, 255, 255)', padding: '4px'}) - .css({marginLeft: ((level * 32 + 32) + 'px')}) - .html('' + html + '') + .addClass(className) + .css({marginLeft: 16 + 'px'}) + .html( + '' + self.options.item.file.replace(Ox.PATH, '') + + ' line ' + self.options.item.line + '' + ) + ); + $elements.push( + Ox.SyntaxHighlighter({ + // fixme: silly + source: item.source.map(function(token) { + return token.source; + }).join(''), + offset: self.options.item.line + }) + .addClass(className) + .css({ + border: '1px solid rgb(192, 192, 192)', + marginTop: '8px', + }) ); } else { item[section].forEach(function(v) { diff --git a/source/Ox.UI/js/Core/Ox.Element.js b/source/Ox.UI/js/Core/Ox.Element.js index 00a2a47b..70917532 100644 --- a/source/Ox.UI/js/Core/Ox.Element.js +++ b/source/Ox.UI/js/Core/Ox.Element.js @@ -12,21 +12,6 @@ Ox.Element Basic UI element object tooltip tooltip (not implemented) options tagname or CSS selector self shared private variable - # Properties --------------------------------------------------------------- - $element jQuery DOM object - bindEvent binds an event to a function, once - # Usage - (event, callback) -> this element - ({event: callback, ...}) -> this element - # Arguments - event event name - callback callback function - data event data - bindEventOnce binds an event to a function - defaults sets the default options - options sets the options - triggerEvent triggers an event - unbindEvent unbinds an event # Events ------------------------------------------------------------------- anyclick anyclick fires on mouseup, but not on any subsequent mouseup within 250 ms @@ -231,11 +216,13 @@ Ox.Element = function() { /*@ bindEvent Binds a function to an event - (event, callback) -> This element - ({event: callback, ...}) -> This element + (event, callback) -> This element + ({event: callback, ...}) -> This element callback Callback function - data event data (key/value pairs) - event Event name (can be namespaced, like "click.foo") + data event data (key/value pairs) + event Event name + Event names can be namespaced, like 'click.foo' + @*/ that.bindEvent = function() { Ox.forEach(Ox.makeObject(arguments), function(fn, event) { @@ -246,11 +233,12 @@ Ox.Element = function() { /*@ bindEventOnce Binds a function to an event, once - (event, callback) -> This element - ({event: callback, ...}) -> This element + (event, callback) -> This element object + ({event: callback, ...}) -> This element object callback Callback function - data event data (key/value pairs) - event Event name (can be namespaced, like "click.foo") + data event data (key/value pairs) + event Event name + Event names can be namespaced, like 'click.foo' @*/ that.bindEventOnce = function() { Ox.forEach(Ox.makeObject(arguments), function(fn, event) { @@ -260,11 +248,10 @@ Ox.Element = function() { }; /*@ - Sets the default options for an element object - ({key: value, ...}) -> - key the name of the default option - that the element object - value the value of the default option + defaults Sets the default options for an element object + ({key: value, ...}) -> This element object + key The name of the default option + value The value of the default option @*/ that.defaults = function(defaults) { // sets the default options @@ -274,9 +261,8 @@ Ox.Element = function() { }; /*@ - Makes an element object gain focus - () -> that - that the element object + gainFocus Makes an element object gain focus + () -> This element object @*/ that.gainFocus = function() { Ox.Focus.focus(that.id); @@ -284,18 +270,16 @@ Ox.Element = function() { }; /*@ - Returns true if an element object has focus - () -> hasFocus - hasFocus true if the element has focus + hasFocus Returns true if an element object has focus + () -> True if the element has focus @*/ that.hasFocus = function() { return Ox.Focus.focused() == that.id; }; /*@ - Makes an element object lose focus - () -> that - that the element object + loseFocus Makes an element object lose focus + () -> This element object @*/ that.loseFocus = function() { @@ -304,8 +288,7 @@ Ox.Element = function() { }; /*@ - .options() - Gets or sets the options of an element object + options Gets or sets the options of an element object # Usage () -> all options (key) -> the value of option[key] @@ -324,10 +307,11 @@ Ox.Element = function() { return Ox.getset(self.options, arguments, self.setOption, that); }; + /*@ + removeElement Removes an element object and its event handler + () -> This element + @*/ that.removeElement = function() { - /*** - remove this element, including its event handler - ***/ that.loseFocus(); delete self.$eventHandler; that.remove(); @@ -335,14 +319,15 @@ Ox.Element = function() { return that; }; + /*@ + triggerEvent Triggers an event + (event) -> This element object + (event, data) -> This element object + ({event: data, ...}) -> This element object + event Event name + data Event data (key/value pairs) + @*/ that.triggerEvent = function() { - /*** - triggers an event - Usage - triggerEvent(event) - triggerEvent(event, data) - triggerEvent({eventA: dataA, eventB: dataB, ...}) - ***/ Ox.forEach(Ox.makeObject(arguments), function(data, event) { if ([ 'mousedown', 'mouserepeat', 'anyclick', 'singleclick', 'doubleclick', @@ -355,17 +340,22 @@ Ox.Element = function() { return that; }; + /*@ + unbindEvent Unbinds all callbacks from an event + To unbind a specific handler, use namespaced events, like + bindEvent('click.foo', callback), and then + unbindEvent('click.foo'). + () -> This element object + Unbinds all events + (event) -> This element object + Unbinds one event + (event, event, ...) -> This element object + Unbinds multiple events + ([event, event, ...]) -> This element object + Unbinds multiple events + event Event name + @*/ that.unbindEvent = function() { - /*** - unbinds an event triggered by this element - Usage - unbindEvent() // unbinds all events - unbindEvent(event) - unbindEvent(eventA, eventB, ...) - unbindEvent([eventA, eventB, ...]) - to unbind a specific handler, use namespaced events - bind('doubleclick.x', fn) ... unbind('doubleclick.x') - ***/ if (arguments.length == 0) { self.$eventHandler.unbind(); } else { diff --git a/source/Ox.UI/js/Core/Ox.SyntaxHighlighter.js b/source/Ox.UI/js/Core/Ox.SyntaxHighlighter.js index d8afb691..6722001d 100644 --- a/source/Ox.UI/js/Core/Ox.SyntaxHighlighter.js +++ b/source/Ox.UI/js/Core/Ox.SyntaxHighlighter.js @@ -11,6 +11,7 @@ Ox.SyntaxHighlighter = function(options, self) { .defaults({ height: 40, lineLength: 80, //@ number of characters per line + offset: 1, //@ first line number showLinebreaks: false, //@ show linebreak symbols showTabs: false, //@ show tab symbols showWhitespace: false, //@ show irregular leading or trailing whitespace @@ -24,19 +25,10 @@ Ox.SyntaxHighlighter = function(options, self) { .options(options || {}) .addClass('OxSyntaxHighlighter'); - var foo = $('
') - //.css({marginTop: '-1000px'}) - .html(Ox.repeat('_', 80)) - .appendTo(that.$element); - //alert(foo.width()); - foo.remove(); - self.options.source = self.options.source .replace(/\r\n/g, '\n') .replace(/\r/g, '\n'); - //self.options.source = Ox.minify(self.options.source); - self.cursor = 0; self.source = ''; self.tokens = Ox.tokenize(self.options.source); @@ -73,7 +65,7 @@ Ox.SyntaxHighlighter = function(options, self) { } }); self.lines = self.source.split('
'); - self.lineNumbersWidth = self.lines.length.toString().length * 7 + 7; + self.lineNumbersWidth = (self.lines.length + self.options.offset - 1).toString().length * 7; self.sourceCodeWidth = 80 * 7 + ( self.lines.length > 40 ? Ox.UI.SCROLLBAR_SIZE : 0 ); @@ -84,28 +76,31 @@ Ox.SyntaxHighlighter = function(options, self) { ); that.css({ - width: self.lineNumbersWidth + self.sourceCodeWidth, - height: self.height + //width: self.lineNumbersWidth + self.sourceCodeWidth, + //height: self.height }); self.$lineNumbers = new Ox.Element() .addClass('OxLineNumbers') .css({ + display: 'table-cell', width: self.lineNumbersWidth + 'px', - height: (self.lines.length * 14) + 'px' + //height: (self.lines.length * 14) + 8 + 'px', + padding: '4px', }) .html( Ox.range(self.lines.length).map(function(line) { - return (line + 1) + ' '; + return (line + self.options.offset); }).join('
') ) .appendTo(that); self.$source = new Ox.Element() .addClass('OxSourceCode') .css({ - left: self.lineNumbersWidth + 'px', - width: self.sourceCodeWidth + 'px', - height: (self.lines.length * 14) + 'px' + display: 'table-cell', + //width: self.sourceCodeWidth + 'px', + //height: (self.lines.length * 14) + 'px', + padding: '4px' }) .html(self.source) .appendTo(that); diff --git a/source/Ox.UI/js/List/Ox.TreeList.js b/source/Ox.UI/js/List/Ox.TreeList.js index d5920b8d..f147a08d 100644 --- a/source/Ox.UI/js/List/Ox.TreeList.js +++ b/source/Ox.UI/js/List/Ox.TreeList.js @@ -1,6 +1,8 @@ // vim: et:ts=4:sw=4:sts=4:ft=js Ox.TreeList = function(options, self) { + // fixme: expanding the last item should cause some scroll + var self = self || {}, that = new Ox.Element({}, self) .defaults({ diff --git a/source/Ox.UI/themes/classic/css/classic.css b/source/Ox.UI/themes/classic/css/classic.css index a73fb217..58ec426d 100644 --- a/source/Ox.UI/themes/classic/css/classic.css +++ b/source/Ox.UI/themes/classic/css/classic.css @@ -368,7 +368,7 @@ SyntaxHighlighter ================================================================================ */ -.OxThemeClassic .OxSyntaxHighlighter .OxSourceCode { +.OxThemeClassic .OxSyntaxHighlighter { background-color: rgb(255, 255, 255); } .OxThemeClassic .OxSyntaxHighlighter .OxLineNumbers { diff --git a/source/Ox.js b/source/Ox.js index 6c14f05d..b18d6a86 100644 --- a/source/Ox.js +++ b/source/Ox.js @@ -116,7 +116,7 @@ Ox.wrap = function(val, chained) { //@ Array ---------------------------------------------------------------------- /*@ -Ox.compact Returns an array w/o nullundefined +Ox.compact Returns an array w/o null or undefined > Ox.compact([null,,1,,2,,3]) [1, 2, 3] @*/ @@ -132,8 +132,8 @@ Ox.compact = function(arr) { /*@ Ox.flatten Flattens an array - > Ox.flatten([1, [2, [3], 4], 5]) - [1, 2, 3, 4, 5] + > Ox.flatten([1, [2, [3], 2], 1]) + [1, 2, 3, 2, 1] @*/ Ox.flatten = function(arr) { // fixme: can this work for objects too? @@ -152,8 +152,8 @@ Ox.flatten = function(arr) { /*@ Ox.merge Merges an array with one or more other arrays - > Ox.merge(['foo'], ['foo', 'bar'], ['bar']) - ['foo', 'foo', 'bar', 'bar'] + > Ox.merge([1], [2, 3, 2], [1]) + [1, 2, 3, 2, 1] @*/ Ox.merge = function(arr) { Ox.forEach(Array.prototype.slice.call(arguments, 1), function(arg) { @@ -1661,7 +1661,7 @@ Ox.element = function(str) { 33819 > Ox.decodeBase32('?').toString() 'NaN' - */ + @*/ Ox.decodeBase32 = function(str) { return parseInt(Ox.map(str.toUpperCase(), function(char) { var index = digits.indexOf(aliases[char] || char); @@ -3014,6 +3014,8 @@ Ox.doc = (function() { if (/^[A-Z]/.test(item.name)) { // main item item.source = parseTokens(tokens[i]); + item.line = source.substr(0, item.source[0].offset) + .split('\n').length; items.push(item); } else { // property of a function item @@ -3428,7 +3430,9 @@ Ox.divideInt = function(num, by) { } /*@ -Ox.limit Returns the logarithm of a given number to a given base +Ox.limit Limits a number by a given mininum and maximum + Ox.limit(num, min, max) is a shorthand for + Math.min(Math.max(num, min), max) (num) -> num (num, max) -> Math.max(num, max) (num, min, max) -> Math.min(Math.max(num, min), max)