From 62f8a907eab954b6395e55b72a0759b0ed919b4a Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Thu, 27 Oct 2011 18:50:23 +0000 Subject: [PATCH] updates for html parsing, request handling, and editable elements --- source/Ox.UI/css/Ox.UI.css | 18 ++++++ source/Ox.UI/js/Core/Ox.Request.js | 97 +++++++++++++++++------------ source/Ox.UI/js/Form/Ox.Editable.js | 49 +++++++++------ source/Ox/js/Encoding.js | 22 ++++++- source/Ox/js/HTML.js | 21 ++++--- source/Ox/js/Object.js | 15 +++++ 6 files changed, 153 insertions(+), 69 deletions(-) diff --git a/source/Ox.UI/css/Ox.UI.css b/source/Ox.UI/css/Ox.UI.css index 51020ee8..f630e475 100644 --- a/source/Ox.UI/css/Ox.UI.css +++ b/source/Ox.UI/css/Ox.UI.css @@ -14,6 +14,9 @@ a:hover { text-decoration: underline; cursor: pointer; } +blockquote { + margin: 0 1.5em 0 1.5em; +} body { margin: 0; overflow: hidden; @@ -30,11 +33,26 @@ div, input, textarea { font-family: Lucida Grande, Segoe UI, DejaVu Sans, Arial; font-size: 11px; } +h1 { + margin: 0; + font-size: 16px; + font-weight: normal; +} img { -moz-user-drag: none; -o-user-drag: none; -webkit-user-drag: none; } +ol, ul { + padding-left: 1.5em; + margin: 0; +} +p:first-child { + margin-top: 0; +} +p:last-child { + margin-bottom: 0; +} td { padding: 0; } diff --git a/source/Ox.UI/js/Core/Ox.Request.js b/source/Ox.UI/js/Core/Ox.Request.js index 084d362f..4032cc74 100644 --- a/source/Ox.UI/js/Core/Ox.Request.js +++ b/source/Ox.UI/js/Core/Ox.Request.js @@ -125,10 +125,9 @@ Ox.Request = function(options) { } else { pending[options.id] = true; $.ajax({ + complete: complete, data: options.data, - dataType: 'json', - error: error, - success: success, + //dataType: 'json', timeout: options.timeout, type: options.type, url: options.url @@ -172,37 +171,66 @@ Ox.Request = function(options) { iframe.close(); } - function error(request, status, error) { + function complete(request) { var data; - if (arguments.length == 1) { - data = arguments[0] - } else { + try { + data = JSON.parse(request.responseText); + } catch (err) { try { - data = JSON.parse(request.responseText); + data = { + status: { + code: request.status, + text: request.statusText + } + }; } catch (err) { - try { - data = { - status: { - code: request.status, - text: request.statusText - } - }; - } catch (err) { - data = { - status: { - code: '500', - text: 'Unknown Error' - } - }; - } + data = { + status: { + code: '500', + text: 'Unknown Error' + } + }; } } - if (data.status.code && data.status.code < 500) { - // 0 is timeout + if (data.status.code == 200) { + cache[req] = { + data: data, + time: Ox.getTime() + }; callback(data); - } else { + } else if (data.status.code >= 400 && data.status.code < 500) { + var $dialog = Ox.Dialog({ + buttons: [ + Ox.Button({ + id: 'close', + title: 'Close' + }) + .bindEvent({ + click: function() { + $dialog.close(); + } + }) + ], + content: Ox.Element() + .append( + $('') + .attr({src: Ox.UI.PATH + 'png/icon128.png'}) + .css({position: 'absolute', left: '16px', top: '16px', width: '64px', height: '64px'}) + ) + .append( + Ox.Element() + .css({position: 'absolute', left: '96px', top: '16px', width: '256px'}) + .html('Sorry, you have made an unauthorized request.') + ), + height: 192, + keys: {enter: 'close', escape: 'close'}, + title: Ox.toTitleCase(data.status.text), + width: 368 + }) + .open(); + } else { + // 0 (timeout) or 500 (error) var $dialog = Ox.Dialog({ - title: 'Application Error', buttons: [ Ox.Button({ id: 'details', @@ -238,28 +266,15 @@ Ox.Request = function(options) { ), height: 192, keys: {enter: 'close', escape: 'close'}, + title: 'Application Error', width: 368 }) .open(); // fixme: change this to Send / Don't Send - /*Ox.print({ - request: request, - status: status, - error: error - });*/ } pending[options.id] = false; } - function success(data) { - pending[options.id] = false; - cache[req] = { - data: data, - time: Ox.getTime() - }; - callback(data); - } - // return dfd.promise(); return options.id; diff --git a/source/Ox.UI/js/Form/Ox.Editable.js b/source/Ox.UI/js/Form/Ox.Editable.js index caaae597..03b11c74 100644 --- a/source/Ox.UI/js/Form/Ox.Editable.js +++ b/source/Ox.UI/js/Form/Ox.Editable.js @@ -18,12 +18,11 @@ Ox.Editable = function(options, self) { tooltip: options.tooltip }, self) .defaults({ - clickLink: function(e) { - document.location.href = $(e.target).attr('href'); - }, + clickLink: null, editable: true, editing: false, format: null, + height: 0, placeholder: '', tooltip: '', value: '', @@ -33,16 +32,20 @@ Ox.Editable = function(options, self) { .options(options || {}) .addClass('OxEditableElement') .bind({ - click: function(e) { - if ($(e.target).is('a')) { - return false; - } + click: function() { + return false; } }) .bindEvent({ doubleclick: edit, singleclick: function(e) { - $(e.target).is('a') && self.options.clickLink(e); + if ($(e.target).is('a')) { + if (self.options.clickLink) { + self.options.clickLink(e); + } else { + document.location.href = $(e.target).attr('href'); + } + } } }); @@ -56,8 +59,9 @@ Ox.Editable = function(options, self) { //border: '1px solid transparent' } : { //padding: '0 4px 0 4px' - width: self.options.width + 'px' + //width: self.options.width + 'px' }) + //.css({background: 'red'}) .html(formatValue()) //[self.options.editing ? 'hide' : 'show']() .appendTo(that); @@ -112,10 +116,11 @@ Ox.Editable = function(options, self) { function change(event) { var height, width; self.options.value = event.value; - self.$value.html(formatValue); + self.$value.html(formatValue()); self.$test.html(formatTestValue()); - height = self.options.height || self.$test.height(); - width = self.options.width || Ox.limit(self.$test.width() + 2, self.minWidth, self.maxWidth) + //height = self.options.height || Ox.limit(self.$test.height() + 2, self.minHeight, self.maxHeight); + height = self.options.height || Math.max(self.$test.height() + 2, self.minHeight); + width = self.options.width || Ox.limit(self.$test.width() + 2, self.minWidth, self.maxWidth); Ox.print(self.options.width, self.$test.width(), 'wxh', width, height) if (self.options.type == 'input') { self.$input.options({ @@ -146,14 +151,16 @@ Ox.Editable = function(options, self) { var height, width; if (self.options.editable && !self.options.editing) { self.originalValue = self.options.value; - self.minWidth = 8 + self.minWidth = 8; self.maxWidth = that.parent().width(); - Ox.print('MAX WIDTH', self.maxWidth); + self.minHeight = 14; + self.maxHeight = that.parent().height(); height = self.options.height || self.$value.height(); - width = self.$value.width(); + width = self.options.width || self.$value.width(); self.$value.hide(); - //self.$test.show(); - Ox.print('HEIGHT', height) + + Ox.print("H:::", self.options.height, self.maxHeight, height) + self.$input.options({ height: height, width: width @@ -179,9 +186,11 @@ Ox.Editable = function(options, self) { } function formatInputValue() { - return self.options.type == 'input' - ? self.options.value - : self.options.value.replace(//g, '\n'); + return Ox.decodeHTML( + self.options.type == 'input' + ? self.options.value + : self.options.value.replace(//g, '\n\n') + ); } function formatTestValue() { diff --git a/source/Ox/js/Encoding.js b/source/Ox/js/Encoding.js index 9c8b84eb..711151ef 100644 --- a/source/Ox/js/Encoding.js +++ b/source/Ox/js/Encoding.js @@ -288,11 +288,31 @@ 'äbçdê' > Ox.decodeHTML('äbçdê') 'äbçdê' + > Ox.decodeHTML('bold') + 'bold' @*/ Ox.decodeHTML = function(str) { // relies on dom, but shorter than using this: // http://www.w3.org/TR/html5/named-character-references.html - return Ox.element('
').html(str)[0].childNodes[0].nodeValue; + return Ox.decodeHTMLEntities(Ox.element('
').html(str).html()); + }; + + Ox.encodeHTMLEntities = function(str) { + return str.replace( + new RegExp('(' + Object.keys(Ox.HTML_ENTITIES).join('|') + ')', 'g'), + function(match) { + return Ox.HTML_ENTITIES[match]; + } + ); + }; + + Ox.decodeHTMLEntities = function(str) { + return str.replace( + new RegExp('(' + Ox.values(Ox.HTML_ENTITIES).join('|') + ')', 'g'), + function(match) { + return Ox.keyOf(Ox.HTML_ENTITIES, match); + } + ); }; /*@ diff --git a/source/Ox/js/HTML.js b/source/Ox/js/HTML.js index 7b6e452e..5ec5de0c 100644 --- a/source/Ox/js/HTML.js +++ b/source/Ox/js/HTML.js @@ -37,15 +37,22 @@ Ox.parseHTML Takes HTML from an untrusted source and returns something sane Ox.parseHTML = (function() { var defaultTags = [ - 'a', 'b', 'blockquote', 'br', 'cite', 'code', - 'del', 'em', 'i', 'img', 'ins', - 'li', 'ol', 'p', 'q', 'rtl', - 's', 'strong', 'sub', 'sup', - 'table', 'tbody', 'td', 'th', 'tr', 'ul', '[]' + // inline formatting + 'b', 'code', 'i', 'q', 's', 'sub', 'sup', 'u', + // block + 'blockquote', 'h1', 'p', 'pre', + // lists + 'li', 'ol', 'ul', + // tables + 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', + // other + 'a', 'br', 'img', + // special + 'rtl', '[]' ], parse = { a: { - ']*?href="(https?:\/\/.+?)".*?>': '', + ']*?href="((https?:\/\/|\/).+?)".*?>': '', '<\/a>': '' }, img: { @@ -90,7 +97,7 @@ Ox.parseHTML = (function() { html = html.replace(new RegExp(tab + i + tab, 'gi'), match); }); //html = html.replace(/\n/g, '
\n'); - html = html.replace(/\n/g, '
'); + html = html.replace(/\n\n/g, '

'); // close extra opening (and remove extra closing) tags // note: this converts '"' to '"' return Ox.element('
').html(html).html(); diff --git a/source/Ox/js/Object.js b/source/Ox/js/Object.js index 9f8e3dcd..bf32b7f9 100644 --- a/source/Ox/js/Object.js +++ b/source/Ox/js/Object.js @@ -14,6 +14,21 @@ Ox.extend = function() { return obj; }; +/*@ +Ox.keyOf undocumented +@*/ + +Ox.keyOf = function(obj, val) { + var key; + Ox.forEach(obj, function(v, k) { + if (v == val) { + key = k; + return false; + } + }); + return key; +}; + /*@ Ox.serialize Parses an object into query parameters > Ox.serialize({a: 1, b: 2, c: 3})