Created
January 26, 2010 03:26
-
-
Save miketaylr/286515 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Titan - Javascript Web Framework | |
* Version 1.1 | |
* Copyright 2009 Valio, Inc. | |
* | |
* Visit the Titan website for more information and documentation: | |
* http://www.titanproject.org | |
* | |
* --------------------------------------------------------------------------- | |
* | |
* CREDITS: | |
* | |
* Mike Osuna, Will Wilson, Drew Wilson | |
* | |
* --------------------------------------------------------------------------- | |
* | |
* LICENCE: | |
* | |
* Released under a MIT Licence: http://www.opensource.org/licenses/mit-license.php | |
* | |
*/ | |
(function ($) { | |
var willChangeStack = []; | |
var didChangeStack = []; | |
function makeChain(target, keys, fn, origTarget, origPath) { | |
var key = keys.shift(); | |
if (keys.length > 0) { | |
var nextTarget = $(target).attr(key); | |
var reobserveOriginal = function () { | |
$(origTarget).unobserve(origPath, fn); | |
$(origTarget).observe(origPath, fn); | |
fn(); | |
}; | |
var undoChainLink = function () { | |
$(target).unbind(key + "-changed", reobserveOriginal); | |
}; | |
if (nextTarget) { | |
$(target).bind(key + "-changed", reobserveOriginal); | |
return [undoChainLink].concat(makeChain(nextTarget, keys, fn, origTarget, origPath)); | |
} | |
} else { | |
$(target).bind(key + "-changed", fn); | |
} | |
return []; | |
} | |
$.extend({ | |
willChangeValueForKey: function (obj, key) { | |
willChangeStack.push({ | |
obj: obj, | |
key: key, | |
val: $(obj).valueForKey(key) | |
}); | |
}, | |
didChangeValueForKey: function (obj, key) { | |
var changed = willChangeStack.pop(); | |
if (changed.key != key) { | |
console.log("Expected didChangeValueForKey: " + changed.key + " but got " + key); | |
} | |
didChangeStack.push(changed); | |
if (willChangeStack.length == 0) { | |
var changes = didChangeStack; | |
didChangeStack = []; | |
$(changes).each(function () { | |
if ($(this.obj).valueForKey(this.key) !== this.val) { | |
$(this.obj).trigger(this.key + "-changed", { | |
oldValue: this.val, | |
newValue: $(this.obj).valueForKey(this.key) | |
}); | |
} | |
}); | |
} | |
}, | |
valueForKey: function (obj, key, value) { | |
if ((value != undefined) && (obj.automaticallyNotifiesObserversForKey === undefined || obj.automaticallyNotifiesObserversForKey(key))) { | |
$.willChangeValueForKey(obj, key); | |
} | |
var val; | |
if ($.isFunction(obj[key])) { | |
val = obj[key].call(obj, key, value); | |
} else { | |
if (value != undefined) { | |
obj[key] = value; | |
} | |
val = obj[key]; | |
} | |
if ((value != undefined) && (obj.automaticallyNotifiesObserversForKey === undefined || obj.automaticallyNotifiesObserversForKey(key))) { | |
$.didChangeValueForKey(obj, key); | |
} | |
return val; | |
}, | |
valueForKeyPath: function (obj, path, value) { | |
var keys = path.split("."); | |
var key; | |
while (keys.length > 1) { | |
key = keys.shift(); | |
obj = $(obj).valueForKey(key); | |
if (obj == undefined) { | |
return undefined; | |
} | |
} | |
key = keys.shift(); | |
return $(obj).valueForKey(key, value); | |
}, | |
observe: function (obj, path, fn) { | |
var keys = path.split("."); | |
var chainKey = path.replace(/\./g, "_"); | |
chain = $(obj).data(chainKey, {}); | |
if (keys.length > 1) { | |
var chain = $(obj).data(chainKey); | |
var tmp = makeChain(obj, keys.slice(), fn, obj, path); | |
chain[$.data(fn)] = tmp; | |
} else { | |
$(obj).bind(path + "-changed", fn); | |
} | |
return fn; | |
}, | |
unobserve: function (obj, path, fn) { | |
var keys = path.split("."); | |
if (keys.length > 1) { | |
var chainKey = path.replace(/\./g, "_"); | |
var chain = $(obj).data(chainKey); | |
$(chain[$.data(fn)]).each(function () { | |
this(); | |
}); | |
} else { | |
$(obj).unbind(path + "-changed", fn); | |
} | |
return fn; | |
}, | |
connect: function (from, fromAttr, to, toAttr) { | |
var binding = { | |
from: from, | |
to: to, | |
fromAttr: fromAttr, | |
toAttr: toAttr, | |
updateTo: true, | |
updateFrom: true | |
}; | |
$(from).data(fromAttr + $.data(to) + toAttr, binding); | |
binding.fromFn = $(from).observe(fromAttr, function () { | |
if (binding.updateTo == false) { | |
binding.updateTo = true; | |
binding.updateFrom = true; | |
return; | |
} | |
binding.updateFrom = false; | |
$(to).valueForKeyPath(toAttr, $(from).valueForKeyPath(fromAttr)); | |
}); | |
binding.toFn = $(to).observe(toAttr, function () { | |
if (binding.updateFrom == false) { | |
binding.updateTo = true; | |
binding.updateFrom = true; | |
return; | |
} | |
binding.updateTo = false; | |
$(from).valueForKeyPath(fromAttr, $(to).valueForKeyPath(toAttr)); | |
}); | |
binding.updateTo = false; | |
$(from).valueForKeyPath(fromAttr, $(to).valueForKeyPath(toAttr)); | |
}, | |
disconnect: function (obj, fromAttr, to, toAttr) { | |
var binding = $(obj).data(fromAttr + $.data(to) + toAttr); | |
binding.to.unobserve(toAttr, binding.toFn); | |
binding.from.unobserve(fromAttr, binding.fromFn); | |
} | |
}); | |
$.fn.extend({ | |
valueForKey: function (key, value) { | |
if (value === undefined) { | |
return $.valueForKey(this[0], key); | |
} | |
return this.each(function () { | |
$.valueForKey(this, key, value); | |
}); | |
}, | |
valueForKeyPath: function (path, value) { | |
if (value === undefined) { | |
return $.valueForKeyPath(this[0], path); | |
} | |
return this.each(function () { | |
$.valueForKeyPath(this, path, value); | |
}); | |
}, | |
observe: function (path, fn) { | |
return this.each(function () { | |
$.observe(this, path, fn); | |
}); | |
}, | |
unobserve: function (path, fn) { | |
return this.each(function () { | |
$.unobserve(this, path, fn); | |
}); | |
}, | |
connect: function (attr, to, toAttr) { | |
return this.each(function () { | |
$.connect(this, attr, to, toAttr); | |
}); | |
}, | |
disconnect: function (attr, to, toAttr) { | |
return this.each(function () { | |
$.disconnect(this, attr, to, toAttr); | |
}); | |
} | |
}); | |
})(jQuery); | |
(function ($) { | |
$.serialize = function (object) { | |
var values = []; | |
var prefix = ''; | |
values = $.serialize.recursive_serialize(object, values, prefix); | |
param_string = values.join('&'); | |
return param_string; | |
}; | |
$.serialize.recursive_serialize = function (object, values, prefix) { | |
var key; | |
for (key in object) { | |
if (typeof object[key] == 'object') { | |
if (prefix.length > 0) { | |
prefix += '[' + key + ']'; | |
} else { | |
prefix += key; | |
} | |
values = $.serialize.recursive_serialize(object[key], values, prefix); | |
prefixes = prefix.split('['); | |
if (prefixes.length > 1) { | |
prefix = prefixes.slice(0, prefixes.length - 1).join('['); | |
} else { | |
prefix = prefixes[0]; | |
} | |
} else { | |
value = encodeURIComponent(object[key]); | |
if (prefix.length > 0) { | |
prefixed_key = prefix + '[' + key + ']'; | |
} else { | |
prefixed_key = key; | |
} | |
prefixed_key = encodeURIComponent(prefixed_key); | |
if (value) values.push(prefixed_key + '=' + value); | |
} | |
} | |
return values; | |
}; | |
})(jQuery); | |
(function ($) { | |
$.controller = { | |
defaults: {}, | |
array: function (model, conditions, options) { | |
if (this.constructor == $.controller.array) { | |
var that = this; | |
this.model = model; | |
if (conditions) { | |
this.conditions = conditions; | |
if (conditions.noRetrieve) { | |
var noRetrieve = conditions.noRetrieve; | |
delete conditions.noRetrieve; | |
} | |
if (conditions.master) { | |
this.master = conditions.master[0]; | |
this.attr = conditions.master[1]; | |
if (this.master) { | |
delete this.conditions.master; | |
$(this.master).observe("selection", function () { | |
if (!conditions.noRetrieve) { | |
if (options && options.success) { | |
that.retrieve({}, | |
{ | |
success: options.success | |
}); | |
} else { | |
that.retrieve(); | |
} | |
} | |
}); | |
} | |
} | |
if (conditions.paginate) { | |
var defaults = { | |
perPage: 10, | |
numberLimit: 10, | |
overlap: false, | |
startPage: 1 | |
} | |
var opts = $.extend(defaults, conditions.paginate); | |
this.paginating = true; | |
this.paginate = conditions.paginate; | |
this.perPage = opts.perPage; | |
this.numberLimit = opts.numberLimit; | |
this._page = opts.startPage; | |
(opts.overlap !== false) ? this.overlap = opts.overlap : this.overlap = 0; | |
delete this.conditions.paginate; | |
} | |
} | |
if (!noRetrieve) { | |
if (options && options.success) { | |
this.retrieve({}, | |
{ | |
success: options.success | |
}); | |
} else { | |
this.retrieve(); | |
} | |
} | |
} else { | |
return new $.controller.array(model, conditions, options); | |
} | |
}, | |
object: function () { | |
if (this.constructor == $.controller.object) {} else { | |
return new $.controller.object(); | |
} | |
}, | |
create: function (model, obj, options) { | |
var that = this; | |
var data = {}; | |
if (model) { | |
data = obj; | |
data = $.serialize(data); | |
} else { | |
data = obj; | |
} | |
$.ajaxq("titan", $.extend({ | |
url: $.controller.defaults.url + "/" + model, | |
data: data, | |
type: "POST" | |
}, | |
options)); | |
}, | |
destroy: function (model, id, options) { | |
var data = {}; | |
data = { | |
id: id | |
}; | |
$.ajaxq("titan", $.extend({ | |
url: $.controller.defaults.url + "/" + model + "?" + $.serialize(data), | |
type: "DELETE" | |
}, | |
options)); | |
}, | |
update: function (model, obj, options) { | |
var data = {}; | |
data = obj; | |
$.ajaxq("titan", $.extend({ | |
url: $.controller.defaults.url + "/" + model, | |
data: $.serialize(data), | |
contentType: "application/json", | |
type: "PUT" | |
}, | |
options)); | |
}, | |
retrieve: function (model, conditions, options) { | |
var that = this; | |
var data = {}; | |
if (conditions && conditions != {}) { | |
data = $.serialize(conditions); | |
} | |
$.ajaxq("titan", $.extend({ | |
url: $.controller.defaults.url + "/" + model, | |
contentType: "application/json", | |
dataType: "json", | |
type: "GET", | |
data: data | |
}, | |
options)); | |
}, | |
count: 0 | |
}; | |
$.extend($.controller.array.prototype, { | |
root: "", | |
page: function (value) { | |
if (value !== undefined) { | |
this._page = value; | |
this.retrieve(); | |
} | |
return this._page; | |
}, | |
create: function (obj) { | |
var that = this; | |
var defaults = { | |
autoRetrieve: true, | |
complete: function () {}, | |
retrieveComplete: function () {}, | |
templateComplete: function () {} | |
}; | |
options = $.extend(defaults, options); | |
$.controller.create(that.model, obj, { | |
success: function (data) { | |
var tpl_complete = function () { | |
options.templateComplete.call(this, data); | |
}; | |
that.templateComplete = tpl_complete; | |
if (options.autoRetrieve) { | |
that.retrieve({}, | |
{ | |
success: options.retrieveComplete | |
}); | |
} | |
options.complete.call(this, data); | |
} | |
}); | |
}, | |
destroy: function (id, options) { | |
var that = this; | |
var defaults = { | |
autoRetrieve: true, | |
complete: function () {}, | |
retrieveComplete: function () {}, | |
templateComplete: function () {} | |
}; | |
options = $.extend(defaults, options); | |
$.controller.destroy(that.model, id, { | |
success: function (data) { | |
var tpl_complete = function () { | |
options.templateComplete.call(this, data); | |
}; | |
that.templateComplete = tpl_complete; | |
if (options.autoRetrieve) { | |
that.retrieve({}, | |
{ | |
success: options.retrieveComplete | |
}); | |
} | |
options.complete.call(this, data); | |
} | |
}); | |
}, | |
update: function (obj, options) { | |
var that = this; | |
var defaults = { | |
autoRetrieve: true, | |
complete: function () {}, | |
retrieveComplete: function () {}, | |
templateComplete: function () {} | |
}; | |
options = $.extend(defaults, options); | |
$.controller.update(that.model, obj, { | |
success: function (data) { | |
var tpl_complete = function () { | |
options.templateComplete.call(this, data); | |
}; | |
that.templateComplete = tpl_complete; | |
if (options.autoRetrieve) { | |
that.retrieve({}, | |
{ | |
success: options.retrieveComplete | |
}); | |
} | |
options.complete.call(this, data); | |
} | |
}); | |
}, | |
retrieve: function (conditions, opts) { | |
var that = this; | |
if (!conditions) { | |
conditions = {}; | |
} | |
if (!opts) { | |
opts = {}; | |
} | |
function onSuccess(data) { | |
if (opts.success) { | |
opts.success.call(this, data); | |
} | |
that.count = parseInt(data.count); | |
data = data.items; | |
that._last_id = undefined; | |
var found = false; | |
if (that._last_id) { | |
$(data).each(function () { | |
if (that._last_id == this.id) { | |
found = true; | |
$(that).valueForKey("selection", this); | |
return false; | |
} | |
}); | |
if (!found && data.length > 0) { | |
$(that).valueForKey("selection", data[0]); | |
} | |
} else { | |
$.willChangeValueForKey(that, "selection"); | |
that.selection = undefined; | |
$.didChangeValueForKey(that, "selection"); | |
} | |
if (that.paginating) { | |
var extra = that.overlap * (that.count / that.perPage); | |
var total = that.count + extra; | |
that.pages = Math.round((total / that.perPage) + 0.5); | |
if (((that.pages - 1) * that.perPage) - (that.overlap * (that.pages - 2)) == that.count && that.pages > 1) { | |
that.pages = that.pages - 1; | |
} | |
that.offset = (that._page - 1) * (that.perPage - that.overlap); | |
$.fn.rearrange.offset = that.offset; | |
$(that.paginate.selector).pager(that); | |
} | |
$(that).valueForKey("contents", data); | |
} | |
if (that.master) { | |
var selection = $(that.master).valueForKey("selection"); | |
if (selection) { | |
if (that.master_last_id != $(selection).valueForKey("id")) { | |
that._page = 1; | |
} | |
conditions[that.attr] = $(selection).valueForKey("id"); | |
that.master_last_id = $(selection).valueForKey("id"); | |
} else { | |
$(that).valueForKey("contents", []); | |
return; | |
} | |
} | |
if ($(that).valueForKey("selection") !== undefined) { | |
that._last_id = $(that).valueForKeyPath("selection.id"); | |
} | |
conditions = $.extend(this.conditions, conditions); | |
if (this.paginating) { | |
that.offset = (that._page - 1) * (that.perPage - that.overlap); | |
conditions['limit'] = that.perPage; | |
conditions['offset'] = that.offset; | |
$.controller.retrieve(that.model, conditions, { | |
success: onSuccess | |
}); | |
} else { | |
$.controller.retrieve(that.model, conditions, { | |
success: onSuccess | |
}); | |
} | |
} | |
}); | |
})(jQuery); | |
(function ($) { | |
$.template = function (root, controller, options) { | |
var tpl = this; | |
var defaults = {}; | |
tpl.root = root; | |
tpl.pristine = $(root).cloneTemplate(true)[0]; | |
tpl.contents = []; | |
tpl.controller = controller; | |
this.options = $.extend(defaults, options); | |
$(tpl).observe("contents", function () { | |
tpl.render(); | |
}); | |
$(this).connect("contents", controller, "contents"); | |
} | |
$.template.prefix = "ti_"; | |
$.template.defaultRender = function (elem, data) { | |
$(elem).data("data", data); | |
if ($(elem).data("format") && !$(elem).data("formatExtend")) { | |
return $(elem).data("format").call(this, elem, data); | |
} else { | |
if ($(elem).data("formatExtend")) { | |
$(elem).data("formatExtend").call(this, elem, data); | |
} | |
var classes = elem.className.split(/\s+/); | |
var prefix = new RegExp("^" + $.template.prefix); | |
for (var i = 0; i < classes.length; i++) { | |
if (prefix.test(classes[i])) { | |
var curData = data[classes[i].replace(prefix, "")]; | |
if (curData != undefined) { | |
if (curData.constructor == Array) { | |
var tmp = $("<div></div>"); | |
$(curData).each(function () { | |
$(tmp).append($.visit($(elem).cloneTemplate(true)[0], this, $.template.defaultRender)); | |
}); | |
$(elem).empty(); | |
$(elem).append($(tmp).contents()); | |
return false; | |
} else { | |
var content = curData; | |
if (/opt_truncate_/.test(classes)) { | |
var flat = classes.toString(); | |
var truncLimit = flat.match(/opt_truncate_\d+/i); | |
truncLimit = truncLimit[0].replace(/opt_truncate_/i, ""); | |
content = content.trunc(truncLimit); | |
} | |
if (/opt_text/.test(classes)) { | |
$(elem).text(content); | |
} else if (/opt_append/.test(classes)) { | |
$(elem).append(content); | |
} else if (/opt_prepend/.test(classes)) { | |
$(elem).prepend(content); | |
} else if (!/opt_no_html/.test(classes)) { | |
$(elem).html(content); | |
} | |
return true; | |
} | |
} | |
} | |
} | |
return true; | |
} | |
}, | |
$.template.prototype = { | |
deactivate: function (root) { | |
if (this.children) { | |
$(this.children).each(function () { | |
this.deactivate(false); | |
}); | |
} | |
if (!root) { | |
$(this).disconnect("contents", this.controller, "contents"); | |
delete this.controller; | |
} | |
}, | |
render: function () { | |
var tpl = this; | |
var contents = $(tpl).valueForKey("contents"); | |
if (contents) { | |
$(tpl.root).empty(); | |
$(contents).each(function (i) { | |
$(tpl.root).append($.visit($(tpl.pristine).cloneTemplate(true)[0], this, $.template.defaultRender)); | |
}); | |
} | |
if (this.options.success) { | |
this.options.success(); | |
} | |
if (tpl.controller.templateComplete) { | |
tpl.controller.templateComplete.call(this); | |
} | |
} | |
} | |
$.visit = function (root, data, fn) { | |
var func, start, current, next = null; | |
current = start = root; | |
do { | |
if (current.nodeType == 1) { | |
if (fn.call(this, current, data)) { | |
next = current.firstChild || current.nextSibling; | |
} else { | |
next = current.nextSibling; | |
} | |
} else { | |
next = current.firstChild || current.nextSibling; | |
} | |
var tmp = current; | |
if (!next) { | |
var tmp = current; | |
do { | |
next = tmp.parentNode || start; | |
if (next == start) break; | |
tmp = next; | |
next = next.nextSibling; | |
} while (!next); | |
} | |
current = next; | |
} while (current != start); | |
return $(start).contents(); | |
} | |
$.fn.cloneTemplate = function (events) { | |
var ret = $(this).clone(events); | |
var clone = ret.find("*").andSelf(); | |
$(this).find("*").andSelf().each(function (i) { | |
if (this.nodeType == 3) return; | |
var format = $.data(this, "format"); | |
if (format) { | |
$.data(clone[i], "format", format); | |
} | |
var formatExtend = $.data(this, "formatExtend"); | |
if (formatExtend) { | |
$.data(clone[i], "formatExtend", formatExtend); | |
} | |
}); | |
return ret; | |
} | |
$.fn.format = function (fn) { | |
return $(this).data("format", fn); | |
} | |
$.fn.formatExtend = function (fn) { | |
return $(this).data("formatExtend", fn); | |
} | |
$.fn.template = function (controller, options) { | |
return this.each(function () { | |
$(this).data("template", new $.template(this, controller, options)) | |
}); | |
} | |
})(jQuery); | |
(function ($) { | |
$.fillIn = function (obj, data) { | |
obj = $.extend({}, | |
obj); | |
for (attr in obj) { | |
if (obj[attr].constructor == Array) { | |
$(obj[attr]).each(function () { | |
obj[attr] = $.fillIn(obj[attr], data); | |
}); | |
} else if (typeof obj[attr] == "object") { | |
obj[attr] = $.fillIn(obj[attr], data); | |
} else if (typeof obj[attr] == "string") { | |
obj[attr] = obj[attr].replace(/{([^{}]*)}/g, function (tag, name) { | |
var value = data[name]; | |
return typeof value === 'string' || typeof value === 'number' ? value : tag; | |
}); | |
} | |
} | |
return obj; | |
} | |
})(jQuery); | |
(function ($) { | |
$.fn.hasData = function (key, value) { | |
var returnVal = false; | |
var curData = $(this).data("data"); | |
if (curData) { | |
$.each(curData, function (objKey, objVal) { | |
if (value) { | |
if (key == objKey && value == objVal) { | |
returnVal = true; | |
} | |
} else { | |
if (key == objKey && objVal != "") { | |
returnVal = true; | |
} | |
} | |
}); | |
} | |
return returnVal; | |
} | |
})(jQuery); | |
function date(format, timestamp) { | |
var a, jsdate = ((typeof(timestamp) == 'undefined') ? new Date() : (typeof(timestamp) == 'number') ? new Date(timestamp * 1000) : new Date(timestamp)); | |
var pad = function (n, c) { | |
if ((n = n + "").length < c) { | |
return new Array(++c - n.length).join("0") + n; | |
} else { | |
return n; | |
} | |
}; | |
var txt_weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; | |
var txt_ordin = { | |
1: "st", | |
2: "nd", | |
3: "rd", | |
21: "st", | |
22: "nd", | |
23: "rd", | |
31: "st" | |
}; | |
var txt_months = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; | |
var f = { | |
d: function () { | |
return pad(f.j(), 2); | |
}, | |
D: function () { | |
var t = f.l(); | |
return t.substr(0, 3); | |
}, | |
j: function () { | |
return jsdate.getDate(); | |
}, | |
l: function () { | |
return txt_weekdays[f.w()]; | |
}, | |
N: function () { | |
return f.w() + 1; | |
}, | |
S: function () { | |
return txt_ordin[f.j()] ? txt_ordin[f.j()] : 'th'; | |
}, | |
w: function () { | |
return jsdate.getDay(); | |
}, | |
z: function () { | |
return (jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5 >> 0; | |
}, | |
W: function () { | |
var a = f.z(), | |
b = 364 + f.L() - a; | |
var nd2, nd = (new Date(jsdate.getFullYear() + "/1/1").getDay() || 7) - 1; | |
if (b <= 2 && ((jsdate.getDay() || 7) - 1) <= 2 - b) { | |
return 1; | |
} else { | |
if (a <= 2 && nd >= 4 && a >= (6 - nd)) { | |
nd2 = new Date(jsdate.getFullYear() - 1 + "/12/31"); | |
return date("W", Math.round(nd2.getTime() / 1000)); | |
} else { | |
return (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0); | |
} | |
} | |
}, | |
F: function () { | |
return txt_months[f.n()]; | |
}, | |
m: function () { | |
return pad(f.n(), 2); | |
}, | |
M: function () { | |
t = f.F(); | |
return t.substr(0, 3); | |
}, | |
n: function () { | |
return jsdate.getMonth() + 1; | |
}, | |
t: function () { | |
var n; | |
if ((n = jsdate.getMonth() + 1) == 2) { | |
return 28 + f.L(); | |
} else { | |
if (n & 1 && n < 8 || !(n & 1) && n > 7) { | |
return 31; | |
} else { | |
return 30; | |
} | |
} | |
}, | |
L: function () { | |
var y = f.Y(); | |
return (! (y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0; | |
}, | |
o: function () { | |
if (f.n() === 12 && f.W() === 1) { | |
return jsdate.getFullYear() + 1; | |
} | |
if (f.n() === 1 && f.W() >= 52) { | |
return jsdate.getFullYear() - 1; | |
} | |
return jsdate.getFullYear(); | |
}, | |
Y: function () { | |
return jsdate.getFullYear(); | |
}, | |
y: function () { | |
return (jsdate.getFullYear() + "").slice(2); | |
}, | |
a: function () { | |
return jsdate.getHours() > 11 ? "pm" : "am"; | |
}, | |
A: function () { | |
return f.a().toUpperCase(); | |
}, | |
B: function () { | |
var off = (jsdate.getTimezoneOffset() + 60) * 60; | |
var theSeconds = (jsdate.getHours() * 3600) + (jsdate.getMinutes() * 60) + jsdate.getSeconds() + off; | |
var beat = Math.floor(theSeconds / 86.4); | |
if (beat > 1000) beat -= 1000; | |
if (beat < 0) beat += 1000; | |
if ((String(beat)).length == 1) beat = "00" + beat; | |
if ((String(beat)).length == 2) beat = "0" + beat; | |
return beat; | |
}, | |
g: function () { | |
return jsdate.getHours() % 12 || 12; | |
}, | |
G: function () { | |
return jsdate.getHours(); | |
}, | |
h: function () { | |
return pad(f.g(), 2); | |
}, | |
H: function () { | |
return pad(jsdate.getHours(), 2); | |
}, | |
i: function () { | |
return pad(jsdate.getMinutes(), 2); | |
}, | |
s: function () { | |
return pad(jsdate.getSeconds(), 2); | |
}, | |
u: function () { | |
return pad(jsdate.getMilliseconds() * 1000, 6); | |
}, | |
I: function () { | |
var DST = (new Date(jsdate.getFullYear(), 6, 1, 0, 0, 0)); | |
DST = DST.getHours() - DST.getUTCHours(); | |
var ref = jsdate.getHours() - jsdate.getUTCHours(); | |
return ref != DST ? 1 : 0; | |
}, | |
O: function () { | |
var t = pad(Math.abs(jsdate.getTimezoneOffset() / 60 * 100), 4); | |
if (jsdate.getTimezoneOffset() > 0) t = "-" + t; | |
else t = "+" + t; | |
return t; | |
}, | |
P: function () { | |
var O = f.O(); | |
return (O.substr(0, 3) + ":" + O.substr(3, 2)); | |
}, | |
Z: function () { | |
var t = -jsdate.getTimezoneOffset() * 60; | |
return t; | |
}, | |
c: function () { | |
return f.Y() + "-" + f.m() + "-" + f.d() + "T" + f.h() + ":" + f.i() + ":" + f.s() + f.P(); | |
}, | |
r: function () { | |
return f.D() + ', ' + f.d() + ' ' + f.M() + ' ' + f.Y() + ' ' + f.H() + ':' + f.i() + ':' + f.s() + ' ' + f.O(); | |
}, | |
U: function () { | |
return Math.round(jsdate.getTime() / 1000); | |
} | |
}; | |
return format.replace(/[\\]?([a-zA-Z])/g, function (t, s) { | |
if (t != s) { | |
ret = s; | |
} else if (f[s]) { | |
ret = f[s](); | |
} else { | |
ret = s; | |
} | |
return ret; | |
}); | |
} | |
function relative_time(time_value) { | |
time_value = new Date(time_value * 1000); | |
var parsed_date = Date.parse(time_value); | |
var relative_to = (arguments.length > 1) ? arguments[1] : new Date(); | |
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000); | |
if (delta < 60) { | |
return 'less than a minute ago'; | |
} else if (delta < 120) { | |
return 'about a minute ago'; | |
} else if (delta < (45 * 60)) { | |
return (parseInt(delta / 60)).toString() + ' minutes ago'; | |
} else if (delta < (90 * 60)) { | |
return 'about an hour ago'; | |
} else if (delta < (24 * 60 * 60)) { | |
return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago'; | |
} else if (delta < (48 * 60 * 60)) { | |
return '1 day ago'; | |
} else { | |
return (parseInt(delta / 86400)).toString() + ' days ago'; | |
} | |
}(function ($) { | |
$.formatDate = function (format, prop, tzoffset) { | |
return function (elem, data) { | |
var ca = $(data).valueForKey(prop); | |
if (ca == undefined || ca == "") { | |
$(elem).html(""); | |
} else { | |
var m = ca.match(/(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/); | |
var t = new Date(m[1], m[2] - 1, m[3], m[4], m[5], m[6]); | |
var tz = 0; | |
if (tzoffset) { | |
tz = t.getTimezoneOffset() * 60; | |
} | |
t = (t.getTime() * 0.001) - tz; | |
if (format == "relative") { | |
$(elem).html(relative_time(t)); | |
} else { | |
$(elem).html(date(format, t)); | |
} | |
} | |
} | |
} | |
$.fn.formatDate = function (format, prop, tzoffset) { | |
return $(this).format($.formatDate(format, prop, tzoffset)); | |
} | |
function number_format(number, decimals, dec_point, thousands_sep) { | |
var n = number, | |
prec = decimals, | |
dec = dec_point, | |
sep = thousands_sep; | |
n = !isFinite(+n) ? 0 : +n; | |
prec = !isFinite(+prec) ? 0 : Math.abs(prec); | |
sep = sep == undefined ? ',' : sep; | |
var s = n.toFixed(prec), | |
abs = Math.abs(n).toFixed(prec), | |
_, i; | |
if (abs > 1000) { | |
_ = abs.split(/\D/); | |
i = _[0].length % 3 || 3; | |
_[0] = s.slice(0, i + (n < 0)) + _[0].slice(i).replace(/(\d{3})/g, sep + '$1'); | |
s = _.join(dec || '.'); | |
} else { | |
s = abs.replace('.', dec_point); | |
} | |
return s; | |
} | |
$.fn.formatNumber = function (number, options) { | |
var defaults = { | |
decimals: 0, | |
decPoint: ".", | |
thousandsSep: "" | |
}; | |
var opts = $.extend(defaults, options); | |
return $(this).format(function (elem, data) { | |
var val = $(data).valueForKey(number); | |
decimals = opts.decimals; | |
decPoint = opts.decPoint; | |
thousandsSep = opts.thousandsSep; | |
if (val == undefined || val == "") { | |
$(elem).html(""); | |
} else { | |
$(elem).html(number_format(val, decimals, decPoint, thousandsSep)); | |
} | |
}); | |
} | |
$.fn.formatLink = function (text, href, options) { | |
var defaults = { | |
title: "", | |
className: "", | |
target: "" | |
}; | |
return $(this).format(function (elem, data) { | |
var opts = $.extend(defaults, { | |
text: text, | |
href: href | |
}, | |
options); | |
opts = $.fillIn(opts, data); | |
$(elem).text(opts.text); | |
$(elem).attr("href", opts.href); | |
if (opts.title != "") { | |
$(elem).attr("title", opts.title); | |
} | |
if (opts.className != "") { | |
$(elem).addClass(opts.className); | |
} | |
if (opts.target != "") { | |
$(elem).attr("target", opts.target); | |
} | |
}); | |
} | |
$.fn.formatForm = function (controller, options) { | |
return $(this).format(function (elem, data) { | |
$(elem).submit(function (event) { | |
event.preventDefault(); | |
var data = $(elem).serialize(); | |
if (options) { | |
data = data + "&" + $.serialize(options); | |
} | |
$.controller.create(false, data, { | |
success: function () { | |
controller.retrieve(); | |
} | |
}); | |
}); | |
}); | |
} | |
$.objCount = function (obj) { | |
var count = 0; | |
for (k in obj) if (obj.hasOwnProperty(k)) count++; | |
return count; | |
} | |
$.fn.objCount = function (obj) { | |
return $.objCount($(this)); | |
} | |
$.ajaxq = function (queue, options) { | |
if (typeof document.ajaxq == "undefined") document.ajaxq = { | |
q: {}, | |
r: null | |
}; | |
if (typeof document.ajaxq.q[queue] == "undefined") document.ajaxq.q[queue] = []; | |
if (typeof options != "undefined") { | |
var optionsCopy = {}; | |
for (var o in options) optionsCopy[o] = options[o]; | |
options = optionsCopy; | |
var originalCompleteCallback = options.complete; | |
options.complete = function (request, status) { | |
document.ajaxq.q[queue].shift(); | |
document.ajaxq.r = null; | |
if (originalCompleteCallback) originalCompleteCallback(request, status); | |
if (document.ajaxq.q[queue].length > 0) document.ajaxq.r = jQuery.ajax(document.ajaxq.q[queue][0]); | |
}; | |
document.ajaxq.q[queue].push(options); | |
if (document.ajaxq.q[queue].length == 1) document.ajaxq.r = jQuery.ajax(options); | |
} else { | |
if (document.ajaxq.r) { | |
document.ajaxq.r.abort(); | |
document.ajaxq.r = null; | |
} | |
document.ajaxq.q[queue] = []; | |
} | |
} | |
})(jQuery); | |
function truncate(limit, post) { | |
if (!limit) { | |
post = 10; | |
} | |
if (!post) { | |
post = "..."; | |
} | |
var s = this.toString(); | |
if (s.length > limit) { | |
var newS = s.slice(0, limit); | |
var newLimit = newS.lastIndexOf(" "); | |
if (newLimit == -1) { | |
newLimit = limit; | |
} | |
s = s.slice(0, newLimit) + post; | |
} | |
return s; | |
} | |
String.prototype.trunc = truncate; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment