diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2013-09-27 11:35:27 +0300 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2013-10-04 13:48:15 +0300 |
commit | 4a9a64f191d32130d2e86eacfaf0cf9e1bdf4c64 (patch) | |
tree | d2e05eda0f2e75e590507cbbd0591add5c78e56d /web | |
parent | 021bf1538afb8c8a80ed3252f30f276653d06900 (diff) | |
download | aconf-4a9a64f191d32130d2e86eacfaf0cf9e1bdf4c64.tar.bz2 aconf-4a9a64f191d32130d2e86eacfaf0cf9e1bdf4c64.tar.xz |
web client: multi-checkbox widget for reference sets
Diffstat (limited to 'web')
-rw-r--r-- | web/client.js | 197 |
1 files changed, 150 insertions, 47 deletions
diff --git a/web/client.js b/web/client.js index a0449c9..2ec122b 100644 --- a/web/client.js +++ b/web/client.js @@ -45,6 +45,13 @@ $(function() { return res; } + function escape(name) { + if (!_.isString(name)) return String(name); + name = name.replace(/([\\\/])/g, "\\$1"); + if (isNaN(Number(name))) return name; + return "\\" + name; + } + function join() { var arg = _.toArray(arguments); if (arg.length == 1) return arg[0]; @@ -52,21 +59,18 @@ $(function() { var path = arg.shift(); var name = arg.shift(); - if (_.isString(name)) { - name = name.replace(/([\\\/])/g, "\\$1"); - if (!isNaN(Number(name))) name = "\\" + name; - } - arg.unshift((path == "/" ? "" : path) + "/" + name); + arg.unshift((path == "/" ? "" : path) + "/" + escape(name)); return join.apply(undefined, arg); } - function isRealSubordinate(p1, p2) { - return !p1.indexOf(p2 + "/"); - } - - function isSubordinate(p1, p2) { - return p1 == p2 || isRealSubordinate(p1, p2); + function isSubordinate(p1, p2, real) { + p1 = split(p1); + p2 = split(p2); + if (real && p1.length <= p2.length) return false; + for (var i = 0; i < p2.length; i++) + if (p1[i] != p2[i]) return false; + return true; } function isTreeNode(meta) { @@ -114,8 +118,15 @@ $(function() { data.get = function(name, valid) { var p = join(path, name); - return (!valid && p in invalid) ? - invalid[p][0] : data.data[index(name)]; + if (!valid && p in invalid) return invalid[p][0]; + + if (data.meta.type == "set") { + return _.contains( + data.data, name + ) ? name : null; + } + + return data.data[index(name)]; }; data.status = function(name) { @@ -156,7 +167,7 @@ $(function() { _.each( _.keys(invalid), function(p) { - if (isRealSubordinate(p, mpath)) + if (isSubordinate(p, mpath, true)) delete invalid[p]; } ); @@ -166,10 +177,13 @@ $(function() { } function validate() { + var del = newValue == null; + var set = data.meta.type == "set"; + var options; - if (newValue != null) + if (!del) options = { - type: "PUT", + type: set ? "POST" : "PUT", data: JSON.stringify(newValue) }; else if (data.get(name, true) != null) @@ -185,7 +199,9 @@ $(function() { return; } - objRequest(mpath, options).done(function() { + objRequest( + set && !del ? path : mpath, options + ).done(function() { if (!(mpath in changed)) changed[mpath] = value; if (!tn && newValue == changed[mpath]) @@ -195,32 +211,40 @@ $(function() { _.each( _.keys(changed), function(p) { - if (isRealSubordinate(p, mpath)) + if (isSubordinate(p, mpath, true)) delete changed[p]; } ); - data.data[index(name)] = npv; - - if (tn) query(mpath).done(function(data) { - if (mpath in invalid && - data.meta.type == "model") - _.each( - data.meta.fields, - function(field) { - var mmpath = join( - mpath, field.name - ); - if (field.required && - !(mmpath in invalid) && - data.get( - field.name - ) == null) - invalid[mmpath] = [ - null - ]; - }); - resolve(); - }).fail(reject); + + if (!set) data.data[index(name)] = npv; + else if (del) + data.data.splice( + data.data.indexOf(name), 1 + ); + else data.data.push(name); + + if (tn && !set) + query(mpath).done(function(data) { + + if (mpath in invalid && + data.meta.type == "model") + _.each( + data.meta.fields, + function(field) { + var mmpath = join( + mpath, field.name + ); + if (field.required && + !(mmpath in invalid) && + data.get( + field.name + ) == null) + invalid[mmpath] = [ + null + ]; + }); + resolve(); + }).fail(reject); else resolve(); @@ -238,6 +262,10 @@ $(function() { return def; }; + data.add = function(name) { + return data.set(name, name); + }; + data.delete = function(name) { var def = $.Deferred(); function resolve(txnValid) { def.resolve(txnValid); } @@ -257,7 +285,9 @@ $(function() { var length = data.data.length; data.set(name, null).done(function(txnValid) { - if (isTreeNode(data.meta)) { + if (isTreeNode(data.meta) && + data.meta.type != "set") { + delete changed[join(path, name)]; changed[path] = path; @@ -607,7 +637,8 @@ $(function() { }); else _.each(data.data, function(value, name) { - if (_.isArray(data.data)) name++; + if (data.meta.type == "set") name = data.data[name]; + else if (_.isArray(data.data)) name++; self.renderCollectionMember(name, data.meta); }); }; @@ -687,16 +718,23 @@ $(function() { }; - var Vertical = Object.create(Inline); - - Vertical.createEl = function() { return $("<div>"); }; + var HeaderInline = Object.create(Inline); - Vertical.wrap = function() { return $("<div>").html(this.el); }; + HeaderInline.createEl = function() { return $("<div>"); }; - Vertical.render = function(data, meta) { + HeaderInline.render = function(data, meta) { this.el.append( $("<h" + this.level + ">").text(data.meta["ui-name"]) ); + }; + + + var Vertical = Object.create(HeaderInline); + + Vertical.wrap = function() { return $("<div>").html(this.el); }; + + Vertical.render = function(data, meta) { + _.bind(HeaderInline.render, this)(data, meta); if (!isTreeNode(data.meta)) return this.el.append(JSON.stringify(data)); @@ -791,6 +829,70 @@ $(function() { }; + var CheckBoxes = Object.create(HeaderInline); + + CheckBoxes.requestData = function(value, meta) { + var def = $.Deferred(); + Inline.requestData(value, meta).done(function(data, meta) { + txnMgr.query(data.meta.members.scope).done(function(sdata) { + meta.primitive = sdata.meta.type == "set"; + meta.choice = meta.primitive ? + _.values(sdata.data) : _.keys(sdata.data); + def.resolve(data, meta); + }); + }); + return def; + }; + + CheckBoxes.render = function(data, meta) { + _.bind(HeaderInline.render, this)(data, meta); + + var table = $("<table>"); + this.el.append(table); + + var self = this; + + _.each(meta.choice, function(choice) { + var ec = meta.primitive ? escape(choice) : choice; + + var cbox = $("<input>").attr({ + type: "checkbox", + checked: _.contains(data.data, ec) + }); + + var row = $("<tr>"); + row.append($("<td>").html(cbox)); + + var item = $("<td>"); + if (meta.primitive) item.text(choice); + else item.html( + Link.staticRender( + join(data.meta.members.scope, choice) + ).text(choice) + ); + row.append(item); + + function setStatus() { + self.setElStatus(row, data.status(ec)); + } + setStatus(); + + cbox.change(function() { + ( + cbox.is(":checked") ? + data.add(ec) : + data.delete(ec) + ).done(function(txnValid) { + setStatus(); + statusBar.validationReady(txnValid); + }); + }); + + table.append(row); + }); + }; + + var Reference = Object.create(ComboBox); Reference.init = function( @@ -843,6 +945,7 @@ $(function() { var widgets = { boolean: CheckBox, + checkboxes: CheckBoxes, combobox: ComboBox, field: Field, inline: Vertical, |