diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-02-06 11:34:26 +0200 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-02-12 12:38:31 +0200 |
commit | cbd09bd37c87539889f6be688276a84bc57e5bf5 (patch) | |
tree | d116b74b81a9aebf1979a811cb910f069ce955db | |
parent | 62c559013516b74d59ef54ea316f8dc35ef2f477 (diff) | |
download | aconf-cbd09bd37c87539889f6be688276a84bc57e5bf5.tar.bz2 aconf-cbd09bd37c87539889f6be688276a84bc57e5bf5.tar.xz |
web client: use RequireJS for dependency management
-rw-r--r-- | web/client.html | 11 | ||||
-rw-r--r-- | web/client.js | 2558 | ||||
-rw-r--r-- | web/lib/require.js | 36 |
3 files changed, 1328 insertions, 1277 deletions
diff --git a/web/client.html b/web/client.html index da812f3..7cce3ca 100644 --- a/web/client.html +++ b/web/client.html @@ -9,15 +9,8 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="stylesheet" type="text/css" href="client.css"></link> - <script type="text/javascript" src="lib/underscore.js"></script> - <script type="text/javascript" src="lib/jquery.js"></script> - <script type="text/javascript" src="lib/jquery-bbq.js"></script> - <script type="text/javascript" src="lib/jquery-blockui.js"></script> - <script type="text/javascript" src="lib/jquery-ui/core.js"></script> - <script type="text/javascript" src="lib/jquery-ui/widget.js"></script> - <script type="text/javascript" src="lib/jquery-ui/mouse.js"></script> - <script type="text/javascript" src="lib/jquery-ui/sortable.js"></script> - <script type="text/javascript" src="client.js"></script> + <script type="text/javascript" data-main="client.js" src="lib/require.js"> + </script> </head> <body> <div id="status"> diff --git a/web/client.js b/web/client.js index f4fd89d..25cf988 100644 --- a/web/client.js +++ b/web/client.js @@ -3,1494 +3,1516 @@ * See LICENSE file for license details */ -$(function() { - $("#login").submit(function() { - - var statusBar = (function() { - function set(status, msg, mode) { - $("#status").prop("class", status); - $("#status p").text(msg); - $("#logout").prop("class", mode ? "hidden" : null); - $("#status div").prop("class", mode == "txn" ? null : "hidden"); - $("#commit").prop("disabled", status == "invalid"); - } - - function setError(msg, mode) { set("invalid", msg, mode); }; - - return { - reset: function() { set(null, ""); }, - setError: setError, - validationReady: function(txnValid) { - if (txnValid) - set("changed", "You have uncommitted changes", "txn"); - else setError("Some values need checking", "txn"); - } - } - })(); - - $.ajax("/login", { - type: "POST", - data: JSON.stringify({ - username: $("#username").val(), password: $("#password").val() - }) - }).done(function(data, status, xhr) { - - function split(path) { - var res = []; - while (path && path != "/") { - var comp = path.match(/^\/([^\\\/]|\\.)+/)[0]; - res.push(comp.substring(1)); - path = path.substring(comp.length); - } - 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]; - - var path = arg.shift(); - var name = arg.shift(); - - arg.unshift((path == "/" ? "" : path) + "/" + escape(name)); - - return join.apply(undefined, arg); - } - - 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 isList(meta) { - return _.contains(["list", "set"], meta.type); - } - - function isCollection(meta) { - return meta.type == "collection" || isList(meta); - } - - function isTreeNode(meta) { - return meta.type == "model" || isCollection(meta); - } - - - var txnMgr = (function(token, saveRequired) { - var txn, changed, invalid; - - function reset() { - txn = null; - changed = {}; - invalid = {}; +requirejs.config({ + baseUrl: "lib", + shim: { + underscore: {exports: "_"}, + "jquery-bbq": {deps: ["jquery"]}, + "jquery-blockui": {deps: ["jquery"]}, + "jquery-ui/core": {deps: ["jquery"]}, + "jquery-ui/mouse": {deps: ["jquery-ui/widget"]}, + "jquery-ui/sortable": {deps: ["jquery-ui/core", "jquery-ui/mouse"]}, + "jquery-ui/widget": {deps: ["jquery"]}, + } +}); + +require( + [ + "jquery", + "underscore", + "jquery-bbq", + "jquery-blockui", + "jquery-ui/sortable" + ], + function($, _) { + $("#login").submit(function() { + + var statusBar = (function() { + function set(status, msg, mode) { + $("#status").prop("class", status); + $("#status p").text(msg); + $("#logout").prop("class", mode ? "hidden" : null); + $("#status div").prop("class", mode == "txn" ? null : "hidden"); + $("#commit").prop("disabled", status == "invalid"); } - reset(); - function isValid() { return !(_.size(invalid)); } + function setError(msg, mode) { set("invalid", msg, mode); }; - function request(url, options) { - options = options || {}; - options.headers = {"X-ACF-Auth-Token": token}; - if (txn) options.headers["X-ACF-Transaction-ID"] = txn; - if (options.data != undefined) - options.data = JSON.stringify(options.data); - return $.ajax(url, options); + return { + reset: function() { set(null, ""); }, + setError: setError, + validationReady: function(txnValid) { + if (txnValid) + set("changed", "You have uncommitted changes", "txn"); + else setError("Some values need checking", "txn"); + } } + })(); - function abort() { - request("/transaction", {type: "DELETE"}); - reset(); + $.ajax("/login", { + type: "POST", + data: JSON.stringify({ + username: $("#username").val(), password: $("#password").val() + }) + }).done(function(data, status, xhr) { + + function split(path) { + var res = []; + while (path && path != "/") { + var comp = path.match(/^\/([^\\\/]|\\.)+/)[0]; + res.push(comp.substring(1)); + path = path.substring(comp.length); + } + return res; } - - function objRequest(path, options) { - return request("/config" + path, options); + + function escape(name) { + if (!_.isString(name)) return String(name); + name = name.replace(/([\\\/])/g, "\\$1"); + if (isNaN(Number(name))) return name; + return "\\" + name; } - function exclusive(task) { - $.blockUI(); + function join() { + var arg = _.toArray(arguments); + if (arg.length == 1) return arg[0]; - var def = $.Deferred(); - function resolve(txnValid) { def.resolve(txnValid); } - function reject() { def.reject(); } + var path = arg.shift(); + var name = arg.shift(); - var tasks = _.filter( - _.pluck(_.values(invalid), 1), function(d) { - return d && d.state() == "pending"; - } - ); + arg.unshift((path == "/" ? "" : path) + "/" + escape(name)); - if (tasks.length) - tasks[0].always(function() { - exclusive(task).done(resolve).fail(reject); - }); - else task().always($.unblockUI).done(resolve).fail(reject); - - return def; + return join.apply(undefined, arg); + } + + 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 isList(meta) { + return _.contains(["list", "set"], meta.type); + } + + function isCollection(meta) { + return meta.type == "collection" || isList(meta); + } + + function isTreeNode(meta) { + return meta.type == "model" || isCollection(meta); } + - function query(path) { - var def = $.Deferred(); + var txnMgr = (function(token, saveRequired) { + var txn, changed, invalid; + + function reset() { + txn = null; + changed = {}; + invalid = {}; + } + reset(); - objRequest(path).done(function(data) { - if (isTreeNode(data.meta) && !_.size(data.data)) - data.data = isList(data.meta) ? [] : {}; + function isValid() { return !(_.size(invalid)); } - function index(name) { - return _.isArray(data.data) ? name - 1 : name; - } + function request(url, options) { + options = options || {}; + options.headers = {"X-ACF-Auth-Token": token}; + if (txn) options.headers["X-ACF-Transaction-ID"] = txn; + if (options.data != undefined) + options.data = JSON.stringify(options.data); + return $.ajax(url, options); + } + + function abort() { + request("/transaction", {type: "DELETE"}); + reset(); + } + + function objRequest(path, options) { + return request("/config" + path, options); + } - data.get = function(name, valid) { - var p = join(path, name); - if (!valid && p in invalid) return invalid[p][0]; + function exclusive(task) { + $.blockUI(); - if (data.meta.type == "set") { - return _.contains( - data.data, name - ) ? name : null; - } + var def = $.Deferred(); + function resolve(txnValid) { def.resolve(txnValid); } + function reject() { def.reject(); } - return data.data[index(name)]; - }; - - data.metaRequest = function(name) { - return request("/meta" + join(path, name)); - }; - - data.match = function(filter) { - if (!filter) return true; - return _.every(_.map(filter, function(values, key) { - return _.contains(values, data.data[key]); - })); - }; - - data.status = function(name) { - var p = name ? join(path, name) : path; - function scan(objs) { - return _.size(_.filter( - _.keys(objs), function(obj) { - return isSubordinate(obj, p); - } - )); + var tasks = _.filter( + _.pluck(_.values(invalid), 1), function(d) { + return d && d.state() == "pending"; } + ); + + if (tasks.length) + tasks[0].always(function() { + exclusive(task).done(resolve).fail(reject); + }); + else task().always($.unblockUI).done(resolve).fail(reject); + + return def; + } + + function query(path) { + var def = $.Deferred(); - if (scan(invalid)) return "invalid"; - if (scan(changed)) return "changed"; - return null; - }; - - data.validate = function() { - var valid = true; - if (data.meta.required) { - valid = _.size(data.data); - if (valid) delete invalid[path]; - else invalid[path] = [path]; + objRequest(path).done(function(data) { + if (isTreeNode(data.meta) && !_.size(data.data)) + data.data = isList(data.meta) ? [] : {}; + + function index(name) { + return _.isArray(data.data) ? name - 1 : name; } - return valid && isValid(); - }; - data.set = function(name, newValue) { - var def = $.Deferred(); - function reject(xhr) { def.reject(xhr); } + data.get = function(name, valid) { + var p = join(path, name); + if (!valid && p in invalid) return invalid[p][0]; - var mpath = join(path, name); + if (data.meta.type == "set") { + return _.contains( + data.data, name + ) ? name : null; + } - var value = data.get(name, true); - if (value == undefined) value = null; + return data.data[index(name)]; + }; + + data.metaRequest = function(name) { + return request("/meta" + join(path, name)); + }; + + data.match = function(filter) { + if (!filter) return true; + return _.every(_.map(filter, function(values, key) { + return _.contains(values, data.data[key]); + })); + }; + + data.status = function(name) { + var p = name ? join(path, name) : path; + function scan(objs) { + return _.size(_.filter( + _.keys(objs), function(obj) { + return isSubordinate(obj, p); + } + )); + } - var tn = _.isObject(newValue); - var npv = tn ? mpath : newValue; + if (scan(invalid)) return "invalid"; + if (scan(changed)) return "changed"; + return null; + }; + + data.validate = function() { + var valid = true; + if (data.meta.required) { + valid = _.size(data.data); + if (valid) delete invalid[path]; + else invalid[path] = [path]; + } + return valid && isValid(); + }; - function ignore(path) { - _.each(_.keys(invalid), function(p) { - if (isSubordinate(p, path)) - delete invalid[p]; - }); - } + data.set = function(name, newValue) { + var def = $.Deferred(); + function reject(xhr) { def.reject(xhr); } - function resolve() { - if (mpath in invalid && - invalid[mpath][1] == def) { - - var del = invalid[mpath][0] == null; + var mpath = join(path, name); + + var value = data.get(name, true); + if (value == undefined) value = null; - delete invalid[mpath]; - if (del) ignore(mpath); + var tn = _.isObject(newValue); + var npv = tn ? mpath : newValue; + + function ignore(path) { + _.each(_.keys(invalid), function(p) { + if (isSubordinate(p, path)) + delete invalid[p]; + }); } - - def.resolve(isValid()); - } - function validate() { - var del = newValue == null; - var set = data.meta.type == "set"; + function resolve() { + if (mpath in invalid && + invalid[mpath][1] == def) { + + var del = invalid[mpath][0] == null; - var options; - if (!del) - options = { - type: set ? "POST" : "PUT", - data: newValue - }; - else if (data.get(name, true) != null) - options = {type: "DELETE"}; - - if (!options) { - if (data.meta.type == "model" && - _.findWhere( - data.meta.fields, {name: name} - ).required) - def.reject("Required value not set"); - else resolve(); - return; + delete invalid[mpath]; + if (del) ignore(mpath); + } + + def.resolve(isValid()); } - - objRequest( - set && !del ? path : mpath, options - ).done(function() { - if (!(mpath in changed)) - changed[mpath] = value; - if (!tn && newValue == changed[mpath]) - delete changed[mpath]; + + function validate() { + var del = newValue == null; + var set = data.meta.type == "set"; + + var options; + if (!del) + options = { + type: set ? "POST" : "PUT", + data: newValue + }; + else if (data.get(name, true) != null) + options = {type: "DELETE"}; + + if (!options) { + if (data.meta.type == "model" && + _.findWhere( + data.meta.fields, {name: name} + ).required) + def.reject("Required value not set"); + else resolve(); + return; + } - if (npv == null) - _.each( - _.keys(changed), - function(p) { - if (isSubordinate(p, mpath, true)) - delete changed[p]; - } - ); + objRequest( + set && !del ? path : mpath, options + ).done(function() { + if (!(mpath in changed)) + changed[mpath] = value; + if (!tn && newValue == changed[mpath]) + delete changed[mpath]; + + if (npv == null) + _.each( + _.keys(changed), + function(p) { + if (isSubordinate(p, mpath, true)) + delete changed[p]; + } + ); + + if (data.meta.type == "list" && del) + data.data.splice(name - 1, 1); + else if (!set) data.data[index(name)] = npv; + else if (del) + data.data.splice( + data.data.indexOf(name), 1 + ); + else data.data.push(name); + + data.validate(); + + if (data.meta.type == "model") + _.each( + data.meta.fields, function(field) { + if (field.condition && + field.condition[name] && + !_.contains( + field.condition[name], + newValue + )) + ignore( + join(path, field.name) + ); + } + ); + + if (tn && !set) + query(mpath).done(function(data) { + + if (mpath in invalid) { + if (data.meta.type == "model") + _.each( + data.meta.fields, + function(field) { + var mmpath = join( + mpath, + field.name + ); + if (field.required && + data.match( + field.condition + ) && + !(mmpath in invalid) && + (isCollection( + field + ) || data.get( + field.name + ) == null)) { + invalid[ + mmpath + ] = [ + null + ]; + } + }); + + else if (isCollection(data.meta) && + data.meta.required) + invalid[mpath] = [mpath]; + } + + resolve(); + }).fail(reject); + + else resolve(); + + }).fail(reject); + } + + var prevTask; + if (mpath in invalid) prevTask = invalid[mpath][1]; - if (data.meta.type == "list" && del) - data.data.splice(name - 1, 1); - else if (!set) data.data[index(name)] = npv; - else if (del) - data.data.splice( - data.data.indexOf(name), 1 - ); - else data.data.push(name); + invalid[mpath] = [npv, def]; - data.validate(); + if (prevTask) prevTask.always(validate); + else validate(); - if (data.meta.type == "model") + return def; + }; + + data.add = function(name) { + return data.set(name, name); + }; + + function adjustListIndex(oldIndex, newIndex) { + var opath = join(path, oldIndex); + var npath = join(path, newIndex); + _.each( + [changed, invalid], + function(map) { _.each( - data.meta.fields, function(field) { - if (field.condition && - field.condition[name] && - !_.contains( - field.condition[name], - newValue - )) - ignore( - join(path, field.name) - ); - } - ); - - if (tn && !set) - query(mpath).done(function(data) { - - if (mpath in invalid) { - if (data.meta.type == "model") - _.each( - data.meta.fields, - function(field) { - var mmpath = join( - mpath, - field.name - ); - if (field.required && - data.match( - field.condition - ) && - !(mmpath in invalid) && - (isCollection( - field - ) || data.get( - field.name - ) == null)) { - invalid[ - mmpath - ] = [ - null - ]; - } - }); - - else if (isCollection(data.meta) && - data.meta.required) - invalid[mpath] = [mpath]; - } + _.keys(map), + function(p) { + if (isSubordinate( + p, opath + )) { + map[npath + + p.substring( + opath.length + )] = map[p]; + delete map[p]; + } + }); + } + ); + } - resolve(); - }).fail(reject); - - else resolve(); - - }).fail(reject); + function adjustListIndices(start, end) { + var offset = start < end ? 1 : -1; + for (var i = start; i != end; i += offset) + adjustListIndex(i + offset, i); } - var prevTask; - if (mpath in invalid) prevTask = invalid[mpath][1]; + function _delete(name) { + var def = $.Deferred(); + var length = data.data.length; - invalid[mpath] = [npv, def]; + data.set(name, null).done(function(txnValid) { + if (isTreeNode(data.meta) && + data.meta.type != "set") { - if (prevTask) prevTask.always(validate); - else validate(); + delete changed[join(path, name)]; + changed[path] = path; - return def; - }; - - data.add = function(name) { - return data.set(name, name); - }; - - function adjustListIndex(oldIndex, newIndex) { - var opath = join(path, oldIndex); - var npath = join(path, newIndex); - _.each( - [changed, invalid], - function(map) { - _.each( - _.keys(map), - function(p) { - if (isSubordinate( - p, opath - )) { - map[npath + - p.substring( - opath.length - )] = map[p]; - delete map[p]; - } - }); - } - ); - } + if (data.meta.type == "list") + adjustListIndices(name, length); + } + def.resolve(txnValid); - function adjustListIndices(start, end) { - var offset = start < end ? 1 : -1; - for (var i = start; i != end; i += offset) - adjustListIndex(i + offset, i); - } + }).fail(function() { def.reject(); }); - function _delete(name) { - var def = $.Deferred(); - var length = data.data.length; + return def; + } - data.set(name, null).done(function(txnValid) { - if (isTreeNode(data.meta) && - data.meta.type != "set") { + data.delete = function(name) { + return exclusive(function() { + return _delete(name); + }); + }; - delete changed[join(path, name)]; - changed[path] = path; + data.move = function(oldIndex, newIndex) { + if (oldIndex == newIndex) + return $.Deferred().resolve(isValid()); - if (data.meta.type == "list") - adjustListIndices(name, length); - } - def.resolve(txnValid); + var value = data.get(oldIndex); + var length = data.data.length; - }).fail(function() { def.reject(); }); + return exclusive(function() { + var def = $.Deferred(); + function reject() { def.reject(); } - return def; - } + if (oldIndex > newIndex) oldIndex++; + else newIndex++; - data.delete = function(name) { - return exclusive(function() { - return _delete(name); - }); - }; + objRequest(path, {type: "POST", data: { + index: newIndex, + data: isTreeNode(data.meta.members) ? + join(path, oldIndex) : value + }}).done(function() { - data.move = function(oldIndex, newIndex) { - if (oldIndex == newIndex) - return $.Deferred().resolve(isValid()); + data.data.splice(newIndex - 1, 0, value); - var value = data.get(oldIndex); - var length = data.data.length; + adjustListIndices(length + 1, newIndex); + adjustListIndex(oldIndex, newIndex); - return exclusive(function() { - var def = $.Deferred(); - function reject() { def.reject(); } + data.delete(oldIndex) + .done(function(txnValid) { + def.resolve(txnValid); + }) + .fail(reject); - if (oldIndex > newIndex) oldIndex++; - else newIndex++; + }).fail(reject); - objRequest(path, {type: "POST", data: { - index: newIndex, - data: isTreeNode(data.meta.members) ? - join(path, oldIndex) : value - }}).done(function() { + return def; + }); + }; - data.data.splice(newIndex - 1, 0, value); + data.invoke = function(name) { + return objRequest(join(path, name), {type: "POST"}); + }; - adjustListIndices(length + 1, newIndex); - adjustListIndex(oldIndex, newIndex); + def.resolve(data); + }).fail(function() { def.reject(); }); + + return def; + } - data.delete(oldIndex) - .done(function(txnValid) { - def.resolve(txnValid); - }) - .fail(reject); + return { + start: function() { + var def = $.Deferred(); + if (txn && isValid() && !(_.size(changed))) abort(); - }).fail(reject); + if (txn) + def.resolve(); - return def; - }); - }; + else request("/transaction", {type: "POST"}) + .done(function(data, status, xhr) { + txn = xhr.getResponseHeader( + "X-ACF-Transaction-ID" + ); + def.resolve(); + }) + .fail(function() { def.reject(); }); - data.invoke = function(name) { - return objRequest(join(path, name), {type: "POST"}); - }; + return def; + }, - def.resolve(data); - }).fail(function() { def.reject(); }); - - return def; - } + commit: function() { + var def = $.Deferred(); + function reject(xhr) { def.reject(xhr); } + request( + "/transaction", {type: "PUT"} + ).done(function() { + reset(); + if (saveRequired) + request( + "/save", {type: "POST"} + ).done(function() { + def.resolve(); + }).fail(reject); + else def.resolve(); + }).fail(reject); + return def; + }, - return { - start: function() { - var def = $.Deferred(); - if (txn && isValid() && !(_.size(changed))) abort(); + abort: abort, - if (txn) - def.resolve(); + query: query, - else request("/transaction", {type: "POST"}) - .done(function(data, status, xhr) { - txn = xhr.getResponseHeader( - "X-ACF-Transaction-ID" - ); - def.resolve(); - }) - .fail(function() { def.reject(); }); + logout: function() { + return request("/login", {type: "DELETE"}); + } + }; + })( + xhr.getResponseHeader("X-ACF-Auth-Token"), + xhr.getResponseHeader("X-ACF-Save-Required") == "1" + ); + - return def; - }, - commit: function() { - var def = $.Deferred(); - function reject(xhr) { def.reject(xhr); } - request( - "/transaction", {type: "PUT"} - ).done(function() { - reset(); - if (saveRequired) - request( - "/save", {type: "POST"} - ).done(function() { - def.resolve(); - }).fail(reject); - else def.resolve(); - }).fail(reject); - return def; - }, + function formatError(msg, xhr) { + msg += " " + xhr.statusCode().status; + if (xhr.responseText) msg += ': ' + xhr.responseText; + return msg; + } - abort: abort, - query: query, + function href() { + return $("<a>").attr({href: "javascript:void(0);"}); + } - logout: function() { - return request("/login", {type: "DELETE"}); + function objectRef(value, el) { + el = el || href(); + if (value) { + el.click(function() { + $.bbq.pushState("#" + value); + }).text("Show"); } + return el; }; - })( - xhr.getResponseHeader("X-ACF-Auth-Token"), - xhr.getResponseHeader("X-ACF-Save-Required") == "1" - ); - - - - function formatError(msg, xhr) { - msg += " " + xhr.statusCode().status; - if (xhr.responseText) msg += ': ' + xhr.responseText; - return msg; - } - - - function href() { - return $("<a>").attr({href: "javascript:void(0);"}); - } - - function objectRef(value, el) { - el = el || href(); - if (value) { - el.click(function() { - $.bbq.pushState("#" + value); - }).text("Show"); + + function makeRow(el) { + if (el.is("td")) return $("<tr>").html(el); + return el; } - return el; - }; - function makeRow(el) { - if (el.is("td")) return $("<tr>").html(el); - return el; - } + function setStatus(el, status) { el.prop("class", status); } + - function setStatus(el, status) { el.prop("class", status); } + var Widget = { + 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); + }, - var Widget = { - extend: function(spec) { - var res = Object.create(this); - for (key in spec) res[key] = spec[key]; - res.base = this; - return res; - }, + new: function(data, name, meta, level, editable, removable) { + return Object.create(this).init( + data, name, meta, level, editable, removable + ); + }, - super: function() { - var args = _.toArray(arguments); - var cls = args.shift(); - var key = args.shift(); - return cls.base[key].apply(this, args); - }, + init: function(data, name, meta, level, editable, removable) { + this.data = data; + this.name = name; + this.meta = meta; + this.level = level; - 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) { - setStatus(el, status); - return el; + var value = data.get(name); + var status = data.status(name); + + if (!editable || !meta.editable) { + var el = this.staticRender(value, meta); + if (el) { + setStatus(el, status); + return el; + } } - } - this.makeEl(); - this.dynamic = meta.dynamic; + this.makeEl(); + this.dynamic = meta.dynamic; - var self = this; + 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); - }); - } + 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; + this.wrapped = this.wrap(); + this.visible = true; + + if (removable) { + var link = href().click(function() { + data.delete(name).done(function(txnValid) { + $("#content").trigger("reload", [txnValid]); + }) + }).text("Delete"); + this.wrapped = makeRow(this.wrapped); + if (this.wrapped.is("tr")) link = $("<td>").html(link); + this.wrapped.append(link); + } - if (removable) { - var link = href().click(function() { - data.delete(name).done(function(txnValid) { - $("#content").trigger("reload", [txnValid]); - }) - }).text("Delete"); - this.wrapped = makeRow(this.wrapped); - if (this.wrapped.is("tr")) link = $("<td>").html(link); - this.wrapped.append(link); - } + handleRequest(this.requestData(value, meta)); - handleRequest(this.requestData(value, meta)); + function validate() { + request.done(function(value) { + self.validate(value); + }); + } - 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("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(); + }); - 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; + }, - return this.wrapped; - }, + makeEl: function() { this.el = this.createEl(); }, - makeEl: function() { this.el = this.createEl(); }, + requestData: function(value, meta) { + return $.Deferred().resolve(value, meta); + }, - 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; + }, - 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; }, - wrap: function() { return this.el; }, + showStatus: true, - showStatus: true, + setStatus: function(status) { + if (this.el && this.showStatus) + setStatus(this.statusEl(), status); + }, - setStatus: function(status) { - if (this.el && this.showStatus) - setStatus(this.statusEl(), status); - }, + statusEl: function() { return this.el; }, - statusEl: function() { return this.el; }, + setVisible: function() { + this.visible = this.data.match(this.meta.condition); + if (this.wrapped) + this.wrapped.trigger("setVisible", [this.visible]); + }, - setVisible: function() { - this.visible = this.data.match(this.meta.condition); - if (this.wrapped) - this.wrapped.trigger("setVisible", [this.visible]); - }, + validate: function(value) { this.setVisible(); } + }; - validate: function(value) { this.setVisible(); } - }; + var Field = Widget.extend({ + init: function( + data, name, meta, level, editable, removable + ) { + this.editable = editable && meta.editable; - var Field = Widget.extend({ - init: function( - data, name, meta, level, editable, removable - ) { - this.editable = editable && meta.editable; + var el = this.super( + Field, + "init", + data, + name, + meta, + level, + editable, + removable + ); - var el = this.super( - Field, - "init", - data, - name, - meta, - level, - editable, - removable - ); + if (this.editable) + this.field.change(_.bind(this.validateChange, this)); + + return el; + }, - if (this.editable) - this.field.change(_.bind(this.validateChange, this)); - - return el; - }, - - staticRender: function(value, meta) { - return $("<td>").text(value); - }, - - makeEl: function() { - this.super(Field, "makeEl"); - if (!this.field) this.field = this.el; - }, - - createEl: function() { return $("<input>"); }, - - render: function(value, meta) { - this.field.attr({type: "text", value: value}); - }, - - wrap: function() { - var td = $("<td>"); - this.msg = $("<div>"); - td.append(this.msg); - td.append(this.el); - return td; - }, - - validate: function(value) { - this.super(Field, "validate", value); - if (!this.visible || !this.editable) return; - this.validateChange(); - }, - - validateChange: function() { - this.msg.text("[checking]"); - statusBar.setError("Validating changes", "validate"); - - var self = this; - - this.data.set(this.name, this.get()) - .done(function(txnValid) { - self.msg.empty() - self.setStatus(self.data.status(self.name)); - statusBar.validationReady(txnValid); - self.el.trigger("validated"); - - }) - .fail(function(xhr) { - if (_.isString(xhr)) self.msg.text(xhr); - - else if (xhr.statusCode().status == 422) - self.msg.html( - _.reduce( - _.map( - $.parseJSON(xhr.responseText), - _.escape - ), - function(a, b) { - return a + "<br/>" + b; - } - ) - ); - - else self.msg.text(formatError("Error", xhr)); - - self.setStatus("invalid"); - statusBar.validationReady(false); - }); - }, + staticRender: function(value, meta) { + return $("<td>").text(value); + }, - get: function() { - return this.editable ? ( - this.field.val() || null - ) : this.data.get(this.name); - } - }); + makeEl: function() { + this.super(Field, "makeEl"); + if (!this.field) this.field = this.el; + }, + createEl: function() { return $("<input>"); }, - var ComboBox = Field.extend({ - createEl: function() { return $("<select>"); }, + render: function(value, meta) { + this.field.attr({type: "text", value: value}); + }, + + wrap: function() { + var td = $("<td>"); + this.msg = $("<div>"); + td.append(this.msg); + td.append(this.el); + return td; + }, + + validate: function(value) { + this.super(Field, "validate", value); + if (!this.visible || !this.editable) return; + this.validateChange(); + }, - staticRender: function(value, meta) { - return this.super( - ComboBox, - "staticRender", - _.findWhere(meta.choice, {value: value})["ui-value"], - meta - ); - }, + validateChange: function() { + this.msg.text("[checking]"); + statusBar.setError("Validating changes", "validate"); - render: function(value, meta) { - var el = this.field.empty(); + var self = this; + + this.data.set(this.name, this.get()) + .done(function(txnValid) { + self.msg.empty() + self.setStatus(self.data.status(self.name)); + statusBar.validationReady(txnValid); + self.el.trigger("validated"); + + }) + .fail(function(xhr) { + if (_.isString(xhr)) self.msg.text(xhr); + + else if (xhr.statusCode().status == 422) + self.msg.html( + _.reduce( + _.map( + $.parseJSON(xhr.responseText), + _.escape + ), + function(a, b) { + return a + "<br/>" + b; + } + ) + ); + + else self.msg.text(formatError("Error", xhr)); + + self.setStatus("invalid"); + statusBar.validationReady(false); + }); + }, - function opt(value, ui_value, selected) { - el.append($("<option>").attr( - {value: value, selected: selected} - ).text(ui_value)); + get: function() { + return this.editable ? ( + this.field.val() || null + ) : this.data.get(this.name); } + }); - if (!meta.required) opt("", "(none)", value == null); - _.each( - meta.choice, - function(choice) { - var selected = value == choice.value; - if (choice.enabled || selected) - opt(choice.value, choice["ui-value"], selected); - } - ); - } - }); + var ComboBox = Field.extend({ + createEl: function() { return $("<select>"); }, - var CheckBox = Field.extend({ - staticRender: function(value, meta) { - return $("<td>").text(value ? "Yes" : "No"); - }, + staticRender: function(value, meta) { + return this.super( + ComboBox, + "staticRender", + _.findWhere(meta.choice, {value: value})["ui-value"], + meta + ); + }, - statusEl: function() { return this.el.parent(); }, + render: function(value, meta) { + var el = this.field.empty(); - render: function(value, meta) { - this.field.attr({type: "checkbox", checked: value}); - }, + function opt(value, ui_value, selected) { + el.append($("<option>").attr( + {value: value, selected: selected} + ).text(ui_value)); + } - get: function() { return this.field.is(":checked"); } - }); + if (!meta.required) opt("", "(none)", value == null); + _.each( + meta.choice, + function(choice) { + var selected = value == choice.value; + if (choice.enabled || selected) + opt(choice.value, choice["ui-value"], selected); + } + ); + } + }); - var Link = Widget.extend({ - staticRender: function(value, meta) { - return $("<td>").html(objectRef(value)); - }, + var CheckBox = Field.extend({ + staticRender: function(value, meta) { + return $("<td>").text(value ? "Yes" : "No"); + }, - createEl: href, + statusEl: function() { return this.el.parent(); }, - render: function(value, meta) { objectRef(value, this.el) }, + render: function(value, meta) { + this.field.attr({type: "checkbox", checked: value}); + }, - wrap: function() { return $("<td>").html(this.el); }, - - get: function() { return {}; } - }); + get: function() { return this.field.is(":checked"); } + }); - var Inline = Link.extend({ - init: function( - data, name, meta, level, editable, removable - ) { - return this.super( - Inline, - "init", - data, - name, - meta, - Math.min(6, level + 1), - editable, - removable - ); - }, + var Link = Widget.extend({ + staticRender: function(value, meta) { + return $("<td>").html(objectRef(value)); + }, - staticRender: function(value, meta) { return null; }, + createEl: href, - createEl: function() { return $("<div>"); }, + render: function(value, meta) { objectRef(value, this.el) }, - showStatus: false, - - requestData: function(value, meta) { - this.path = value; - return this.refreshData(); - }, - - refreshData: function() { - var def = $.Deferred(); - txnMgr.query(this.path).done(function(data) { - def.resolve(data, data.meta); - }); - return def; - }, + wrap: function() { return $("<td>").html(this.el); }, + + get: function() { return {}; } + }); - showHeading: true, - render: function(data, meta) { - if (this.showHeading) - this.el.html( - $("<h" + this.level + ">").text(meta["ui-name"]) + var Inline = Link.extend({ + init: function( + data, name, meta, level, editable, removable + ) { + return this.super( + Inline, + "init", + data, + name, + meta, + Math.min(6, level + 1), + editable, + removable ); - }, + }, - wrap: function() { return this.el; }, + staticRender: function(value, meta) { return null; }, - validate: function(data) { - this.super(Inline, "validate", data); + createEl: function() { return $("<div>"); }, + + showStatus: false, - if (this.data.match(this.meta.condition)) { - var valid = data.validate(); - this.setStatus(data.status()); - statusBar.validationReady(valid); - } - - if (this.fields) - _.each(this.fields, function(field) { - field.trigger("updated"); - }); - } - }); + requestData: function(value, meta) { + this.path = value; + return this.refreshData(); + }, + refreshData: function() { + var def = $.Deferred(); + txnMgr.query(this.path).done(function(data) { + def.resolve(data, data.meta); + }); + return def; + }, - var InlineFields = Inline.extend({ + showHeading: true, - render: function(data, meta) { - this.super(InlineFields, "render", data, meta); + render: function(data, meta) { + if (this.showHeading) + this.el.html( + $("<h" + this.level + ">").text(meta["ui-name"]) + ); + }, - this.appendAboveFields(data, meta); + wrap: function() { return this.el; }, - this.reqData = data; - var self = this; - - if (meta.type == "model") { - this.fields = {}; - _.each(meta.fields, function(field) { - if (field.visible) - self.fields[field.name] = self.renderField( - field.name, - field, - field["ui-name"], - true, - false - ); - }); + validate: function(data) { + this.super(Inline, "validate", data); - _.each(this.fields, function(f1, name) { - _.each(self.fields, function(f2) { - if (f1 != f2) - f1.on("validated", function(event) { - f2.trigger("updated", [name]); - event.stopPropagation(); - }); + if (this.data.match(this.meta.condition)) { + var valid = data.validate(); + this.setStatus(data.status()); + statusBar.validationReady(valid); + } + + if (this.fields) + _.each(this.fields, function(field) { + field.trigger("updated"); }); - }); - - _.each(this.fields, function(field) { - field.trigger("start"); - }); } - - else _.each(data.data, function(value, name) { - if (meta.type == "set") name = data.data[name]; - else if (_.isArray(data.data)) name++; - self.renderCollectionMember(name, meta); - }); + }); - this.appendBelowFields(data, meta); - }, - - appendAboveFields: function(data, meta) {}, - appendBelowFields: function(data, meta) {}, - - renderField: function( - name, meta, label, editable, removable - ) { - var widget = this.widget(meta).new( - this.reqData, - name, - meta, - this.level, - editable, - removable - ); - var container = this.appendWidget(widget, label); - widget.on("setVisible", function(event, visible) { - if (visible) container.show(); - else container.hide(); - event.stopPropagation(); - }); - return widget; - }, - - renderCollectionMember: function(name, meta) { - var set = meta.type == "set"; - this.renderField( - name, - meta.members, - meta["ui-member"] + " " + name, - !set, - !set && _.contains(meta.removable, name) - ).trigger("start"); - }, - - widget: function(meta) { return widgets[meta.widget]; } - }); + var InlineFields = Inline.extend({ - var Horizontal = InlineFields.extend({ - createEl: function() { - this.previous = null; - return $("<tr>").html($("<td>").prop( - "class", "placeholder" - )); - }, + render: function(data, meta) { + this.super(InlineFields, "render", data, meta); - showHeading: false, + this.appendAboveFields(data, meta); - appendWidget: function(el, label) { - if (!el.is("td")) return null; - if (this.previous) this.previous.after(el); - else { - var ph = this.el.find(".placeholder"); - ph.after(el); - ph.remove(); - } - this.previous = el; - return el; - } - }); + this.reqData = data; + var self = this; + + if (meta.type == "model") { + this.fields = {}; + _.each(meta.fields, function(field) { + if (field.visible) + self.fields[field.name] = self.renderField( + field.name, + field, + field["ui-name"], + true, + false + ); + }); + + _.each(this.fields, function(f1, name) { + _.each(self.fields, function(f2) { + if (f1 != f2) + f1.on("validated", function(event) { + f2.trigger("updated", [name]); + event.stopPropagation(); + }); + }); + }); + _.each(this.fields, function(field) { + field.trigger("start"); + }); + } + + else _.each(data.data, function(value, name) { + if (meta.type == "set") name = data.data[name]; + else if (_.isArray(data.data)) name++; + self.renderCollectionMember(name, meta); + }); - var HeaderHorizontal = Horizontal.extend({ - init: function( - data, name, meta, level, editable, removable - ) { - this.header = $("<tr>"); - var table = $("<table>"); - table.append($("<thead>").html(this.header)); - table.append($("<tbody>").html( - this.super( - HeaderHorizontal, - "init", - data, + this.appendBelowFields(data, meta); + }, + + appendAboveFields: function(data, meta) {}, + appendBelowFields: function(data, meta) {}, + + renderField: function( + name, meta, label, editable, removable + ) { + var widget = this.widget(meta).new( + this.reqData, name, meta, - level, + this.level, editable, removable - ) - )); - return table; - }, - - appendWidget: function(el, label) { - el = this.super( - HeaderHorizontal, "appendWidget", el, label - ); - if (el) this.header.append($("<th>").text(label)); - return el; - } - }); + ); + var container = this.appendWidget(widget, label); + widget.on("setVisible", function(event, visible) { + if (visible) container.show(); + else container.hide(); + event.stopPropagation(); + }); + return widget; + }, + + renderCollectionMember: function(name, meta) { + var set = meta.type == "set"; + this.renderField( + name, + meta.members, + meta["ui-member"] + " " + name, + !set, + !set && _.contains(meta.removable, name) + ).trigger("start"); + }, + + widget: function(meta) { return widgets[meta.widget]; } + }); - var Vertical = InlineFields.extend({ - wrap: function() { return $("<div>").html(this.el); }, - - appendAboveFields: function(data, meta) { - this.div = $("<div>"); - this.el.append(this.div); + var Horizontal = InlineFields.extend({ + createEl: function() { + this.previous = null; + return $("<tr>").html($("<td>").prop( + "class", "placeholder" + )); + }, + + showHeading: false, + + appendWidget: function(el, label) { + if (!el.is("td")) return null; + if (this.previous) this.previous.after(el); + else { + var ph = this.el.find(".placeholder"); + ph.after(el); + ph.remove(); + } + this.previous = el; + return el; + } + }); - var self = this; + + var HeaderHorizontal = Horizontal.extend({ + init: function( + data, name, meta, level, editable, removable + ) { + this.header = $("<tr>"); + var table = $("<table>"); + table.append($("<thead>").html(this.header)); + table.append($("<tbody>").html( + this.super( + HeaderHorizontal, + "init", + data, + name, + meta, + level, + editable, + removable + ) + )); + return table; + }, - if (meta.type == "model") - _.each(meta.actions, function(action) { - self.div.append($("<input>").attr( - {type: "submit", value: action["ui-name"]} - ).click(function() { - data.invoke(action.name).done(function() { - alert("Done"); - }).fail(function() { - alert("Failed"); - }); - })); - }); - }, + appendWidget: function(el, label) { + el = this.super( + HeaderHorizontal, "appendWidget", el, label + ); + if (el) this.header.append($("<th>").text(label)); + return el; + } + }); + + + var Vertical = InlineFields.extend({ + wrap: function() { return $("<div>").html(this.el); }, - appendBelowFields: function(data, meta) { - if (meta.editable && - _.contains(["collection", "list"], meta.type)) { - if (!this.table) this.makeSortable(this.div); + appendAboveFields: function(data, meta) { + this.div = $("<div>"); + this.el.append(this.div); var self = this; - var keys = _.clone(_.keys(data.data)); - var button = $("<input>").attr( - {type: "submit", value: "Insert"} - ).click(function() { - - var getter; + if (meta.type == "model") + _.each(meta.actions, function(action) { + self.div.append($("<input>").attr( + {type: "submit", value: action["ui-name"]} + ).click(function() { + data.invoke(action.name).done(function() { + alert("Done"); + }).fail(function() { + alert("Failed"); + }); + })); + }); + }, + + appendBelowFields: function(data, meta) { + if (meta.editable && + _.contains(["collection", "list"], meta.type)) { + if (!this.table) this.makeSortable(this.div); + + var self = this; + var keys = _.clone(_.keys(data.data)); - function insert() { - var name = getter(); + var button = $("<input>").attr( + {type: "submit", value: "Insert"} + ).click(function() { - if (_.contains(keys, name)) { - button.prop("class", null); - return; + var getter; + + function insert() { + var name = getter(); + + if (_.contains(keys, name)) { + button.prop("class", null); + return; + } + keys.push(name); + + data.set( + name, + isTreeNode(meta.members) ? {} : null + ).done(function(txnValid) { + if (_.isObject(meta.removable)) + meta.removable = []; + meta.removable.push(name); + + self.renderCollectionMember(name, meta); + button.prop("class", null); + statusBar.validationReady(txnValid); + }); } - keys.push(name); + + button.prop("class", "hidden"); - data.set( - name, - isTreeNode(meta.members) ? {} : null - ).done(function(txnValid) { - if (_.isObject(meta.removable)) - meta.removable = []; - meta.removable.push(name); + if (meta.type == "collection") { + var field = $("<input>").attr({type: "text"}); + var row = $("<tr>").html($("<td>").html(field)); + getter = function() { + var res = field.val(); + row.remove(); + return res; + } + field.change(insert); + self.appendRow(row); + } + else { + getter = function() { + return data.data.length + 1; + }; + insert(); + } + }); + this.el.append($("<p>").html(button)); + } + }, - self.renderCollectionMember(name, meta); - button.prop("class", null); - statusBar.validationReady(txnValid); + appendWidget: function(el, label) { + var self = this; + el = makeRow(el); + + if (el.is("tr")) { + el.prepend($("<td>").text(label)); + this.appendRow(el); + } + else { + if (el.is("table")) { + this.makeSortable(el.find("tbody")); + var td; + el.find("tr").each(function(index, row) { + td = $("<td>"); + $(row).prepend(td); }); + td.text(label); + this.table = el; } + else this.table = null; + this.div.append(el); + } + + return el; + }, + + appendRow: function(row) { + if (!this.table) { + this.table = this.makeSortable($("<tbody>")); + this.div.append($("<table>").html(this.table)); + } + this.table.append(row); + }, - button.prop("class", "hidden"); - - if (meta.type == "collection") { - var field = $("<input>").attr({type: "text"}); - var row = $("<tr>").html($("<td>").html(field)); - getter = function() { - var res = field.val(); - row.remove(); - return res; + makeSortable: function(el) { + var data = this.reqData; + + if (data.meta.type == "list") + el.sortable({ + start: function(event, ui) { + $(":focus").change(); + ui.item.data("index", ui.item.index()); + }, + stop: function(event, ui) { + var oldIndex = ui.item.data("index") + 1; + var newIndex = ui.item.index() + 1; + if (newIndex != oldIndex) + data.move(oldIndex, newIndex) + .done(function(txnValid) { + $("#content").trigger( + "reload", [txnValid] + ); + }); } - field.change(insert); - self.appendRow(row); - } - else { - getter = function() { - return data.data.length + 1; - }; - insert(); - } - }); - this.el.append($("<p>").html(button)); - } - }, - - appendWidget: function(el, label) { - var self = this; - el = makeRow(el); - - if (el.is("tr")) { - el.prepend($("<td>").text(label)); - this.appendRow(el); - } - else { - if (el.is("table")) { - this.makeSortable(el.find("tbody")); - var td; - el.find("tr").each(function(index, row) { - td = $("<td>"); - $(row).prepend(td); }); - td.text(label); - this.table = el; - } - else this.table = null; - this.div.append(el); - } - - return el; - }, - - appendRow: function(row) { - if (!this.table) { - this.table = this.makeSortable($("<tbody>")); - this.div.append($("<table>").html(this.table)); + return el; } - this.table.append(row); - }, + }); - makeSortable: function(el) { - var data = this.reqData; - if (data.meta.type == "list") - el.sortable({ - start: function(event, ui) { - $(":focus").change(); - ui.item.data("index", ui.item.index()); - }, - stop: function(event, ui) { - var oldIndex = ui.item.data("index") + 1; - var newIndex = ui.item.index() + 1; - if (newIndex != oldIndex) - data.move(oldIndex, newIndex) - .done(function(txnValid) { - $("#content").trigger( - "reload", [txnValid] - ); - }); - } - }); - return el; - } - }); + var CheckBoxes = Inline.extend({ + showStatus: true, + setStatus: function(status) { + this.super( + CheckBoxes, + "setStatus", + status == "invalid" ? "invalid" : null + ); + }, + + render: function(data, meta) { + this.dynamic = meta.members.dynamic; + + this.super(CheckBoxes, "render", data, meta); + + var table = $("<tbody>"); + this.el.append($("<table>").html(table)); + + var self = this; + + _.each(meta.members.choice, function(choice) { + var selected = _.contains(data.data, choice.value); + if (!(choice.enabled || selected)) return; + + var cbox = $("<input>").attr({ + type: "checkbox", checked: selected + }); + + var row = $("<tr>"); + row.append($("<td>").html(cbox)); + + var item = $("<td>"); + if (choice.ref) + item.html(objectRef(choice.ref) + .text(choice["ui-value"])); + else item.text(choice["ui-value"]); + row.append(item); + + function setRowStatus() { + setStatus(row, data.status(choice.value)); + } + setRowStatus(); + + cbox.change(function() { + ( + cbox.is(":checked") ? + data.add(choice.value) : + data.delete(choice.value) + ).done(function(txnValid) { + self.setStatus(data.status()); + setRowStatus(); + statusBar.validationReady(txnValid); + }); + }); - var CheckBoxes = Inline.extend({ - showStatus: true, + table.append(row); + }); + } + }); - setStatus: function(status) { - this.super( - CheckBoxes, - "setStatus", - status == "invalid" ? "invalid" : null - ); - }, - - render: function(data, meta) { - this.dynamic = meta.members.dynamic; - this.super(CheckBoxes, "render", data, meta); + var Reference = ComboBox.extend({ + init: function( + data, name, meta, level, editable, removable + ) { + this.field = ComboBox.createEl(); + return this.super( + Reference, + "init", + data, + name, + meta, + level, + editable, + removable + ); + }, - var table = $("<tbody>"); - this.el.append($("<table>").html(table)); + staticRender: function(value, meta) { + return $("<td>").html(objectRef(value).text(value)); + }, - var self = this; + statusEl: function() { return this.el.find("select"); }, + + createEl: function() { return $("<div>"); }, - _.each(meta.members.choice, function(choice) { - var selected = _.contains(data.data, choice.value); - if (!(choice.enabled || selected)) return; - - var cbox = $("<input>").attr({ - type: "checkbox", checked: selected - }); + render: function(value, meta) { + this.super(Reference, "render", value, meta); - var row = $("<tr>"); - row.append($("<td>").html(cbox)); - - var item = $("<td>"); - if (choice.ref) - item.html(objectRef(choice.ref) - .text(choice["ui-value"])); - else item.text(choice["ui-value"]); - row.append(item); + this.el.html(this.field); + this.el.append(" "); - function setRowStatus() { - setStatus(row, data.status(choice.value)); - } - setRowStatus(); + var link = $("<div>"); + var update = _.bind(function() { + link.html(objectRef(this.get())); + }, this); + this.el.append(link); - cbox.change(function() { - ( - cbox.is(":checked") ? - data.add(choice.value) : - data.delete(choice.value) - ).done(function(txnValid) { - self.setStatus(data.status()); - setRowStatus(); - statusBar.validationReady(txnValid); - }); - }); + this.field.change(update); + update(); + } + }); - table.append(row); - }); - } - }); + var widgets = { + boolean: CheckBox, + checkboxes: CheckBoxes, + combobox: ComboBox, + field: Field, + inline: Vertical, + link: Link, + reference: Reference + }; - var Reference = ComboBox.extend({ - init: function( - data, name, meta, level, editable, removable - ) { - this.field = ComboBox.createEl(); - return this.super( - Reference, - "init", - data, - name, - meta, - level, - editable, - removable - ); - }, - - staticRender: function(value, meta) { - return $("<td>").html(objectRef(value).text(value)); - }, - - statusEl: function() { return this.el.find("select"); }, - createEl: function() { return $("<div>"); }, - - render: function(value, meta) { - this.super(Reference, "render", value, meta); - - this.el.html(this.field); - this.el.append(" "); - - var link = $("<div>"); - var update = _.bind(function() { - link.html(objectRef(this.get())); - }, this); - this.el.append(link); + var Tabular = Vertical.extend({ + render: function(data, meta) { + this.header = true; + this.super(Tabular, "render", data, meta); + }, - this.field.change(update); - update(); - } - }); + widget: function(meta) { + if (!isTreeNode(meta)) + return this.super(Tabular, "widget", meta); + if (!this.header) return Horizontal; + this.header = false; + return HeaderHorizontal; + } + }); - var widgets = { - boolean: CheckBox, - checkboxes: CheckBoxes, - combobox: ComboBox, - field: Field, - inline: Vertical, - link: Link, - reference: Reference - }; + var Stacked = Vertical.extend({ + widget: function(meta) { + return isTreeNode(meta) ? + Vertical : this.super(Stacked, "widget", meta); + } + }); - var Tabular = Vertical.extend({ - render: function(data, meta) { - this.header = true; - this.super(Tabular, "render", data, meta); - }, - - widget: function(meta) { - if (!isTreeNode(meta)) - return this.super(Tabular, "widget", meta); - if (!this.header) return Horizontal; - this.header = false; - return HeaderHorizontal; - } - }); + var layouts = {stacked: Stacked, tabular: Tabular}; - var Stacked = Vertical.extend({ - widget: function(meta) { - return isTreeNode(meta) ? - Vertical : this.super(Stacked, "widget", meta); - } - }); + function redirect(path) { $.bbq.pushState("#" + path); } + function renderObject(path, data) { + path = path || $.param.fragment(); - var layouts = {stacked: Stacked, tabular: Tabular}; + return ( + data ? $.Deferred().resolve(data) : txnMgr.query(path) + ).done(function(data) { + var layout = data.meta.widget; + var name = split(path).pop(); + (layout ? layouts[layout] : Vertical).extend({ + createEl: function() { return $("#content").empty(); }, + wrap: function() { return this.el; }, + requestData: function(value, meta) { + return $.Deferred().resolve(data, data.meta); + } + }).new( + { + get: function(name) { return path; }, + status: function(name) { return null; }, + match: function(filter) { return true; } + }, + name, + {}, + 0, + true, + false + ); + }).fail(function() { + var comps = split(path); + comps.pop(); + comps.unshift("/"); + redirect(join.apply(undefined, comps)); + }); + }; + $("#content").on("reload", function(event, txnValid) { + statusBar.validationReady(txnValid); + renderObject(); + event.stopPropagation(); + }); - function redirect(path) { $.bbq.pushState("#" + path); } - function renderObject(path, data) { - path = path || $.param.fragment(); + function render() { + var path = $.param.fragment(); - return ( - data ? $.Deferred().resolve(data) : txnMgr.query(path) - ).done(function(data) { - var layout = data.meta.widget; - var name = split(path).pop(); - (layout ? layouts[layout] : Vertical).extend({ - createEl: function() { return $("#content").empty(); }, - wrap: function() { return this.el; }, - requestData: function(value, meta) { - return $.Deferred().resolve(data, data.meta); - } - }).new( - { - get: function(name) { return path; }, - status: function(name) { return null; }, - match: function(filter) { return true; } - }, - name, - {}, - 0, - true, - false - ); - }).fail(function() { - var comps = split(path); - comps.pop(); - comps.unshift("/"); - redirect(join.apply(undefined, comps)); - }); - }; + function renderMenu(target, path, current, selectFirst) { + var def = $.Deferred(); - $("#content").on("reload", function(event, txnValid) { - statusBar.validationReady(txnValid); - renderObject(); - event.stopPropagation(); - }); + txnMgr.query(path).done(function(data) { + if (data.meta.type != "model") { + def.reject(data); + return; + } + var tnFields = []; + var extraFields = false; - function render() { - var path = $.param.fragment(); + _.each(data.meta.fields, function(field) { + if (!field.visible) return; - function renderMenu(target, path, current, selectFirst) { - var def = $.Deferred(); + if (!isTreeNode(field)) extraFields = true; + else if (data.data[field.name]) + tnFields.push(field); + }); - txnMgr.query(path).done(function(data) { - if (data.meta.type != "model") { - def.reject(data); - return; - } + if (!tnFields.length) { + def.reject(data); + return; + } + + function addItem(path, ui_name, status, current) { + var el = $("<li>").html(objectRef(path).text(ui_name)); + el.prop("class", status); + if (current) el.addClass("current"); + target.append(el); + } - var tnFields = []; - var extraFields = false; + if (extraFields) { + addItem(path, "General", null, !current); + selectFirst = false; + } - _.each(data.meta.fields, function(field) { - if (!field.visible) return; + _.each(tnFields, function(field, i) { + addItem( + data.get(field.name), + field["ui-name"], + data.status(field.name), + current == field.name || ( + !current && !i && selectFirst + ) + ); + field.visible = false; + }); - if (!isTreeNode(field)) extraFields = true; - else if (data.data[field.name]) - tnFields.push(field); + def.resolve(extraFields ? data : tnFields[0].name); }); - if (!tnFields.length) { - def.reject(data); - return; - } + return def; + } - function addItem(path, ui_name, status, current) { - var el = $("<li>").html(objectRef(path).text(ui_name)); - el.prop("class", status); - if (current) el.addClass("current"); - target.append(el); - } - if (extraFields) { - addItem(path, "General", null, !current); - selectFirst = false; + if (path > "/") $("#content").text("Loading..."); + + txnMgr.start().done(function() { + var comps = split(path); + renderMenu($("#modules").empty(), "/", comps[0], false); + var tabs = $("#tabs").empty(); + + if (path == "/") return; + + function renderTabs(p) { + p = join(p, comps.shift()); + renderMenu(tabs, p, comps[0], true) + .done(function(data) { + var tabLevel = !comps.length; + renderObject( + ( + tabLevel && _.isString(data) + ) ? join(p, data) : path, + tabLevel && _.isObject(data) ? data : null + ); + }) + .fail(function(data) { + if (comps.length) renderTabs(p); + else renderObject(p, data); + }); } - - _.each(tnFields, function(field, i) { - addItem( - data.get(field.name), - field["ui-name"], - data.status(field.name), - current == field.name || ( - !current && !i && selectFirst - ) - ); - field.visible = false; - }); - - def.resolve(extraFields ? data : tnFields[0].name); + renderTabs("/"); }); - - return def; } - - if (path > "/") $("#content").text("Loading..."); - - txnMgr.start().done(function() { - var comps = split(path); - renderMenu($("#modules").empty(), "/", comps[0], false); - var tabs = $("#tabs").empty(); - - if (path == "/") return; - - function renderTabs(p) { - p = join(p, comps.shift()); - renderMenu(tabs, p, comps[0], true) - .done(function(data) { - var tabLevel = !comps.length; - renderObject( - ( - tabLevel && _.isString(data) - ) ? join(p, data) : path, - tabLevel && _.isObject(data) ? data : null - ); - }) - .fail(function(data) { - if (comps.length) renderTabs(p); - else renderObject(p, data); - }); - } - renderTabs("/"); + + function clearState() { + statusBar.reset(); + render(); + $.unblockUI(); + } + + $("#commit").click(function() { + $.blockUI(); + txnMgr.commit().done(clearState).fail(function(xhr) { + statusBar.setError( + formatError("Commit failed", xhr), "txn" + ); + }) }); - } - - - function clearState() { - statusBar.reset(); - render(); - $.unblockUI(); - } - - $("#commit").click(function() { - $.blockUI(); - txnMgr.commit().done(clearState).fail(function(xhr) { - statusBar.setError( - formatError("Commit failed", xhr), "txn" - ); - }) - }); - $("#revert").click(function() { - $.blockUI(); - txnMgr.abort(); - clearState(); - }); - - $("#logout").click(function() { - txnMgr.logout().done(function() { - $("body").html($("<p>").text("Logged out")); + $("#revert").click(function() { + $.blockUI(); + txnMgr.abort(); + clearState(); }); - }); - - statusBar.reset(); - $("#content").empty(); + + $("#logout").click(function() { + txnMgr.logout().done(function() { + $("body").html($("<p>").text("Logged out")); + }); + }); + + statusBar.reset(); + $("#content").empty(); - $(window).bind("hashchange", render); - redirect("/"); + $(window).bind("hashchange", render); + redirect("/"); - }).fail(function() { - statusBar.setError("Login failed", "login"); - }); + }).fail(function() { + statusBar.setError("Login failed", "login"); + }); - return false; - }); + return false; + }); - $("#username").focus(); -}); + $("#username").focus(); + } +); diff --git a/web/lib/require.js b/web/lib/require.js new file mode 100644 index 0000000..84d1d67 --- /dev/null +++ b/web/lib/require.js @@ -0,0 +1,36 @@ +/* + RequireJS 2.1.10 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. + Available via the MIT or new BSD license. + see: http://github.com/jrburke/requirejs for details +*/ +var requirejs,require,define; +(function(ca){function G(b){return"[object Function]"===N.call(b)}function H(b){return"[object Array]"===N.call(b)}function v(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function U(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function j(b,c){return s(b,c)&&b[c]}function B(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function V(b,c,d,g){c&&B(c,function(c,h){if(d||!s(b,h))g&&"object"===typeof c&&c&&!H(c)&&!G(c)&&!(c instanceof +RegExp)?(b[h]||(b[h]={}),V(b[h],c,d,g)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function da(b){throw b;}function ea(b){if(!b)return b;var c=ca;v(b.split("."),function(b){c=c[b]});return c}function C(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=g;d&&(c.originalError=d);return c}function ha(b){function c(a,e,b){var f,n,c,d,g,h,i,I=e&&e.split("/");n=I;var m=l.map,k=m&&m["*"];if(a&&"."===a.charAt(0))if(e){n= +I.slice(0,I.length-1);a=a.split("/");e=a.length-1;l.nodeIdCompat&&R.test(a[e])&&(a[e]=a[e].replace(R,""));n=a=n.concat(a);d=n.length;for(e=0;e<d;e++)if(c=n[e],"."===c)n.splice(e,1),e-=1;else if(".."===c)if(1===e&&(".."===n[2]||".."===n[0]))break;else 0<e&&(n.splice(e-1,2),e-=2);a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if(b&&m&&(I||k)){n=a.split("/");e=n.length;a:for(;0<e;e-=1){d=n.slice(0,e).join("/");if(I)for(c=I.length;0<c;c-=1)if(b=j(m,I.slice(0,c).join("/")))if(b=j(b,d)){f=b; +g=e;break a}!h&&(k&&j(k,d))&&(h=j(k,d),i=e)}!f&&h&&(f=h,g=i);f&&(n.splice(0,g,f),a=n.join("/"))}return(f=j(l.pkgs,a))?f:a}function d(a){z&&v(document.getElementsByTagName("script"),function(e){if(e.getAttribute("data-requiremodule")===a&&e.getAttribute("data-requirecontext")===i.contextName)return e.parentNode.removeChild(e),!0})}function g(a){var e=j(l.paths,a);if(e&&H(e)&&1<e.length)return e.shift(),i.require.undef(a),i.require([a]),!0}function u(a){var e,b=a?a.indexOf("!"):-1;-1<b&&(e=a.substring(0, +b),a=a.substring(b+1,a.length));return[e,a]}function m(a,e,b,f){var n,d,g=null,h=e?e.name:null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(N+=1));a=u(a);g=a[0];a=a[1];g&&(g=c(g,h,f),d=j(p,g));a&&(g?k=d&&d.normalize?d.normalize(a,function(a){return c(a,h,f)}):c(a,h,f):(k=c(a,h,f),a=u(k),g=a[0],k=a[1],b=!0,n=i.nameToUrl(k)));b=g&&!d&&!b?"_unnormalized"+(Q+=1):"";return{prefix:g,name:k,parentMap:e,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(g?g+"!"+k:k)+b}}function q(a){var e=a.id,b=j(k,e);b||(b=k[e]=new i.Module(a)); +return b}function r(a,e,b){var f=a.id,n=j(k,f);if(s(p,f)&&(!n||n.defineEmitComplete))"defined"===e&&b(p[f]);else if(n=q(a),n.error&&"error"===e)b(n.error);else n.on(e,b)}function w(a,e){var b=a.requireModules,f=!1;if(e)e(a);else if(v(b,function(e){if(e=j(k,e))e.error=a,e.events.error&&(f=!0,e.emit("error",a))}),!f)h.onError(a)}function x(){S.length&&(ia.apply(A,[A.length,0].concat(S)),S=[])}function y(a){delete k[a];delete W[a]}function F(a,e,b){var f=a.map.id;a.error?a.emit("error",a.error):(e[f]= +!0,v(a.depMaps,function(f,c){var d=f.id,g=j(k,d);g&&(!a.depMatched[c]&&!b[d])&&(j(e,d)?(a.defineDep(c,p[d]),a.check()):F(g,e,b))}),b[f]=!0)}function D(){var a,e,b=(a=1E3*l.waitSeconds)&&i.startTime+a<(new Date).getTime(),f=[],c=[],h=!1,k=!0;if(!X){X=!0;B(W,function(a){var i=a.map,m=i.id;if(a.enabled&&(i.isDefine||c.push(a),!a.error))if(!a.inited&&b)g(m)?h=e=!0:(f.push(m),d(m));else if(!a.inited&&(a.fetched&&i.isDefine)&&(h=!0,!i.prefix))return k=!1});if(b&&f.length)return a=C("timeout","Load timeout for modules: "+ +f,null,f),a.contextName=i.contextName,w(a);k&&v(c,function(a){F(a,{},{})});if((!b||e)&&h)if((z||fa)&&!Y)Y=setTimeout(function(){Y=0;D()},50);X=!1}}function E(a){s(p,a[0])||q(m(a[0],null,!0)).init(a[1],a[2])}function L(a){var a=a.currentTarget||a.srcElement,e=i.onScriptLoad;a.detachEvent&&!Z?a.detachEvent("onreadystatechange",e):a.removeEventListener("load",e,!1);e=i.onScriptError;(!a.detachEvent||Z)&&a.removeEventListener("error",e,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function M(){var a; +for(x();A.length;){a=A.shift();if(null===a[0])return w(C("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));E(a)}}var X,$,i,K,Y,l={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},k={},W={},aa={},A=[],p={},T={},ba={},N=1,Q=1;K={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module: +a.module={id:a.map.id,uri:a.map.url,config:function(){return j(l.config,a.map.id)||{}},exports:K.exports(a)}}};$=function(a){this.events=j(aa,a.id)||{};this.map=a;this.shim=j(l.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};$.prototype={init:function(a,e,b,f){f=f||{};if(!this.inited){this.factory=e;if(b)this.on("error",b);else this.events.error&&(b=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=b;this.inited= +!0;this.ignore=f.ignore;f.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,e){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=e)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a= +this.map.url;T[a]||(T[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,e,b=this.map.id;e=this.depExports;var f=this.exports,c=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&& +(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a= +this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f); +if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval", +"fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(K,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b, +a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(K,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m, +nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b, +a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild= +!0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(K,f))return K[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}M();i.nextTick(function(){M();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!== +d&&(!("."===g||".."===g)||1<d))e=b.substring(d,b.length),b=b.substring(0,d);return i.nameToUrl(c(b,a&&a.id,!0),e,!0)},defined:function(b){return s(p,m(b,a,!1,!0).id)},specified:function(b){b=m(b,a,!1,!0).id;return s(p,b)||s(k,b)}});a||(g.undef=function(b){x();var c=m(b,a,!0),e=j(k,b);d(b);delete p[b];delete T[c.url];delete aa[b];U(A,function(a,c){a[0]===b&&A.splice(c,1)});e&&(e.events.defined&&(aa[b]=e.events),y(b))});return g},enable:function(a){j(k,a.id)&&q(a).enable()},completeLoad:function(a){var b, +c,f=j(l.shim,a)||{},d=f.exports;for(x();A.length;){c=A.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=j(k,a);if(!b&&!s(p,a)&&c&&!c.inited){if(l.enforceDefine&&(!d||!ea(d)))return g(a)?void 0:w(C("nodefine","No define call for "+a,null,[a]));E([a,f.deps||[],f.exportsFn])}D()},nameToUrl:function(a,b,c){var f,d,g;(f=j(l.pkgs,a))&&(a=f);if(f=j(ba,a))return i.nameToUrl(f,b,c);if(h.jsExtRegExp.test(a))f=a+(b||"");else{f=l.paths;a=a.split("/");for(d=a.length;0<d;d-=1)if(g=a.slice(0, +d).join("/"),g=j(f,g)){H(g)&&(g=g[0]);a.splice(0,d,g);break}f=a.join("/");f+=b||(/^data\:|\?/.test(f)||c?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":l.baseUrl)+f}return l.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+l.urlArgs):f},load:function(a,b){h.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=L(a),i.completeLoad(a.id)},onScriptError:function(a){var b=L(a);if(!g(b.id))return w(C("scripterror", +"Script error for: "+b.id,a,[b.id]))}};i.require=i.makeRequire();return i}var h,x,y,D,L,E,P,M,q,Q,la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,R=/\.js$/,ja=/^\.\//;x=Object.prototype;var N=x.toString,ga=x.hasOwnProperty,ia=Array.prototype.splice,z=!!("undefined"!==typeof window&&"undefined"!==typeof navigator&&window.document),fa=!z&&"undefined"!==typeof importScripts,ka=z&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/, +Z="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),F={},r={},S=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(G(requirejs))return;r=requirejs;requirejs=void 0}"undefined"!==typeof require&&!G(require)&&(r=require,require=void 0);h=requirejs=function(b,c,d,g){var u,m="_";!H(b)&&"string"!==typeof b&&(u=b,H(c)?(b=c,c=d,d=g):b=[]);u&&u.context&&(m=u.context);(g=j(F,m))||(g=F[m]=h.s.newContext(m));u&&g.configure(u);return g.require(b,c,d)};h.config=function(b){return h(b)}; +h.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=h);h.version="2.1.10";h.jsExtRegExp=/^\/|:|\?|\.js$/;h.isBrowser=z;x=h.s={contexts:F,newContext:ha};h({});v(["toUrl","undef","defined","specified"],function(b){h[b]=function(){var c=F._;return c.require[b].apply(c,arguments)}});if(z&&(y=x.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))y=x.head=D.parentNode;h.onError=da;h.createNode=function(b){var c= +b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};h.load=function(b,c,d){var g=b&&b.config||{};if(z)return g=h.createNode(g,c,d),g.setAttribute("data-requirecontext",b.contextName),g.setAttribute("data-requiremodule",c),g.attachEvent&&!(g.attachEvent.toString&&0>g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)): +(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,M=g,D?y.insertBefore(g,D):y.appendChild(g),M=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(L=b.getAttribute("data-main"))return q=L,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl= +Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=L),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=M))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b|| +(b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this); |