diff --git a/.gitignore b/.gitignore index 4157ddb..b66ad50 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.iml .vscode build +dist downloads node_modules *.zip diff --git a/HISTORY.md b/HISTORY.md index 100db8c..0aaa520 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,11 @@ https://github.com/josdejong/jsoneditor +## not yet published, version 7.0.0 + +- Dropped support for bower, removed the `dist` folder from the git repository. + + ## 2019-08-28, version 6.4.0 - Replaces CSS with SASS internally, improvements in styling. Thanks @ppetkow. diff --git a/bower.json b/bower.json deleted file mode 100644 index 933e66d..0000000 --- a/bower.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "jsoneditor", - "description": "A web-based tool to view, edit and format JSON", - "tags": [ - "json", - "editor", - "viewer", - "formatter" - ], - "homepage": "http://jsoneditoronline.org/", - "repository": { - "type": "git", - "url": "https://github.com/josdejong/jsoneditor.git" - }, - "main": [ - "./dist/jsoneditor.min.js", - "./dist/jsoneditor.min.css" - ], - "bugs": "https://github.com/josdejong/jsoneditor/issues", - "ignore": [ - "misc", - "node_modules", - "test", - "tools", - "gulpfile.js", - "npm-debug.log", - ".idea", - ".npmignore", - ".gitignore" - ], - "dependencies": {} -} diff --git a/dist/img/jsoneditor-icons.svg b/dist/img/jsoneditor-icons.svg deleted file mode 100644 index c2c2765..0000000 --- a/dist/img/jsoneditor-icons.svg +++ /dev/null @@ -1,749 +0,0 @@ - - - JSON Editor Icons - - - - image/svg+xml - - JSON Editor Icons - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dist/jsoneditor-minimalist.js b/dist/jsoneditor-minimalist.js deleted file mode 100644 index b718e8f..0000000 --- a/dist/jsoneditor-minimalist.js +++ /dev/null @@ -1,20628 +0,0 @@ -/*! - * jsoneditor.js - * - * @brief - * JSONEditor is a web-based tool to view, edit, format, and validate JSON. - * It has various modes such as a tree editor, a code editor, and a plain text - * editor. - * - * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ - * - * @license - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - * Copyright (c) 2011-2019 Jos de Jong, http://jsoneditoronline.org - * - * @author Jos de Jong, - * @version 6.4.0 - * @date 2019-08-28 - */ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["JSONEditor"] = factory(); - else - root["JSONEditor"] = factory(); -})(window, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 16); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -__webpack_require__(10); -var naturalSort = __webpack_require__(11); -var jsonlint = __webpack_require__(23); -var jsonMap = __webpack_require__(24); -var translate = __webpack_require__(1).translate; - -var MAX_ITEMS_FIELDS_COLLECTION = 10000; - -/** - * Parse JSON using the parser built-in in the browser. - * On exception, the jsonString is validated and a detailed error is thrown. - * @param {String} jsonString - * @return {JSON} json - */ -exports.parse = function parse(jsonString) { - try { - return JSON.parse(jsonString); - } - catch (err) { - // try to throw a more detailed error message using validate - exports.validate(jsonString); - - // rethrow the original error - throw err; - } -}; - -/** - * Repair a JSON-like string containing. For example changes JavaScript - * notation into JSON notation. - * This function for example changes a string like "{a: 2, 'b': {c: 'd'}" - * into '{"a": 2, "b": {"c": "d"}' - * @param {string} jsString - * @returns {string} json - */ -exports.repair = function (jsString) { - // TODO: refactor this function, it's too large and complicated now - - // escape all single and double quotes inside strings - var chars = []; - var i = 0; - - //If JSON starts with a function (characters/digits/"_-"), remove this function. - //This is useful for "stripping" JSONP objects to become JSON - //For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}] - var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/); - if (match) { - jsString = match[3]; - } - - var controlChars = { - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t' - }; - - var quote = '\''; - var quoteDbl = '"'; - var quoteLeft = '\u2018'; - var quoteRight = '\u2019'; - var quoteDblLeft = '\u201C'; - var quoteDblRight = '\u201D'; - var graveAccent = '\u0060'; - var acuteAccent = '\u00B4'; - - // helper functions to get the current/prev/next character - function curr () { return jsString.charAt(i); } - function next() { return jsString.charAt(i + 1); } - function prev() { return jsString.charAt(i - 1); } - - function isWhiteSpace(c) { - return c === ' ' || c === '\n' || c === '\r' || c === '\t'; - } - - // get the last parsed non-whitespace character - function lastNonWhitespace () { - var p = chars.length - 1; - - while (p >= 0) { - var pp = chars[p]; - if (!isWhiteSpace(pp)) { - return pp; - } - p--; - } - - return ''; - } - - // get at the first next non-white space character - function nextNonWhiteSpace() { - var iNext = i + 1; - while (iNext < jsString.length && isWhiteSpace(jsString[iNext])) { - iNext++; - } - - return jsString[iNext]; - } - - // skip a block comment '/* ... */' - function skipBlockComment () { - i += 2; - while (i < jsString.length && (curr() !== '*' || next() !== '/')) { - i++; - } - i += 2; - } - - // skip a comment '// ...' - function skipComment () { - i += 2; - while (i < jsString.length && (curr() !== '\n')) { - i++; - } - } - - /** - * parse single or double quoted string. Returns the parsed string - * @param {string} endQuote - * @return {string} - */ - function parseString(endQuote) { - var string = ''; - - string += '"'; - i++; - var c = curr(); - while (i < jsString.length && c !== endQuote) { - if (c === '"' && prev() !== '\\') { - // unescaped double quote, escape it - string += '\\"'; - } - else if (controlChars.hasOwnProperty(c)) { - // replace unescaped control characters with escaped ones - string += controlChars[c] - } - else if (c === '\\') { - // remove the escape character when followed by a single quote ', not needed - i++; - c = curr(); - if (c !== '\'') { - string += '\\'; - } - string += c; - } - else { - // regular character - string += c; - } - - i++; - c = curr(); - } - if (c === endQuote) { - string += '"'; - i++; - } - - return string; - } - - // parse an unquoted key - function parseKey() { - var specialValues = ['null', 'true', 'false']; - var key = ''; - var c = curr(); - - var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character - while (regexp.test(c)) { - key += c; - i++; - c = curr(); - } - - if (specialValues.indexOf(key) === -1) { - return '"' + key + '"'; - } - else { - return key; - } - } - - function parseMongoDataType () { - var c = curr(); - var value; - var dataType = ''; - while (/[a-zA-Z_$]/.test(c)) { - dataType += c - i++; - c = curr(); - } - - if (dataType.length > 0 && c === '(') { - // This is an MongoDB data type like {"_id": ObjectId("123")} - i++; - c = curr(); - if (c === '"') { - // a data type containing a string, like ISODate("2012-12-19T06:01:17.171Z") - value = parseString(c); - c = curr(); - } - else { - // a data type containing a value, like 'NumberLong(2)' - value = ''; - while(c !== ')' && c !== '') { - value += c; - i++; - c = curr(); - } - } - - if (c === ')') { - // skip the closing bracket at the end - i++; - - // return the value (strip the data type object) - return value; - } - else { - // huh? that's unexpected. don't touch it - return dataType + '(' + value + c; - } - } - else { - // hm, no Mongo data type after all - return dataType; - } - } - - function isSpecialWhiteSpace (c) { - return ( - c === '\u00A0' || - (c >= '\u2000' && c <= '\u200A') || - c === '\u202F' || - c === '\u205F' || - c === '\u3000') - } - - while(i < jsString.length) { - var c = curr(); - - if (c === '/' && next() === '*') { - skipBlockComment(); - } - else if (c === '/' && next() === '/') { - skipComment(); - } - else if (isSpecialWhiteSpace(c)) { - // special white spaces (like non breaking space) - chars.push(' '); - i++ - } - else if (c === quote) { - chars.push(parseString(c)); - } - else if (c === quoteDbl) { - chars.push(parseString(quoteDbl)); - } - else if (c === graveAccent) { - chars.push(parseString(acuteAccent)); - } - else if (c === quoteLeft) { - chars.push(parseString(quoteRight)); - } - else if (c === quoteDblLeft) { - chars.push(parseString(quoteDblRight)); - } - else if (c === ',' && [']', '}'].indexOf(nextNonWhiteSpace()) !== -1) { - // skip trailing commas - i++; - } - else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { - // an unquoted object key (like a in '{a:2}') - chars.push(parseKey()); - } - else { - if (/[a-zA-Z_$]/.test(c)) { - chars.push(parseMongoDataType()); - } - else { - chars.push(c); - i++; - } - } - } - - return chars.join(''); -}; - -/** - * Escape unicode characters. - * For example input '\u2661' (length 1) will output '\\u2661' (length 5). - * @param {string} text - * @return {string} - */ -exports.escapeUnicodeChars = function (text) { - // see https://www.wikiwand.com/en/UTF-16 - // note: we leave surrogate pairs as two individual chars, - // as JSON doesn't interpret them as a single unicode char. - return text.replace(/[\u007F-\uFFFF]/g, function(c) { - return '\\u'+('0000' + c.charCodeAt(0).toString(16)).slice(-4); - }) -}; - -/** - * Validate a string containing a JSON object - * This method uses JSONLint to validate the String. If JSONLint is not - * available, the built-in JSON parser of the browser is used. - * @param {String} jsonString String with an (invalid) JSON object - * @throws Error - */ -exports.validate = function validate(jsonString) { - if (typeof(jsonlint) != 'undefined') { - jsonlint.parse(jsonString); - } - else { - JSON.parse(jsonString); - } -}; - -/** - * Extend object a with the properties of object b - * @param {Object} a - * @param {Object} b - * @return {Object} a - */ -exports.extend = function extend(a, b) { - for (var prop in b) { - if (b.hasOwnProperty(prop)) { - a[prop] = b[prop]; - } - } - return a; -}; - -/** - * Remove all properties from object a - * @param {Object} a - * @return {Object} a - */ -exports.clear = function clear (a) { - for (var prop in a) { - if (a.hasOwnProperty(prop)) { - delete a[prop]; - } - } - return a; -}; - -/** - * Get the type of an object - * @param {*} object - * @return {String} type - */ -exports.type = function type (object) { - if (object === null) { - return 'null'; - } - if (object === undefined) { - return 'undefined'; - } - if ((object instanceof Number) || (typeof object === 'number')) { - return 'number'; - } - if ((object instanceof String) || (typeof object === 'string')) { - return 'string'; - } - if ((object instanceof Boolean) || (typeof object === 'boolean')) { - return 'boolean'; - } - if ((object instanceof RegExp) || (typeof object === 'regexp')) { - return 'regexp'; - } - if (exports.isArray(object)) { - return 'array'; - } - - return 'object'; -}; - -/** - * Test whether a text contains a url (matches when a string starts - * with 'http://*' or 'https://*' and has no whitespace characters) - * @param {String} text - */ -var isUrlRegex = /^https?:\/\/\S+$/; -exports.isUrl = function isUrl (text) { - return (typeof text == 'string' || text instanceof String) && - isUrlRegex.test(text); -}; - -/** - * Tes whether given object is an Array - * @param {*} obj - * @returns {boolean} returns true when obj is an array - */ -exports.isArray = function (obj) { - return Object.prototype.toString.call(obj) === '[object Array]'; -}; - -/** - * Retrieve the absolute left value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {Number} left The absolute left position of this element - * in the browser page. - */ -exports.getAbsoluteLeft = function getAbsoluteLeft(elem) { - var rect = elem.getBoundingClientRect(); - return rect.left + window.pageXOffset || document.scrollLeft || 0; -}; - -/** - * Retrieve the absolute top value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {Number} top The absolute top position of this element - * in the browser page. - */ -exports.getAbsoluteTop = function getAbsoluteTop(elem) { - var rect = elem.getBoundingClientRect(); - return rect.top + window.pageYOffset || document.scrollTop || 0; -}; - -/** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ -exports.addClassName = function addClassName(elem, className) { - var classes = elem.className.split(' '); - if (classes.indexOf(className) == -1) { - classes.push(className); // add the class to the array - elem.className = classes.join(' '); - } -}; - -/** - * remove all classes from the given elements style - * @param {Element} elem - */ -exports.removeAllClassNames = function removeAllClassNames(elem) { - elem.className = ""; -}; - -/** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ -exports.removeClassName = function removeClassName(elem, className) { - var classes = elem.className.split(' '); - var index = classes.indexOf(className); - if (index != -1) { - classes.splice(index, 1); // remove the class from the array - elem.className = classes.join(' '); - } -}; - -/** - * Strip the formatting from the contents of a div - * the formatting from the div itself is not stripped, only from its childs. - * @param {Element} divElement - */ -exports.stripFormatting = function stripFormatting(divElement) { - var childs = divElement.childNodes; - for (var i = 0, iMax = childs.length; i < iMax; i++) { - var child = childs[i]; - - // remove the style - if (child.style) { - // TODO: test if child.attributes does contain style - child.removeAttribute('style'); - } - - // remove all attributes - var attributes = child.attributes; - if (attributes) { - for (var j = attributes.length - 1; j >= 0; j--) { - var attribute = attributes[j]; - if (attribute.specified === true) { - child.removeAttribute(attribute.name); - } - } - } - - // recursively strip childs - exports.stripFormatting(child); - } -}; - -/** - * Set focus to the end of an editable div - * code from Nico Burns - * http://stackoverflow.com/users/140293/nico-burns - * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity - * @param {Element} contentEditableElement A content editable div - */ -exports.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) { - var range, selection; - if(document.createRange) { - range = document.createRange();//Create a range (a range is a like the selection but invisible) - range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range - range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start - selection = window.getSelection();//get the selection object (allows you to change selection) - selection.removeAllRanges();//remove any selections already made - selection.addRange(range);//make the range you have just created the visible selection - } -}; - -/** - * Select all text of a content editable div. - * http://stackoverflow.com/a/3806004/1262753 - * @param {Element} contentEditableElement A content editable div - */ -exports.selectContentEditable = function selectContentEditable(contentEditableElement) { - if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') { - return; - } - - var sel, range; - if (window.getSelection && document.createRange) { - range = document.createRange(); - range.selectNodeContents(contentEditableElement); - sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } -}; - -/** - * Get text selection - * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore - * @return {Range | TextRange | null} range - */ -exports.getSelection = function getSelection() { - if (window.getSelection) { - var sel = window.getSelection(); - if (sel.getRangeAt && sel.rangeCount) { - return sel.getRangeAt(0); - } - } - return null; -}; - -/** - * Set text selection - * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore - * @param {Range | TextRange | null} range - */ -exports.setSelection = function setSelection(range) { - if (range) { - if (window.getSelection) { - var sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } - } -}; - -/** - * Get selected text range - * @return {Object} params object containing parameters: - * {Number} startOffset - * {Number} endOffset - * {Element} container HTML element holding the - * selected text element - * Returns null if no text selection is found - */ -exports.getSelectionOffset = function getSelectionOffset() { - var range = exports.getSelection(); - - if (range && 'startOffset' in range && 'endOffset' in range && - range.startContainer && (range.startContainer == range.endContainer)) { - return { - startOffset: range.startOffset, - endOffset: range.endOffset, - container: range.startContainer.parentNode - }; - } - - return null; -}; - -/** - * Set selected text range in given element - * @param {Object} params An object containing: - * {Element} container - * {Number} startOffset - * {Number} endOffset - */ -exports.setSelectionOffset = function setSelectionOffset(params) { - if (document.createRange && window.getSelection) { - var selection = window.getSelection(); - if(selection) { - var range = document.createRange(); - - if (!params.container.firstChild) { - params.container.appendChild(document.createTextNode('')); - } - - // TODO: do not suppose that the first child of the container is a textnode, - // but recursively find the textnodes - range.setStart(params.container.firstChild, params.startOffset); - range.setEnd(params.container.firstChild, params.endOffset); - - exports.setSelection(range); - } - } -}; - -/** - * Get the inner text of an HTML element (for example a div element) - * @param {Element} element - * @param {Object} [buffer] - * @return {String} innerText - */ -exports.getInnerText = function getInnerText(element, buffer) { - var first = (buffer == undefined); - if (first) { - buffer = { - 'text': '', - 'flush': function () { - var text = this.text; - this.text = ''; - return text; - }, - 'set': function (text) { - this.text = text; - } - }; - } - - // text node - if (element.nodeValue) { - return buffer.flush() + element.nodeValue; - } - - // divs or other HTML elements - if (element.hasChildNodes()) { - var childNodes = element.childNodes; - var innerText = ''; - - for (var i = 0, iMax = childNodes.length; i < iMax; i++) { - var child = childNodes[i]; - - if (child.nodeName == 'DIV' || child.nodeName == 'P') { - var prevChild = childNodes[i - 1]; - var prevName = prevChild ? prevChild.nodeName : undefined; - if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') { - innerText += '\n'; - buffer.flush(); - } - innerText += exports.getInnerText(child, buffer); - buffer.set('\n'); - } - else if (child.nodeName == 'BR') { - innerText += buffer.flush(); - buffer.set('\n'); - } - else { - innerText += exports.getInnerText(child, buffer); - } - } - - return innerText; - } - else { - if (element.nodeName == 'P' && exports.getInternetExplorerVersion() != -1) { - // On Internet Explorer, a

