diff options
Diffstat (limited to 'web/widget/abstract/base.js')
-rw-r--r-- | web/widget/abstract/base.js | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/web/widget/abstract/base.js b/web/widget/abstract/base.js new file mode 100644 index 0000000..4a49e0b --- /dev/null +++ b/web/widget/abstract/base.js @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2012-2014 Kaarle Ritvanen + * See LICENSE file for license details + */ + +define(["acf2/dom", "jquery", "underscore"], function(dom, $, _) { + return { + extend: function(spec) { + var res = Object.create(this); + for (key in spec) res[key] = spec[key]; + res.base = this; + return res; + }, + + super: function() { + var args = _.toArray(arguments); + var cls = args.shift(); + var key = args.shift(); + return cls.base[key].apply(this, args); + }, + + new: function(data, name, meta, level, editable, removable) { + return Object.create(this).init( + data, name, meta, level, editable, removable + ); + }, + + init: function(data, name, meta, level, editable, removable) { + this.data = data; + this.name = name; + this.meta = meta; + this.level = level; + + var value = data.get(name); + var status = data.status(name); + + if (!editable || !meta.editable) { + var el = this.staticRender(value, meta); + if (el) { + dom.setStatus(el, status); + return el; + } + } + + this.makeEl(); + this.dynamic = meta.dynamic; + + var self = this; + + var request; + function handleRequest(req) { + request = req; + req.done(function(value, meta) { + if (req != request) return; + self.render(value, meta); + self.setStatus(status); + }); + } + + this.wrapped = this.wrap(); + this.visible = true; + + if (removable) { + var link = dom.href().click(function() { + data.delete(name).done(function(txnValid) { + $("#content").trigger("reload", [txnValid]); + }) + }).text("Delete"); + this.wrapped = dom.makeRow(this.wrapped); + if (this.wrapped.is("tr")) link = $("<td>").html(link); + this.wrapped.append(link); + } + + handleRequest(this.requestData(value, meta)); + + function validate() { + request.done(function(value) { + self.validate(value); + }); + } + + this.wrapped.on("start", function(event) { + if (data.status(name) == "invalid") validate(); + else self.setVisible(); + event.stopPropagation(); + }); + + this.wrapped.on("updated", function(event, field) { + if (self.dynamic) handleRequest(self.refreshData()); + if (!field || + self.dynamic || + (meta.condition && field in meta.condition)) + validate(); + event.stopPropagation(); + }); + + return this.wrapped; + }, + + makeEl: function() { this.el = this.createEl(); }, + + requestData: function(value, meta) { + return $.Deferred().resolve(value, meta); + }, + + refreshData: function() { + var def = $.Deferred(); + var self = this; + this.data.metaRequest(this.name).done(function(data) { + def.resolve(self.get(), data); + }); + return def; + }, + + wrap: function() { return this.el; }, + + showStatus: true, + + setStatus: function(status) { + if (this.el && this.showStatus) + dom.setStatus(this.statusEl(), status); + }, + + statusEl: function() { return this.el; }, + + setVisible: function() { + this.visible = this.data.match(this.meta.condition); + if (this.wrapped) + this.wrapped.trigger("setVisible", [this.visible]); + }, + + validate: function(value) { this.setVisible(); } + }; +}); |