updates for html parsing, request handling, and editable elements
This commit is contained in:
parent
a949ad2cf4
commit
62f8a907ea
6 changed files with 153 additions and 69 deletions
|
@ -14,6 +14,9 @@ a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
blockquote {
|
||||||
|
margin: 0 1.5em 0 1.5em;
|
||||||
|
}
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -30,11 +33,26 @@ div, input, textarea {
|
||||||
font-family: Lucida Grande, Segoe UI, DejaVu Sans, Arial;
|
font-family: Lucida Grande, Segoe UI, DejaVu Sans, Arial;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
img {
|
img {
|
||||||
-moz-user-drag: none;
|
-moz-user-drag: none;
|
||||||
-o-user-drag: none;
|
-o-user-drag: none;
|
||||||
-webkit-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 {
|
td {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,10 +125,9 @@ Ox.Request = function(options) {
|
||||||
} else {
|
} else {
|
||||||
pending[options.id] = true;
|
pending[options.id] = true;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
complete: complete,
|
||||||
data: options.data,
|
data: options.data,
|
||||||
dataType: 'json',
|
//dataType: 'json',
|
||||||
error: error,
|
|
||||||
success: success,
|
|
||||||
timeout: options.timeout,
|
timeout: options.timeout,
|
||||||
type: options.type,
|
type: options.type,
|
||||||
url: options.url
|
url: options.url
|
||||||
|
@ -172,37 +171,66 @@ Ox.Request = function(options) {
|
||||||
iframe.close();
|
iframe.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function error(request, status, error) {
|
function complete(request) {
|
||||||
var data;
|
var data;
|
||||||
if (arguments.length == 1) {
|
try {
|
||||||
data = arguments[0]
|
data = JSON.parse(request.responseText);
|
||||||
} else {
|
} catch (err) {
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(request.responseText);
|
data = {
|
||||||
|
status: {
|
||||||
|
code: request.status,
|
||||||
|
text: request.statusText
|
||||||
|
}
|
||||||
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
try {
|
data = {
|
||||||
data = {
|
status: {
|
||||||
status: {
|
code: '500',
|
||||||
code: request.status,
|
text: 'Unknown Error'
|
||||||
text: request.statusText
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
data = {
|
|
||||||
status: {
|
|
||||||
code: '500',
|
|
||||||
text: 'Unknown Error'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.status.code && data.status.code < 500) {
|
if (data.status.code == 200) {
|
||||||
// 0 is timeout
|
cache[req] = {
|
||||||
|
data: data,
|
||||||
|
time: Ox.getTime()
|
||||||
|
};
|
||||||
callback(data);
|
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(
|
||||||
|
$('<img>')
|
||||||
|
.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({
|
var $dialog = Ox.Dialog({
|
||||||
title: 'Application Error',
|
|
||||||
buttons: [
|
buttons: [
|
||||||
Ox.Button({
|
Ox.Button({
|
||||||
id: 'details',
|
id: 'details',
|
||||||
|
@ -238,28 +266,15 @@ Ox.Request = function(options) {
|
||||||
),
|
),
|
||||||
height: 192,
|
height: 192,
|
||||||
keys: {enter: 'close', escape: 'close'},
|
keys: {enter: 'close', escape: 'close'},
|
||||||
|
title: 'Application Error',
|
||||||
width: 368
|
width: 368
|
||||||
})
|
})
|
||||||
.open();
|
.open();
|
||||||
// fixme: change this to Send / Don't Send
|
// fixme: change this to Send / Don't Send
|
||||||
/*Ox.print({
|
|
||||||
request: request,
|
|
||||||
status: status,
|
|
||||||
error: error
|
|
||||||
});*/
|
|
||||||
}
|
}
|
||||||
pending[options.id] = false;
|
pending[options.id] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function success(data) {
|
|
||||||
pending[options.id] = false;
|
|
||||||
cache[req] = {
|
|
||||||
data: data,
|
|
||||||
time: Ox.getTime()
|
|
||||||
};
|
|
||||||
callback(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return dfd.promise();
|
// return dfd.promise();
|
||||||
|
|
||||||
return options.id;
|
return options.id;
|
||||||
|
|
|
@ -18,12 +18,11 @@ Ox.Editable = function(options, self) {
|
||||||
tooltip: options.tooltip
|
tooltip: options.tooltip
|
||||||
}, self)
|
}, self)
|
||||||
.defaults({
|
.defaults({
|
||||||
clickLink: function(e) {
|
clickLink: null,
|
||||||
document.location.href = $(e.target).attr('href');
|
|
||||||
},
|
|
||||||
editable: true,
|
editable: true,
|
||||||
editing: false,
|
editing: false,
|
||||||
format: null,
|
format: null,
|
||||||
|
height: 0,
|
||||||
placeholder: '',
|
placeholder: '',
|
||||||
tooltip: '',
|
tooltip: '',
|
||||||
value: '',
|
value: '',
|
||||||
|
@ -33,16 +32,20 @@ Ox.Editable = function(options, self) {
|
||||||
.options(options || {})
|
.options(options || {})
|
||||||
.addClass('OxEditableElement')
|
.addClass('OxEditableElement')
|
||||||
.bind({
|
.bind({
|
||||||
click: function(e) {
|
click: function() {
|
||||||
if ($(e.target).is('a')) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.bindEvent({
|
.bindEvent({
|
||||||
doubleclick: edit,
|
doubleclick: edit,
|
||||||
singleclick: function(e) {
|
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'
|
//border: '1px solid transparent'
|
||||||
} : {
|
} : {
|
||||||
//padding: '0 4px 0 4px'
|
//padding: '0 4px 0 4px'
|
||||||
width: self.options.width + 'px'
|
//width: self.options.width + 'px'
|
||||||
})
|
})
|
||||||
|
//.css({background: 'red'})
|
||||||
.html(formatValue())
|
.html(formatValue())
|
||||||
//[self.options.editing ? 'hide' : 'show']()
|
//[self.options.editing ? 'hide' : 'show']()
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
|
@ -112,10 +116,11 @@ Ox.Editable = function(options, self) {
|
||||||
function change(event) {
|
function change(event) {
|
||||||
var height, width;
|
var height, width;
|
||||||
self.options.value = event.value;
|
self.options.value = event.value;
|
||||||
self.$value.html(formatValue);
|
self.$value.html(formatValue());
|
||||||
self.$test.html(formatTestValue());
|
self.$test.html(formatTestValue());
|
||||||
height = self.options.height || self.$test.height();
|
//height = self.options.height || Ox.limit(self.$test.height() + 2, self.minHeight, self.maxHeight);
|
||||||
width = self.options.width || Ox.limit(self.$test.width() + 2, self.minWidth, self.maxWidth)
|
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)
|
Ox.print(self.options.width, self.$test.width(), 'wxh', width, height)
|
||||||
if (self.options.type == 'input') {
|
if (self.options.type == 'input') {
|
||||||
self.$input.options({
|
self.$input.options({
|
||||||
|
@ -146,14 +151,16 @@ Ox.Editable = function(options, self) {
|
||||||
var height, width;
|
var height, width;
|
||||||
if (self.options.editable && !self.options.editing) {
|
if (self.options.editable && !self.options.editing) {
|
||||||
self.originalValue = self.options.value;
|
self.originalValue = self.options.value;
|
||||||
self.minWidth = 8
|
self.minWidth = 8;
|
||||||
self.maxWidth = that.parent().width();
|
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();
|
height = self.options.height || self.$value.height();
|
||||||
width = self.$value.width();
|
width = self.options.width || self.$value.width();
|
||||||
self.$value.hide();
|
self.$value.hide();
|
||||||
//self.$test.show();
|
|
||||||
Ox.print('HEIGHT', height)
|
Ox.print("H:::", self.options.height, self.maxHeight, height)
|
||||||
|
|
||||||
self.$input.options({
|
self.$input.options({
|
||||||
height: height,
|
height: height,
|
||||||
width: width
|
width: width
|
||||||
|
@ -179,9 +186,11 @@ Ox.Editable = function(options, self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatInputValue() {
|
function formatInputValue() {
|
||||||
return self.options.type == 'input'
|
return Ox.decodeHTML(
|
||||||
? self.options.value
|
self.options.type == 'input'
|
||||||
: self.options.value.replace(/<br\/?>/g, '\n');
|
? self.options.value
|
||||||
|
: self.options.value.replace(/<br\/?><br\/?>/g, '\n\n')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatTestValue() {
|
function formatTestValue() {
|
||||||
|
|
|
@ -288,11 +288,31 @@
|
||||||
'äbçdê'
|
'äbçdê'
|
||||||
> Ox.decodeHTML('äbçdê')
|
> Ox.decodeHTML('äbçdê')
|
||||||
'äbçdê'
|
'äbçdê'
|
||||||
|
> Ox.decodeHTML('<b>bold</b>')
|
||||||
|
'<b>bold</b>'
|
||||||
@*/
|
@*/
|
||||||
Ox.decodeHTML = function(str) {
|
Ox.decodeHTML = function(str) {
|
||||||
// relies on dom, but shorter than using this:
|
// relies on dom, but shorter than using this:
|
||||||
// http://www.w3.org/TR/html5/named-character-references.html
|
// http://www.w3.org/TR/html5/named-character-references.html
|
||||||
return Ox.element('<div>').html(str)[0].childNodes[0].nodeValue;
|
return Ox.decodeHTMLEntities(Ox.element('<div>').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);
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
|
|
|
@ -37,15 +37,22 @@ Ox.parseHTML <f> Takes HTML from an untrusted source and returns something sane
|
||||||
|
|
||||||
Ox.parseHTML = (function() {
|
Ox.parseHTML = (function() {
|
||||||
var defaultTags = [
|
var defaultTags = [
|
||||||
'a', 'b', 'blockquote', 'br', 'cite', 'code',
|
// inline formatting
|
||||||
'del', 'em', 'i', 'img', 'ins',
|
'b', 'code', 'i', 'q', 's', 'sub', 'sup', 'u',
|
||||||
'li', 'ol', 'p', 'q', 'rtl',
|
// block
|
||||||
's', 'strong', 'sub', 'sup',
|
'blockquote', 'h1', 'p', 'pre',
|
||||||
'table', 'tbody', 'td', 'th', 'tr', 'ul', '[]'
|
// lists
|
||||||
|
'li', 'ol', 'ul',
|
||||||
|
// tables
|
||||||
|
'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr',
|
||||||
|
// other
|
||||||
|
'a', 'br', 'img',
|
||||||
|
// special
|
||||||
|
'rtl', '[]'
|
||||||
],
|
],
|
||||||
parse = {
|
parse = {
|
||||||
a: {
|
a: {
|
||||||
'<a [^<>]*?href="(https?:\/\/.+?)".*?>': '<a href="{1}" title="{1}">',
|
'<a [^<>]*?href="((https?:\/\/|\/).+?)".*?>': '<a href="{1}" title="{1}">',
|
||||||
'<\/a>': '</a>'
|
'<\/a>': '</a>'
|
||||||
},
|
},
|
||||||
img: {
|
img: {
|
||||||
|
@ -90,7 +97,7 @@ Ox.parseHTML = (function() {
|
||||||
html = html.replace(new RegExp(tab + i + tab, 'gi'), match);
|
html = html.replace(new RegExp(tab + i + tab, 'gi'), match);
|
||||||
});
|
});
|
||||||
//html = html.replace(/\n/g, '<br/>\n');
|
//html = html.replace(/\n/g, '<br/>\n');
|
||||||
html = html.replace(/\n/g, '<br/>');
|
html = html.replace(/\n\n/g, '<br/><br/>');
|
||||||
// close extra opening (and remove extra closing) tags
|
// close extra opening (and remove extra closing) tags
|
||||||
// note: this converts '"' to '"'
|
// note: this converts '"' to '"'
|
||||||
return Ox.element('<div>').html(html).html();
|
return Ox.element('<div>').html(html).html();
|
||||||
|
|
|
@ -14,6 +14,21 @@ Ox.extend = function() {
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.keyOf <f> 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 <f> Parses an object into query parameters
|
Ox.serialize <f> Parses an object into query parameters
|
||||||
> Ox.serialize({a: 1, b: 2, c: 3})
|
> Ox.serialize({a: 1, b: 2, c: 3})
|
||||||
|
|
Loading…
Reference in a new issue