with hasChildNodes()==false is - // rendered with a new line. Note that a

with - // hasChildNodes()==true is rendered without a new line - // Other browsers always ensure there is a
inside the

, - // and if not, the

does not render a new line - return buffer.flush(); - } - } - - // br or unknown - return ''; -}; - -/** - * Test whether an element has the provided parent node somewhere up the node tree. - * @param {Element} elem - * @param {Element} parent - * @return {boolean} - */ -exports.hasParentNode = function (elem, parent) { - var e = elem ? elem.parentNode : undefined; - - while (e) { - if (e === parent) { - return true; - } - e = e.parentNode; - } - - return false; -} - -/** - * Returns the version of Internet Explorer or a -1 - * (indicating the use of another browser). - * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx - * @return {Number} Internet Explorer version, or -1 in case of an other browser - */ -exports.getInternetExplorerVersion = function getInternetExplorerVersion() { - if (_ieVersion == -1) { - var rv = -1; // Return value assumes failure. - if (typeof navigator !== 'undefined' && navigator.appName == 'Microsoft Internet Explorer') { - var ua = navigator.userAgent; - var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); - if (re.exec(ua) != null) { - rv = parseFloat( RegExp.$1 ); - } - } - - _ieVersion = rv; - } - - return _ieVersion; -}; - -/** - * Test whether the current browser is Firefox - * @returns {boolean} isFirefox - */ -exports.isFirefox = function isFirefox () { - return (typeof navigator !== 'undefined' && navigator.userAgent.indexOf("Firefox") !== -1); -}; - -/** - * cached internet explorer version - * @type {Number} - * @private - */ -var _ieVersion = -1; - -/** - * Add and event listener. Works for all browsers - * @param {Element} element An html element - * @param {string} action The action, for example "click", - * without the prefix "on" - * @param {function} listener The callback function to be executed - * @param {boolean} [useCapture] false by default - * @return {function} the created event listener - */ -exports.addEventListener = function addEventListener(element, action, listener, useCapture) { - if (element.addEventListener) { - if (useCapture === undefined) - useCapture = false; - - if (action === "mousewheel" && exports.isFirefox()) { - action = "DOMMouseScroll"; // For Firefox - } - - element.addEventListener(action, listener, useCapture); - return listener; - } else if (element.attachEvent) { - // Old IE browsers - var f = function () { - return listener.call(element, window.event); - }; - element.attachEvent("on" + action, f); - return f; - } -}; - -/** - * Remove an event listener from an element - * @param {Element} element An html dom element - * @param {string} action The name of the event, for example "mousedown" - * @param {function} listener The listener function - * @param {boolean} [useCapture] false by default - */ -exports.removeEventListener = function removeEventListener(element, action, listener, useCapture) { - if (element.removeEventListener) { - if (useCapture === undefined) - useCapture = false; - - if (action === "mousewheel" && exports.isFirefox()) { - action = "DOMMouseScroll"; // For Firefox - } - - element.removeEventListener(action, listener, useCapture); - } else if (element.detachEvent) { - // Old IE browsers - element.detachEvent("on" + action, listener); - } -}; - -/** - * Test if an element is a child of a parent element. - * @param {Element} elem - * @param {Element} parent - * @return {boolean} returns true if elem is a child of the parent - */ -exports.isChildOf = function (elem, parent) { - var e = elem.parentNode; - while (e) { - if (e === parent) { - return true; - } - e = e.parentNode; - } - - return false; -}; - -/** - * Parse a JSON path like '.items[3].name' into an array - * @param {string} jsonPath - * @return {Array} - */ -exports.parsePath = function parsePath(jsonPath) { - var path = []; - var i = 0; - - function parseProperty () { - var prop = '' - while (jsonPath[i] !== undefined && /[\w$]/.test(jsonPath[i])) { - prop += jsonPath[i]; - i++; - } - - if (prop === '') { - throw new Error('Invalid JSON path: property name expected at index ' + i); - } - - return prop; - } - - function parseIndex (end) { - var name = '' - while (jsonPath[i] !== undefined && jsonPath[i] !== end) { - name += jsonPath[i]; - i++; - } - - if (jsonPath[i] !== end) { - throw new Error('Invalid JSON path: unexpected end, character ' + end + ' expected') - } - - return name; - } - - while (jsonPath[i] !== undefined) { - if (jsonPath[i] === '.') { - i++; - path.push(parseProperty()); - } - else if (jsonPath[i] === '[') { - i++; - - if (jsonPath[i] === '\'' || jsonPath[i] === '"') { - var end = jsonPath[i] - i++; - - path.push(parseIndex(end)); - - if (jsonPath[i] !== end) { - throw new Error('Invalid JSON path: closing quote \' expected at index ' + i) - } - i++; - } - else { - var index = parseIndex(']').trim() - if (index.length === 0) { - throw new Error('Invalid JSON path: array value expected at index ' + i) - } - // Coerce numeric indices to numbers, but ignore star - index = index === '*' ? index : JSON.parse(index); - path.push(index); - } - - if (jsonPath[i] !== ']') { - throw new Error('Invalid JSON path: closing bracket ] expected at index ' + i) - } - i++; - } - else { - throw new Error('Invalid JSON path: unexpected character "' + jsonPath[i] + '" at index ' + i); - } - } - - return path; -}; - -/** - * Stringify an array with a path in a JSON path like '.items[3].name' - * @param {Array.} path - * @returns {string} - */ -exports.stringifyPath = function stringifyPath(path) { - return path - .map(function (p) { - if (typeof p === 'number'){ - return ('[' + p + ']'); - } else if(typeof p === 'string' && p.match(/^[A-Za-z0-9_$]+$/)) { - return '.' + p; - } else { - return '["' + p + '"]'; - } - }) - .join(''); -}; - -/** - * Improve the error message of a JSON schema error - * @param {Object} error - * @return {Object} The error - */ -exports.improveSchemaError = function (error) { - if (error.keyword === 'enum' && Array.isArray(error.schema)) { - var enums = error.schema; - if (enums) { - enums = enums.map(function (value) { - return JSON.stringify(value); - }); - - if (enums.length > 5) { - var more = ['(' + (enums.length - 5) + ' more...)']; - enums = enums.slice(0, 5); - enums.push(more); - } - error.message = 'should be equal to one of: ' + enums.join(', '); - } - } - - if (error.keyword === 'additionalProperties') { - error.message = 'should NOT have additional property: ' + error.params.additionalProperty; - } - - return error; -}; - -/** - * Test whether something is a Promise - * @param {*} object - * @returns {boolean} Returns true when object is a promise, false otherwise - */ -exports.isPromise = function (object) { - return object && typeof object.then === 'function' && typeof object.catch === 'function'; -}; - -/** - * Test whether a custom validation error has the correct structure - * @param {*} validationError The error to be checked. - * @returns {boolean} Returns true if the structure is ok, false otherwise - */ -exports.isValidValidationError = function (validationError) { - return typeof validationError === 'object' && - Array.isArray(validationError.path) && - typeof validationError.message === 'string'; -}; - -/** - * Test whether the child rect fits completely inside the parent rect. - * @param {ClientRect} parent - * @param {ClientRect} child - * @param {number} margin - */ -exports.insideRect = function (parent, child, margin) { - var _margin = margin !== undefined ? margin : 0; - return child.left - _margin >= parent.left - && child.right + _margin <= parent.right - && child.top - _margin >= parent.top - && child.bottom + _margin <= parent.bottom; -}; - -/** - * Returns a function, that, as long as it continues to be invoked, will not - * be triggered. The function will be called after it stops being called for - * N milliseconds. - * - * Source: https://davidwalsh.name/javascript-debounce-function - * - * @param {function} func - * @param {number} wait Number in milliseconds - * @param {boolean} [immediate=false] If `immediate` is passed, trigger the - * function on the leading edge, instead - * of the trailing. - * @return {function} Return the debounced function - */ -exports.debounce = function debounce(func, wait, immediate) { - var timeout; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); - }; -}; - -/** - * Determines the difference between two texts. - * Can only detect one removed or inserted block of characters. - * @param {string} oldText - * @param {string} newText - * @return {{start: number, end: number}} Returns the start and end - * of the changed part in newText. - */ -exports.textDiff = function textDiff(oldText, newText) { - var len = newText.length; - var start = 0; - var oldEnd = oldText.length; - var newEnd = newText.length; - - while (newText.charAt(start) === oldText.charAt(start) - && start < len) { - start++; - } - - while (newText.charAt(newEnd - 1) === oldText.charAt(oldEnd - 1) - && newEnd > start && oldEnd > 0) { - newEnd--; - oldEnd--; - } - - return {start: start, end: newEnd}; -}; - - -/** - * Return an object with the selection range or cursor position (if both have the same value) - * Support also old browsers (IE8-) - * Source: http://ourcodeworld.com/articles/read/282/how-to-get-the-current-cursor-position-and-selection-within-a-text-input-or-textarea-in-javascript - * @param {DOMElement} el A dom element of a textarea or input text. - * @return {Object} reference Object with 2 properties (start and end) with the identifier of the location of the cursor and selected text. - **/ -exports.getInputSelection = function(el) { - var startIndex = 0, endIndex = 0, normalizedValue, range, textInputRange, len, endRange; - - if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { - startIndex = el.selectionStart; - endIndex = el.selectionEnd; - } else { - range = document.selection.createRange(); - - if (range && range.parentElement() == el) { - len = el.value.length; - normalizedValue = el.value.replace(/\r\n/g, "\n"); - - // Create a working TextRange that lives only in the input - textInputRange = el.createTextRange(); - textInputRange.moveToBookmark(range.getBookmark()); - - // Check if the startIndex and endIndex of the selection are at the very end - // of the input, since moveStart/moveEnd doesn't return what we want - // in those cases - endRange = el.createTextRange(); - endRange.collapse(false); - - if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { - startIndex = endIndex = len; - } else { - startIndex = -textInputRange.moveStart("character", -len); - startIndex += normalizedValue.slice(0, startIndex).split("\n").length - 1; - - if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { - endIndex = len; - } else { - endIndex = -textInputRange.moveEnd("character", -len); - endIndex += normalizedValue.slice(0, endIndex).split("\n").length - 1; - } - } - } - } - - return { - startIndex: startIndex, - endIndex: endIndex, - start: _positionForIndex(startIndex), - end: _positionForIndex(endIndex) - }; - - /** - * Returns textarea row and column position for certain index - * @param {Number} index text index - * @returns {{row: Number, col: Number}} - */ - function _positionForIndex(index) { - var textTillIndex = el.value.substring(0,index); - var row = (textTillIndex.match(/\n/g) || []).length + 1; - var col = textTillIndex.length - textTillIndex.lastIndexOf("\n"); - - return { - row: row, - column: col - } - } -} - -/** - * Returns the index for certaion position in text element - * @param {DOMElement} el A dom element of a textarea or input text. - * @param {Number} row row value, > 0, if exceeds rows number - last row will be returned - * @param {Number} column column value, > 0, if exceeds column length - end of column will be returned - * @returns {Number} index of position in text, -1 if not found - */ -exports.getIndexForPosition = function(el, row, column) { - var text = el.value || ''; - if (row > 0 && column > 0) { - var rows = text.split('\n', row); - row = Math.min(rows.length, row); - column = Math.min(rows[row - 1].length, column - 1); - var columnCount = (row == 1 ? column : column + 1); // count new line on multiple rows - return rows.slice(0, row - 1).join('\n').length + columnCount; - } - return -1; -} - -/** - * Returns location of json paths in certain json string - * @param {String} text json string - * @param {Array} paths array of json paths - * @returns {Array<{path: String, line: Number, row: Number}>} - */ -exports.getPositionForPath = function(text, paths) { - var me = this; - var result = []; - var jsmap; - if (!paths || !paths.length) { - return result; - } - - try { - jsmap = jsonMap.parse(text); - } catch (err) { - return result; - } - - paths.forEach(function (path) { - var pathArr = me.parsePath(path); - var pointerName = exports.compileJSONPointer(pathArr); - var pointer = jsmap.pointers[pointerName]; - if (pointer) { - result.push({ - path: path, - line: pointer.key ? pointer.key.line : (pointer.value ? pointer.value.line : 0), - column: pointer.key ? pointer.key.column : (pointer.value ? pointer.value.column : 0) - }); - } - }); - - return result; - -} - -/** - * Compile a JSON Pointer - * WARNING: this is an incomplete implementation - * @param {Array.} path - * @return {string} - */ -exports.compileJSONPointer = function (path) { - return path - .map(function (p) { - return ('/' + String(p) - .replace(/~/g, '~0') - .replace(/\//g, '~1') - ); - }) - .join(''); -}; - -/** - * Get the applied color given a color name or code - * Source: https://stackoverflow.com/questions/6386090/validating-css-color-names/33184805 - * @param {string} color - * @returns {string | null} returns the color if the input is a valid - * color, and returns null otherwise. Example output: - * 'rgba(255,0,0,0.7)' or 'rgb(255,0,0)' - */ -exports.getColorCSS = function (color) { - var ele = document.createElement('div'); - ele.style.color = color; - return ele.style.color.split(/\s+/).join('').toLowerCase() || null; -} - -/** - * Test if a string contains a valid color name or code. - * @param {string} color - * @returns {boolean} returns true if a valid color, false otherwise - */ -exports.isValidColor = function (color) { - return !!exports.getColorCSS(color); -} - -/** - * Make a tooltip for a field based on the field's schema. - * @param {object} schema JSON schema - * @param {string} [locale] Locale code (for example, zh-CN) - * @returns {string} Field tooltip, may be empty string if all relevant schema properties are missing - */ -exports.makeFieldTooltip = function (schema, locale) { - if (!schema) { - return ''; - } - - var tooltip = ''; - if (schema.title) { - tooltip += schema.title; - } - - if (schema.description) { - if (tooltip.length > 0) { - tooltip += '\n'; - } - tooltip += schema.description; - } - - if (schema.default) { - if (tooltip.length > 0) { - tooltip += '\n\n'; - } - tooltip += translate('default', undefined, locale) + '\n'; - tooltip += JSON.stringify(schema.default, null, 2); - } - - if (Array.isArray(schema.examples) && schema.examples.length > 0) { - if (tooltip.length > 0) { - tooltip += '\n\n'; - } - tooltip += translate('examples', undefined, locale) + '\n'; - schema.examples.forEach(function (example, index) { - tooltip += JSON.stringify(example, null, 2); - if (index !== schema.examples.length - 1) { - tooltip += '\n'; - } - }); - } - - return tooltip; -} - -/** - * Get a nested property from an object. - * Returns undefined when the property does not exist. - * @param {Object} object - * @param {string[]} path - * @return {*} - */ -exports.get = function (object, path) { - var value = object - - for (var i = 0; i < path.length && value !== undefined && value !== null; i++) { - value = value[path[i]] - } - - return value; -} - -/** - * Find a unique name. Suffix the name with ' (copy)', '(copy 2)', etc - * until a unique name is found - * @param {string} name - * @param {Array} existingPropNames Array with existing prop names - */ -exports.findUniqueName = function(name, existingPropNames) { - var strippedName = name.replace(/ \(copy( \d+)?\)$/, '') - var validName = strippedName - var i = 1 - - while (existingPropNames.indexOf(validName) !== -1) { - var copy = 'copy' + (i > 1 ? (' ' + i) : '') - validName = strippedName + ' (' + copy + ')' - i++ - } - - return validName -} - -/** - * Get the child paths of an array - * @param {JSON} json - * @param {boolean} [includeObjects=false] If true, object and array paths are returned as well - * @return {string[]} - */ -exports.getChildPaths = function (json, includeObjects) { - var pathsMap = {}; - - function getObjectChildPaths (json, pathsMap, rootPath, includeObjects) { - var isValue = !Array.isArray(json) && !exports.isObject(json) - - if (isValue || includeObjects) { - pathsMap[rootPath || ''] = true; - } - - if (exports.isObject(json)) { - Object.keys(json).forEach(function (field) { - getObjectChildPaths(json[field], pathsMap, rootPath + '.' + field, includeObjects); - }); - } - } - - if (Array.isArray(json)) { - var max = Math.min(json.length, MAX_ITEMS_FIELDS_COLLECTION); - for (var i = 0; i < max; i++) { - var item = json[i]; - getObjectChildPaths(item, pathsMap, '', includeObjects); - } - } - else { - pathsMap[''] = true; - } - - return Object.keys(pathsMap).sort(); -} - -/** - * Sort object keys using natural sort - * @param {Array} array - * @param {String} [path] JSON pointer - * @param {'asc' | 'desc'} [direction] - */ -exports.sort = function (array, path, direction) { - var parsedPath = path && path !== '.' ? exports.parsePath(path) : [] - var sign = direction === 'desc' ? -1: 1 - - var sortedArray = array.slice() - sortedArray.sort(function (a, b) { - var aValue = exports.get(a, parsedPath); - var bValue = exports.get(b, parsedPath); - - return sign * (aValue > bValue ? 1 : aValue < bValue ? -1 : 0); - }) - - return sortedArray; -} - -/** - * Sort object keys using natural sort - * @param {Object} object - * @param {'asc' | 'desc'} [direction] - */ -exports.sortObjectKeys = function (object, direction) { - var sign = (direction === 'desc') ? -1 : 1; - var sortedFields = Object.keys(object).sort(function (a, b) { - return sign * naturalSort(a, b); - }); - - var sortedObject = {}; - sortedFields.forEach(function (field) { - sortedObject[field] = object[field]; - }); - - return sortedObject; -} - -/** - * Cast contents of a string to the correct type. - * This can be a string, a number, a boolean, etc - * @param {String} str - * @return {*} castedStr - * @private - */ -exports.parseString = function(str) { - var lower = str.toLowerCase(); - var num = Number(str); // will nicely fail with '123ab' - var numFloat = parseFloat(str); // will nicely fail with ' ' - - if (str === '') { - return ''; - } - else if (lower === 'null') { - return null; - } - else if (lower === 'true') { - return true; - } - else if (lower === 'false') { - return false; - } - else if (!isNaN(num) && !isNaN(numFloat)) { - return num; - } - else { - return str; - } -}; - -/** - * Return a human readable document size - * For example formatSize(7570718) outputs '7.2 MiB' - * @param {number} size - * @return {string} Returns a human readable size - */ -exports.formatSize = function (size) { - if (size < 900) { - return size.toFixed() + ' B'; - } - - var KiB = size / 1024; - if (KiB < 900) { - return KiB.toFixed(1) + ' KiB'; - } - - var MiB = KiB / 1024; - if (MiB < 900) { - return MiB.toFixed(1) + ' MiB'; - } - - var GiB = MiB / 1024; - if (GiB < 900) { - return GiB.toFixed(1) + ' GiB'; - } - - var TiB = GiB / 1024; - return TiB.toFixed(1) + ' TiB'; -} - -/** - * Limit text to a maximum number of characters - * @param {string} text - * @param {number} maxCharacterCount - * @return {string} Returns the limited text, - * ending with '...' if the max was exceeded - */ -exports.limitCharacters = function (text, maxCharacterCount) { - if (text.length <= maxCharacterCount) { - return text; - } - - return text.slice(0, maxCharacterCount) + '...'; -} - -/** - * Test whether a value is an Object - * @param {*} value - * @return {boolean} - */ -exports.isObject = function (value) { - return typeof value === 'object' && value !== null && !Array.isArray(value) -} - -/** - * Helper function to test whether an array contains an item - * @param {Array} array - * @param {*} item - * @return {boolean} Returns true if `item` is in `array`, returns false otherwise. - */ -exports.contains = function (array, item) { - return array.indexOf(item) !== -1; -} - - -/***/ }), -/* 1 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -__webpack_require__(10); - -var _locales = ['en', 'pt-BR', 'zh-CN', 'tr']; -var _defs = { - en: { - array: 'Array', - auto: 'Auto', - appendText: 'Append', - appendTitle: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', - appendSubmenuTitle: 'Select the type of the field to be appended', - appendTitleAuto: 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', - ascending: 'Ascending', - ascendingTitle: 'Sort the childs of this ${type} in ascending order', - actionsMenu: 'Click to open the actions menu (Ctrl+M)', - collapseAll: 'Collapse all fields', - descending: 'Descending', - descendingTitle: 'Sort the childs of this ${type} in descending order', - drag: 'Drag to move this field (Alt+Shift+Arrows)', - duplicateKey: 'duplicate key', - duplicateText: 'Duplicate', - duplicateTitle: 'Duplicate selected fields (Ctrl+D)', - duplicateField: 'Duplicate this field (Ctrl+D)', - duplicateFieldError: 'Duplicate field name', - cannotParseFieldError: 'Cannot parse field into JSON', - cannotParseValueError: 'Cannot parse value into JSON', - empty: 'empty', - expandAll: 'Expand all fields', - expandTitle: 'Click to expand/collapse this field (Ctrl+E). \n' + - 'Ctrl+Click to expand/collapse including all childs.', - insert: 'Insert', - insertTitle: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', - insertSub: 'Select the type of the field to be inserted', - object: 'Object', - ok: 'Ok', - redo: 'Redo (Ctrl+Shift+Z)', - removeText: 'Remove', - removeTitle: 'Remove selected fields (Ctrl+Del)', - removeField: 'Remove this field (Ctrl+Del)', - selectNode: 'Select a node...', - showAll: 'show all', - showMore: 'show more', - showMoreStatus: 'displaying ${visibleChilds} of ${totalChilds} items.', - sort: 'Sort', - sortTitle: 'Sort the childs of this ${type}', - sortTitleShort: 'Sort contents', - sortFieldLabel: 'Field:', - sortDirectionLabel: 'Direction:', - sortFieldTitle: 'Select the nested field by which to sort the array or object', - sortAscending: 'Ascending', - sortAscendingTitle: 'Sort the selected field in ascending order', - sortDescending: 'Descending', - sortDescendingTitle: 'Sort the selected field in descending order', - string: 'String', - transform: 'Transform', - transformTitle: 'Filter, sort, or transform the childs of this ${type}', - transformTitleShort: 'Filter, sort, or transform contents', - extract: 'Extract', - extractTitle: 'Extract this ${type}', - transformQueryTitle: 'Enter a JMESPath query', - transformWizardLabel: 'Wizard', - transformWizardFilter: 'Filter', - transformWizardSortBy: 'Sort by', - transformWizardSelectFields: 'Select fields', - transformQueryLabel: 'Query', - transformPreviewLabel: 'Preview', - type: 'Type', - typeTitle: 'Change the type of this field', - openUrl: 'Ctrl+Click or Ctrl+Enter to open url in new window', - undo: 'Undo last action (Ctrl+Z)', - validationCannotMove: 'Cannot move a field into a child of itself', - autoType: 'Field type "auto". ' + - 'The field type is automatically determined from the value ' + - 'and can be a string, number, boolean, or null.', - objectType: 'Field type "object". ' + - 'An object contains an unordered set of key/value pairs.', - arrayType: 'Field type "array". ' + - 'An array contains an ordered collection of values.', - stringType: 'Field type "string". ' + - 'Field type is not determined from the value, ' + - 'but always returned as string.', - modeCodeText: 'Code', - modeCodeTitle: 'Switch to code highlighter', - modeFormText: 'Form', - modeFormTitle: 'Switch to form editor', - modeTextText: 'Text', - modeTextTitle: 'Switch to plain text editor', - modeTreeText: 'Tree', - modeTreeTitle: 'Switch to tree editor', - modeViewText: 'View', - modeViewTitle: 'Switch to tree view', - modePreviewText: 'Preview', - modePreviewTitle: 'Switch to preview mode', - examples: 'Examples', - default: 'Default', - }, - 'zh-CN': { - array: '数组', - auto: '自动', - appendText: '追加', - appendTitle: '在此字段后追加一个类型为“auto”的新字段 (Ctrl+Shift+Ins)', - appendSubmenuTitle: '选择要追加的字段类型', - appendTitleAuto: '追加类型为“auto”的新字段 (Ctrl+Shift+Ins)', - ascending: '升序', - ascendingTitle: '升序排列${type}的子节点', - actionsMenu: '点击打开动作菜单(Ctrl+M)', - collapseAll: '缩进所有字段', - descending: '降序', - descendingTitle: '降序排列${type}的子节点', - drag: '拖拽移动该节点(Alt+Shift+Arrows)', - duplicateKey: '重复键', - duplicateText: '复制', - duplicateTitle: '复制选中字段(Ctrl+D)', - duplicateField: '复制该字段(Ctrl+D)', - duplicateFieldError: '重复的字段名称', - cannotParseFieldError: '无法将字段解析为JSON', - cannotParseValueError: '无法将值解析为JSON', - empty: '清空', - expandAll: '展开所有字段', - expandTitle: '点击 展开/收缩 该字段(Ctrl+E). \n' + - 'Ctrl+Click 展开/收缩 包含所有子节点.', - insert: '插入', - insertTitle: '在此字段前插入类型为“auto”的新字段 (Ctrl+Ins)', - insertSub: '选择要插入的字段类型', - object: '对象', - ok: 'Ok', - redo: '重做 (Ctrl+Shift+Z)', - removeText: '移除', - removeTitle: '移除选中字段 (Ctrl+Del)', - removeField: '移除该字段 (Ctrl+Del)', - selectNode: '选择一个节点...', - showAll: '展示全部', - showMore: '展示更多', - showMoreStatus: '显示${totalChilds}的${visibleChilds}项目.', - sort: '排序', - sortTitle: '排序${type}的子节点', - sortTitleShort: '内容排序', - sortFieldLabel: '字段:', - sortDirectionLabel: '方向:', - sortFieldTitle: '选择用于对数组或对象排序的嵌套字段', - sortAscending: '升序排序', - sortAscendingTitle: '按照该字段升序排序', - sortDescending: '降序排序', - sortDescendingTitle: '按照该字段降序排序', - string: '字符串', - transform: '变换', - transformTitle: '筛选,排序,或者转换${type}的子节点', - transformTitleShort: '筛选,排序,或者转换内容', - extract: '提取', - extractTitle: '提取这个 ${type}', - transformQueryTitle: '输入JMESPath查询', - transformWizardLabel: '向导', - transformWizardFilter: '筛选', - transformWizardSortBy: '排序', - transformWizardSelectFields: '选择字段', - transformQueryLabel: '查询', - transformPreviewLabel: '预览', - type: '类型', - typeTitle: '更改字段类型', - openUrl: 'Ctrl+Click 或者 Ctrl+Enter 在新窗口打开链接', - undo: '撤销上次动作 (Ctrl+Z)', - validationCannotMove: '无法将字段移入其子节点', - autoType: '字段类型 "auto". ' + - '字段类型由值自动确定 ' + - '可以为 string,number,boolean,或者 null.', - objectType: '字段类型 "object". ' + - '对象包含一组无序的键/值对.', - arrayType: '字段类型 "array". ' + - '数组包含值的有序集合.', - stringType: '字段类型 "string". ' + - '字段类型由值自动确定,' + - '但始终作为字符串返回.', - modeCodeText: '代码', - modeCodeTitle: '切换至代码高亮', - modeFormText: '表单', - modeFormTitle: '切换至表单编辑', - modeTextText: '文本', - modeTextTitle: '切换至文本编辑', - modeTreeText: '树', - modeTreeTitle: '切换至树编辑', - modeViewText: '视图', - modeViewTitle: '切换至树视图', - modePreviewText: '预览', - modePreviewTitle: '切换至预览模式', - examples: '例子', - default: '缺省', - }, - 'pt-BR': { - array: 'Lista', - auto: 'Automatico', - appendText: 'Adicionar', - appendTitle: 'Adicionar novo campo com tipo \'auto\' depois deste campo (Ctrl+Shift+Ins)', - appendSubmenuTitle: 'Selecione o tipo do campo a ser adicionado', - appendTitleAuto: 'Adicionar novo campo com tipo \'auto\' (Ctrl+Shift+Ins)', - ascending: 'Ascendente', - ascendingTitle: 'Organizar filhor do tipo ${type} em crescente', - actionsMenu: 'Clique para abrir o menu de ações (Ctrl+M)', - collapseAll: 'Fechar todos campos', - descending: 'Descendente', - descendingTitle: 'Organizar o filhos do tipo ${type} em decrescente', - duplicateKey: 'chave duplicada', - drag: 'Arraste para mover este campo (Alt+Shift+Arrows)', - duplicateText: 'Duplicar', - duplicateTitle: 'Duplicar campos selecionados (Ctrl+D)', - duplicateField: 'Duplicar este campo (Ctrl+D)', - duplicateFieldError: 'Nome do campo duplicado', - cannotParseFieldError: 'Não é possível analisar o campo no JSON', - cannotParseValueError: 'Não é possível analisar o valor em JSON', - empty: 'vazio', - expandAll: 'Expandir todos campos', - expandTitle: 'Clique para expandir/encolher este campo (Ctrl+E). \n' + - 'Ctrl+Click para expandir/encolher incluindo todos os filhos.', - insert: 'Inserir', - insertTitle: 'Inserir um novo campo do tipo \'auto\' antes deste campo (Ctrl+Ins)', - insertSub: 'Selecionar o tipo de campo a ser inserido', - object: 'Objeto', - ok: 'Ok', - redo: 'Refazer (Ctrl+Shift+Z)', - removeText: 'Remover', - removeTitle: 'Remover campos selecionados (Ctrl+Del)', - removeField: 'Remover este campo (Ctrl+Del)', - // TODO: correctly translate - selectNode: 'Select a node...', - // TODO: correctly translate - showAll: 'mostre tudo', - // TODO: correctly translate - showMore: 'mostre mais', - // TODO: correctly translate - showMoreStatus: 'exibindo ${visibleChilds} de ${totalChilds} itens.', - sort: 'Organizar', - sortTitle: 'Organizar os filhos deste ${type}', - // TODO: correctly translate - sortTitleShort: 'Organizar os filhos', - // TODO: correctly translate - sortFieldLabel: 'Field:', - // TODO: correctly translate - sortDirectionLabel: 'Direction:', - // TODO: correctly translate - sortFieldTitle: 'Select the nested field by which to sort the array or object', - // TODO: correctly translate - sortAscending: 'Ascending', - // TODO: correctly translate - sortAscendingTitle: 'Sort the selected field in ascending order', - // TODO: correctly translate - sortDescending: 'Descending', - // TODO: correctly translate - sortDescendingTitle: 'Sort the selected field in descending order', - string: 'Texto', - // TODO: correctly translate - transform: 'Transform', - // TODO: correctly translate - transformTitle: 'Filter, sort, or transform the childs of this ${type}', - // TODO: correctly translate - transformTitleShort: 'Filter, sort, or transform contents', - // TODO: correctly translate - transformQueryTitle: 'Enter a JMESPath query', - // TODO: correctly translate - transformWizardLabel: 'Wizard', - // TODO: correctly translate - transformWizardFilter: 'Filter', - // TODO: correctly translate - transformWizardSortBy: 'Sort by', - // TODO: correctly translate - transformWizardSelectFields: 'Select fields', - // TODO: correctly translate - transformQueryLabel: 'Query', - // TODO: correctly translate - transformPreviewLabel: 'Preview', - type: 'Tipo', - typeTitle: 'Mudar o tipo deste campo', - openUrl: 'Ctrl+Click ou Ctrl+Enter para abrir link em nova janela', - undo: 'Desfazer último ação (Ctrl+Z)', - validationCannotMove: 'Não pode mover um campo como filho dele mesmo', - autoType: 'Campo do tipo "auto". ' + - 'O tipo do campo é determinao automaticamente a partir do seu valor ' + - 'e pode ser texto, número, verdade/falso ou nulo.', - objectType: 'Campo do tipo "objeto". ' + - 'Um objeto contém uma lista de pares com chave e valor.', - arrayType: 'Campo do tipo "lista". ' + - 'Uma lista contem uma coleção de valores ordenados.', - stringType: 'Campo do tipo "string". ' + - 'Campo do tipo nao é determinado através do seu valor, ' + - 'mas sempre retornara um texto.', - examples: 'Exemplos', - default: 'Revelia', - }, - tr: { - array: 'Dizin', - auto: 'Otomatik', - appendText: 'Ekle', - appendTitle: 'Bu alanın altına \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)', - appendSubmenuTitle: 'Eklenecek alanın tipini seç', - appendTitleAuto: '\'Otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)', - ascending: 'Artan', - ascendingTitle: '${type}\'ın alt tiplerini artan düzende sırala', - actionsMenu: 'Aksiyon menüsünü açmak için tıklayın (Ctrl+M)', - collapseAll: 'Tüm alanları kapat', - descending: 'Azalan', - descendingTitle: '${type}\'ın alt tiplerini azalan düzende sırala', - drag: 'Bu alanı taşımak için sürükleyin (Alt+Shift+Arrows)', - duplicateKey: 'Var olan anahtar', - duplicateText: 'Aşağıya kopyala', - duplicateTitle: 'Seçili alanlardan bir daha oluştur (Ctrl+D)', - duplicateField: 'Bu alandan bir daha oluştur (Ctrl+D)', - duplicateFieldError: 'Duplicate field name', - cannotParseFieldError: 'Alan JSON\'a ayrıştırılamıyor', - cannotParseValueError: 'JSON\'a değer ayrıştırılamıyor', - empty: 'boş', - expandAll: 'Tüm alanları aç', - expandTitle: 'Bu alanı açmak/kapatmak için tıkla (Ctrl+E). \n' + - 'Alt alanlarda dahil tüm alanları açmak için Ctrl+Click ', - insert: 'Ekle', - insertTitle: 'Bu alanın üstüne \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Ins)', - insertSub: 'Araya eklenecek alanın tipini seç', - object: 'Nesne', - ok: 'Tamam', - redo: 'Yeniden yap (Ctrl+Shift+Z)', - removeText: 'Kaldır', - removeTitle: 'Seçilen alanları kaldır (Ctrl+Del)', - removeField: 'Bu alanı kaldır (Ctrl+Del)', - selectNode: 'Bir nesne seç...', - showAll: 'tümünü göster', - showMore: 'daha fazla göster', - showMoreStatus: '${totalChilds} alanın ${visibleChilds} alt alanları gösteriliyor', - sort: 'Sırala', - sortTitle: '${type}\'ın alt alanlarını sırala', - sortTitleShort: 'İçerikleri sırala', - sortFieldLabel: 'Alan:', - sortDirectionLabel: 'Yön:', - sortFieldTitle: 'Diziyi veya nesneyi sıralamak için iç içe geçmiş alanı seçin', - sortAscending: 'Artan', - sortAscendingTitle: 'Seçili alanı artan düzende sırala', - sortDescending: 'Azalan', - sortDescendingTitle: 'Seçili alanı azalan düzende sırala', - string: 'Karakter Dizisi', - transform: 'Dönüştür', - transformTitle: '${type}\'ın alt alanlarını filtrele, sırala veya dönüştür', - transformTitleShort: 'İçerikleri filterele, sırala veya dönüştür', - transformQueryTitle: 'JMESPath sorgusu gir', - transformWizardLabel: 'Sihirbaz', - transformWizardFilter: 'Filtre', - transformWizardSortBy: 'Sırala', - transformWizardSelectFields: 'Alanları seç', - transformQueryLabel: 'Sorgu', - transformPreviewLabel: 'Önizleme', - type: 'Tip', - typeTitle: 'Bu alanın tipini değiştir', - openUrl: 'URL\'i yeni bir pencerede açmak için Ctrl+Click veya Ctrl+Enter', - undo: 'Son değişikliği geri al (Ctrl+Z)', - validationCannotMove: 'Alt alan olarak taşınamıyor', - autoType: 'Alan tipi "otomatik". ' + - 'Alan türü otomatik olarak değerden belirlenir' + - 've bir dize, sayı, boolean veya null olabilir.', - objectType: 'Alan tipi "nesne". ' + - 'Bir nesne, sıralanmamış bir anahtar / değer çifti kümesi içerir.', - arrayType: 'Alan tipi "dizi". ' + - 'Bir dizi, düzenli değerler koleksiyonu içerir.', - stringType: 'Alan tipi "karakter dizisi". ' + - 'Alan türü değerden belirlenmez,' + - 'ancak her zaman karakter dizisi olarak döndürülür.', - modeCodeText: 'Kod', - modeCodeTitle: 'Kod vurgulayıcıya geç', - modeFormText: 'Form', - modeFormTitle: 'Form düzenleyiciye geç', - modeTextText: 'Metin', - modeTextTitle: 'Düz metin düzenleyiciye geç', - modeTreeText: 'Ağaç', - modeTreeTitle: 'Ağaç düzenleyiciye geç', - modeViewText: 'Görünüm', - modeViewTitle: 'Ağaç görünümüne geç', - examples: 'Örnekler', - default: 'Varsayılan', - } -}; - -var _defaultLang = 'en'; -var _lang; -var userLang = typeof navigator !== 'undefined' ? - navigator.language || navigator.userLanguage : - undefined; -_lang = _locales.find(function (l) { - return l === userLang; -}); -if (!_lang) { - _lang = _defaultLang; -} - -module.exports = { - // supported locales - _locales: _locales, - _defs: _defs, - _lang: _lang, - setLanguage: function (lang) { - if (!lang) { - return; - } - var langFound = _locales.find(function (l) { - return l === lang; - }); - if (langFound) { - _lang = langFound; - } else { - console.error('Language not found'); - } - }, - setLanguages: function (languages) { - if (!languages) { - return; - } - for (var key in languages) { - var langFound = _locales.find(function (l) { - return l === key; - }); - if (!langFound) { - _locales.push(key); - } - _defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]); - } - }, - translate: function (key, data, lang) { - if (!lang) { - lang = _lang; - } - var text = _defs[lang][key]; - if (data) { - for (key in data) { - text = text.replace('${' + key + '}', data[key]); - } - } - return text || key; - } -}; - -/***/ }), -/* 2 */ -/***/ (function(module, exports) { - - -exports.DEFAULT_MODAL_ANCHOR = document.body; -exports.SIZE_LARGE = 10 * 1024 * 1024; // 10 MB - -exports.MAX_PREVIEW_CHARACTERS = 20000; - -exports.PREVIEW_HISTORY_LIMIT = 2 * 1024 * 1024 * 1024; // 2 GB - - -/***/ }), -/* 3 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var createAbsoluteAnchor = __webpack_require__(12).createAbsoluteAnchor; -var util = __webpack_require__(0); -var translate = __webpack_require__(1).translate; - -/** - * A context menu - * @param {Object[]} items Array containing the menu structure - * TODO: describe structure - * @param {Object} [options] Object with options. Available options: - * {function} close Callback called when the - * context menu is being closed. - * @constructor - */ -function ContextMenu (items, options) { - this.dom = {}; - - var me = this; - var dom = this.dom; - this.anchor = undefined; - this.items = items; - this.eventListeners = {}; - this.selection = undefined; // holds the selection before the menu was opened - this.onClose = options ? options.close : undefined; - - // create root element - var root = document.createElement('div'); - root.className = 'jsoneditor-contextmenu-root'; - dom.root = root; - - // create a container element - var menu = document.createElement('div'); - menu.className = 'jsoneditor-contextmenu'; - dom.menu = menu; - root.appendChild(menu); - - // create a list to hold the menu items - var list = document.createElement('ul'); - list.className = 'jsoneditor-menu'; - menu.appendChild(list); - dom.list = list; - dom.items = []; // list with all buttons - - // create a (non-visible) button to set the focus to the menu - var focusButton = document.createElement('button'); - focusButton.type = 'button'; - dom.focusButton = focusButton; - var li = document.createElement('li'); - li.style.overflow = 'hidden'; - li.style.height = '0'; - li.appendChild(focusButton); - list.appendChild(li); - - function createMenuItems (list, domItems, items) { - items.forEach(function (item) { - if (item.type == 'separator') { - // create a separator - var separator = document.createElement('div'); - separator.className = 'jsoneditor-separator'; - li = document.createElement('li'); - li.appendChild(separator); - list.appendChild(li); - } - else { - var domItem = {}; - - // create a menu item - var li = document.createElement('li'); - list.appendChild(li); - - // create a button in the menu item - var button = document.createElement('button'); - button.type = 'button'; - button.className = item.className; - domItem.button = button; - if (item.title) { - button.title = item.title; - } - if (item.click) { - button.onclick = function (event) { - event.preventDefault(); - me.hide(); - item.click(); - }; - } - li.appendChild(button); - - // create the contents of the button - if (item.submenu) { - // add the icon to the button - var divIcon = document.createElement('div'); - divIcon.className = 'jsoneditor-icon'; - button.appendChild(divIcon); - var divText = document.createElement('div'); - divText.className = 'jsoneditor-text' + - (item.click ? '' : ' jsoneditor-right-margin'); - divText.appendChild(document.createTextNode(item.text)); - button.appendChild(divText); - - var buttonSubmenu; - if (item.click) { - // submenu and a button with a click handler - button.className += ' jsoneditor-default'; - - var buttonExpand = document.createElement('button'); - buttonExpand.type = 'button'; - domItem.buttonExpand = buttonExpand; - buttonExpand.className = 'jsoneditor-expand'; - buttonExpand.innerHTML = '

