|
@@ -0,0 +1,1650 @@
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/lib/Class.coffee ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function() {
|
|
|
+ var Class,
|
|
|
+ slice = [].slice;
|
|
|
+
|
|
|
+ Class = (function() {
|
|
|
+ function Class() {}
|
|
|
+
|
|
|
+ Class.prototype.trace = true;
|
|
|
+
|
|
|
+ Class.prototype.log = function() {
|
|
|
+ var args;
|
|
|
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
|
|
+ if (!this.trace) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (typeof console === 'undefined') {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ args.unshift("[" + this.constructor.name + "]");
|
|
|
+ console.log.apply(console, args);
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+
|
|
|
+ Class.prototype.logStart = function() {
|
|
|
+ var args, name;
|
|
|
+ name = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
|
|
+ if (!this.trace) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.logtimers || (this.logtimers = {});
|
|
|
+ this.logtimers[name] = +(new Date);
|
|
|
+ if (args.length > 0) {
|
|
|
+ this.log.apply(this, ["" + name].concat(slice.call(args), ["(started)"]));
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+
|
|
|
+ Class.prototype.logEnd = function() {
|
|
|
+ var args, ms, name;
|
|
|
+ name = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
|
|
+ ms = +(new Date) - this.logtimers[name];
|
|
|
+ this.log.apply(this, ["" + name].concat(slice.call(args), ["(Done in " + ms + "ms)"]));
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+
|
|
|
+ return Class;
|
|
|
+
|
|
|
+ })();
|
|
|
+
|
|
|
+ window.Class = Class;
|
|
|
+
|
|
|
+}).call(this);
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/lib/Promise.coffee ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function() {
|
|
|
+ var Promise,
|
|
|
+ slice = [].slice;
|
|
|
+
|
|
|
+ Promise = (function() {
|
|
|
+ Promise.when = function() {
|
|
|
+ var args, fn, i, len, num_uncompleted, promise, task, task_id, tasks;
|
|
|
+ tasks = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
|
|
+ num_uncompleted = tasks.length;
|
|
|
+ args = new Array(num_uncompleted);
|
|
|
+ promise = new Promise();
|
|
|
+ fn = function(task_id) {
|
|
|
+ return task.then(function() {
|
|
|
+ args[task_id] = Array.prototype.slice.call(arguments);
|
|
|
+ num_uncompleted--;
|
|
|
+ if (num_uncompleted === 0) {
|
|
|
+ return promise.complete.apply(promise, args);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ for (task_id = i = 0, len = tasks.length; i < len; task_id = ++i) {
|
|
|
+ task = tasks[task_id];
|
|
|
+ fn(task_id);
|
|
|
+ }
|
|
|
+ return promise;
|
|
|
+ };
|
|
|
+
|
|
|
+ function Promise() {
|
|
|
+ this.resolved = false;
|
|
|
+ this.end_promise = null;
|
|
|
+ this.result = null;
|
|
|
+ this.callbacks = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ Promise.prototype.resolve = function() {
|
|
|
+ var back, callback, i, len, ref;
|
|
|
+ if (this.resolved) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ this.resolved = true;
|
|
|
+ this.data = arguments;
|
|
|
+ if (!arguments.length) {
|
|
|
+ this.data = [true];
|
|
|
+ }
|
|
|
+ this.result = this.data[0];
|
|
|
+ ref = this.callbacks;
|
|
|
+ for (i = 0, len = ref.length; i < len; i++) {
|
|
|
+ callback = ref[i];
|
|
|
+ back = callback.apply(callback, this.data);
|
|
|
+ }
|
|
|
+ if (this.end_promise) {
|
|
|
+ return this.end_promise.resolve(back);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ Promise.prototype.fail = function() {
|
|
|
+ return this.resolve(false);
|
|
|
+ };
|
|
|
+
|
|
|
+ Promise.prototype.then = function(callback) {
|
|
|
+ if (this.resolved === true) {
|
|
|
+ callback.apply(callback, this.data);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.callbacks.push(callback);
|
|
|
+ return this.end_promise = new Promise();
|
|
|
+ };
|
|
|
+
|
|
|
+ return Promise;
|
|
|
+
|
|
|
+ })();
|
|
|
+
|
|
|
+ window.Promise = Promise;
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ s = Date.now()
|
|
|
+ log = (text) ->
|
|
|
+ console.log Date.now()-s, Array.prototype.slice.call(arguments).join(", ")
|
|
|
+
|
|
|
+ log "Started"
|
|
|
+
|
|
|
+ cmd = (query) ->
|
|
|
+ p = new Promise()
|
|
|
+ setTimeout ( ->
|
|
|
+ p.resolve query+" Result"
|
|
|
+ ), 100
|
|
|
+ return p
|
|
|
+
|
|
|
+ back = cmd("SELECT * FROM message").then (res) ->
|
|
|
+ log res
|
|
|
+ return "Return from query"
|
|
|
+ .then (res) ->
|
|
|
+ log "Back then", res
|
|
|
+
|
|
|
+ log "Query started", back
|
|
|
+ */
|
|
|
+
|
|
|
+}).call(this);
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/lib/Prototypes.coffee ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function() {
|
|
|
+ String.prototype.startsWith = function(s) {
|
|
|
+ return this.slice(0, s.length) === s;
|
|
|
+ };
|
|
|
+
|
|
|
+ String.prototype.endsWith = function(s) {
|
|
|
+ return s === '' || this.slice(-s.length) === s;
|
|
|
+ };
|
|
|
+
|
|
|
+ String.prototype.repeat = function(count) {
|
|
|
+ return new Array(count + 1).join(this);
|
|
|
+ };
|
|
|
+
|
|
|
+ window.isEmpty = function(obj) {
|
|
|
+ var key;
|
|
|
+ for (key in obj) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ };
|
|
|
+
|
|
|
+}).call(this);
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/lib/maquette.js ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function (root, factory) {
|
|
|
+ if (typeof define === 'function' && define.amd) {
|
|
|
+ // AMD. Register as an anonymous module.
|
|
|
+ define(['exports'], factory);
|
|
|
+ } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
|
|
+ // CommonJS
|
|
|
+ factory(exports);
|
|
|
+ } else {
|
|
|
+ // Browser globals
|
|
|
+ factory(root.maquette = {});
|
|
|
+ }
|
|
|
+}(this, function (exports) {
|
|
|
+ 'use strict';
|
|
|
+ ;
|
|
|
+ ;
|
|
|
+ ;
|
|
|
+ ;
|
|
|
+ var NAMESPACE_W3 = 'http://www.w3.org/';
|
|
|
+ var NAMESPACE_SVG = NAMESPACE_W3 + '2000/svg';
|
|
|
+ var NAMESPACE_XLINK = NAMESPACE_W3 + '1999/xlink';
|
|
|
+ // Utilities
|
|
|
+ var emptyArray = [];
|
|
|
+ var extend = function (base, overrides) {
|
|
|
+ var result = {};
|
|
|
+ Object.keys(base).forEach(function (key) {
|
|
|
+ result[key] = base[key];
|
|
|
+ });
|
|
|
+ if (overrides) {
|
|
|
+ Object.keys(overrides).forEach(function (key) {
|
|
|
+ result[key] = overrides[key];
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ };
|
|
|
+ // Hyperscript helper functions
|
|
|
+ var same = function (vnode1, vnode2) {
|
|
|
+ if (vnode1.vnodeSelector !== vnode2.vnodeSelector) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (vnode1.properties && vnode2.properties) {
|
|
|
+ if (vnode1.properties.key !== vnode2.properties.key) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return vnode1.properties.bind === vnode2.properties.bind;
|
|
|
+ }
|
|
|
+ return !vnode1.properties && !vnode2.properties;
|
|
|
+ };
|
|
|
+ var toTextVNode = function (data) {
|
|
|
+ return {
|
|
|
+ vnodeSelector: '',
|
|
|
+ properties: undefined,
|
|
|
+ children: undefined,
|
|
|
+ text: data.toString(),
|
|
|
+ domNode: null
|
|
|
+ };
|
|
|
+ };
|
|
|
+ var appendChildren = function (parentSelector, insertions, main) {
|
|
|
+ for (var i = 0; i < insertions.length; i++) {
|
|
|
+ var item = insertions[i];
|
|
|
+ if (Array.isArray(item)) {
|
|
|
+ appendChildren(parentSelector, item, main);
|
|
|
+ } else {
|
|
|
+ if (item !== null && item !== undefined) {
|
|
|
+ if (!item.hasOwnProperty('vnodeSelector')) {
|
|
|
+ item = toTextVNode(item);
|
|
|
+ }
|
|
|
+ main.push(item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // Render helper functions
|
|
|
+ var missingTransition = function () {
|
|
|
+ throw new Error('Provide a transitions object to the projectionOptions to do animations');
|
|
|
+ };
|
|
|
+ var DEFAULT_PROJECTION_OPTIONS = {
|
|
|
+ namespace: undefined,
|
|
|
+ eventHandlerInterceptor: undefined,
|
|
|
+ styleApplyer: function (domNode, styleName, value) {
|
|
|
+ // Provides a hook to add vendor prefixes for browsers that still need it.
|
|
|
+ domNode.style[styleName] = value;
|
|
|
+ },
|
|
|
+ transitions: {
|
|
|
+ enter: missingTransition,
|
|
|
+ exit: missingTransition
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var applyDefaultProjectionOptions = function (projectorOptions) {
|
|
|
+ return extend(DEFAULT_PROJECTION_OPTIONS, projectorOptions);
|
|
|
+ };
|
|
|
+ var checkStyleValue = function (styleValue) {
|
|
|
+ if (typeof styleValue !== 'string') {
|
|
|
+ throw new Error('Style values must be strings');
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var setProperties = function (domNode, properties, projectionOptions) {
|
|
|
+ if (!properties) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var eventHandlerInterceptor = projectionOptions.eventHandlerInterceptor;
|
|
|
+ var propNames = Object.keys(properties);
|
|
|
+ var propCount = propNames.length;
|
|
|
+ for (var i = 0; i < propCount; i++) {
|
|
|
+ var propName = propNames[i];
|
|
|
+ /* tslint:disable:no-var-keyword: edge case */
|
|
|
+ var propValue = properties[propName];
|
|
|
+ /* tslint:enable:no-var-keyword */
|
|
|
+ if (propName === 'className') {
|
|
|
+ throw new Error('Property "className" is not supported, use "class".');
|
|
|
+ } else if (propName === 'class') {
|
|
|
+ if (domNode.className) {
|
|
|
+ // May happen if classes is specified before class
|
|
|
+ domNode.className += ' ' + propValue;
|
|
|
+ } else {
|
|
|
+ domNode.className = propValue;
|
|
|
+ }
|
|
|
+ } else if (propName === 'classes') {
|
|
|
+ // object with string keys and boolean values
|
|
|
+ var classNames = Object.keys(propValue);
|
|
|
+ var classNameCount = classNames.length;
|
|
|
+ for (var j = 0; j < classNameCount; j++) {
|
|
|
+ var className = classNames[j];
|
|
|
+ if (propValue[className]) {
|
|
|
+ domNode.classList.add(className);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (propName === 'styles') {
|
|
|
+ // object with string keys and string (!) values
|
|
|
+ var styleNames = Object.keys(propValue);
|
|
|
+ var styleCount = styleNames.length;
|
|
|
+ for (var j = 0; j < styleCount; j++) {
|
|
|
+ var styleName = styleNames[j];
|
|
|
+ var styleValue = propValue[styleName];
|
|
|
+ if (styleValue) {
|
|
|
+ checkStyleValue(styleValue);
|
|
|
+ projectionOptions.styleApplyer(domNode, styleName, styleValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (propName === 'key') {
|
|
|
+ continue;
|
|
|
+ } else if (propValue === null || propValue === undefined) {
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ var type = typeof propValue;
|
|
|
+ if (type === 'function') {
|
|
|
+ if (propName.lastIndexOf('on', 0) === 0) {
|
|
|
+ if (eventHandlerInterceptor) {
|
|
|
+ propValue = eventHandlerInterceptor(propName, propValue, domNode, properties); // intercept eventhandlers
|
|
|
+ }
|
|
|
+ if (propName === 'oninput') {
|
|
|
+ (function () {
|
|
|
+ // record the evt.target.value, because IE and Edge sometimes do a requestAnimationFrame between changing value and running oninput
|
|
|
+ var oldPropValue = propValue;
|
|
|
+ propValue = function (evt) {
|
|
|
+ evt.target['oninput-value'] = evt.target.value;
|
|
|
+ // may be HTMLTextAreaElement as well
|
|
|
+ oldPropValue.apply(this, [evt]);
|
|
|
+ };
|
|
|
+ }());
|
|
|
+ }
|
|
|
+ domNode[propName] = propValue;
|
|
|
+ }
|
|
|
+ } else if (type === 'string' && propName !== 'value' && propName !== 'innerHTML') {
|
|
|
+ if (projectionOptions.namespace === NAMESPACE_SVG && propName === 'href') {
|
|
|
+ domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
|
|
|
+ } else {
|
|
|
+ domNode.setAttribute(propName, propValue);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ domNode[propName] = propValue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var updateProperties = function (domNode, previousProperties, properties, projectionOptions) {
|
|
|
+ if (!properties) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var propertiesUpdated = false;
|
|
|
+ var propNames = Object.keys(properties);
|
|
|
+ var propCount = propNames.length;
|
|
|
+ for (var i = 0; i < propCount; i++) {
|
|
|
+ var propName = propNames[i];
|
|
|
+ // assuming that properties will be nullified instead of missing is by design
|
|
|
+ var propValue = properties[propName];
|
|
|
+ var previousValue = previousProperties[propName];
|
|
|
+ if (propName === 'class') {
|
|
|
+ if (previousValue !== propValue) {
|
|
|
+ throw new Error('"class" property may not be updated. Use the "classes" property for conditional css classes.');
|
|
|
+ }
|
|
|
+ } else if (propName === 'classes') {
|
|
|
+ var classList = domNode.classList;
|
|
|
+ var classNames = Object.keys(propValue);
|
|
|
+ var classNameCount = classNames.length;
|
|
|
+ for (var j = 0; j < classNameCount; j++) {
|
|
|
+ var className = classNames[j];
|
|
|
+ var on = !!propValue[className];
|
|
|
+ var previousOn = !!previousValue[className];
|
|
|
+ if (on === previousOn) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ propertiesUpdated = true;
|
|
|
+ if (on) {
|
|
|
+ classList.add(className);
|
|
|
+ } else {
|
|
|
+ classList.remove(className);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (propName === 'styles') {
|
|
|
+ var styleNames = Object.keys(propValue);
|
|
|
+ var styleCount = styleNames.length;
|
|
|
+ for (var j = 0; j < styleCount; j++) {
|
|
|
+ var styleName = styleNames[j];
|
|
|
+ var newStyleValue = propValue[styleName];
|
|
|
+ var oldStyleValue = previousValue[styleName];
|
|
|
+ if (newStyleValue === oldStyleValue) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ propertiesUpdated = true;
|
|
|
+ if (newStyleValue) {
|
|
|
+ checkStyleValue(newStyleValue);
|
|
|
+ projectionOptions.styleApplyer(domNode, styleName, newStyleValue);
|
|
|
+ } else {
|
|
|
+ projectionOptions.styleApplyer(domNode, styleName, '');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (!propValue && typeof previousValue === 'string') {
|
|
|
+ propValue = '';
|
|
|
+ }
|
|
|
+ if (propName === 'value') {
|
|
|
+ if (domNode[propName] !== propValue && domNode['oninput-value'] !== propValue) {
|
|
|
+ domNode[propName] = propValue;
|
|
|
+ // Reset the value, even if the virtual DOM did not change
|
|
|
+ domNode['oninput-value'] = undefined;
|
|
|
+ }
|
|
|
+ // else do not update the domNode, otherwise the cursor position would be changed
|
|
|
+ if (propValue !== previousValue) {
|
|
|
+ propertiesUpdated = true;
|
|
|
+ }
|
|
|
+ } else if (propValue !== previousValue) {
|
|
|
+ var type = typeof propValue;
|
|
|
+ if (type === 'function') {
|
|
|
+ throw new Error('Functions may not be updated on subsequent renders (property: ' + propName + '). Hint: declare event handler functions outside the render() function.');
|
|
|
+ }
|
|
|
+ if (type === 'string' && propName !== 'innerHTML') {
|
|
|
+ if (projectionOptions.namespace === NAMESPACE_SVG && propName === 'href') {
|
|
|
+ domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
|
|
|
+ } else {
|
|
|
+ domNode.setAttribute(propName, propValue);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (domNode[propName] !== propValue) {
|
|
|
+ domNode[propName] = propValue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ propertiesUpdated = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return propertiesUpdated;
|
|
|
+ };
|
|
|
+ var findIndexOfChild = function (children, sameAs, start) {
|
|
|
+ if (sameAs.vnodeSelector !== '') {
|
|
|
+ // Never scan for text-nodes
|
|
|
+ for (var i = start; i < children.length; i++) {
|
|
|
+ if (same(children[i], sameAs)) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ };
|
|
|
+ var nodeAdded = function (vNode, transitions) {
|
|
|
+ if (vNode.properties) {
|
|
|
+ var enterAnimation = vNode.properties.enterAnimation;
|
|
|
+ if (enterAnimation) {
|
|
|
+ if (typeof enterAnimation === 'function') {
|
|
|
+ enterAnimation(vNode.domNode, vNode.properties);
|
|
|
+ } else {
|
|
|
+ transitions.enter(vNode.domNode, vNode.properties, enterAnimation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var nodeToRemove = function (vNode, transitions) {
|
|
|
+ var domNode = vNode.domNode;
|
|
|
+ if (vNode.properties) {
|
|
|
+ var exitAnimation = vNode.properties.exitAnimation;
|
|
|
+ if (exitAnimation) {
|
|
|
+ domNode.style.pointerEvents = 'none';
|
|
|
+ var removeDomNode = function () {
|
|
|
+ if (domNode.parentNode) {
|
|
|
+ domNode.parentNode.removeChild(domNode);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ if (typeof exitAnimation === 'function') {
|
|
|
+ exitAnimation(domNode, removeDomNode, vNode.properties);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ transitions.exit(vNode.domNode, vNode.properties, exitAnimation, removeDomNode);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (domNode.parentNode) {
|
|
|
+ domNode.parentNode.removeChild(domNode);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var checkDistinguishable = function (childNodes, indexToCheck, parentVNode, operation) {
|
|
|
+ var childNode = childNodes[indexToCheck];
|
|
|
+ if (childNode.vnodeSelector === '') {
|
|
|
+ return; // Text nodes need not be distinguishable
|
|
|
+ }
|
|
|
+ var properties = childNode.properties;
|
|
|
+ var key = properties ? properties.key === undefined ? properties.bind : properties.key : undefined;
|
|
|
+ if (!key) {
|
|
|
+ for (var i = 0; i < childNodes.length; i++) {
|
|
|
+ if (i !== indexToCheck) {
|
|
|
+ var node = childNodes[i];
|
|
|
+ if (same(node, childNode)) {
|
|
|
+ if (operation === 'added') {
|
|
|
+ throw new Error(parentVNode.vnodeSelector + ' had a ' + childNode.vnodeSelector + ' child ' + 'added, but there is now more than one. You must add unique key properties to make them distinguishable.');
|
|
|
+ } else {
|
|
|
+ throw new Error(parentVNode.vnodeSelector + ' had a ' + childNode.vnodeSelector + ' child ' + 'removed, but there were more than one. You must add unique key properties to make them distinguishable.');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var createDom;
|
|
|
+ var updateDom;
|
|
|
+ var updateChildren = function (vnode, domNode, oldChildren, newChildren, projectionOptions) {
|
|
|
+ if (oldChildren === newChildren) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ oldChildren = oldChildren || emptyArray;
|
|
|
+ newChildren = newChildren || emptyArray;
|
|
|
+ var oldChildrenLength = oldChildren.length;
|
|
|
+ var newChildrenLength = newChildren.length;
|
|
|
+ var transitions = projectionOptions.transitions;
|
|
|
+ var oldIndex = 0;
|
|
|
+ var newIndex = 0;
|
|
|
+ var i;
|
|
|
+ var textUpdated = false;
|
|
|
+ while (newIndex < newChildrenLength) {
|
|
|
+ var oldChild = oldIndex < oldChildrenLength ? oldChildren[oldIndex] : undefined;
|
|
|
+ var newChild = newChildren[newIndex];
|
|
|
+ if (oldChild !== undefined && same(oldChild, newChild)) {
|
|
|
+ textUpdated = updateDom(oldChild, newChild, projectionOptions) || textUpdated;
|
|
|
+ oldIndex++;
|
|
|
+ } else {
|
|
|
+ var findOldIndex = findIndexOfChild(oldChildren, newChild, oldIndex + 1);
|
|
|
+ if (findOldIndex >= 0) {
|
|
|
+ // Remove preceding missing children
|
|
|
+ for (i = oldIndex; i < findOldIndex; i++) {
|
|
|
+ nodeToRemove(oldChildren[i], transitions);
|
|
|
+ checkDistinguishable(oldChildren, i, vnode, 'removed');
|
|
|
+ }
|
|
|
+ textUpdated = updateDom(oldChildren[findOldIndex], newChild, projectionOptions) || textUpdated;
|
|
|
+ oldIndex = findOldIndex + 1;
|
|
|
+ } else {
|
|
|
+ // New child
|
|
|
+ createDom(newChild, domNode, oldIndex < oldChildrenLength ? oldChildren[oldIndex].domNode : undefined, projectionOptions);
|
|
|
+ nodeAdded(newChild, transitions);
|
|
|
+ checkDistinguishable(newChildren, newIndex, vnode, 'added');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ newIndex++;
|
|
|
+ }
|
|
|
+ if (oldChildrenLength > oldIndex) {
|
|
|
+ // Remove child fragments
|
|
|
+ for (i = oldIndex; i < oldChildrenLength; i++) {
|
|
|
+ nodeToRemove(oldChildren[i], transitions);
|
|
|
+ checkDistinguishable(oldChildren, i, vnode, 'removed');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return textUpdated;
|
|
|
+ };
|
|
|
+ var addChildren = function (domNode, children, projectionOptions) {
|
|
|
+ if (!children) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (var i = 0; i < children.length; i++) {
|
|
|
+ createDom(children[i], domNode, undefined, projectionOptions);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var initPropertiesAndChildren = function (domNode, vnode, projectionOptions) {
|
|
|
+ addChildren(domNode, vnode.children, projectionOptions);
|
|
|
+ // children before properties, needed for value property of <select>.
|
|
|
+ if (vnode.text) {
|
|
|
+ domNode.textContent = vnode.text;
|
|
|
+ }
|
|
|
+ setProperties(domNode, vnode.properties, projectionOptions);
|
|
|
+ if (vnode.properties && vnode.properties.afterCreate) {
|
|
|
+ vnode.properties.afterCreate(domNode, projectionOptions, vnode.vnodeSelector, vnode.properties, vnode.children);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ createDom = function (vnode, parentNode, insertBefore, projectionOptions) {
|
|
|
+ var domNode, i, c, start = 0, type, found;
|
|
|
+ var vnodeSelector = vnode.vnodeSelector;
|
|
|
+ if (vnodeSelector === '') {
|
|
|
+ domNode = vnode.domNode = document.createTextNode(vnode.text);
|
|
|
+ if (insertBefore !== undefined) {
|
|
|
+ parentNode.insertBefore(domNode, insertBefore);
|
|
|
+ } else {
|
|
|
+ parentNode.appendChild(domNode);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (i = 0; i <= vnodeSelector.length; ++i) {
|
|
|
+ c = vnodeSelector.charAt(i);
|
|
|
+ if (i === vnodeSelector.length || c === '.' || c === '#') {
|
|
|
+ type = vnodeSelector.charAt(start - 1);
|
|
|
+ found = vnodeSelector.slice(start, i);
|
|
|
+ if (type === '.') {
|
|
|
+ domNode.classList.add(found);
|
|
|
+ } else if (type === '#') {
|
|
|
+ domNode.id = found;
|
|
|
+ } else {
|
|
|
+ if (found === 'svg') {
|
|
|
+ projectionOptions = extend(projectionOptions, { namespace: NAMESPACE_SVG });
|
|
|
+ }
|
|
|
+ if (projectionOptions.namespace !== undefined) {
|
|
|
+ domNode = vnode.domNode = document.createElementNS(projectionOptions.namespace, found);
|
|
|
+ } else {
|
|
|
+ domNode = vnode.domNode = document.createElement(found);
|
|
|
+ }
|
|
|
+ if (insertBefore !== undefined) {
|
|
|
+ parentNode.insertBefore(domNode, insertBefore);
|
|
|
+ } else {
|
|
|
+ parentNode.appendChild(domNode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ start = i + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ initPropertiesAndChildren(domNode, vnode, projectionOptions);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ updateDom = function (previous, vnode, projectionOptions) {
|
|
|
+ var domNode = previous.domNode;
|
|
|
+ var textUpdated = false;
|
|
|
+ if (previous === vnode) {
|
|
|
+ return false; // By contract, VNode objects may not be modified anymore after passing them to maquette
|
|
|
+ }
|
|
|
+ var updated = false;
|
|
|
+ if (vnode.vnodeSelector === '') {
|
|
|
+ if (vnode.text !== previous.text) {
|
|
|
+ var newVNode = document.createTextNode(vnode.text);
|
|
|
+ domNode.parentNode.replaceChild(newVNode, domNode);
|
|
|
+ vnode.domNode = newVNode;
|
|
|
+ textUpdated = true;
|
|
|
+ return textUpdated;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (vnode.vnodeSelector.lastIndexOf('svg', 0) === 0) {
|
|
|
+ projectionOptions = extend(projectionOptions, { namespace: NAMESPACE_SVG });
|
|
|
+ }
|
|
|
+ if (previous.text !== vnode.text) {
|
|
|
+ updated = true;
|
|
|
+ if (vnode.text === undefined) {
|
|
|
+ domNode.removeChild(domNode.firstChild); // the only textnode presumably
|
|
|
+ } else {
|
|
|
+ domNode.textContent = vnode.text;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ updated = updateChildren(vnode, domNode, previous.children, vnode.children, projectionOptions) || updated;
|
|
|
+ updated = updateProperties(domNode, previous.properties, vnode.properties, projectionOptions) || updated;
|
|
|
+ if (vnode.properties && vnode.properties.afterUpdate) {
|
|
|
+ vnode.properties.afterUpdate(domNode, projectionOptions, vnode.vnodeSelector, vnode.properties, vnode.children);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (updated && vnode.properties && vnode.properties.updateAnimation) {
|
|
|
+ vnode.properties.updateAnimation(domNode, vnode.properties, previous.properties);
|
|
|
+ }
|
|
|
+ vnode.domNode = previous.domNode;
|
|
|
+ return textUpdated;
|
|
|
+ };
|
|
|
+ var createProjection = function (vnode, projectionOptions) {
|
|
|
+ return {
|
|
|
+ update: function (updatedVnode) {
|
|
|
+ if (vnode.vnodeSelector !== updatedVnode.vnodeSelector) {
|
|
|
+ throw new Error('The selector for the root VNode may not be changed. (consider using dom.merge and add one extra level to the virtual DOM)');
|
|
|
+ }
|
|
|
+ updateDom(vnode, updatedVnode, projectionOptions);
|
|
|
+ vnode = updatedVnode;
|
|
|
+ },
|
|
|
+ domNode: vnode.domNode
|
|
|
+ };
|
|
|
+ };
|
|
|
+ ;
|
|
|
+ // The other two parameters are not added here, because the Typescript compiler creates surrogate code for desctructuring 'children'.
|
|
|
+ exports.h = function (selector) {
|
|
|
+ var properties = arguments[1];
|
|
|
+ if (typeof selector !== 'string') {
|
|
|
+ throw new Error();
|
|
|
+ }
|
|
|
+ var childIndex = 1;
|
|
|
+ if (properties && !properties.hasOwnProperty('vnodeSelector') && !Array.isArray(properties) && typeof properties === 'object') {
|
|
|
+ childIndex = 2;
|
|
|
+ } else {
|
|
|
+ // Optional properties argument was omitted
|
|
|
+ properties = undefined;
|
|
|
+ }
|
|
|
+ var text = undefined;
|
|
|
+ var children = undefined;
|
|
|
+ var argsLength = arguments.length;
|
|
|
+ // Recognize a common special case where there is only a single text node
|
|
|
+ if (argsLength === childIndex + 1) {
|
|
|
+ var onlyChild = arguments[childIndex];
|
|
|
+ if (typeof onlyChild === 'string') {
|
|
|
+ text = onlyChild;
|
|
|
+ } else if (onlyChild !== undefined && onlyChild.length === 1 && typeof onlyChild[0] === 'string') {
|
|
|
+ text = onlyChild[0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (text === undefined) {
|
|
|
+ children = [];
|
|
|
+ for (; childIndex < arguments.length; childIndex++) {
|
|
|
+ var child = arguments[childIndex];
|
|
|
+ if (child === null || child === undefined) {
|
|
|
+ continue;
|
|
|
+ } else if (Array.isArray(child)) {
|
|
|
+ appendChildren(selector, child, children);
|
|
|
+ } else if (child.hasOwnProperty('vnodeSelector')) {
|
|
|
+ children.push(child);
|
|
|
+ } else {
|
|
|
+ children.push(toTextVNode(child));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ vnodeSelector: selector,
|
|
|
+ properties: properties,
|
|
|
+ children: children,
|
|
|
+ text: text === '' ? undefined : text,
|
|
|
+ domNode: null
|
|
|
+ };
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Contains simple low-level utility functions to manipulate the real DOM.
|
|
|
+ */
|
|
|
+ exports.dom = {
|
|
|
+ /**
|
|
|
+ * Creates a real DOM tree from `vnode`. The [[Projection]] object returned will contain the resulting DOM Node in
|
|
|
+ * its [[Projection.domNode|domNode]] property.
|
|
|
+ * This is a low-level method. Users wil typically use a [[Projector]] instead.
|
|
|
+ * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
|
|
|
+ * objects may only be rendered once.
|
|
|
+ * @param projectionOptions - Options to be used to create and update the projection.
|
|
|
+ * @returns The [[Projection]] which also contains the DOM Node that was created.
|
|
|
+ */
|
|
|
+ create: function (vnode, projectionOptions) {
|
|
|
+ projectionOptions = applyDefaultProjectionOptions(projectionOptions);
|
|
|
+ createDom(vnode, document.createElement('div'), undefined, projectionOptions);
|
|
|
+ return createProjection(vnode, projectionOptions);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Appends a new childnode to the DOM which is generated from a [[VNode]].
|
|
|
+ * This is a low-level method. Users wil typically use a [[Projector]] instead.
|
|
|
+ * @param parentNode - The parent node for the new childNode.
|
|
|
+ * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
|
|
|
+ * objects may only be rendered once.
|
|
|
+ * @param projectionOptions - Options to be used to create and update the [[Projection]].
|
|
|
+ * @returns The [[Projection]] that was created.
|
|
|
+ */
|
|
|
+ append: function (parentNode, vnode, projectionOptions) {
|
|
|
+ projectionOptions = applyDefaultProjectionOptions(projectionOptions);
|
|
|
+ createDom(vnode, parentNode, undefined, projectionOptions);
|
|
|
+ return createProjection(vnode, projectionOptions);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Inserts a new DOM node which is generated from a [[VNode]].
|
|
|
+ * This is a low-level method. Users wil typically use a [[Projector]] instead.
|
|
|
+ * @param beforeNode - The node that the DOM Node is inserted before.
|
|
|
+ * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function.
|
|
|
+ * NOTE: [[VNode]] objects may only be rendered once.
|
|
|
+ * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
|
|
|
+ * @returns The [[Projection]] that was created.
|
|
|
+ */
|
|
|
+ insertBefore: function (beforeNode, vnode, projectionOptions) {
|
|
|
+ projectionOptions = applyDefaultProjectionOptions(projectionOptions);
|
|
|
+ createDom(vnode, beforeNode.parentNode, beforeNode, projectionOptions);
|
|
|
+ return createProjection(vnode, projectionOptions);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Merges a new DOM node which is generated from a [[VNode]] with an existing DOM Node.
|
|
|
+ * This means that the virtual DOM and the real DOM will have one overlapping element.
|
|
|
+ * Therefore the selector for the root [[VNode]] will be ignored, but its properties and children will be applied to the Element provided.
|
|
|
+ * This is a low-level method. Users wil typically use a [[Projector]] instead.
|
|
|
+ * @param domNode - The existing element to adopt as the root of the new virtual DOM. Existing attributes and childnodes are preserved.
|
|
|
+ * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]] objects
|
|
|
+ * may only be rendered once.
|
|
|
+ * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
|
|
|
+ * @returns The [[Projection]] that was created.
|
|
|
+ */
|
|
|
+ merge: function (element, vnode, projectionOptions) {
|
|
|
+ projectionOptions = applyDefaultProjectionOptions(projectionOptions);
|
|
|
+ vnode.domNode = element;
|
|
|
+ initPropertiesAndChildren(element, vnode, projectionOptions);
|
|
|
+ return createProjection(vnode, projectionOptions);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Creates a [[CalculationCache]] object, useful for caching [[VNode]] trees.
|
|
|
+ * In practice, caching of [[VNode]] trees is not needed, because achieving 60 frames per second is almost never a problem.
|
|
|
+ * For more information, see [[CalculationCache]].
|
|
|
+ *
|
|
|
+ * @param <Result> The type of the value that is cached.
|
|
|
+ */
|
|
|
+ exports.createCache = function () {
|
|
|
+ var cachedInputs = undefined;
|
|
|
+ var cachedOutcome = undefined;
|
|
|
+ var result = {
|
|
|
+ invalidate: function () {
|
|
|
+ cachedOutcome = undefined;
|
|
|
+ cachedInputs = undefined;
|
|
|
+ },
|
|
|
+ result: function (inputs, calculation) {
|
|
|
+ if (cachedInputs) {
|
|
|
+ for (var i = 0; i < inputs.length; i++) {
|
|
|
+ if (cachedInputs[i] !== inputs[i]) {
|
|
|
+ cachedOutcome = undefined;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!cachedOutcome) {
|
|
|
+ cachedOutcome = calculation();
|
|
|
+ cachedInputs = inputs;
|
|
|
+ }
|
|
|
+ return cachedOutcome;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return result;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Creates a {@link Mapping} instance that keeps an array of result objects synchronized with an array of source objects.
|
|
|
+ * See {@link http://maquettejs.org/docs/arrays.html|Working with arrays}.
|
|
|
+ *
|
|
|
+ * @param <Source> The type of source items. A database-record for instance.
|
|
|
+ * @param <Target> The type of target items. A [[Component]] for instance.
|
|
|
+ * @param getSourceKey `function(source)` that must return a key to identify each source object. The result must either be a string or a number.
|
|
|
+ * @param createResult `function(source, index)` that must create a new result object from a given source. This function is identical
|
|
|
+ * to the `callback` argument in `Array.map(callback)`.
|
|
|
+ * @param updateResult `function(source, target, index)` that updates a result to an updated source.
|
|
|
+ */
|
|
|
+ exports.createMapping = function (getSourceKey, createResult, updateResult) {
|
|
|
+ var keys = [];
|
|
|
+ var results = [];
|
|
|
+ return {
|
|
|
+ results: results,
|
|
|
+ map: function (newSources) {
|
|
|
+ var newKeys = newSources.map(getSourceKey);
|
|
|
+ var oldTargets = results.slice();
|
|
|
+ var oldIndex = 0;
|
|
|
+ for (var i = 0; i < newSources.length; i++) {
|
|
|
+ var source = newSources[i];
|
|
|
+ var sourceKey = newKeys[i];
|
|
|
+ if (sourceKey === keys[oldIndex]) {
|
|
|
+ results[i] = oldTargets[oldIndex];
|
|
|
+ updateResult(source, oldTargets[oldIndex], i);
|
|
|
+ oldIndex++;
|
|
|
+ } else {
|
|
|
+ var found = false;
|
|
|
+ for (var j = 1; j < keys.length; j++) {
|
|
|
+ var searchIndex = (oldIndex + j) % keys.length;
|
|
|
+ if (keys[searchIndex] === sourceKey) {
|
|
|
+ results[i] = oldTargets[searchIndex];
|
|
|
+ updateResult(newSources[i], oldTargets[searchIndex], i);
|
|
|
+ oldIndex = searchIndex + 1;
|
|
|
+ found = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!found) {
|
|
|
+ results[i] = createResult(source, i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ results.length = newSources.length;
|
|
|
+ keys = newKeys;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Creates a [[Projector]] instance using the provided projectionOptions.
|
|
|
+ *
|
|
|
+ * For more information, see [[Projector]].
|
|
|
+ *
|
|
|
+ * @param projectionOptions Options that influence how the DOM is rendered and updated.
|
|
|
+ */
|
|
|
+ exports.createProjector = function (projectorOptions) {
|
|
|
+ var projector;
|
|
|
+ var projectionOptions = applyDefaultProjectionOptions(projectorOptions);
|
|
|
+ projectionOptions.eventHandlerInterceptor = function (propertyName, eventHandler, domNode, properties) {
|
|
|
+ return function () {
|
|
|
+ // intercept function calls (event handlers) to do a render afterwards.
|
|
|
+ projector.scheduleRender();
|
|
|
+ return eventHandler.apply(properties.bind || this, arguments);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ var renderCompleted = true;
|
|
|
+ var scheduled;
|
|
|
+ var stopped = false;
|
|
|
+ var projections = [];
|
|
|
+ var renderFunctions = [];
|
|
|
+ // matches the projections array
|
|
|
+ var doRender = function () {
|
|
|
+ scheduled = undefined;
|
|
|
+ if (!renderCompleted) {
|
|
|
+ return; // The last render threw an error, it should be logged in the browser console.
|
|
|
+ }
|
|
|
+ renderCompleted = false;
|
|
|
+ for (var i = 0; i < projections.length; i++) {
|
|
|
+ var updatedVnode = renderFunctions[i]();
|
|
|
+ projections[i].update(updatedVnode);
|
|
|
+ }
|
|
|
+ renderCompleted = true;
|
|
|
+ };
|
|
|
+ projector = {
|
|
|
+ scheduleRender: function () {
|
|
|
+ if (!scheduled && !stopped) {
|
|
|
+ scheduled = requestAnimationFrame(doRender);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ stop: function () {
|
|
|
+ if (scheduled) {
|
|
|
+ cancelAnimationFrame(scheduled);
|
|
|
+ scheduled = undefined;
|
|
|
+ }
|
|
|
+ stopped = true;
|
|
|
+ },
|
|
|
+ resume: function () {
|
|
|
+ stopped = false;
|
|
|
+ renderCompleted = true;
|
|
|
+ projector.scheduleRender();
|
|
|
+ },
|
|
|
+ append: function (parentNode, renderMaquetteFunction) {
|
|
|
+ projections.push(exports.dom.append(parentNode, renderMaquetteFunction(), projectionOptions));
|
|
|
+ renderFunctions.push(renderMaquetteFunction);
|
|
|
+ },
|
|
|
+ insertBefore: function (beforeNode, renderMaquetteFunction) {
|
|
|
+ projections.push(exports.dom.insertBefore(beforeNode, renderMaquetteFunction(), projectionOptions));
|
|
|
+ renderFunctions.push(renderMaquetteFunction);
|
|
|
+ },
|
|
|
+ merge: function (domNode, renderMaquetteFunction) {
|
|
|
+ projections.push(exports.dom.merge(domNode, renderMaquetteFunction(), projectionOptions));
|
|
|
+ renderFunctions.push(renderMaquetteFunction);
|
|
|
+ },
|
|
|
+ replace: function (domNode, renderMaquetteFunction) {
|
|
|
+ var vnode = renderMaquetteFunction();
|
|
|
+ createDom(vnode, domNode.parentNode, domNode, projectionOptions);
|
|
|
+ domNode.parentNode.removeChild(domNode);
|
|
|
+ projections.push(createProjection(vnode, projectionOptions));
|
|
|
+ renderFunctions.push(renderMaquetteFunction);
|
|
|
+ },
|
|
|
+ detach: function (renderMaquetteFunction) {
|
|
|
+ for (var i = 0; i < renderFunctions.length; i++) {
|
|
|
+ if (renderFunctions[i] === renderMaquetteFunction) {
|
|
|
+ renderFunctions.splice(i, 1);
|
|
|
+ return projections.splice(i, 1)[0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new Error('renderMaquetteFunction was not found');
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return projector;
|
|
|
+ };
|
|
|
+}));
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/utils/Dollar.coffee ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function() {
|
|
|
+ window.$ = function(selector) {
|
|
|
+ if (selector.startsWith("#")) {
|
|
|
+ return document.getElementById(selector.replace("#", ""));
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+}).call(this);
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/utils/ZeroFrame.coffee ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function() {
|
|
|
+ var ZeroFrame,
|
|
|
+ bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
|
|
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
|
+ hasProp = {}.hasOwnProperty;
|
|
|
+
|
|
|
+ ZeroFrame = (function(superClass) {
|
|
|
+ extend(ZeroFrame, superClass);
|
|
|
+
|
|
|
+ function ZeroFrame(url) {
|
|
|
+ this.onCloseWebsocket = bind(this.onCloseWebsocket, this);
|
|
|
+ this.onOpenWebsocket = bind(this.onOpenWebsocket, this);
|
|
|
+ this.onRequest = bind(this.onRequest, this);
|
|
|
+ this.onMessage = bind(this.onMessage, this);
|
|
|
+ this.url = url;
|
|
|
+ this.waiting_cb = {};
|
|
|
+ this.wrapper_nonce = document.location.href.replace(/.*wrapper_nonce=([A-Za-z0-9]+).*/, "$1");
|
|
|
+ this.connect();
|
|
|
+ this.next_message_id = 1;
|
|
|
+ this.history_state = {};
|
|
|
+ this.init();
|
|
|
+ }
|
|
|
+
|
|
|
+ ZeroFrame.prototype.init = function() {
|
|
|
+ return this;
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.connect = function() {
|
|
|
+ this.target = window.parent;
|
|
|
+ window.addEventListener("message", this.onMessage, false);
|
|
|
+ this.cmd("innerReady");
|
|
|
+ window.addEventListener("beforeunload", (function(_this) {
|
|
|
+ return function(e) {
|
|
|
+ _this.log("save scrollTop", window.pageYOffset);
|
|
|
+ _this.history_state["scrollTop"] = window.pageYOffset;
|
|
|
+ return _this.cmd("wrapperReplaceState", [_this.history_state, null]);
|
|
|
+ };
|
|
|
+ })(this));
|
|
|
+ return this.cmd("wrapperGetState", [], (function(_this) {
|
|
|
+ return function(state) {
|
|
|
+ if (state != null) {
|
|
|
+ _this.history_state = state;
|
|
|
+ }
|
|
|
+ _this.log("restore scrollTop", state, window.pageYOffset);
|
|
|
+ if (window.pageYOffset === 0 && state) {
|
|
|
+ return window.scroll(window.pageXOffset, state.scrollTop);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ })(this));
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.onMessage = function(e) {
|
|
|
+ var cmd, message;
|
|
|
+ message = e.data;
|
|
|
+ cmd = message.cmd;
|
|
|
+ if (cmd === "response") {
|
|
|
+ if (this.waiting_cb[message.to] != null) {
|
|
|
+ return this.waiting_cb[message.to](message.result);
|
|
|
+ } else {
|
|
|
+ return this.log("Websocket callback not found:", message);
|
|
|
+ }
|
|
|
+ } else if (cmd === "wrapperReady") {
|
|
|
+ return this.cmd("innerReady");
|
|
|
+ } else if (cmd === "ping") {
|
|
|
+ return this.response(message.id, "pong");
|
|
|
+ } else if (cmd === "wrapperOpenedWebsocket") {
|
|
|
+ return this.onOpenWebsocket();
|
|
|
+ } else if (cmd === "wrapperClosedWebsocket") {
|
|
|
+ return this.onCloseWebsocket();
|
|
|
+ } else {
|
|
|
+ return this.onRequest(cmd, message.params);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.onRequest = function(cmd, message) {
|
|
|
+ return this.log("Unknown request", message);
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.response = function(to, result) {
|
|
|
+ return this.send({
|
|
|
+ "cmd": "response",
|
|
|
+ "to": to,
|
|
|
+ "result": result
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.cmd = function(cmd, params, cb) {
|
|
|
+ if (params == null) {
|
|
|
+ params = {};
|
|
|
+ }
|
|
|
+ if (cb == null) {
|
|
|
+ cb = null;
|
|
|
+ }
|
|
|
+ return this.send({
|
|
|
+ "cmd": cmd,
|
|
|
+ "params": params
|
|
|
+ }, cb);
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.send = function(message, cb) {
|
|
|
+ if (cb == null) {
|
|
|
+ cb = null;
|
|
|
+ }
|
|
|
+ message.wrapper_nonce = this.wrapper_nonce;
|
|
|
+ message.id = this.next_message_id;
|
|
|
+ this.next_message_id += 1;
|
|
|
+ this.target.postMessage(message, "*");
|
|
|
+ if (cb) {
|
|
|
+ return this.waiting_cb[message.id] = cb;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.onOpenWebsocket = function() {
|
|
|
+ return this.log("Websocket open");
|
|
|
+ };
|
|
|
+
|
|
|
+ ZeroFrame.prototype.onCloseWebsocket = function() {
|
|
|
+ return this.log("Websocket close");
|
|
|
+ };
|
|
|
+
|
|
|
+ return ZeroFrame;
|
|
|
+
|
|
|
+ })(Class);
|
|
|
+
|
|
|
+ window.ZeroFrame = ZeroFrame;
|
|
|
+
|
|
|
+}).call(this);
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/ConfigStorage.coffee ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function() {
|
|
|
+ var ConfigStorage,
|
|
|
+ bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
|
|
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
|
+ hasProp = {}.hasOwnProperty;
|
|
|
+
|
|
|
+ ConfigStorage = (function(superClass) {
|
|
|
+ extend(ConfigStorage, superClass);
|
|
|
+
|
|
|
+ function ConfigStorage(config) {
|
|
|
+ this.config = config;
|
|
|
+ this.createSection = bind(this.createSection, this);
|
|
|
+ this.items = [];
|
|
|
+ this.createSections();
|
|
|
+ this.setValues(this.config);
|
|
|
+ }
|
|
|
+
|
|
|
+ ConfigStorage.prototype.setValues = function(values) {
|
|
|
+ var i, item, len, ref, results, section;
|
|
|
+ ref = this.items;
|
|
|
+ results = [];
|
|
|
+ for (i = 0, len = ref.length; i < len; i++) {
|
|
|
+ section = ref[i];
|
|
|
+ results.push((function() {
|
|
|
+ var j, len1, ref1, results1;
|
|
|
+ ref1 = section.items;
|
|
|
+ results1 = [];
|
|
|
+ for (j = 0, len1 = ref1.length; j < len1; j++) {
|
|
|
+ item = ref1[j];
|
|
|
+ if (!values[item.key]) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ item.value = this.formatValue(values[item.key].value);
|
|
|
+ item["default"] = this.formatValue(values[item.key]["default"]);
|
|
|
+ results1.push(item.pending = values[item.key].pending);
|
|
|
+ }
|
|
|
+ return results1;
|
|
|
+ }).call(this));
|
|
|
+ }
|
|
|
+ return results;
|
|
|
+ };
|
|
|
+
|
|
|
+ ConfigStorage.prototype.formatValue = function(value) {
|
|
|
+ if (!value) {
|
|
|
+ return false;
|
|
|
+ } else if (typeof value === "object") {
|
|
|
+ return value.join("\n");
|
|
|
+ } else if (typeof value === "number") {
|
|
|
+ return value.toString();
|
|
|
+ } else {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ ConfigStorage.prototype.deformatValue = function(value, type) {
|
|
|
+ if (type === "object") {
|
|
|
+ return value.split("\n");
|
|
|
+ }
|
|
|
+ if (type === "boolean" && !value) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ ConfigStorage.prototype.createSections = function() {
|
|
|
+ var section;
|
|
|
+ section = this.createSection("Web Interface");
|
|
|
+ section.items.push({
|
|
|
+ key: "open_browser",
|
|
|
+ title: "Open web browser on ZeroNet startup",
|
|
|
+ type: "checkbox"
|
|
|
+ });
|
|
|
+ section = this.createSection("Network");
|
|
|
+ section.items.push({
|
|
|
+ key: "fileserver_port",
|
|
|
+ title: "File server port",
|
|
|
+ type: "text",
|
|
|
+ restrict: "number",
|
|
|
+ description: "Other peers will use this port to reach your served sites. (default: 15441)"
|
|
|
+ });
|
|
|
+ section.items.push({
|
|
|
+ title: "Tor",
|
|
|
+ key: "tor",
|
|
|
+ type: "select",
|
|
|
+ options: [
|
|
|
+ {
|
|
|
+ title: "Disable",
|
|
|
+ value: "disable"
|
|
|
+ }, {
|
|
|
+ title: "Enable",
|
|
|
+ value: "enable"
|
|
|
+ }, {
|
|
|
+ title: "Always",
|
|
|
+ value: "always"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ value: "Enable",
|
|
|
+ description: ["Disable: Don't connect to peers on Tor network", h("br"), "Enable: Only use Tor for Tor network peers", h("br"), "Always: Use Tor for every connections to hide your IP address (slower)"]
|
|
|
+ });
|
|
|
+ section.items.push({
|
|
|
+ title: "Use Tor bridges",
|
|
|
+ key: "tor_use_bridges",
|
|
|
+ type: "checkbox",
|
|
|
+ description: "Use obfuscated bridge relays to avoid network level Tor block (even slower)"
|
|
|
+ });
|
|
|
+ section.items.push({
|
|
|
+ title: "Trackers",
|
|
|
+ key: "trackers",
|
|
|
+ type: "textarea",
|
|
|
+ description: "Discover new peers using these adresses"
|
|
|
+ });
|
|
|
+ section.items.push({
|
|
|
+ title: "Trackers files",
|
|
|
+ key: "trackers_file",
|
|
|
+ type: "text",
|
|
|
+ description: "Load additional list of torrent trackers dynamically, from a file",
|
|
|
+ placeholder: "Eg.: data/trackers.json",
|
|
|
+ value_pos: "fullwidth"
|
|
|
+ });
|
|
|
+ return section.items.push({
|
|
|
+ title: "Proxy for tracker connections",
|
|
|
+ key: "trackers_proxy",
|
|
|
+ type: "select",
|
|
|
+ options: [
|
|
|
+ {
|
|
|
+ title: "Disable",
|
|
|
+ value: "disable"
|
|
|
+ }, {
|
|
|
+ title: "Tor",
|
|
|
+ value: "tor"
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ ConfigStorage.prototype.createSection = function(title) {
|
|
|
+ var section;
|
|
|
+ section = {};
|
|
|
+ section.title = title;
|
|
|
+ section.items = [];
|
|
|
+ this.items.push(section);
|
|
|
+ return section;
|
|
|
+ };
|
|
|
+
|
|
|
+ return ConfigStorage;
|
|
|
+
|
|
|
+ })(Class);
|
|
|
+
|
|
|
+ window.ConfigStorage = ConfigStorage;
|
|
|
+
|
|
|
+}).call(this);
|
|
|
+
|
|
|
+
|
|
|
+/* ---- plugins/UiConfig/media/js/UiConfig.coffee ---- */
|
|
|
+
|
|
|
+
|
|
|
+(function() {
|
|
|
+ var UiConfig,
|
|
|
+ bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
|
|
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
|
+ hasProp = {}.hasOwnProperty;
|
|
|
+
|
|
|
+ window.h = maquette.h;
|
|
|
+
|
|
|
+ UiConfig = (function(superClass) {
|
|
|
+ extend(UiConfig, superClass);
|
|
|
+
|
|
|
+ function UiConfig() {
|
|
|
+ this.renderBottomRestart = bind(this.renderBottomRestart, this);
|
|
|
+ this.handleRestartClick = bind(this.handleRestartClick, this);
|
|
|
+ this.renderBottomSave = bind(this.renderBottomSave, this);
|
|
|
+ this.handleSaveClick = bind(this.handleSaveClick, this);
|
|
|
+ this.render = bind(this.render, this);
|
|
|
+ this.renderValueSelect = bind(this.renderValueSelect, this);
|
|
|
+ this.renderValueCheckbox = bind(this.renderValueCheckbox, this);
|
|
|
+ this.renderValueTextarea = bind(this.renderValueTextarea, this);
|
|
|
+ this.autosizeTextarea = bind(this.autosizeTextarea, this);
|
|
|
+ this.renderValueText = bind(this.renderValueText, this);
|
|
|
+ this.handleCheckboxChange = bind(this.handleCheckboxChange, this);
|
|
|
+ this.handleInputChange = bind(this.handleInputChange, this);
|
|
|
+ this.renderSectionItem = bind(this.renderSectionItem, this);
|
|
|
+ this.handleResetClick = bind(this.handleResetClick, this);
|
|
|
+ this.renderSection = bind(this.renderSection, this);
|
|
|
+ this.saveValue = bind(this.saveValue, this);
|
|
|
+ this.saveValues = bind(this.saveValues, this);
|
|
|
+ this.getValuesPending = bind(this.getValuesPending, this);
|
|
|
+ this.getValuesChanged = bind(this.getValuesChanged, this);
|
|
|
+ this.createProjector = bind(this.createProjector, this);
|
|
|
+ this.updateConfig = bind(this.updateConfig, this);
|
|
|
+ this.onOpenWebsocket = bind(this.onOpenWebsocket, this);
|
|
|
+ return UiConfig.__super__.constructor.apply(this, arguments);
|
|
|
+ }
|
|
|
+
|
|
|
+ UiConfig.prototype.init = function() {
|
|
|
+ this.save_visible = true;
|
|
|
+ this.config = null;
|
|
|
+ this.values = null;
|
|
|
+ return window.onbeforeunload = (function(_this) {
|
|
|
+ return function() {
|
|
|
+ if (_this.getValuesChanged().length > 0) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ })(this);
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.onOpenWebsocket = function() {
|
|
|
+ this.cmd("wrapperSetTitle", "Config - ZeroNet");
|
|
|
+ return this.updateConfig();
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.updateConfig = function(cb) {
|
|
|
+ return this.cmd("configList", [], (function(_this) {
|
|
|
+ return function(res) {
|
|
|
+ var item, key;
|
|
|
+ _this.config = res;
|
|
|
+ _this.values = {};
|
|
|
+ _this.config_storage = new ConfigStorage(_this.config);
|
|
|
+ for (key in res) {
|
|
|
+ item = res[key];
|
|
|
+ _this.values[key] = _this.config_storage.formatValue(item.value);
|
|
|
+ }
|
|
|
+ _this.projector.scheduleRender();
|
|
|
+ return typeof cb === "function" ? cb() : void 0;
|
|
|
+ };
|
|
|
+ })(this));
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.createProjector = function() {
|
|
|
+ this.projector = maquette.createProjector();
|
|
|
+ this.projector.replace($("#content"), this.render);
|
|
|
+ this.projector.replace($("#bottom-save"), this.renderBottomSave);
|
|
|
+ return this.projector.replace($("#bottom-restart"), this.renderBottomRestart);
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.getValuesChanged = function() {
|
|
|
+ var key, ref, value, values_changed;
|
|
|
+ values_changed = [];
|
|
|
+ ref = this.values;
|
|
|
+ for (key in ref) {
|
|
|
+ value = ref[key];
|
|
|
+ if (this.config_storage.formatValue(value) !== this.config_storage.formatValue(this.config[key].value)) {
|
|
|
+ values_changed.push({
|
|
|
+ key: key,
|
|
|
+ value: value
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return values_changed;
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.getValuesPending = function() {
|
|
|
+ var item, key, ref, values_pending;
|
|
|
+ values_pending = [];
|
|
|
+ ref = this.config;
|
|
|
+ for (key in ref) {
|
|
|
+ item = ref[key];
|
|
|
+ if (item.pending) {
|
|
|
+ values_pending.push(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return values_pending;
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.saveValues = function(cb) {
|
|
|
+ var changed_values, i, item, j, last, len, results, value, value_same_as_default;
|
|
|
+ changed_values = this.getValuesChanged();
|
|
|
+ results = [];
|
|
|
+ for (i = j = 0, len = changed_values.length; j < len; i = ++j) {
|
|
|
+ item = changed_values[i];
|
|
|
+ last = i === changed_values.length - 1;
|
|
|
+ value = this.config_storage.deformatValue(item.value, typeof this.config[item.key]["default"]);
|
|
|
+ value_same_as_default = JSON.stringify(this.config[item.key]["default"]) === JSON.stringify(value);
|
|
|
+ if (value_same_as_default) {
|
|
|
+ value = null;
|
|
|
+ }
|
|
|
+ results.push(this.saveValue(item.key, value, last ? cb : null));
|
|
|
+ }
|
|
|
+ return results;
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.saveValue = function(key, value, cb) {
|
|
|
+ if (key === "open_browser") {
|
|
|
+ if (value) {
|
|
|
+ value = "default_browser";
|
|
|
+ } else {
|
|
|
+ value = "False";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Page.cmd("configSet", [key, value], (function(_this) {
|
|
|
+ return function(res) {
|
|
|
+ if (res !== "ok") {
|
|
|
+ Page.cmd("wrapperNotification", ["error", res.error]);
|
|
|
+ }
|
|
|
+ return typeof cb === "function" ? cb() : void 0;
|
|
|
+ };
|
|
|
+ })(this));
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderSection = function(section) {
|
|
|
+ return h("div.section", {
|
|
|
+ key: section.title
|
|
|
+ }, [h("h2", section.title), h("div.config-items", section.items.map(this.renderSectionItem))]);
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.handleResetClick = function(e) {
|
|
|
+ var config_key, default_value, node, ref;
|
|
|
+ node = e.currentTarget;
|
|
|
+ config_key = node.attributes.config_key.value;
|
|
|
+ default_value = (ref = node.attributes.default_value) != null ? ref.value : void 0;
|
|
|
+ return Page.cmd("wrapperConfirm", ["Reset " + config_key + " value?", "Reset to default"], (function(_this) {
|
|
|
+ return function(res) {
|
|
|
+ if (res) {
|
|
|
+ _this.values[config_key] = default_value;
|
|
|
+ }
|
|
|
+ return Page.projector.scheduleRender();
|
|
|
+ };
|
|
|
+ })(this));
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderSectionItem = function(item) {
|
|
|
+ var marker_title, ref, value_changed, value_default, value_pos;
|
|
|
+ value_pos = item.value_pos;
|
|
|
+ if (item.type === "textarea") {
|
|
|
+ if (value_pos == null) {
|
|
|
+ value_pos = "fullwidth";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (value_pos == null) {
|
|
|
+ value_pos = "right";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ value_changed = this.config_storage.formatValue(this.values[item.key]) !== item.value;
|
|
|
+ value_default = this.config_storage.formatValue(this.values[item.key]) === item["default"];
|
|
|
+ if ((ref = item.key) === "open_browser" || ref === "fileserver_port") {
|
|
|
+ value_default = true;
|
|
|
+ }
|
|
|
+ marker_title = "Changed from default value: " + item["default"] + " -> " + this.values[item.key];
|
|
|
+ if (item.pending) {
|
|
|
+ marker_title += " (change pending until client restart)";
|
|
|
+ }
|
|
|
+ return h("div.config-item", [
|
|
|
+ h("div.title", [h("h3", item.title), h("div.description", item.description)]), h("div.value.value-" + value_pos, item.type === "select" ? this.renderValueSelect(item) : item.type === "checkbox" ? this.renderValueCheckbox(item) : item.type === "textarea" ? this.renderValueTextarea(item) : this.renderValueText(item), h("a.marker", {
|
|
|
+ href: "#Reset",
|
|
|
+ title: marker_title,
|
|
|
+ onclick: this.handleResetClick,
|
|
|
+ config_key: item.key,
|
|
|
+ default_value: item["default"],
|
|
|
+ classes: {
|
|
|
+ "default": value_default,
|
|
|
+ changed: value_changed,
|
|
|
+ visible: !value_default || value_changed || item.pending,
|
|
|
+ pending: item.pending
|
|
|
+ }
|
|
|
+ }, "\u2022"))
|
|
|
+ ]);
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.handleInputChange = function(e) {
|
|
|
+ var config_key, node;
|
|
|
+ node = e.target;
|
|
|
+ config_key = node.attributes.config_key.value;
|
|
|
+ this.values[config_key] = node.value;
|
|
|
+ return Page.projector.scheduleRender();
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.handleCheckboxChange = function(e) {
|
|
|
+ var config_key, node, value;
|
|
|
+ node = e.currentTarget;
|
|
|
+ config_key = node.attributes.config_key.value;
|
|
|
+ value = !node.classList.contains("checked");
|
|
|
+ this.values[config_key] = value;
|
|
|
+ return Page.projector.scheduleRender();
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderValueText = function(item) {
|
|
|
+ var value;
|
|
|
+ value = this.values[item.key];
|
|
|
+ if (!value) {
|
|
|
+ value = "";
|
|
|
+ }
|
|
|
+ return h("input.input-" + item.type, {
|
|
|
+ type: item.type,
|
|
|
+ config_key: item.key,
|
|
|
+ value: value,
|
|
|
+ placeholder: item.placeholder,
|
|
|
+ oninput: this.handleInputChange
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.autosizeTextarea = function(e) {
|
|
|
+ var h, height_before, node, scrollh;
|
|
|
+ this.log("autosize", arguments);
|
|
|
+ if (e.currentTarget) {
|
|
|
+ node = e.currentTarget;
|
|
|
+ } else {
|
|
|
+ node = e;
|
|
|
+ }
|
|
|
+ height_before = node.style.height;
|
|
|
+ if (height_before) {
|
|
|
+ node.style.height = "0px";
|
|
|
+ }
|
|
|
+ h = node.offsetHeight;
|
|
|
+ scrollh = node.scrollHeight + 20;
|
|
|
+ if (scrollh > h) {
|
|
|
+ return node.style.height = scrollh + "px";
|
|
|
+ } else {
|
|
|
+ return node.style.height = height_before;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderValueTextarea = function(item) {
|
|
|
+ var value;
|
|
|
+ value = this.values[item.key];
|
|
|
+ if (!value) {
|
|
|
+ value = "";
|
|
|
+ }
|
|
|
+ return h("textarea.input-" + item.type + ".input-text", {
|
|
|
+ type: item.type,
|
|
|
+ config_key: item.key,
|
|
|
+ oninput: this.handleInputChange,
|
|
|
+ afterCreate: this.autosizeTextarea,
|
|
|
+ updateAnimation: this.autosizeTextarea,
|
|
|
+ value: value
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderValueCheckbox = function(item) {
|
|
|
+ var checked;
|
|
|
+ if (this.values[item.key] && this.values[item.key] !== "False") {
|
|
|
+ checked = true;
|
|
|
+ } else {
|
|
|
+ checked = false;
|
|
|
+ }
|
|
|
+ return h("div.checkbox", {
|
|
|
+ onclick: this.handleCheckboxChange,
|
|
|
+ config_key: item.key,
|
|
|
+ classes: {
|
|
|
+ checked: checked
|
|
|
+ }
|
|
|
+ }, h("div.checkbox-skin"));
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderValueSelect = function(item) {
|
|
|
+ return h("select.input-select", {
|
|
|
+ config_key: item.key,
|
|
|
+ oninput: this.handleInputChange
|
|
|
+ }, item.options.map((function(_this) {
|
|
|
+ return function(option) {
|
|
|
+ return h("option", {
|
|
|
+ selected: option.value === _this.values[item.key],
|
|
|
+ value: option.value
|
|
|
+ }, option.title);
|
|
|
+ };
|
|
|
+ })(this)));
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.render = function() {
|
|
|
+ if (!this.config) {
|
|
|
+ return h("div.content");
|
|
|
+ }
|
|
|
+ return h("div.content", [this.config_storage.items.map(this.renderSection)]);
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.handleSaveClick = function() {
|
|
|
+ this.save_loading = true;
|
|
|
+ this.logStart("Save");
|
|
|
+ this.saveValues((function(_this) {
|
|
|
+ return function() {
|
|
|
+ _this.save_loading = false;
|
|
|
+ _this.logEnd("Save");
|
|
|
+ _this.updateConfig();
|
|
|
+ return Page.projector.scheduleRender();
|
|
|
+ };
|
|
|
+ })(this));
|
|
|
+ return false;
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderBottomSave = function() {
|
|
|
+ var values_changed;
|
|
|
+ values_changed = this.getValuesChanged();
|
|
|
+ return h("div.bottom.bottom-save", {
|
|
|
+ classes: {
|
|
|
+ visible: values_changed.length
|
|
|
+ }
|
|
|
+ }, h("div.bottom-content", [
|
|
|
+ h("div.title", values_changed.length + " configuration item value changed"), h("a.button.button-submit.button-save", {
|
|
|
+ href: "#Save",
|
|
|
+ classes: {
|
|
|
+ loading: this.save_loading
|
|
|
+ },
|
|
|
+ onclick: this.handleSaveClick
|
|
|
+ }, "Save settings")
|
|
|
+ ]));
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.handleRestartClick = function() {
|
|
|
+ this.restart_loading = true;
|
|
|
+ Page.cmd("serverShutdown", {
|
|
|
+ restart: true
|
|
|
+ });
|
|
|
+ Page.projector.scheduleRender();
|
|
|
+ return false;
|
|
|
+ };
|
|
|
+
|
|
|
+ UiConfig.prototype.renderBottomRestart = function() {
|
|
|
+ var values_changed, values_pending;
|
|
|
+ values_pending = this.getValuesPending();
|
|
|
+ values_changed = this.getValuesChanged();
|
|
|
+ return h("div.bottom.bottom-restart", {
|
|
|
+ classes: {
|
|
|
+ visible: values_pending.length && !values_changed.length
|
|
|
+ }
|
|
|
+ }, h("div.bottom-content", [
|
|
|
+ h("div.title", "Some changes settings requires restart"), h("a.button.button-submit.button-restart", {
|
|
|
+ href: "#Restart",
|
|
|
+ classes: {
|
|
|
+ loading: this.restart_loading
|
|
|
+ },
|
|
|
+ onclick: this.handleRestartClick
|
|
|
+ }, "Restart ZeroNet client")
|
|
|
+ ]));
|
|
|
+ };
|
|
|
+
|
|
|
+ return UiConfig;
|
|
|
+
|
|
|
+ })(ZeroFrame);
|
|
|
+
|
|
|
+ window.Page = new UiConfig();
|
|
|
+
|
|
|
+ window.Page.createProjector();
|
|
|
+
|
|
|
+}).call(this);
|