'; - li.appendChild(buttonExpand); - if (item.submenuTitle) { - buttonExpand.title = item.submenuTitle; - } - - buttonSubmenu = buttonExpand; - } - else { - // submenu and a button without a click handler - var divExpand = document.createElement('div'); - divExpand.className = 'jsoneditor-expand'; - button.appendChild(divExpand); - - buttonSubmenu = button; - } - - // attach a handler to expand/collapse the submenu - buttonSubmenu.onclick = function (event) { - event.preventDefault(); - me._onExpandItem(domItem); - buttonSubmenu.focus(); - }; - - // create the submenu - var domSubItems = []; - domItem.subItems = domSubItems; - var ul = document.createElement('ul'); - domItem.ul = ul; - ul.className = 'jsoneditor-menu'; - ul.style.height = '0'; - li.appendChild(ul); - createMenuItems(ul, domSubItems, item.submenu); - } - else { - // no submenu, just a button with clickhandler - button.innerHTML = '
' + - '
' + translate(item.text) + '
'; - } - - domItems.push(domItem); - } - }); - } - createMenuItems(list, this.dom.items, items); - - // TODO: when the editor is small, show the submenu on the right instead of inline? - - // calculate the max height of the menu with one submenu expanded - this.maxHeight = 0; // height in pixels - items.forEach(function (item) { - var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24; - me.maxHeight = Math.max(me.maxHeight, height); - }); -} - -/** - * Get the currently visible buttons - * @return {Array.} buttons - * @private - */ -ContextMenu.prototype._getVisibleButtons = function () { - var buttons = []; - var me = this; - this.dom.items.forEach(function (item) { - buttons.push(item.button); - if (item.buttonExpand) { - buttons.push(item.buttonExpand); - } - if (item.subItems && item == me.expandedItem) { - item.subItems.forEach(function (subItem) { - buttons.push(subItem.button); - if (subItem.buttonExpand) { - buttons.push(subItem.buttonExpand); - } - // TODO: change to fully recursive method - }); - } - }); - - return buttons; -}; - -// currently displayed context menu, a singleton. We may only have one visible context menu -ContextMenu.visibleMenu = undefined; - -/** - * Attach the menu to an anchor - * @param {HTMLElement} anchor Anchor where the menu will be attached as sibling. - * @param {HTMLElement} frame The root of the JSONEditor window - * @param {Boolean=} ignoreParent ignore anchor parent in regard to the calculation of the position, needed when the parent position is absolute - */ -ContextMenu.prototype.show = function (anchor, frame, ignoreParent) { - this.hide(); - - // determine whether to display the menu below or above the anchor - var showBelow = true; - var parent = anchor.parentNode; - var anchorRect = anchor.getBoundingClientRect(); - var parentRect = parent.getBoundingClientRect(); - var frameRect = frame.getBoundingClientRect(); - - var me = this; - this.dom.absoluteAnchor = createAbsoluteAnchor(anchor, frame, function () { - me.hide() - }); - - if (anchorRect.bottom + this.maxHeight < frameRect.bottom) { - // fits below -> show below - } - else if (anchorRect.top - this.maxHeight > frameRect.top) { - // fits above -> show above - showBelow = false; - } - else { - // doesn't fit above nor below -> show below - } - - var topGap = ignoreParent ? 0 : (anchorRect.top - parentRect.top); - - // position the menu - if (showBelow) { - // display the menu below the anchor - var anchorHeight = anchor.offsetHeight; - this.dom.menu.style.left = '0'; - this.dom.menu.style.top = topGap + anchorHeight + 'px'; - this.dom.menu.style.bottom = ''; - } - else { - // display the menu above the anchor - this.dom.menu.style.left = '0'; - this.dom.menu.style.top = ''; - this.dom.menu.style.bottom = '0px'; - } - - // attach the menu to the temporary, absolute anchor - // parent.insertBefore(this.dom.root, anchor); - this.dom.absoluteAnchor.appendChild(this.dom.root); - - // move focus to the first button in the context menu - this.selection = util.getSelection(); - this.anchor = anchor; - setTimeout(function () { - me.dom.focusButton.focus(); - }, 0); - - if (ContextMenu.visibleMenu) { - ContextMenu.visibleMenu.hide(); - } - ContextMenu.visibleMenu = this; -}; - -/** - * Hide the context menu if visible - */ -ContextMenu.prototype.hide = function () { - // remove temporary absolutely positioned anchor - if (this.dom.absoluteAnchor) { - this.dom.absoluteAnchor.destroy(); - delete this.dom.absoluteAnchor; - } - - // remove the menu from the DOM - if (this.dom.root.parentNode) { - this.dom.root.parentNode.removeChild(this.dom.root); - if (this.onClose) { - this.onClose(); - } - } - - if (ContextMenu.visibleMenu == this) { - ContextMenu.visibleMenu = undefined; - } -}; - -/** - * Expand a submenu - * Any currently expanded submenu will be hided. - * @param {Object} domItem - * @private - */ -ContextMenu.prototype._onExpandItem = function (domItem) { - var me = this; - var alreadyVisible = (domItem == this.expandedItem); - - // hide the currently visible submenu - var expandedItem = this.expandedItem; - if (expandedItem) { - //var ul = expandedItem.ul; - expandedItem.ul.style.height = '0'; - expandedItem.ul.style.padding = ''; - setTimeout(function () { - if (me.expandedItem != expandedItem) { - expandedItem.ul.style.display = ''; - util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected'); - } - }, 300); // timeout duration must match the css transition duration - this.expandedItem = undefined; - } - - if (!alreadyVisible) { - var ul = domItem.ul; - ul.style.display = 'block'; - var height = ul.clientHeight; // force a reflow in Firefox - setTimeout(function () { - if (me.expandedItem == domItem) { - var childsHeight = 0; - for (var i = 0; i < ul.childNodes.length; i++) { - childsHeight += ul.childNodes[i].clientHeight; - } - ul.style.height = childsHeight + 'px'; - ul.style.padding = '5px 10px'; - } - }, 0); - util.addClassName(ul.parentNode, 'jsoneditor-selected'); - this.expandedItem = domItem; - } -}; - -/** - * Handle onkeydown event - * @param {Event} event - * @private - */ -ContextMenu.prototype._onKeyDown = function (event) { - var target = event.target; - var keynum = event.which; - var handled = false; - var buttons, targetIndex, prevButton, nextButton; - - if (keynum == 27) { // ESC - // hide the menu on ESC key - - // restore previous selection and focus - if (this.selection) { - util.setSelection(this.selection); - } - if (this.anchor) { - this.anchor.focus(); - } - - this.hide(); - - handled = true; - } - else if (keynum == 9) { // Tab - if (!event.shiftKey) { // Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == buttons.length - 1) { - // move to first button - buttons[0].focus(); - handled = true; - } - } - else { // Shift+Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == 0) { - // move to last button - buttons[buttons.length - 1].focus(); - handled = true; - } - } - } - else if (keynum == 37) { // Arrow Left - if (target.className == 'jsoneditor-expand') { - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - prevButton = buttons[targetIndex - 1]; - if (prevButton) { - prevButton.focus(); - } - } - handled = true; - } - else if (keynum == 38) { // Arrow Up - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - prevButton = buttons[targetIndex - 1]; - if (prevButton && prevButton.className == 'jsoneditor-expand') { - // skip expand button - prevButton = buttons[targetIndex - 2]; - } - if (!prevButton) { - // move to last button - prevButton = buttons[buttons.length - 1]; - } - if (prevButton) { - prevButton.focus(); - } - handled = true; - } - else if (keynum == 39) { // Arrow Right - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - nextButton = buttons[targetIndex + 1]; - if (nextButton && nextButton.className == 'jsoneditor-expand') { - nextButton.focus(); - } - handled = true; - } - else if (keynum == 40) { // Arrow Down - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - nextButton = buttons[targetIndex + 1]; - if (nextButton && nextButton.className == 'jsoneditor-expand') { - // skip expand button - nextButton = buttons[targetIndex + 2]; - } - if (!nextButton) { - // move to first button - nextButton = buttons[0]; - } - if (nextButton) { - nextButton.focus(); - handled = true; - } - handled = true; - } - // TODO: arrow left and right - - if (handled) { - event.stopPropagation(); - event.preventDefault(); - } -}; - -module.exports = ContextMenu; - - -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - -(function(exports) { - "use strict"; - - function isArray(obj) { - if (obj !== null) { - return Object.prototype.toString.call(obj) === "[object Array]"; - } else { - return false; - } - } - - function isObject(obj) { - if (obj !== null) { - return Object.prototype.toString.call(obj) === "[object Object]"; - } else { - return false; - } - } - - function strictDeepEqual(first, second) { - // Check the scalar case first. - if (first === second) { - return true; - } - - // Check if they are the same type. - var firstType = Object.prototype.toString.call(first); - if (firstType !== Object.prototype.toString.call(second)) { - return false; - } - // We know that first and second have the same type so we can just check the - // first type from now on. - if (isArray(first) === true) { - // Short circuit if they're not the same length; - if (first.length !== second.length) { - return false; - } - for (var i = 0; i < first.length; i++) { - if (strictDeepEqual(first[i], second[i]) === false) { - return false; - } - } - return true; - } - if (isObject(first) === true) { - // An object is equal if it has the same key/value pairs. - var keysSeen = {}; - for (var key in first) { - if (hasOwnProperty.call(first, key)) { - if (strictDeepEqual(first[key], second[key]) === false) { - return false; - } - keysSeen[key] = true; - } - } - // Now check that there aren't any keys in second that weren't - // in first. - for (var key2 in second) { - if (hasOwnProperty.call(second, key2)) { - if (keysSeen[key2] !== true) { - return false; - } - } - } - return true; - } - return false; - } - - function isFalse(obj) { - // From the spec: - // A false value corresponds to the following values: - // Empty list - // Empty object - // Empty string - // False boolean - // null value - - // First check the scalar values. - if (obj === "" || obj === false || obj === null) { - return true; - } else if (isArray(obj) && obj.length === 0) { - // Check for an empty array. - return true; - } else if (isObject(obj)) { - // Check for an empty object. - for (var key in obj) { - // If there are any keys, then - // the object is not empty so the object - // is not false. - if (obj.hasOwnProperty(key)) { - return false; - } - } - return true; - } else { - return false; - } - } - - function objValues(obj) { - var keys = Object.keys(obj); - var values = []; - for (var i = 0; i < keys.length; i++) { - values.push(obj[keys[i]]); - } - return values; - } - - function merge(a, b) { - var merged = {}; - for (var key in a) { - merged[key] = a[key]; - } - for (var key2 in b) { - merged[key2] = b[key2]; - } - return merged; - } - - var trimLeft; - if (typeof String.prototype.trimLeft === "function") { - trimLeft = function(str) { - return str.trimLeft(); - }; - } else { - trimLeft = function(str) { - return str.match(/^\s*(.*)/)[1]; - }; - } - - // Type constants used to define functions. - var TYPE_NUMBER = 0; - var TYPE_ANY = 1; - var TYPE_STRING = 2; - var TYPE_ARRAY = 3; - var TYPE_OBJECT = 4; - var TYPE_BOOLEAN = 5; - var TYPE_EXPREF = 6; - var TYPE_NULL = 7; - var TYPE_ARRAY_NUMBER = 8; - var TYPE_ARRAY_STRING = 9; - - var TOK_EOF = "EOF"; - var TOK_UNQUOTEDIDENTIFIER = "UnquotedIdentifier"; - var TOK_QUOTEDIDENTIFIER = "QuotedIdentifier"; - var TOK_RBRACKET = "Rbracket"; - var TOK_RPAREN = "Rparen"; - var TOK_COMMA = "Comma"; - var TOK_COLON = "Colon"; - var TOK_RBRACE = "Rbrace"; - var TOK_NUMBER = "Number"; - var TOK_CURRENT = "Current"; - var TOK_EXPREF = "Expref"; - var TOK_PIPE = "Pipe"; - var TOK_OR = "Or"; - var TOK_AND = "And"; - var TOK_EQ = "EQ"; - var TOK_GT = "GT"; - var TOK_LT = "LT"; - var TOK_GTE = "GTE"; - var TOK_LTE = "LTE"; - var TOK_NE = "NE"; - var TOK_FLATTEN = "Flatten"; - var TOK_STAR = "Star"; - var TOK_FILTER = "Filter"; - var TOK_DOT = "Dot"; - var TOK_NOT = "Not"; - var TOK_LBRACE = "Lbrace"; - var TOK_LBRACKET = "Lbracket"; - var TOK_LPAREN= "Lparen"; - var TOK_LITERAL= "Literal"; - - // The "&", "[", "<", ">" tokens - // are not in basicToken because - // there are two token variants - // ("&&", "[?", "<=", ">="). This is specially handled - // below. - - var basicTokens = { - ".": TOK_DOT, - "*": TOK_STAR, - ",": TOK_COMMA, - ":": TOK_COLON, - "{": TOK_LBRACE, - "}": TOK_RBRACE, - "]": TOK_RBRACKET, - "(": TOK_LPAREN, - ")": TOK_RPAREN, - "@": TOK_CURRENT - }; - - var operatorStartToken = { - "<": true, - ">": true, - "=": true, - "!": true - }; - - var skipChars = { - " ": true, - "\t": true, - "\n": true - }; - - - function isAlpha(ch) { - return (ch >= "a" && ch <= "z") || - (ch >= "A" && ch <= "Z") || - ch === "_"; - } - - function isNum(ch) { - return (ch >= "0" && ch <= "9") || - ch === "-"; - } - function isAlphaNum(ch) { - return (ch >= "a" && ch <= "z") || - (ch >= "A" && ch <= "Z") || - (ch >= "0" && ch <= "9") || - ch === "_"; - } - - function Lexer() { - } - Lexer.prototype = { - tokenize: function(stream) { - var tokens = []; - this._current = 0; - var start; - var identifier; - var token; - while (this._current < stream.length) { - if (isAlpha(stream[this._current])) { - start = this._current; - identifier = this._consumeUnquotedIdentifier(stream); - tokens.push({type: TOK_UNQUOTEDIDENTIFIER, - value: identifier, - start: start}); - } else if (basicTokens[stream[this._current]] !== undefined) { - tokens.push({type: basicTokens[stream[this._current]], - value: stream[this._current], - start: this._current}); - this._current++; - } else if (isNum(stream[this._current])) { - token = this._consumeNumber(stream); - tokens.push(token); - } else if (stream[this._current] === "[") { - // No need to increment this._current. This happens - // in _consumeLBracket - token = this._consumeLBracket(stream); - tokens.push(token); - } else if (stream[this._current] === "\"") { - start = this._current; - identifier = this._consumeQuotedIdentifier(stream); - tokens.push({type: TOK_QUOTEDIDENTIFIER, - value: identifier, - start: start}); - } else if (stream[this._current] === "'") { - start = this._current; - identifier = this._consumeRawStringLiteral(stream); - tokens.push({type: TOK_LITERAL, - value: identifier, - start: start}); - } else if (stream[this._current] === "`") { - start = this._current; - var literal = this._consumeLiteral(stream); - tokens.push({type: TOK_LITERAL, - value: literal, - start: start}); - } else if (operatorStartToken[stream[this._current]] !== undefined) { - tokens.push(this._consumeOperator(stream)); - } else if (skipChars[stream[this._current]] !== undefined) { - // Ignore whitespace. - this._current++; - } else if (stream[this._current] === "&") { - start = this._current; - this._current++; - if (stream[this._current] === "&") { - this._current++; - tokens.push({type: TOK_AND, value: "&&", start: start}); - } else { - tokens.push({type: TOK_EXPREF, value: "&", start: start}); - } - } else if (stream[this._current] === "|") { - start = this._current; - this._current++; - if (stream[this._current] === "|") { - this._current++; - tokens.push({type: TOK_OR, value: "||", start: start}); - } else { - tokens.push({type: TOK_PIPE, value: "|", start: start}); - } - } else { - var error = new Error("Unknown character:" + stream[this._current]); - error.name = "LexerError"; - throw error; - } - } - return tokens; - }, - - _consumeUnquotedIdentifier: function(stream) { - var start = this._current; - this._current++; - while (this._current < stream.length && isAlphaNum(stream[this._current])) { - this._current++; - } - return stream.slice(start, this._current); - }, - - _consumeQuotedIdentifier: function(stream) { - var start = this._current; - this._current++; - var maxLength = stream.length; - while (stream[this._current] !== "\"" && this._current < maxLength) { - // You can escape a double quote and you can escape an escape. - var current = this._current; - if (stream[current] === "\\" && (stream[current + 1] === "\\" || - stream[current + 1] === "\"")) { - current += 2; - } else { - current++; - } - this._current = current; - } - this._current++; - return JSON.parse(stream.slice(start, this._current)); - }, - - _consumeRawStringLiteral: function(stream) { - var start = this._current; - this._current++; - var maxLength = stream.length; - while (stream[this._current] !== "'" && this._current < maxLength) { - // You can escape a single quote and you can escape an escape. - var current = this._current; - if (stream[current] === "\\" && (stream[current + 1] === "\\" || - stream[current + 1] === "'")) { - current += 2; - } else { - current++; - } - this._current = current; - } - this._current++; - var literal = stream.slice(start + 1, this._current - 1); - return literal.replace("\\'", "'"); - }, - - _consumeNumber: function(stream) { - var start = this._current; - this._current++; - var maxLength = stream.length; - while (isNum(stream[this._current]) && this._current < maxLength) { - this._current++; - } - var value = parseInt(stream.slice(start, this._current)); - return {type: TOK_NUMBER, value: value, start: start}; - }, - - _consumeLBracket: function(stream) { - var start = this._current; - this._current++; - if (stream[this._current] === "?") { - this._current++; - return {type: TOK_FILTER, value: "[?", start: start}; - } else if (stream[this._current] === "]") { - this._current++; - return {type: TOK_FLATTEN, value: "[]", start: start}; - } else { - return {type: TOK_LBRACKET, value: "[", start: start}; - } - }, - - _consumeOperator: function(stream) { - var start = this._current; - var startingChar = stream[start]; - this._current++; - if (startingChar === "!") { - if (stream[this._current] === "=") { - this._current++; - return {type: TOK_NE, value: "!=", start: start}; - } else { - return {type: TOK_NOT, value: "!", start: start}; - } - } else if (startingChar === "<") { - if (stream[this._current] === "=") { - this._current++; - return {type: TOK_LTE, value: "<=", start: start}; - } else { - return {type: TOK_LT, value: "<", start: start}; - } - } else if (startingChar === ">") { - if (stream[this._current] === "=") { - this._current++; - return {type: TOK_GTE, value: ">=", start: start}; - } else { - return {type: TOK_GT, value: ">", start: start}; - } - } else if (startingChar === "=") { - if (stream[this._current] === "=") { - this._current++; - return {type: TOK_EQ, value: "==", start: start}; - } - } - }, - - _consumeLiteral: function(stream) { - this._current++; - var start = this._current; - var maxLength = stream.length; - var literal; - while(stream[this._current] !== "`" && this._current < maxLength) { - // You can escape a literal char or you can escape the escape. - var current = this._current; - if (stream[current] === "\\" && (stream[current + 1] === "\\" || - stream[current + 1] === "`")) { - current += 2; - } else { - current++; - } - this._current = current; - } - var literalString = trimLeft(stream.slice(start, this._current)); - literalString = literalString.replace("\\`", "`"); - if (this._looksLikeJSON(literalString)) { - literal = JSON.parse(literalString); - } else { - // Try to JSON parse it as "" - literal = JSON.parse("\"" + literalString + "\""); - } - // +1 gets us to the ending "`", +1 to move on to the next char. - this._current++; - return literal; - }, - - _looksLikeJSON: function(literalString) { - var startingChars = "[{\""; - var jsonLiterals = ["true", "false", "null"]; - var numberLooking = "-0123456789"; - - if (literalString === "") { - return false; - } else if (startingChars.indexOf(literalString[0]) >= 0) { - return true; - } else if (jsonLiterals.indexOf(literalString) >= 0) { - return true; - } else if (numberLooking.indexOf(literalString[0]) >= 0) { - try { - JSON.parse(literalString); - return true; - } catch (ex) { - return false; - } - } else { - return false; - } - } - }; - - var bindingPower = {}; - bindingPower[TOK_EOF] = 0; - bindingPower[TOK_UNQUOTEDIDENTIFIER] = 0; - bindingPower[TOK_QUOTEDIDENTIFIER] = 0; - bindingPower[TOK_RBRACKET] = 0; - bindingPower[TOK_RPAREN] = 0; - bindingPower[TOK_COMMA] = 0; - bindingPower[TOK_RBRACE] = 0; - bindingPower[TOK_NUMBER] = 0; - bindingPower[TOK_CURRENT] = 0; - bindingPower[TOK_EXPREF] = 0; - bindingPower[TOK_PIPE] = 1; - bindingPower[TOK_OR] = 2; - bindingPower[TOK_AND] = 3; - bindingPower[TOK_EQ] = 5; - bindingPower[TOK_GT] = 5; - bindingPower[TOK_LT] = 5; - bindingPower[TOK_GTE] = 5; - bindingPower[TOK_LTE] = 5; - bindingPower[TOK_NE] = 5; - bindingPower[TOK_FLATTEN] = 9; - bindingPower[TOK_STAR] = 20; - bindingPower[TOK_FILTER] = 21; - bindingPower[TOK_DOT] = 40; - bindingPower[TOK_NOT] = 45; - bindingPower[TOK_LBRACE] = 50; - bindingPower[TOK_LBRACKET] = 55; - bindingPower[TOK_LPAREN] = 60; - - function Parser() { - } - - Parser.prototype = { - parse: function(expression) { - this._loadTokens(expression); - this.index = 0; - var ast = this.expression(0); - if (this._lookahead(0) !== TOK_EOF) { - var t = this._lookaheadToken(0); - var error = new Error( - "Unexpected token type: " + t.type + ", value: " + t.value); - error.name = "ParserError"; - throw error; - } - return ast; - }, - - _loadTokens: function(expression) { - var lexer = new Lexer(); - var tokens = lexer.tokenize(expression); - tokens.push({type: TOK_EOF, value: "", start: expression.length}); - this.tokens = tokens; - }, - - expression: function(rbp) { - var leftToken = this._lookaheadToken(0); - this._advance(); - var left = this.nud(leftToken); - var currentToken = this._lookahead(0); - while (rbp < bindingPower[currentToken]) { - this._advance(); - left = this.led(currentToken, left); - currentToken = this._lookahead(0); - } - return left; - }, - - _lookahead: function(number) { - return this.tokens[this.index + number].type; - }, - - _lookaheadToken: function(number) { - return this.tokens[this.index + number]; - }, - - _advance: function() { - this.index++; - }, - - nud: function(token) { - var left; - var right; - var expression; - switch (token.type) { - case TOK_LITERAL: - return {type: "Literal", value: token.value}; - case TOK_UNQUOTEDIDENTIFIER: - return {type: "Field", name: token.value}; - case TOK_QUOTEDIDENTIFIER: - var node = {type: "Field", name: token.value}; - if (this._lookahead(0) === TOK_LPAREN) { - throw new Error("Quoted identifier not allowed for function names."); - } else { - return node; - } - break; - case TOK_NOT: - right = this.expression(bindingPower.Not); - return {type: "NotExpression", children: [right]}; - case TOK_STAR: - left = {type: "Identity"}; - right = null; - if (this._lookahead(0) === TOK_RBRACKET) { - // This can happen in a multiselect, - // [a, b, *] - right = {type: "Identity"}; - } else { - right = this._parseProjectionRHS(bindingPower.Star); - } - return {type: "ValueProjection", children: [left, right]}; - case TOK_FILTER: - return this.led(token.type, {type: "Identity"}); - case TOK_LBRACE: - return this._parseMultiselectHash(); - case TOK_FLATTEN: - left = {type: TOK_FLATTEN, children: [{type: "Identity"}]}; - right = this._parseProjectionRHS(bindingPower.Flatten); - return {type: "Projection", children: [left, right]}; - case TOK_LBRACKET: - if (this._lookahead(0) === TOK_NUMBER || this._lookahead(0) === TOK_COLON) { - right = this._parseIndexExpression(); - return this._projectIfSlice({type: "Identity"}, right); - } else if (this._lookahead(0) === TOK_STAR && - this._lookahead(1) === TOK_RBRACKET) { - this._advance(); - this._advance(); - right = this._parseProjectionRHS(bindingPower.Star); - return {type: "Projection", - children: [{type: "Identity"}, right]}; - } else { - return this._parseMultiselectList(); - } - break; - case TOK_CURRENT: - return {type: TOK_CURRENT}; - case TOK_EXPREF: - expression = this.expression(bindingPower.Expref); - return {type: "ExpressionReference", children: [expression]}; - case TOK_LPAREN: - var args = []; - while (this._lookahead(0) !== TOK_RPAREN) { - if (this._lookahead(0) === TOK_CURRENT) { - expression = {type: TOK_CURRENT}; - this._advance(); - } else { - expression = this.expression(0); - } - args.push(expression); - } - this._match(TOK_RPAREN); - return args[0]; - default: - this._errorToken(token); - } - }, - - led: function(tokenName, left) { - var right; - switch(tokenName) { - case TOK_DOT: - var rbp = bindingPower.Dot; - if (this._lookahead(0) !== TOK_STAR) { - right = this._parseDotRHS(rbp); - return {type: "Subexpression", children: [left, right]}; - } else { - // Creating a projection. - this._advance(); - right = this._parseProjectionRHS(rbp); - return {type: "ValueProjection", children: [left, right]}; - } - break; - case TOK_PIPE: - right = this.expression(bindingPower.Pipe); - return {type: TOK_PIPE, children: [left, right]}; - case TOK_OR: - right = this.expression(bindingPower.Or); - return {type: "OrExpression", children: [left, right]}; - case TOK_AND: - right = this.expression(bindingPower.And); - return {type: "AndExpression", children: [left, right]}; - case TOK_LPAREN: - var name = left.name; - var args = []; - var expression, node; - while (this._lookahead(0) !== TOK_RPAREN) { - if (this._lookahead(0) === TOK_CURRENT) { - expression = {type: TOK_CURRENT}; - this._advance(); - } else { - expression = this.expression(0); - } - if (this._lookahead(0) === TOK_COMMA) { - this._match(TOK_COMMA); - } - args.push(expression); - } - this._match(TOK_RPAREN); - node = {type: "Function", name: name, children: args}; - return node; - case TOK_FILTER: - var condition = this.expression(0); - this._match(TOK_RBRACKET); - if (this._lookahead(0) === TOK_FLATTEN) { - right = {type: "Identity"}; - } else { - right = this._parseProjectionRHS(bindingPower.Filter); - } - return {type: "FilterProjection", children: [left, right, condition]}; - case TOK_FLATTEN: - var leftNode = {type: TOK_FLATTEN, children: [left]}; - var rightNode = this._parseProjectionRHS(bindingPower.Flatten); - return {type: "Projection", children: [leftNode, rightNode]}; - case TOK_EQ: - case TOK_NE: - case TOK_GT: - case TOK_GTE: - case TOK_LT: - case TOK_LTE: - return this._parseComparator(left, tokenName); - case TOK_LBRACKET: - var token = this._lookaheadToken(0); - if (token.type === TOK_NUMBER || token.type === TOK_COLON) { - right = this._parseIndexExpression(); - return this._projectIfSlice(left, right); - } else { - this._match(TOK_STAR); - this._match(TOK_RBRACKET); - right = this._parseProjectionRHS(bindingPower.Star); - return {type: "Projection", children: [left, right]}; - } - break; - default: - this._errorToken(this._lookaheadToken(0)); - } - }, - - _match: function(tokenType) { - if (this._lookahead(0) === tokenType) { - this._advance(); - } else { - var t = this._lookaheadToken(0); - var error = new Error("Expected " + tokenType + ", got: " + t.type); - error.name = "ParserError"; - throw error; - } - }, - - _errorToken: function(token) { - var error = new Error("Invalid token (" + - token.type + "): \"" + - token.value + "\""); - error.name = "ParserError"; - throw error; - }, - - - _parseIndexExpression: function() { - if (this._lookahead(0) === TOK_COLON || this._lookahead(1) === TOK_COLON) { - return this._parseSliceExpression(); - } else { - var node = { - type: "Index", - value: this._lookaheadToken(0).value}; - this._advance(); - this._match(TOK_RBRACKET); - return node; - } - }, - - _projectIfSlice: function(left, right) { - var indexExpr = {type: "IndexExpression", children: [left, right]}; - if (right.type === "Slice") { - return { - type: "Projection", - children: [indexExpr, this._parseProjectionRHS(bindingPower.Star)] - }; - } else { - return indexExpr; - } - }, - - _parseSliceExpression: function() { - // [start:end:step] where each part is optional, as well as the last - // colon. - var parts = [null, null, null]; - var index = 0; - var currentToken = this._lookahead(0); - while (currentToken !== TOK_RBRACKET && index < 3) { - if (currentToken === TOK_COLON) { - index++; - this._advance(); - } else if (currentToken === TOK_NUMBER) { - parts[index] = this._lookaheadToken(0).value; - this._advance(); - } else { - var t = this._lookahead(0); - var error = new Error("Syntax error, unexpected token: " + - t.value + "(" + t.type + ")"); - error.name = "Parsererror"; - throw error; - } - currentToken = this._lookahead(0); - } - this._match(TOK_RBRACKET); - return { - type: "Slice", - children: parts - }; - }, - - _parseComparator: function(left, comparator) { - var right = this.expression(bindingPower[comparator]); - return {type: "Comparator", name: comparator, children: [left, right]}; - }, - - _parseDotRHS: function(rbp) { - var lookahead = this._lookahead(0); - var exprTokens = [TOK_UNQUOTEDIDENTIFIER, TOK_QUOTEDIDENTIFIER, TOK_STAR]; - if (exprTokens.indexOf(lookahead) >= 0) { - return this.expression(rbp); - } else if (lookahead === TOK_LBRACKET) { - this._match(TOK_LBRACKET); - return this._parseMultiselectList(); - } else if (lookahead === TOK_LBRACE) { - this._match(TOK_LBRACE); - return this._parseMultiselectHash(); - } - }, - - _parseProjectionRHS: function(rbp) { - var right; - if (bindingPower[this._lookahead(0)] < 10) { - right = {type: "Identity"}; - } else if (this._lookahead(0) === TOK_LBRACKET) { - right = this.expression(rbp); - } else if (this._lookahead(0) === TOK_FILTER) { - right = this.expression(rbp); - } else if (this._lookahead(0) === TOK_DOT) { - this._match(TOK_DOT); - right = this._parseDotRHS(rbp); - } else { - var t = this._lookaheadToken(0); - var error = new Error("Sytanx error, unexpected token: " + - t.value + "(" + t.type + ")"); - error.name = "ParserError"; - throw error; - } - return right; - }, - - _parseMultiselectList: function() { - var expressions = []; - while (this._lookahead(0) !== TOK_RBRACKET) { - var expression = this.expression(0); - expressions.push(expression); - if (this._lookahead(0) === TOK_COMMA) { - this._match(TOK_COMMA); - if (this._lookahead(0) === TOK_RBRACKET) { - throw new Error("Unexpected token Rbracket"); - } - } - } - this._match(TOK_RBRACKET); - return {type: "MultiSelectList", children: expressions}; - }, - - _parseMultiselectHash: function() { - var pairs = []; - var identifierTypes = [TOK_UNQUOTEDIDENTIFIER, TOK_QUOTEDIDENTIFIER]; - var keyToken, keyName, value, node; - for (;;) { - keyToken = this._lookaheadToken(0); - if (identifierTypes.indexOf(keyToken.type) < 0) { - throw new Error("Expecting an identifier token, got: " + - keyToken.type); - } - keyName = keyToken.value; - this._advance(); - this._match(TOK_COLON); - value = this.expression(0); - node = {type: "KeyValuePair", name: keyName, value: value}; - pairs.push(node); - if (this._lookahead(0) === TOK_COMMA) { - this._match(TOK_COMMA); - } else if (this._lookahead(0) === TOK_RBRACE) { - this._match(TOK_RBRACE); - break; - } - } - return {type: "MultiSelectHash", children: pairs}; - } - }; - - - function TreeInterpreter(runtime) { - this.runtime = runtime; - } - - TreeInterpreter.prototype = { - search: function(node, value) { - return this.visit(node, value); - }, - - visit: function(node, value) { - var matched, current, result, first, second, field, left, right, collected, i; - switch (node.type) { - case "Field": - if (value === null ) { - return null; - } else if (isObject(value)) { - field = value[node.name]; - if (field === undefined) { - return null; - } else { - return field; - } - } else { - return null; - } - break; - case "Subexpression": - result = this.visit(node.children[0], value); - for (i = 1; i < node.children.length; i++) { - result = this.visit(node.children[1], result); - if (result === null) { - return null; - } - } - return result; - case "IndexExpression": - left = this.visit(node.children[0], value); - right = this.visit(node.children[1], left); - return right; - case "Index": - if (!isArray(value)) { - return null; - } - var index = node.value; - if (index < 0) { - index = value.length + index; - } - result = value[index]; - if (result === undefined) { - result = null; - } - return result; - case "Slice": - if (!isArray(value)) { - return null; - } - var sliceParams = node.children.slice(0); - var computed = this.computeSliceParams(value.length, sliceParams); - var start = computed[0]; - var stop = computed[1]; - var step = computed[2]; - result = []; - if (step > 0) { - for (i = start; i < stop; i += step) { - result.push(value[i]); - } - } else { - for (i = start; i > stop; i += step) { - result.push(value[i]); - } - } - return result; - case "Projection": - // Evaluate left child. - var base = this.visit(node.children[0], value); - if (!isArray(base)) { - return null; - } - collected = []; - for (i = 0; i < base.length; i++) { - current = this.visit(node.children[1], base[i]); - if (current !== null) { - collected.push(current); - } - } - return collected; - case "ValueProjection": - // Evaluate left child. - base = this.visit(node.children[0], value); - if (!isObject(base)) { - return null; - } - collected = []; - var values = objValues(base); - for (i = 0; i < values.length; i++) { - current = this.visit(node.children[1], values[i]); - if (current !== null) { - collected.push(current); - } - } - return collected; - case "FilterProjection": - base = this.visit(node.children[0], value); - if (!isArray(base)) { - return null; - } - var filtered = []; - var finalResults = []; - for (i = 0; i < base.length; i++) { - matched = this.visit(node.children[2], base[i]); - if (!isFalse(matched)) { - filtered.push(base[i]); - } - } - for (var j = 0; j < filtered.length; j++) { - current = this.visit(node.children[1], filtered[j]); - if (current !== null) { - finalResults.push(current); - } - } - return finalResults; - case "Comparator": - first = this.visit(node.children[0], value); - second = this.visit(node.children[1], value); - switch(node.name) { - case TOK_EQ: - result = strictDeepEqual(first, second); - break; - case TOK_NE: - result = !strictDeepEqual(first, second); - break; - case TOK_GT: - result = first > second; - break; - case TOK_GTE: - result = first >= second; - break; - case TOK_LT: - result = first < second; - break; - case TOK_LTE: - result = first <= second; - break; - default: - throw new Error("Unknown comparator: " + node.name); - } - return result; - case TOK_FLATTEN: - var original = this.visit(node.children[0], value); - if (!isArray(original)) { - return null; - } - var merged = []; - for (i = 0; i < original.length; i++) { - current = original[i]; - if (isArray(current)) { - merged.push.apply(merged, current); - } else { - merged.push(current); - } - } - return merged; - case "Identity": - return value; - case "MultiSelectList": - if (value === null) { - return null; - } - collected = []; - for (i = 0; i < node.children.length; i++) { - collected.push(this.visit(node.children[i], value)); - } - return collected; - case "MultiSelectHash": - if (value === null) { - return null; - } - collected = {}; - var child; - for (i = 0; i < node.children.length; i++) { - child = node.children[i]; - collected[child.name] = this.visit(child.value, value); - } - return collected; - case "OrExpression": - matched = this.visit(node.children[0], value); - if (isFalse(matched)) { - matched = this.visit(node.children[1], value); - } - return matched; - case "AndExpression": - first = this.visit(node.children[0], value); - - if (isFalse(first) === true) { - return first; - } - return this.visit(node.children[1], value); - case "NotExpression": - first = this.visit(node.children[0], value); - return isFalse(first); - case "Literal": - return node.value; - case TOK_PIPE: - left = this.visit(node.children[0], value); - return this.visit(node.children[1], left); - case TOK_CURRENT: - return value; - case "Function": - var resolvedArgs = []; - for (i = 0; i < node.children.length; i++) { - resolvedArgs.push(this.visit(node.children[i], value)); - } - return this.runtime.callFunction(node.name, resolvedArgs); - case "ExpressionReference": - var refNode = node.children[0]; - // Tag the node with a specific attribute so the type - // checker verify the type. - refNode.jmespathType = TOK_EXPREF; - return refNode; - default: - throw new Error("Unknown node type: " + node.type); - } - }, - - computeSliceParams: function(arrayLength, sliceParams) { - var start = sliceParams[0]; - var stop = sliceParams[1]; - var step = sliceParams[2]; - var computed = [null, null, null]; - if (step === null) { - step = 1; - } else if (step === 0) { - var error = new Error("Invalid slice, step cannot be 0"); - error.name = "RuntimeError"; - throw error; - } - var stepValueNegative = step < 0 ? true : false; - - if (start === null) { - start = stepValueNegative ? arrayLength - 1 : 0; - } else { - start = this.capSliceRange(arrayLength, start, step); - } - - if (stop === null) { - stop = stepValueNegative ? -1 : arrayLength; - } else { - stop = this.capSliceRange(arrayLength, stop, step); - } - computed[0] = start; - computed[1] = stop; - computed[2] = step; - return computed; - }, - - capSliceRange: function(arrayLength, actualValue, step) { - if (actualValue < 0) { - actualValue += arrayLength; - if (actualValue < 0) { - actualValue = step < 0 ? -1 : 0; - } - } else if (actualValue >= arrayLength) { - actualValue = step < 0 ? arrayLength - 1 : arrayLength; - } - return actualValue; - } - - }; - - function Runtime(interpreter) { - this._interpreter = interpreter; - this.functionTable = { - // name: [function, ] - // The can be: - // - // { - // args: [[type1, type2], [type1, type2]], - // variadic: true|false - // } - // - // Each arg in the arg list is a list of valid types - // (if the function is overloaded and supports multiple - // types. If the type is "any" then no type checking - // occurs on the argument. Variadic is optional - // and if not provided is assumed to be false. - abs: {_func: this._functionAbs, _signature: [{types: [TYPE_NUMBER]}]}, - avg: {_func: this._functionAvg, _signature: [{types: [TYPE_ARRAY_NUMBER]}]}, - ceil: {_func: this._functionCeil, _signature: [{types: [TYPE_NUMBER]}]}, - contains: { - _func: this._functionContains, - _signature: [{types: [TYPE_STRING, TYPE_ARRAY]}, - {types: [TYPE_ANY]}]}, - "ends_with": { - _func: this._functionEndsWith, - _signature: [{types: [TYPE_STRING]}, {types: [TYPE_STRING]}]}, - floor: {_func: this._functionFloor, _signature: [{types: [TYPE_NUMBER]}]}, - length: { - _func: this._functionLength, - _signature: [{types: [TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT]}]}, - map: { - _func: this._functionMap, - _signature: [{types: [TYPE_EXPREF]}, {types: [TYPE_ARRAY]}]}, - max: { - _func: this._functionMax, - _signature: [{types: [TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING]}]}, - "merge": { - _func: this._functionMerge, - _signature: [{types: [TYPE_OBJECT], variadic: true}] - }, - "max_by": { - _func: this._functionMaxBy, - _signature: [{types: [TYPE_ARRAY]}, {types: [TYPE_EXPREF]}] - }, - sum: {_func: this._functionSum, _signature: [{types: [TYPE_ARRAY_NUMBER]}]}, - "starts_with": { - _func: this._functionStartsWith, - _signature: [{types: [TYPE_STRING]}, {types: [TYPE_STRING]}]}, - min: { - _func: this._functionMin, - _signature: [{types: [TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING]}]}, - "min_by": { - _func: this._functionMinBy, - _signature: [{types: [TYPE_ARRAY]}, {types: [TYPE_EXPREF]}] - }, - type: {_func: this._functionType, _signature: [{types: [TYPE_ANY]}]}, - keys: {_func: this._functionKeys, _signature: [{types: [TYPE_OBJECT]}]}, - values: {_func: this._functionValues, _signature: [{types: [TYPE_OBJECT]}]}, - sort: {_func: this._functionSort, _signature: [{types: [TYPE_ARRAY_STRING, TYPE_ARRAY_NUMBER]}]}, - "sort_by": { - _func: this._functionSortBy, - _signature: [{types: [TYPE_ARRAY]}, {types: [TYPE_EXPREF]}] - }, - join: { - _func: this._functionJoin, - _signature: [ - {types: [TYPE_STRING]}, - {types: [TYPE_ARRAY_STRING]} - ] - }, - reverse: { - _func: this._functionReverse, - _signature: [{types: [TYPE_STRING, TYPE_ARRAY]}]}, - "to_array": {_func: this._functionToArray, _signature: [{types: [TYPE_ANY]}]}, - "to_string": {_func: this._functionToString, _signature: [{types: [TYPE_ANY]}]}, - "to_number": {_func: this._functionToNumber, _signature: [{types: [TYPE_ANY]}]}, - "not_null": { - _func: this._functionNotNull, - _signature: [{types: [TYPE_ANY], variadic: true}] - } - }; - } - - Runtime.prototype = { - callFunction: function(name, resolvedArgs) { - var functionEntry = this.functionTable[name]; - if (functionEntry === undefined) { - throw new Error("Unknown function: " + name + "()"); - } - this._validateArgs(name, resolvedArgs, functionEntry._signature); - return functionEntry._func.call(this, resolvedArgs); - }, - - _validateArgs: function(name, args, signature) { - // Validating the args requires validating - // the correct arity and the correct type of each arg. - // If the last argument is declared as variadic, then we need - // a minimum number of args to be required. Otherwise it has to - // be an exact amount. - var pluralized; - if (signature[signature.length - 1].variadic) { - if (args.length < signature.length) { - pluralized = signature.length === 1 ? " argument" : " arguments"; - throw new Error("ArgumentError: " + name + "() " + - "takes at least" + signature.length + pluralized + - " but received " + args.length); - } - } else if (args.length !== signature.length) { - pluralized = signature.length === 1 ? " argument" : " arguments"; - throw new Error("ArgumentError: " + name + "() " + - "takes " + signature.length + pluralized + - " but received " + args.length); - } - var currentSpec; - var actualType; - var typeMatched; - for (var i = 0; i < signature.length; i++) { - typeMatched = false; - currentSpec = signature[i].types; - actualType = this._getTypeName(args[i]); - for (var j = 0; j < currentSpec.length; j++) { - if (this._typeMatches(actualType, currentSpec[j], args[i])) { - typeMatched = true; - break; - } - } - if (!typeMatched) { - throw new Error("TypeError: " + name + "() " + - "expected argument " + (i + 1) + - " to be type " + currentSpec + - " but received type " + actualType + - " instead."); - } - } - }, - - _typeMatches: function(actual, expected, argValue) { - if (expected === TYPE_ANY) { - return true; - } - if (expected === TYPE_ARRAY_STRING || - expected === TYPE_ARRAY_NUMBER || - expected === TYPE_ARRAY) { - // The expected type can either just be array, - // or it can require a specific subtype (array of numbers). - // - // The simplest case is if "array" with no subtype is specified. - if (expected === TYPE_ARRAY) { - return actual === TYPE_ARRAY; - } else if (actual === TYPE_ARRAY) { - // Otherwise we need to check subtypes. - // I think this has potential to be improved. - var subtype; - if (expected === TYPE_ARRAY_NUMBER) { - subtype = TYPE_NUMBER; - } else if (expected === TYPE_ARRAY_STRING) { - subtype = TYPE_STRING; - } - for (var i = 0; i < argValue.length; i++) { - if (!this._typeMatches( - this._getTypeName(argValue[i]), subtype, - argValue[i])) { - return false; - } - } - return true; - } - } else { - return actual === expected; - } - }, - _getTypeName: function(obj) { - switch (Object.prototype.toString.call(obj)) { - case "[object String]": - return TYPE_STRING; - case "[object Number]": - return TYPE_NUMBER; - case "[object Array]": - return TYPE_ARRAY; - case "[object Boolean]": - return TYPE_BOOLEAN; - case "[object Null]": - return TYPE_NULL; - case "[object Object]": - // Check if it's an expref. If it has, it's been - // tagged with a jmespathType attr of 'Expref'; - if (obj.jmespathType === TOK_EXPREF) { - return TYPE_EXPREF; - } else { - return TYPE_OBJECT; - } - } - }, - - _functionStartsWith: function(resolvedArgs) { - return resolvedArgs[0].lastIndexOf(resolvedArgs[1]) === 0; - }, - - _functionEndsWith: function(resolvedArgs) { - var searchStr = resolvedArgs[0]; - var suffix = resolvedArgs[1]; - return searchStr.indexOf(suffix, searchStr.length - suffix.length) !== -1; - }, - - _functionReverse: function(resolvedArgs) { - var typeName = this._getTypeName(resolvedArgs[0]); - if (typeName === TYPE_STRING) { - var originalStr = resolvedArgs[0]; - var reversedStr = ""; - for (var i = originalStr.length - 1; i >= 0; i--) { - reversedStr += originalStr[i]; - } - return reversedStr; - } else { - var reversedArray = resolvedArgs[0].slice(0); - reversedArray.reverse(); - return reversedArray; - } - }, - - _functionAbs: function(resolvedArgs) { - return Math.abs(resolvedArgs[0]); - }, - - _functionCeil: function(resolvedArgs) { - return Math.ceil(resolvedArgs[0]); - }, - - _functionAvg: function(resolvedArgs) { - var sum = 0; - var inputArray = resolvedArgs[0]; - for (var i = 0; i < inputArray.length; i++) { - sum += inputArray[i]; - } - return sum / inputArray.length; - }, - - _functionContains: function(resolvedArgs) { - return resolvedArgs[0].indexOf(resolvedArgs[1]) >= 0; - }, - - _functionFloor: function(resolvedArgs) { - return Math.floor(resolvedArgs[0]); - }, - - _functionLength: function(resolvedArgs) { - if (!isObject(resolvedArgs[0])) { - return resolvedArgs[0].length; - } else { - // As far as I can tell, there's no way to get the length - // of an object without O(n) iteration through the object. - return Object.keys(resolvedArgs[0]).length; - } - }, - - _functionMap: function(resolvedArgs) { - var mapped = []; - var interpreter = this._interpreter; - var exprefNode = resolvedArgs[0]; - var elements = resolvedArgs[1]; - for (var i = 0; i < elements.length; i++) { - mapped.push(interpreter.visit(exprefNode, elements[i])); - } - return mapped; - }, - - _functionMerge: function(resolvedArgs) { - var merged = {}; - for (var i = 0; i < resolvedArgs.length; i++) { - var current = resolvedArgs[i]; - for (var key in current) { - merged[key] = current[key]; - } - } - return merged; - }, - - _functionMax: function(resolvedArgs) { - if (resolvedArgs[0].length > 0) { - var typeName = this._getTypeName(resolvedArgs[0][0]); - if (typeName === TYPE_NUMBER) { - return Math.max.apply(Math, resolvedArgs[0]); - } else { - var elements = resolvedArgs[0]; - var maxElement = elements[0]; - for (var i = 1; i < elements.length; i++) { - if (maxElement.localeCompare(elements[i]) < 0) { - maxElement = elements[i]; - } - } - return maxElement; - } - } else { - return null; - } - }, - - _functionMin: function(resolvedArgs) { - if (resolvedArgs[0].length > 0) { - var typeName = this._getTypeName(resolvedArgs[0][0]); - if (typeName === TYPE_NUMBER) { - return Math.min.apply(Math, resolvedArgs[0]); - } else { - var elements = resolvedArgs[0]; - var minElement = elements[0]; - for (var i = 1; i < elements.length; i++) { - if (elements[i].localeCompare(minElement) < 0) { - minElement = elements[i]; - } - } - return minElement; - } - } else { - return null; - } - }, - - _functionSum: function(resolvedArgs) { - var sum = 0; - var listToSum = resolvedArgs[0]; - for (var i = 0; i < listToSum.length; i++) { - sum += listToSum[i]; - } - return sum; - }, - - _functionType: function(resolvedArgs) { - switch (this._getTypeName(resolvedArgs[0])) { - case TYPE_NUMBER: - return "number"; - case TYPE_STRING: - return "string"; - case TYPE_ARRAY: - return "array"; - case TYPE_OBJECT: - return "object"; - case TYPE_BOOLEAN: - return "boolean"; - case TYPE_EXPREF: - return "expref"; - case TYPE_NULL: - return "null"; - } - }, - - _functionKeys: function(resolvedArgs) { - return Object.keys(resolvedArgs[0]); - }, - - _functionValues: function(resolvedArgs) { - var obj = resolvedArgs[0]; - var keys = Object.keys(obj); - var values = []; - for (var i = 0; i < keys.length; i++) { - values.push(obj[keys[i]]); - } - return values; - }, - - _functionJoin: function(resolvedArgs) { - var joinChar = resolvedArgs[0]; - var listJoin = resolvedArgs[1]; - return listJoin.join(joinChar); - }, - - _functionToArray: function(resolvedArgs) { - if (this._getTypeName(resolvedArgs[0]) === TYPE_ARRAY) { - return resolvedArgs[0]; - } else { - return [resolvedArgs[0]]; - } - }, - - _functionToString: function(resolvedArgs) { - if (this._getTypeName(resolvedArgs[0]) === TYPE_STRING) { - return resolvedArgs[0]; - } else { - return JSON.stringify(resolvedArgs[0]); - } - }, - - _functionToNumber: function(resolvedArgs) { - var typeName = this._getTypeName(resolvedArgs[0]); - var convertedValue; - if (typeName === TYPE_NUMBER) { - return resolvedArgs[0]; - } else if (typeName === TYPE_STRING) { - convertedValue = +resolvedArgs[0]; - if (!isNaN(convertedValue)) { - return convertedValue; - } - } - return null; - }, - - _functionNotNull: function(resolvedArgs) { - for (var i = 0; i < resolvedArgs.length; i++) { - if (this._getTypeName(resolvedArgs[i]) !== TYPE_NULL) { - return resolvedArgs[i]; - } - } - return null; - }, - - _functionSort: function(resolvedArgs) { - var sortedArray = resolvedArgs[0].slice(0); - sortedArray.sort(); - return sortedArray; - }, - - _functionSortBy: function(resolvedArgs) { - var sortedArray = resolvedArgs[0].slice(0); - if (sortedArray.length === 0) { - return sortedArray; - } - var interpreter = this._interpreter; - var exprefNode = resolvedArgs[1]; - var requiredType = this._getTypeName( - interpreter.visit(exprefNode, sortedArray[0])); - if ([TYPE_NUMBER, TYPE_STRING].indexOf(requiredType) < 0) { - throw new Error("TypeError"); - } - var that = this; - // In order to get a stable sort out of an unstable - // sort algorithm, we decorate/sort/undecorate (DSU) - // by creating a new list of [index, element] pairs. - // In the cmp function, if the evaluated elements are - // equal, then the index will be used as the tiebreaker. - // After the decorated list has been sorted, it will be - // undecorated to extract the original elements. - var decorated = []; - for (var i = 0; i < sortedArray.length; i++) { - decorated.push([i, sortedArray[i]]); - } - decorated.sort(function(a, b) { - var exprA = interpreter.visit(exprefNode, a[1]); - var exprB = interpreter.visit(exprefNode, b[1]); - if (that._getTypeName(exprA) !== requiredType) { - throw new Error( - "TypeError: expected " + requiredType + ", received " + - that._getTypeName(exprA)); - } else if (that._getTypeName(exprB) !== requiredType) { - throw new Error( - "TypeError: expected " + requiredType + ", received " + - that._getTypeName(exprB)); - } - if (exprA > exprB) { - return 1; - } else if (exprA < exprB) { - return -1; - } else { - // If they're equal compare the items by their - // order to maintain relative order of equal keys - // (i.e. to get a stable sort). - return a[0] - b[0]; - } - }); - // Undecorate: extract out the original list elements. - for (var j = 0; j < decorated.length; j++) { - sortedArray[j] = decorated[j][1]; - } - return sortedArray; - }, - - _functionMaxBy: function(resolvedArgs) { - var exprefNode = resolvedArgs[1]; - var resolvedArray = resolvedArgs[0]; - var keyFunction = this.createKeyFunction(exprefNode, [TYPE_NUMBER, TYPE_STRING]); - var maxNumber = -Infinity; - var maxRecord; - var current; - for (var i = 0; i < resolvedArray.length; i++) { - current = keyFunction(resolvedArray[i]); - if (current > maxNumber) { - maxNumber = current; - maxRecord = resolvedArray[i]; - } - } - return maxRecord; - }, - - _functionMinBy: function(resolvedArgs) { - var exprefNode = resolvedArgs[1]; - var resolvedArray = resolvedArgs[0]; - var keyFunction = this.createKeyFunction(exprefNode, [TYPE_NUMBER, TYPE_STRING]); - var minNumber = Infinity; - var minRecord; - var current; - for (var i = 0; i < resolvedArray.length; i++) { - current = keyFunction(resolvedArray[i]); - if (current < minNumber) { - minNumber = current; - minRecord = resolvedArray[i]; - } - } - return minRecord; - }, - - createKeyFunction: function(exprefNode, allowedTypes) { - var that = this; - var interpreter = this._interpreter; - var keyFunc = function(x) { - var current = interpreter.visit(exprefNode, x); - if (allowedTypes.indexOf(that._getTypeName(current)) < 0) { - var msg = "TypeError: expected one of " + allowedTypes + - ", received " + that._getTypeName(current); - throw new Error(msg); - } - return current; - }; - return keyFunc; - } - - }; - - function compile(stream) { - var parser = new Parser(); - var ast = parser.parse(stream); - return ast; - } - - function tokenize(stream) { - var lexer = new Lexer(); - return lexer.tokenize(stream); - } - - function search(data, expression) { - var parser = new Parser(); - // This needs to be improved. Both the interpreter and runtime depend on - // each other. The runtime needs the interpreter to support exprefs. - // There's likely a clean way to avoid the cyclic dependency. - var runtime = new Runtime(); - var interpreter = new TreeInterpreter(runtime); - runtime._interpreter = interpreter; - var node = parser.parse(expression); - return interpreter.search(node, data); - } - - exports.tokenize = tokenize; - exports.compile = compile; - exports.search = search; - exports.strictDeepEqual = strictDeepEqual; -})( false ? undefined : exports); - - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - -var picoModal = __webpack_require__(13); -var translate = __webpack_require__(1).translate; -var util = __webpack_require__(0); - -/** - * Show advanced sorting modal - * @param {HTMLElement} container The container where to center - * the modal and create an overlay - * @param {JSON} json The JSON data to be sorted. - * @param {function} onSort Callback function, invoked with - * an object containing the selected - * path and direction - * @param {Object} options - * Available options: - * - {string} path The selected path - * - {'asc' | 'desc'} direction The selected direction - */ -function showSortModal (container, json, onSort, options) { - var paths = Array.isArray(json) - ? util.getChildPaths(json) - : ['']; - var selectedPath = options && options.path && util.contains(paths, options.path) - ? options.path - : paths[0] - var selectedDirection = options && options.direction || 'asc' - - var content = '
' + - '
' + translate('sort') + '
' + - '
' + - '' + - '' + - '' + - ' ' + - ' ' + - '' + - '' + - ' ' + - ' ' + - '' + - '' + - '' + - '' + - '' + - '
' + translate('sortFieldLabel') + ' ' + - '
' + - ' ' + - '
' + - '
' + translate('sortDirectionLabel') + ' ' + - '
' + - '' + - '' + - '
' + - '
' + - ' ' + - '
' + - '
' + - '
'; - - picoModal({ - parent: container, - content: content, - overlayClass: 'jsoneditor-modal-overlay', - overlayStyles: { - backgroundColor: "rgb(1,1,1)", - opacity: 0.3 - }, - modalClass: 'jsoneditor-modal jsoneditor-modal-sort' - }) - .afterCreate(function (modal) { - var form = modal.modalElem().querySelector('form'); - var ok = modal.modalElem().querySelector('#ok'); - var field = modal.modalElem().querySelector('#field'); - var direction = modal.modalElem().querySelector('#direction'); - - function preprocessPath(path) { - return (path === '') - ? '@' - : (path[0] === '.') - ? path.slice(1) - : path; - } - - paths.forEach(function (path) { - var option = document.createElement('option'); - option.text = preprocessPath(path); - option.value = path; - field.appendChild(option); - }); - - function setDirection(value) { - direction.value = value; - direction.className = 'jsoneditor-button-group jsoneditor-button-group-value-' + direction.value; - } - - field.value = selectedPath || paths[0]; - setDirection(selectedDirection || 'asc'); - - direction.onclick = function (event) { - setDirection(event.target.getAttribute('data-value')); - }; - - ok.onclick = function (event) { - event.preventDefault(); - event.stopPropagation(); - - modal.close(); - - onSort({ - path: field.value, - direction: direction.value - }) - }; - - if (form) { // form is not available when JSONEditor is created inside a form - form.onsubmit = ok.onclick; - } - }) - .afterClose(function (modal) { - modal.destroy(); - }) - .show(); -} - -module.exports = showSortModal; - - -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { - -var jmespath = __webpack_require__(4); -var picoModal = __webpack_require__(13); -var Selectr = __webpack_require__(30); -var translate = __webpack_require__(1).translate; -var stringifyPartial = __webpack_require__(31).stringifyPartial; -var util = __webpack_require__(0); -var MAX_PREVIEW_CHARACTERS = __webpack_require__(2).MAX_PREVIEW_CHARACTERS -var debounce = util.debounce; - -/** - * Show advanced filter and transform modal using JMESPath - * @param {HTMLElement} container The container where to center - * the modal and create an overlay - * @param {JSON} json The json data to be transformed - * @param {function} onTransform Callback invoked with the created - * query as callback - */ -function showTransformModal (container, json, onTransform) { - var value = json; - - var content = '