diff --git a/.travis.yml b/.travis.yml index 9ef0fde..05b1883 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,10 @@ language: node_js node_js: - "lts/*" + +jobs: + include: + - name: Lint + stage: other + script: npm run lint + node_js: lts/* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 110c5df..0390880 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,10 +6,18 @@ up with ideas and suggestions, and contribute to the code. There are a few preferences regarding code contributions: -- `jsoneditor` follows the node.js code style as described - [here](http://nodeguide.com/style.html). -- Send pull requests to the `develop` branch, not the `master` branch. -- Only commit changes done in the source files under `./src`, not to the builds - which are located under the `./dist` folder. +- Send pull requests to the `develop` branch, not the `master` branch. +- You can use modern JavaScript features, the code is transpiled using Babel. +- `jsoneditor` follows the https://standardjs.com/ code style. To test: + + ``` + npm run lint + ``` + +- If possible, create a unit test for any new functionality. To run tests: + + ``` + npm test + ``` Thanks! diff --git a/README.md b/README.md index 20360fd..c55ca9c 100644 --- a/README.md +++ b/README.md @@ -96,9 +96,9 @@ with npm (recommended): diff --git a/examples/requirejs_demo/requirejs_demo.html b/examples/requirejs_demo/requirejs_demo.html index ba8f49e..166bf89 100644 --- a/examples/requirejs_demo/requirejs_demo.html +++ b/examples/requirejs_demo/requirejs_demo.html @@ -9,7 +9,7 @@ } - +

diff --git a/examples/requirejs_demo/scripts/main.js b/examples/requirejs_demo/scripts/main.js index 4303b1a..f05b4e9 100644 --- a/examples/requirejs_demo/scripts/main.js +++ b/examples/requirejs_demo/scripts/main.js @@ -1,25 +1,25 @@ -var module = '../../../dist/jsoneditor'; +var module = '../../../dist/jsoneditor' require([module], function (JSONEditor) { // create the editor - var container = document.getElementById('jsoneditor'); - var editor = new JSONEditor(container); + var container = document.getElementById('jsoneditor') + var editor = new JSONEditor(container) // set json document.getElementById('setJSON').onclick = function () { var json = { - 'array': [1, 2, 3], - 'boolean': true, - 'null': null, - 'number': 123, - 'object': {'a': 'b', 'c': 'd'}, - 'string': 'Hello World' - }; - editor.set(json); - }; + array: [1, 2, 3], + boolean: true, + null: null, + number: 123, + object: { a: 'b', c: 'd' }, + string: 'Hello World' + } + editor.set(json) + } // get json document.getElementById('getJSON').onclick = function () { - var json = editor.get(); - alert(JSON.stringify(json, null, 2)); - }; -}); + var json = editor.get() + window.alert(JSON.stringify(json, null, 2)) + } +}) diff --git a/examples/requirejs_demo/scripts/require.js b/examples/requirejs_demo/scripts/require.js deleted file mode 100644 index d65036f..0000000 --- a/examples/requirejs_demo/scripts/require.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - RequireJS 2.1.13 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. - Available via the MIT or new BSD license. - see: http://github.com/jrburke/requirejs for details -*/ -var requirejs,require,define; -(function(ba){function G(b){return"[object Function]"===K.call(b)}function H(b){return"[object Array]"===K.call(b)}function v(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(G(l)){if(this.events.error&&this.map.isDefine||g.onError!==ca)try{f=i.execCb(c,l,b,f)}catch(d){a=d}else f=i.execCb(c,l,b,f);this.map.isDefine&&void 0===f&&((b=this.module)?f=b.exports:this.usingExports&& -(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=l;this.exports=f;if(this.map.isDefine&&!this.ignore&&(r[c]=f,g.onResourceLoad))g.onResourceLoad(i,this.map,this.depMaps);y(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a= -this.map,b=a.id,d=p(a.prefix);this.depMaps.push(d);q(d,"defined",u(this,function(f){var l,d;d=m(aa,this.map.id);var e=this.map.name,P=this.map.parentMap?this.map.parentMap.name:null,n=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(e=f.normalize(e,function(a){return c(a,P,!0)})||""),f=p(a.prefix+"!"+e,this.map.parentMap),q(f,"defined",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=m(h,f.id)){this.depMaps.push(f); -if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else d?(this.map.url=i.nameToUrl(d),this.load()):(l=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),l.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(h,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),l.fromText=u(this,function(f,c){var d=a.name,e=p(d),P=M;c&&(f=c);P&&(M=!1);s(e);t(j.config,b)&&(j.config[d]=j.config[b]);try{g.exec(f)}catch(h){return w(C("fromtexteval", -"fromText eval for "+b+" failed: "+h,h,[b]))}P&&(M=!0);this.depMaps.push(e);i.completeLoad(d);n([d],l)}),f.load(a.name,n,l,j))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){V[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,u(this,function(a,b){var c,f;if("string"===typeof a){a=p(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=m(L,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;q(a,"defined",u(this,function(a){this.defineDep(b, -a);this.check()}));this.errback&&q(a,"error",u(this,this.errback))}c=a.id;f=h[c];!t(L,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,u(this,function(a){var b=m(h,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:j,contextName:b,registry:h,defined:r,urlFetched:S,defQueue:A,Module:Z,makeModuleMap:p, -nextTick:g.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=j.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(j[b]||(j[b]={}),U(j[b],a,!0,!0)):j[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(aa[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),j.shim=b);a.packages&&v(a.packages,function(a){var b, -a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(j.paths[b]=a.location);j.pkgs[b]=a.name+"/"+(a.main||"main").replace(ia,"").replace(Q,"")});B(h,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=p(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ba,arguments));return b||a.exports&&da(a.exports)}},makeRequire:function(a,e){function j(c,d,m){var n,q;e.enableBuildCallback&&(d&&G(d))&&(d.__requireJsBuild= -!0);if("string"===typeof c){if(G(d))return w(C("requireargs","Invalid require call"),m);if(a&&t(L,c))return L[c](h[a.id]);if(g.get)return g.get(i,c,a,j);n=p(c,a,!1,!0);n=n.id;return!t(r,n)?w(C("notloaded",'Module name "'+n+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):r[n]}J();i.nextTick(function(){J();q=s(p(null,a));q.skipMap=e.skipMap;q.init(c,d,m,{enabled:!0});D()});return j}e=e||{};U(j,{isBrowser:z,toUrl:function(b){var d,e=b.lastIndexOf("."),k=b.split("/")[0];if(-1!== -e&&(!("."===k||".."===k)||1e.attachEvent.toString().indexOf("[native code"))&&!Y?(M=!0,e.attachEvent("onreadystatechange",b.onScriptLoad)): -(e.addEventListener("load",b.onScriptLoad,!1),e.addEventListener("error",b.onScriptError,!1)),e.src=d,J=e,D?y.insertBefore(e,D):y.appendChild(e),J=null,e;if(ea)try{importScripts(d),b.completeLoad(c)}catch(m){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,m,[c]))}};z&&!q.skipDataMain&&T(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(I=b.getAttribute("data-main"))return s=I,q.baseUrl||(E=s.split("/"),s=E.pop(),O=E.length?E.join("/")+"/":"./",q.baseUrl= -O),s=s.replace(Q,""),g.jsExtRegExp.test(s)&&(s=I),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var e,g;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(ka,"").replace(la,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(M){if(!(e=J))N&&"interactive"===N.readyState||T(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return N=b}),e=N;e&&(b|| -(b=e.getAttribute("data-requiremodule")),g=F[e.getAttribute("data-requirecontext")])}(g?g.defQueue:R).push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(q)}})(this); diff --git a/gulpfile.js b/gulpfile.js index fed112c..cb02d8d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,38 +1,38 @@ -var fs = require('fs'); -var path = require('path'); -var gulp = require('gulp'); -var log = require('fancy-log'); -var format = require('date-format'); -var concatCss = require('gulp-concat-css'); -var minifyCSS = require('gulp-clean-css'); +var fs = require('fs') +var path = require('path') +var gulp = require('gulp') +var log = require('fancy-log') +var format = require('date-format') +var concatCss = require('gulp-concat-css') +var minifyCSS = require('gulp-clean-css') var sass = require('gulp-sass') -var mkdirp = require('mkdirp'); -var webpack = require('webpack'); -var uglify = require('uglify-js'); +var mkdirp = require('mkdirp') +var webpack = require('webpack') +var uglify = require('uglify-js') -var NAME = 'jsoneditor'; -var NAME_MINIMALIST = 'jsoneditor-minimalist'; -var ENTRY = './src/js/JSONEditor.js'; -var HEADER = './src/js/header.js'; -var IMAGE = './src/scss/img/jsoneditor-icons.svg'; -var DOCS = './src/docs/*'; -var DIST = path.join(__dirname, 'dist'); +var NAME = 'jsoneditor' +var NAME_MINIMALIST = 'jsoneditor-minimalist' +var ENTRY = './src/js/JSONEditor.js' +var HEADER = './src/js/header.js' +var IMAGE = './src/scss/img/jsoneditor-icons.svg' +var DOCS = './src/docs/*' +var DIST = path.join(__dirname, 'dist') // generate banner with today's date and correct version -function createBanner() { - var today = format.asString('yyyy-MM-dd', new Date()); // today, formatted as yyyy-MM-dd - var version = require('./package.json').version; // math.js version +function createBanner () { + var today = format.asString('yyyy-MM-dd', new Date()) // today, formatted as yyyy-MM-dd + var version = require('./package.json').version // math.js version return String(fs.readFileSync(HEADER)) .replace('@@date', today) - .replace('@@version', version); + .replace('@@version', version) } var bannerPlugin = new webpack.BannerPlugin({ banner: createBanner(), entryOnly: true, raw: true -}); +}) var webpackConfigModule = { rules: [ @@ -47,7 +47,7 @@ var webpackConfigModule = { } } ] -}; +} // create a single instance of the compiler to allow caching var compiler = webpack({ @@ -66,10 +66,10 @@ var compiler = webpack({ module: webpackConfigModule, resolve: { extensions: ['.js'], - mainFields: [ 'main' ], // pick ES5 version of vanilla-picker + mainFields: ['main'] // pick ES5 version of vanilla-picker }, cache: true -}); +}) // create a single instance of the compiler to allow caching var compilerMinimalist = webpack({ @@ -92,10 +92,10 @@ var compilerMinimalist = webpack({ minimize: false }, cache: true -}); +}) -function minify(name) { - var code = String(fs.readFileSync(DIST + '/' + name + '.js')); +function minify (name) { + var code = String(fs.readFileSync(DIST + '/' + name + '.js')) var result = uglify.minify(code, { sourceMap: { url: name + '.map' @@ -104,80 +104,80 @@ function minify(name) { comments: /@license/, max_line_len: 64000 // extra large because we have embedded code for workers } - }); + }) if (result.error) { - throw result.error; + throw result.error } - var fileMin = DIST + '/' + name + '.min.js'; - var fileMap = DIST + '/' + name + '.map'; + var fileMin = DIST + '/' + name + '.min.js' + var fileMap = DIST + '/' + name + '.map' - fs.writeFileSync(fileMin, result.code); - fs.writeFileSync(fileMap, result.map); + fs.writeFileSync(fileMin, result.code) + fs.writeFileSync(fileMap, result.map) - log('Minified ' + fileMin); - log('Mapped ' + fileMap); + log('Minified ' + fileMin) + log('Mapped ' + fileMap) } // make dist folder structure -gulp.task('mkdir', function(done) { - mkdirp.sync(DIST); - mkdirp.sync(DIST + '/img'); +gulp.task('mkdir', function (done) { + mkdirp.sync(DIST) + mkdirp.sync(DIST + '/img') - done(); -}); + done() +}) // bundle javascript -gulp.task('bundle', function(done) { +gulp.task('bundle', function (done) { // update the banner contents (has a date in it which should stay up to date) - bannerPlugin.banner = createBanner(); + bannerPlugin.banner = createBanner() - compiler.run(function(err, stats) { + compiler.run(function (err, stats) { if (err) { - log(err); + log(err) } - log('bundled ' + NAME + '.js'); + log('bundled ' + NAME + '.js') - done(); - }); -}); + done() + }) +}) // bundle minimalist version of javascript -gulp.task('bundle-minimalist', function(done) { +gulp.task('bundle-minimalist', function (done) { // update the banner contents (has a date in it which should stay up to date) - bannerPlugin.banner = createBanner(); + bannerPlugin.banner = createBanner() - compilerMinimalist.run(function(err, stats) { + compilerMinimalist.run(function (err, stats) { if (err) { - log(err); + log(err) } - log('bundled ' + NAME_MINIMALIST + '.js'); + log('bundled ' + NAME_MINIMALIST + '.js') - done(); - }); -}); + done() + }) +}) // bundle css -gulp.task('bundle-css', function(done) { +gulp.task('bundle-css', function (done) { gulp - .src([ - 'src/scss/reset.scss', - 'src/scss/jsoneditor.scss', - 'src/scss/contextmenu.scss', - 'src/scss/menu.scss', - 'src/scss/searchbox.scss', - 'src/scss/autocomplete.scss', - 'src/scss/treepath.scss', - 'src/scss/statusbar.scss', - 'src/scss/navigationbar.scss', - 'src/js/assets/selectr/selectr.scss', - ]) + .src([ + 'src/scss/reset.scss', + 'src/scss/jsoneditor.scss', + 'src/scss/contextmenu.scss', + 'src/scss/menu.scss', + 'src/scss/searchbox.scss', + 'src/scss/autocomplete.scss', + 'src/scss/treepath.scss', + 'src/scss/statusbar.scss', + 'src/scss/navigationbar.scss', + 'src/js/assets/selectr/selectr.scss' + ]) .pipe( sass({ - // importer: tildeImporter + // importer: tildeImporter }) ) .pipe(concatCss(NAME + '.css')) @@ -189,48 +189,48 @@ gulp.task('bundle-css', function(done) { }) // create a folder img and copy the icons -gulp.task('copy-img', function(done) { - gulp.src(IMAGE).pipe(gulp.dest(DIST + '/img')); - log('Copied images'); +gulp.task('copy-img', function (done) { + gulp.src(IMAGE).pipe(gulp.dest(DIST + '/img')) + log('Copied images') - done(); -}); + done() +}) // create a folder img and copy the icons -gulp.task('copy-docs', function(done) { - gulp.src(DOCS).pipe(gulp.dest(DIST)); - log('Copied doc'); +gulp.task('copy-docs', function (done) { + gulp.src(DOCS).pipe(gulp.dest(DIST)) + log('Copied doc') - done(); -}); + done() +}) -gulp.task('minify', function(done) { - minify(NAME); +gulp.task('minify', function (done) { + minify(NAME) - done(); -}); + done() +}) -gulp.task('minify-minimalist', function(done) { - minify(NAME_MINIMALIST); +gulp.task('minify-minimalist', function (done) { + minify(NAME_MINIMALIST) - done(); -}); + done() +}) // The watch task (to automatically rebuild when the source code changes) // Does only generate jsoneditor.js and jsoneditor.css, and copy the image // Does NOT minify the code and does NOT generate the minimalist version -gulp.task('watch', gulp.series('bundle', 'bundle-css', 'copy-img', function() { - gulp.watch(['src/**/*'], gulp.series('bundle', 'bundle-css', 'copy-img')); -})); +gulp.task('watch', gulp.series('bundle', 'bundle-css', 'copy-img', function () { + gulp.watch(['src/**/*'], gulp.series('bundle', 'bundle-css', 'copy-img')) +})) // The default task (called when you run `gulp`) gulp.task('default', gulp.series( - 'mkdir', - gulp.parallel( - 'copy-img', - 'copy-docs', - 'bundle-css', - gulp.series('bundle', 'minify'), - gulp.series('bundle-minimalist', 'minify-minimalist') - ) -)); + 'mkdir', + gulp.parallel( + 'copy-img', + 'copy-docs', + 'bundle-css', + gulp.series('bundle', 'minify'), + gulp.series('bundle-minimalist', 'minify-minimalist') + ) +)) diff --git a/index.js b/index.js index 8442caf..2df7e5a 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -module.exports = require('./src/js/JSONEditor'); +module.exports = require('./src/js/JSONEditor') diff --git a/package-lock.json b/package-lock.json index f868e68..9f868f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1035,6 +1035,12 @@ "acorn-walk": "^6.0.1" } }, + "acorn-jsx": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz", + "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==", + "dev": true + }, "acorn-walk": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", @@ -1070,6 +1076,49 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -1088,6 +1137,12 @@ "ansi-wrap": "0.1.0" } }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-gray": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", @@ -1231,6 +1286,16 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", @@ -1377,6 +1442,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -1601,6 +1672,119 @@ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, + "boxen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", + "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, "brace": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz", @@ -1828,6 +2012,12 @@ "unset-value": "^1.0.0" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", @@ -1886,6 +2076,12 @@ } } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "chokidar": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", @@ -1929,6 +2125,12 @@ "tslib": "^1.9.0" } }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -1979,6 +2181,27 @@ } } }, + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -2133,6 +2356,12 @@ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", @@ -2366,6 +2595,12 @@ "ms": "2.0.0" } }, + "debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -2457,6 +2692,28 @@ } } }, + "deglob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-4.0.1.tgz", + "integrity": "sha512-/g+RDZ7yf2HvoW+E5Cy+K94YhgcFgr6C8LuHZD1O5HoNPkf3KY6RfXJ0DBGlB/NkLi5gml+G9zqRzk9S0mHZCg==", + "dev": true, + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^5.0.0", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2502,6 +2759,15 @@ "randombytes": "^2.0.0" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -2717,6 +2983,412 @@ } } }, + "eslint": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.1.0.tgz", + "integrity": "sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^6.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "glob-parent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + } + } + }, + "eslint-config-standard": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.0.1.tgz", + "integrity": "sha512-1RWsAKTDTZgA8bIM6PSC9aTGDAUlKqNkYNJlTZ5xYD/HYkIM6GlcefFvgcJ8xi0SWG5203rttKYX28zW+rKNOg==", + "dev": true + }, + "eslint-config-standard-jsx": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-8.0.1.tgz", + "integrity": "sha512-SDnpVLSzTcT0eLNTG7s8ffRi3WadBBpw+pFsiBj4BcrHOFOga9O/7mjtNRyPgetmsiDPWGxsiS4UdJLZhaIukA==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-es": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz", + "integrity": "sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA==", + "dev": true, + "requires": { + "eslint-utils": "^1.4.2", + "regexpp": "^2.0.1" + } + }, + "eslint-plugin-import": { + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.11.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-9.1.0.tgz", + "integrity": "sha512-ZwQYGm6EoV2cfLpE1wxJWsfnKUIXfM/KM09/TlorkukgCAwmkgajEJnPCmyzoFPQQkmvo5DrW/nyKutNIw36Mw==", + "dev": true, + "requires": { + "eslint-plugin-es": "^1.4.0", + "eslint-utils": "^1.3.1", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true + }, + "eslint-plugin-react": { + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz", + "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.1.0", + "object.entries": "^1.1.0", + "object.fromentries": "^2.0.0", + "object.values": "^1.1.0", + "prop-types": "^15.7.2", + "resolve": "^1.10.1" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-standard": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", + "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", + "dev": true + }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -2727,12 +3399,55 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", + "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.0.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.1.tgz", + "integrity": "sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-jsx": "^5.0.2", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", + "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", + "dev": true + } + } + }, "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", @@ -2856,6 +3571,17 @@ } } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -2961,6 +3687,24 @@ "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", "dev": true }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -2995,6 +3739,12 @@ "pkg-dir": "^3.0.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -3053,6 +3803,34 @@ } } }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -3708,6 +4486,25 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "funding": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/funding/-/funding-1.0.8.tgz", + "integrity": "sha512-M4yYVbIgS9jxKY0XS89DDpsiMHe+JiwavRaXCmJxNmhJhVPEi8KigfP6mP69oOWaTDrCfrF4rE36OhGfoHkTTQ==", + "dev": true, + "requires": { + "boxen": "^3.2.0", + "chalk": "^2.4.2", + "ci-info": "^2.0.0", + "term-size": "^2.1.0", + "word-wrap": "^1.2.3" + } + }, "gauge": { "version": "2.7.4", "resolved": "https://repo.tick42.com:443/api/npm/tick42-npm/gauge/-/gauge-2.7.4.tgz", @@ -4345,6 +5142,22 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "import-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/import-regex/-/import-regex-1.1.0.tgz", @@ -4400,6 +5213,79 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + } + } + }, "interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", @@ -4603,6 +5489,12 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -4860,6 +5752,16 @@ "verror": "1.10.0" } }, + "jsx-ast-utils": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz", + "integrity": "sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "object.assign": "^4.1.0" + } + }, "just-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", @@ -5716,6 +6618,12 @@ "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", "dev": true }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -5741,6 +6649,12 @@ "to-regex": "^3.0.1" } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", @@ -6077,6 +6991,30 @@ "isobject": "^3.0.0" } }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", + "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.11.0", + "function-bind": "^1.1.1", + "has": "^1.0.1" + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -6116,6 +7054,18 @@ "make-iterator": "^1.0.0" } }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6125,6 +7075,23 @@ "wrappy": "1" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + } + } + }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -6244,6 +7211,15 @@ "readable-stream": "^2.1.5" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-asn1": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", @@ -6421,6 +7397,73 @@ "pinkie": "^2.0.0" } }, + "pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "dev": true, + "requires": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + } + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -6495,12 +7538,37 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -6596,6 +7664,12 @@ "safe-buffer": "^5.1.0" } }, + "react-is": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz", + "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==", + "dev": true + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -6702,6 +7776,12 @@ "integrity": "sha512-TsXZ8+cv2uxMEkLfgwO0E068gsNMLfuYwMMhiUxf0Kw2Vcgzq93vgl6wIlIYuPmfMqMjfQ9zAporiozqCnwLuQ==", "dev": true }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "regexpu-core": { "version": "4.5.5", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz", @@ -6913,6 +7993,12 @@ "global-modules": "^1.0.0" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "resolve-options": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", @@ -6928,6 +8014,16 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -7007,6 +8103,21 @@ "inherits": "^2.0.1" } }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", @@ -7016,6 +8127,15 @@ "aproba": "^1.1.1" } }, + "rxjs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -7177,6 +8297,25 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -7418,6 +8557,50 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, + "standard": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/standard/-/standard-14.0.2.tgz", + "integrity": "sha512-2Rjsc+B1zaXiQVfUlH7n+ZIrCpxxAaVEItps2lBQUQLuyCH/Vc788w6q16PMK4ezPA61jm8A1vzBnBwcokGOgQ==", + "dev": true, + "requires": { + "eslint": "~6.1.0", + "eslint-config-standard": "14.0.1", + "eslint-config-standard-jsx": "8.0.1", + "eslint-plugin-import": "~2.18.0", + "eslint-plugin-node": "~9.1.0", + "eslint-plugin-promise": "~4.2.1", + "eslint-plugin-react": "~7.14.2", + "eslint-plugin-standard": "~4.0.0", + "funding": "^1.0.0", + "standard-engine": "^12.0.0" + } + }, + "standard-engine": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-12.0.0.tgz", + "integrity": "sha512-gJIIRb0LpL7AHyGbN9+hJ4UJns37lxmNTnMGRLC8CFrzQ+oB/K60IQjKNgPBCB2VP60Ypm6f8DFXvhVWdBOO+g==", + "dev": true, + "requires": { + "deglob": "^4.0.0", + "get-stdin": "^7.0.0", + "minimist": "^1.1.0", + "pkg-conf": "^3.1.0" + }, + "dependencies": { + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -7583,6 +8766,52 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "tapable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", @@ -7600,6 +8829,12 @@ "inherits": "2" } }, + "term-size": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.1.0.tgz", + "integrity": "sha512-I42EWhJ+2aeNQawGx1VtpO0DFI9YcfuvAMNIdKyf/6sRbHJ4P+ZQ/zIT87tE+ln1ymAGcCJds4dolfSAS0AcNg==", + "dev": true + }, "terser": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/terser/-/terser-4.2.1.tgz", @@ -7644,6 +8879,18 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -7679,6 +8926,15 @@ "setimmediate": "^1.0.4" } }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", @@ -7843,6 +9099,12 @@ "prelude-ls": "~1.1.2" } }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -7936,6 +9198,12 @@ "set-value": "^2.0.1" } }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -8086,6 +9354,12 @@ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "dev": true }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, "v8flags": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", @@ -8335,6 +9609,54 @@ "string-width": "^1.0.2 || 2" } }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -8366,6 +9688,15 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "ws": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz", diff --git a/package.json b/package.json index 911842c..1fd1511 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "build": "gulp", "minify": "gulp minify", "start": "gulp watch", - "test": "mocha test" + "test": "mocha test", + "lint": "standard --env=mocha" }, "dependencies": { "ajv": "6.10.2", @@ -47,7 +48,14 @@ "json-loader": "0.5.7", "mkdirp": "0.5.1", "mocha": "6.2.0", + "standard": "14.0.2", "uglify-js": "3.6.0", "webpack": "4.39.3" + }, + "standard": { + "ignore": [ + "src/js/assets", + "examples/react*" + ] } } diff --git a/src/js/ContextMenu.js b/src/js/ContextMenu.js index 030a75b..f3a0dc9 100644 --- a/src/js/ContextMenu.js +++ b/src/js/ContextMenu.js @@ -1,8 +1,8 @@ -'use strict'; +'use strict' -var createAbsoluteAnchor = require('./createAbsoluteAnchor').createAbsoluteAnchor; -var util = require('./util'); -var translate = require('./i18n').translate; +var createAbsoluteAnchor = require('./createAbsoluteAnchor').createAbsoluteAnchor +var util = require('./util') +var translate = require('./i18n').translate /** * A context menu @@ -14,153 +14,150 @@ var translate = require('./i18n').translate; * @constructor */ function ContextMenu (items, options) { - this.dom = {}; + 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; + 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; + 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); + 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 + 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); + 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') { + 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 = {}; + var separator = document.createElement('div') + separator.className = 'jsoneditor-separator' + const 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); + const 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; + var button = document.createElement('button') + button.type = 'button' + button.className = item.className + domItem.button = button if (item.title) { - button.title = item.title; + button.title = item.title } if (item.click) { button.onclick = function (event) { - event.preventDefault(); - me.hide(); - item.click(); - }; + event.preventDefault() + me.hide() + item.click() + } } - li.appendChild(button); + 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'); + 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); + (item.click ? '' : ' jsoneditor-right-margin') + divText.appendChild(document.createTextNode(item.text)) + button.appendChild(divText) - var buttonSubmenu; + var buttonSubmenu if (item.click) { // submenu and a button with a click handler - button.className += ' jsoneditor-default'; + button.className += ' jsoneditor-default' - var buttonExpand = document.createElement('button'); - buttonExpand.type = 'button'; - domItem.buttonExpand = buttonExpand; - buttonExpand.className = 'jsoneditor-expand'; - buttonExpand.innerHTML = '

'; - li.appendChild(buttonExpand); + 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; + buttonExpand.title = item.submenuTitle } - buttonSubmenu = buttonExpand; - } - else { + buttonSubmenu = buttonExpand + } else { // submenu and a button without a click handler - var divExpand = document.createElement('div'); - divExpand.className = 'jsoneditor-expand'; - button.appendChild(divExpand); + var divExpand = document.createElement('div') + divExpand.className = 'jsoneditor-expand' + button.appendChild(divExpand) - buttonSubmenu = button; + buttonSubmenu = button } // attach a handler to expand/collapse the submenu buttonSubmenu.onclick = function (event) { - event.preventDefault(); - me._onExpandItem(domItem); - buttonSubmenu.focus(); - }; + 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 { + 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) + '
'; + '
' + translate(item.text) + '
' } - domItems.push(domItem); + domItems.push(domItem) } - }); + }) } - createMenuItems(list, this.dom.items, items); + 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 + 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); - }); + var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24 + me.maxHeight = Math.max(me.maxHeight, height) + }) } /** @@ -169,29 +166,29 @@ function ContextMenu (items, options) { * @private */ ContextMenu.prototype._getVisibleButtons = function () { - var buttons = []; - var me = this; + var buttons = [] + var me = this this.dom.items.forEach(function (item) { - buttons.push(item.button); + buttons.push(item.button) if (item.buttonExpand) { - buttons.push(item.buttonExpand); + buttons.push(item.buttonExpand) } - if (item.subItems && item == me.expandedItem) { + if (item.subItems && item === me.expandedItem) { item.subItems.forEach(function (subItem) { - buttons.push(subItem.button); + buttons.push(subItem.button) if (subItem.buttonExpand) { - buttons.push(subItem.buttonExpand); + buttons.push(subItem.buttonExpand) } // TODO: change to fully recursive method - }); + }) } - }); + }) - return buttons; -}; + return buttons +} // currently displayed context menu, a singleton. We may only have one visible context menu -ContextMenu.visibleMenu = undefined; +ContextMenu.visibleMenu = undefined /** * Attach the menu to an anchor @@ -200,64 +197,61 @@ ContextMenu.visibleMenu = undefined; * @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(); + 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 showBelow = true + var parent = anchor.parentNode + var anchorRect = anchor.getBoundingClientRect() + var parentRect = parent.getBoundingClientRect() + var frameRect = frame.getBoundingClientRect() - var me = this; + 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) { + } else if (anchorRect.top - this.maxHeight > frameRect.top) { // fits above -> show above - showBelow = false; - } - else { + showBelow = false + } else { // doesn't fit above nor below -> show below } - var topGap = ignoreParent ? 0 : (anchorRect.top - parentRect.top); + 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 { + 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'; + 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); + this.dom.absoluteAnchor.appendChild(this.dom.root) // move focus to the first button in the context menu - this.selection = util.getSelection(); - this.anchor = anchor; + this.selection = util.getSelection() + this.anchor = anchor setTimeout(function () { - me.dom.focusButton.focus(); - }, 0); + me.dom.focusButton.focus() + }, 0) if (ContextMenu.visibleMenu) { - ContextMenu.visibleMenu.hide(); + ContextMenu.visibleMenu.hide() } - ContextMenu.visibleMenu = this; -}; + ContextMenu.visibleMenu = this +} /** * Hide the context menu if visible @@ -265,22 +259,22 @@ ContextMenu.prototype.show = function (anchor, frame, ignoreParent) { ContextMenu.prototype.hide = function () { // remove temporary absolutely positioned anchor if (this.dom.absoluteAnchor) { - this.dom.absoluteAnchor.destroy(); - delete 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); + this.dom.root.parentNode.removeChild(this.dom.root) if (this.onClose) { - this.onClose(); + this.onClose() } } - if (ContextMenu.visibleMenu == this) { - ContextMenu.visibleMenu = undefined; + if (ContextMenu.visibleMenu === this) { + ContextMenu.visibleMenu = undefined } -}; +} /** * Expand a submenu @@ -289,42 +283,43 @@ ContextMenu.prototype.hide = function () { * @private */ ContextMenu.prototype._onExpandItem = function (domItem) { - var me = this; - var alreadyVisible = (domItem == this.expandedItem); + var me = this + var alreadyVisible = (domItem === this.expandedItem) // hide the currently visible submenu - var expandedItem = this.expandedItem; + var expandedItem = this.expandedItem if (expandedItem) { - //var ul = expandedItem.ul; - expandedItem.ul.style.height = '0'; - expandedItem.ul.style.padding = ''; + // 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'); + 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; + }, 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 + var ul = domItem.ul + ul.style.display = 'block' + // eslint-disable-next-line no-unused-expressions + ul.clientHeight // force a reflow in Firefox setTimeout(function () { - if (me.expandedItem == domItem) { - var childsHeight = 0; + if (me.expandedItem === domItem) { + var childsHeight = 0 for (var i = 0; i < ul.childNodes.length; i++) { - childsHeight += ul.childNodes[i].clientHeight; + childsHeight += ul.childNodes[i].clientHeight } - ul.style.height = childsHeight + 'px'; - ul.style.padding = '5px 10px'; + ul.style.height = childsHeight + 'px' + ul.style.padding = '5px 10px' } - }, 0); - util.addClassName(ul.parentNode, 'jsoneditor-selected'); - this.expandedItem = domItem; + }, 0) + util.addClassName(ul.parentNode, 'jsoneditor-selected') + this.expandedItem = domItem } -}; +} /** * Handle onkeydown event @@ -332,107 +327,101 @@ ContextMenu.prototype._onExpandItem = function (domItem) { * @private */ ContextMenu.prototype._onKeyDown = function (event) { - var target = event.target; - var keynum = event.which; - var handled = false; - var buttons, targetIndex, prevButton, nextButton; + var target = event.target + var keynum = event.which + var handled = false + var buttons, targetIndex, prevButton, nextButton - if (keynum == 27) { // ESC + if (keynum === 27) { // ESC // hide the menu on ESC key // restore previous selection and focus if (this.selection) { - util.setSelection(this.selection); + util.setSelection(this.selection) } if (this.anchor) { - this.anchor.focus(); + this.anchor.focus() } - this.hide(); + this.hide() - handled = true; - } - else if (keynum == 9) { // Tab + handled = true + } else if (keynum === 9) { // Tab if (!event.shiftKey) { // Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == buttons.length - 1) { + buttons = this._getVisibleButtons() + targetIndex = buttons.indexOf(target) + if (targetIndex === buttons.length - 1) { // move to first button - buttons[0].focus(); - handled = true; + buttons[0].focus() + handled = true } - } - else { // Shift+Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == 0) { + } else { // Shift+Tab + buttons = this._getVisibleButtons() + targetIndex = buttons.indexOf(target) + if (targetIndex === 0) { // move to last button - buttons[buttons.length - 1].focus(); - handled = true; + 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]; + } 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(); + 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') { + 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]; + prevButton = buttons[targetIndex - 2] } if (!prevButton) { // move to last button - prevButton = buttons[buttons.length - 1]; + prevButton = buttons[buttons.length - 1] } if (prevButton) { - prevButton.focus(); + 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 === 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') { + 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]; + nextButton = buttons[targetIndex + 2] } if (!nextButton) { // move to first button - nextButton = buttons[0]; + nextButton = buttons[0] } if (nextButton) { - nextButton.focus(); - handled = true; + nextButton.focus() + handled = true } - handled = true; + handled = true } // TODO: arrow left and right if (handled) { - event.stopPropagation(); - event.preventDefault(); + event.stopPropagation() + event.preventDefault() } -}; +} -module.exports = ContextMenu; +module.exports = ContextMenu diff --git a/src/js/ErrorTable.js b/src/js/ErrorTable.js index ba6d218..3ea30b5 100644 --- a/src/js/ErrorTable.js +++ b/src/js/ErrorTable.js @@ -8,170 +8,167 @@ * @constructor */ function ErrorTable (config) { - this.errorTableVisible = config.errorTableVisible; - this.onToggleVisibility = config.onToggleVisibility; - this.onFocusLine = config.onFocusLine || function () {}; - this.onChangeHeight = config.onChangeHeight; + this.errorTableVisible = config.errorTableVisible + this.onToggleVisibility = config.onToggleVisibility + this.onFocusLine = config.onFocusLine || function () {} + this.onChangeHeight = config.onChangeHeight - this.dom = {}; + this.dom = {} - var validationErrorsContainer = document.createElement('div'); - validationErrorsContainer.className = 'jsoneditor-validation-errors-container'; - this.dom.validationErrorsContainer = validationErrorsContainer; + var validationErrorsContainer = document.createElement('div') + validationErrorsContainer.className = 'jsoneditor-validation-errors-container' + this.dom.validationErrorsContainer = validationErrorsContainer - var additionalErrorsIndication = document.createElement('div'); - additionalErrorsIndication.style.display = 'none'; - additionalErrorsIndication.className = "jsoneditor-additional-errors fadein"; - additionalErrorsIndication.innerHTML = "Scroll for more ▿"; - this.dom.additionalErrorsIndication = additionalErrorsIndication; - validationErrorsContainer.appendChild(additionalErrorsIndication); + var additionalErrorsIndication = document.createElement('div') + additionalErrorsIndication.style.display = 'none' + additionalErrorsIndication.className = 'jsoneditor-additional-errors fadein' + additionalErrorsIndication.innerHTML = 'Scroll for more ▿' + this.dom.additionalErrorsIndication = additionalErrorsIndication + validationErrorsContainer.appendChild(additionalErrorsIndication) - var validationErrorIcon = document.createElement('span'); - validationErrorIcon.className = 'jsoneditor-validation-error-icon'; - validationErrorIcon.style.display = 'none'; - this.dom.validationErrorIcon = validationErrorIcon; + var validationErrorIcon = document.createElement('span') + validationErrorIcon.className = 'jsoneditor-validation-error-icon' + validationErrorIcon.style.display = 'none' + this.dom.validationErrorIcon = validationErrorIcon - var validationErrorCount = document.createElement('span'); - validationErrorCount.className = 'jsoneditor-validation-error-count'; - validationErrorCount.style.display = 'none'; - this.dom.validationErrorCount = validationErrorCount; + var validationErrorCount = document.createElement('span') + validationErrorCount.className = 'jsoneditor-validation-error-count' + validationErrorCount.style.display = 'none' + this.dom.validationErrorCount = validationErrorCount - this.dom.parseErrorIndication = document.createElement('span'); - this.dom.parseErrorIndication.className = 'jsoneditor-parse-error-icon'; - this.dom.parseErrorIndication.style.display = 'none'; + this.dom.parseErrorIndication = document.createElement('span') + this.dom.parseErrorIndication.className = 'jsoneditor-parse-error-icon' + this.dom.parseErrorIndication.style.display = 'none' } ErrorTable.prototype.getErrorTable = function () { - return this.dom.validationErrorsContainer; -}; + return this.dom.validationErrorsContainer +} ErrorTable.prototype.getErrorCounter = function () { - return this.dom.validationErrorCount; -}; + return this.dom.validationErrorCount +} ErrorTable.prototype.getWarningIcon = function () { - return this.dom.validationErrorIcon; -}; + return this.dom.validationErrorIcon +} ErrorTable.prototype.getErrorIcon = function () { - return this.dom.parseErrorIndication; -}; + return this.dom.parseErrorIndication +} ErrorTable.prototype.toggleTableVisibility = function () { - this.errorTableVisible = !this.errorTableVisible; - this.onToggleVisibility(this.errorTableVisible); + this.errorTableVisible = !this.errorTableVisible + this.onToggleVisibility(this.errorTableVisible) } ErrorTable.prototype.setErrors = function (errors, errorLocations) { - var me = this; + var me = this // clear any previous errors if (this.dom.validationErrors) { - this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors); - this.dom.validationErrors = null; - this.dom.additionalErrorsIndication.style.display = 'none'; + this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors) + this.dom.validationErrors = null + this.dom.additionalErrorsIndication.style.display = 'none' } // create the table with errors // keep default behavior for parse errors if (this.errorTableVisible && errors.length > 0) { - var validationErrors = document.createElement('div'); - validationErrors.className = 'jsoneditor-validation-errors'; - validationErrors.innerHTML = '
'; - var tbody = validationErrors.getElementsByTagName('tbody')[0]; + var validationErrors = document.createElement('div') + validationErrors.className = 'jsoneditor-validation-errors' + validationErrors.innerHTML = '
' + var tbody = validationErrors.getElementsByTagName('tbody')[0] errors.forEach(function (error) { - var message; + var message if (typeof error === 'string') { - message = '
' + error + '
'; - } - else { + message = '
' + error + '
' + } else { message = '' + (error.dataPath || '') + '' + - '
' + error.message + '
'; + '
' + error.message + '
' } - var line; + var line if (!isNaN(error.line)) { - line = error.line; + line = error.line } else if (error.dataPath) { - var errLoc = errorLocations.find(function(loc) { return loc.path === error.dataPath; }); + var errLoc = errorLocations.find(function (loc) { return loc.path === error.dataPath }) if (errLoc) { - line = errLoc.line + 1; + line = errLoc.line + 1 } } - var trEl = document.createElement('tr'); - trEl.className = !isNaN(line) ? 'jump-to-line' : ''; + var trEl = document.createElement('tr') + trEl.className = !isNaN(line) ? 'jump-to-line' : '' if (error.type === 'error') { - trEl.className += ' parse-error'; + trEl.className += ' parse-error' } else { - trEl.className += ' validation-error'; + trEl.className += ' validation-error' } - trEl.innerHTML = (''+ (!isNaN(line) ? ('Ln ' + line) : '') +'' + message); - trEl.onclick = function() { - me.onFocusLine(line); - }; + trEl.innerHTML = ('' + (!isNaN(line) ? ('Ln ' + line) : '') + '' + message) + trEl.onclick = function () { + me.onFocusLine(line) + } - tbody.appendChild(trEl); - }); + tbody.appendChild(trEl) + }) - this.dom.validationErrors = validationErrors; - this.dom.validationErrorsContainer.appendChild(validationErrors); - this.dom.additionalErrorsIndication.title = errors.length + " errors total"; + this.dom.validationErrors = validationErrors + this.dom.validationErrorsContainer.appendChild(validationErrors) + this.dom.additionalErrorsIndication.title = errors.length + ' errors total' if (this.dom.validationErrorsContainer.clientHeight < this.dom.validationErrorsContainer.scrollHeight) { - this.dom.additionalErrorsIndication.style.display = 'block'; + this.dom.additionalErrorsIndication.style.display = 'block' this.dom.validationErrorsContainer.onscroll = function () { me.dom.additionalErrorsIndication.style.display = - (me.dom.validationErrorsContainer.clientHeight > 0 && me.dom.validationErrorsContainer.scrollTop === 0) ? 'block' : 'none'; + (me.dom.validationErrorsContainer.clientHeight > 0 && me.dom.validationErrorsContainer.scrollTop === 0) ? 'block' : 'none' } } else { - this.dom.validationErrorsContainer.onscroll = undefined; + this.dom.validationErrorsContainer.onscroll = undefined } - var height = this.dom.validationErrorsContainer.clientHeight + (this.dom.statusBar ? this.dom.statusBar.clientHeight : 0); + var height = this.dom.validationErrorsContainer.clientHeight + (this.dom.statusBar ? this.dom.statusBar.clientHeight : 0) // this.content.style.marginBottom = (-height) + 'px'; // this.content.style.paddingBottom = height + 'px'; - this.onChangeHeight(height); + this.onChangeHeight(height) } else { - this.onChangeHeight(0); + this.onChangeHeight(0) } // update the status bar var validationErrorsCount = errors.filter(function (error) { return error.type !== 'error' - }).length; + }).length if (validationErrorsCount > 0) { - this.dom.validationErrorCount.style.display = 'inline'; - this.dom.validationErrorCount.innerText = validationErrorsCount; - this.dom.validationErrorCount.onclick = this.toggleTableVisibility.bind(this); + this.dom.validationErrorCount.style.display = 'inline' + this.dom.validationErrorCount.innerText = validationErrorsCount + this.dom.validationErrorCount.onclick = this.toggleTableVisibility.bind(this) - this.dom.validationErrorIcon.style.display = 'inline'; - this.dom.validationErrorIcon.title = validationErrorsCount + ' schema validation error(s) found'; - this.dom.validationErrorIcon.onclick = this.toggleTableVisibility.bind(this); - } - else { - this.dom.validationErrorCount.style.display = 'none'; - this.dom.validationErrorIcon.style.display = 'none'; + this.dom.validationErrorIcon.style.display = 'inline' + this.dom.validationErrorIcon.title = validationErrorsCount + ' schema validation error(s) found' + this.dom.validationErrorIcon.onclick = this.toggleTableVisibility.bind(this) + } else { + this.dom.validationErrorCount.style.display = 'none' + this.dom.validationErrorIcon.style.display = 'none' } // update the parse error icon var hasParseErrors = errors.some(function (error) { return error.type === 'error' - }); + }) if (hasParseErrors) { var line = errors[0].line - this.dom.parseErrorIndication.style.display = 'block'; + this.dom.parseErrorIndication.style.display = 'block' this.dom.parseErrorIndication.title = !isNaN(line) - ? ('parse error on line ' + line) - : 'parse error - check that the json is valid'; + ? ('parse error on line ' + line) + : 'parse error - check that the json is valid' + } else { + this.dom.parseErrorIndication.style.display = 'none' } - else { - this.dom.parseErrorIndication.style.display = 'none'; - } -}; +} -module.exports = ErrorTable; +module.exports = ErrorTable diff --git a/src/js/Highlighter.js b/src/js/Highlighter.js index 09b03f6..7694e60 100644 --- a/src/js/Highlighter.js +++ b/src/js/Highlighter.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' /** * The highlighter can highlight/unhighlight a node, and @@ -6,7 +6,7 @@ * @constructor Highlighter */ function Highlighter () { - this.locked = false; + this.locked = false } /** @@ -15,23 +15,23 @@ function Highlighter () { */ Highlighter.prototype.highlight = function (node) { if (this.locked) { - return; + return } - if (this.node != node) { + if (this.node !== node) { // unhighlight current node if (this.node) { - this.node.setHighlight(false); + this.node.setHighlight(false) } // highlight new node - this.node = node; - this.node.setHighlight(true); + this.node = node + this.node.setHighlight(true) } // cancel any current timeout - this._cancelUnhighlight(); -}; + this._cancelUnhighlight() +} /** * Unhighlight currently highlighted node. @@ -39,23 +39,23 @@ Highlighter.prototype.highlight = function (node) { */ Highlighter.prototype.unhighlight = function () { if (this.locked) { - return; + return } - var me = this; + var me = this if (this.node) { - this._cancelUnhighlight(); + this._cancelUnhighlight() // do the unhighlighting after a small delay, to prevent re-highlighting // the same node when moving from the drag-icon to the contextmenu-icon // or vice versa. this.unhighlightTimer = setTimeout(function () { - me.node.setHighlight(false); - me.node = undefined; - me.unhighlightTimer = undefined; - }, 0); + me.node.setHighlight(false) + me.node = undefined + me.unhighlightTimer = undefined + }, 0) } -}; +} /** * Cancel an unhighlight action (if before the timeout of the unhighlight action) @@ -63,24 +63,24 @@ Highlighter.prototype.unhighlight = function () { */ Highlighter.prototype._cancelUnhighlight = function () { if (this.unhighlightTimer) { - clearTimeout(this.unhighlightTimer); - this.unhighlightTimer = undefined; + clearTimeout(this.unhighlightTimer) + this.unhighlightTimer = undefined } -}; +} /** * Lock highlighting or unhighlighting nodes. * methods highlight and unhighlight do not work while locked. */ Highlighter.prototype.lock = function () { - this.locked = true; -}; + this.locked = true +} /** * Unlock highlighting or unhighlighting nodes */ Highlighter.prototype.unlock = function () { - this.locked = false; -}; + this.locked = false +} -module.exports = Highlighter; +module.exports = Highlighter diff --git a/src/js/History.js b/src/js/History.js index 452b1ce..3b1adfd 100644 --- a/src/js/History.js +++ b/src/js/History.js @@ -7,82 +7,81 @@ * @constructor */ function History (onChange, calculateItemSize, limit) { - this.onChange = onChange; + this.onChange = onChange this.calculateItemSize = calculateItemSize || function () { - return 1; - }; - this.limit = limit; + return 1 + } + this.limit = limit - this.items = []; - this.index = -1; + this.items = [] + this.index = -1 } History.prototype.add = function (item) { // limit number of items in history so that the total size doesn't // always keep at least one item in memory while (this._calculateHistorySize() > this.limit && this.items.length > 1) { - this.items.shift(); - this.index--; + this.items.shift() + this.index-- } // cleanup any redo action that are not valid anymore - this.items = this.items.slice(0, this.index + 1); + this.items = this.items.slice(0, this.index + 1) - this.items.push(item); - this.index++; + this.items.push(item) + this.index++ - this.onChange(); -}; + this.onChange() +} History.prototype._calculateHistorySize = function () { - var calculateItemSize = this.calculateItemSize; - var totalSize = 0; + var calculateItemSize = this.calculateItemSize + var totalSize = 0 this.items.forEach(function (item) { - totalSize += calculateItemSize(item); - }); + totalSize += calculateItemSize(item) + }) - return totalSize; + return totalSize } History.prototype.undo = function () { if (!this.canUndo()) { - return; + return } - this.index--; + this.index-- - this.onChange(); + this.onChange() - return this.items[this.index]; -}; + return this.items[this.index] +} History.prototype.redo = function () { if (!this.canRedo()) { - return; + return } - this.index++; + this.index++ - this.onChange(); + this.onChange() - return this.items[this.index]; -}; + return this.items[this.index] +} History.prototype.canUndo = function () { - return this.index > 0; -}; + return this.index > 0 +} History.prototype.canRedo = function () { - return this.index < this.items.length - 1; -}; + return this.index < this.items.length - 1 +} History.prototype.clear = function () { - this.items = []; - this.index = -1; + this.items = [] + this.index = -1 - this.onChange(); -}; + this.onChange() +} - -module.exports = History; +module.exports = History diff --git a/src/js/JSONEditor.js b/src/js/JSONEditor.js index b4e03a3..6736445 100644 --- a/src/js/JSONEditor.js +++ b/src/js/JSONEditor.js @@ -1,23 +1,22 @@ -'use strict'; +'use strict' -var Ajv; +var Ajv try { - Ajv = require('ajv'); -} -catch (err) { + Ajv = require('ajv') +} catch (err) { // no problem... when we need Ajv we will throw a neat exception } -var ace = require('./ace'); // may be undefined in case of minimalist bundle -var VanillaPicker = require('./vanilla-picker'); // may be undefined in case of minimalist bundle +var ace = require('./ace') // may be undefined in case of minimalist bundle +var VanillaPicker = require('./vanilla-picker') // may be undefined in case of minimalist bundle -var treemode = require('./treemode'); -var textmode = require('./textmode'); -var previewmode = require('./previewmode'); -var util = require('./util'); +var treemode = require('./treemode') +var textmode = require('./textmode') +var previewmode = require('./previewmode') +var util = require('./util') if (typeof Promise === 'undefined') { - console.error('Promise undefined. Please load a Promise polyfill in the browser in order to use JSONEditor'); + console.error('Promise undefined. Please load a Promise polyfill in the browser in order to use JSONEditor') } /** @@ -89,41 +88,41 @@ if (typeof Promise === 'undefined') { * Only applicable for * modes 'form', 'tree' and * 'view' - * {Number} maxVisibleChilds Number of children allowed for a node - * in 'tree', 'view', or 'form' mode before - * the "show more/show all" buttons appear. + * {Number} maxVisibleChilds Number of children allowed for a node + * in 'tree', 'view', or 'form' mode before + * the "show more/show all" buttons appear. * 100 by default. * * @param {Object | undefined} json JSON object */ function JSONEditor (container, options, json) { if (!(this instanceof JSONEditor)) { - throw new Error('JSONEditor constructor called without "new".'); + throw new Error('JSONEditor constructor called without "new".') } // check for unsupported browser (IE8 and older) - var ieVersion = util.getInternetExplorerVersion(); - if (ieVersion != -1 && ieVersion < 9) { + var ieVersion = util.getInternetExplorerVersion() + if (ieVersion !== -1 && ieVersion < 9) { throw new Error('Unsupported browser, IE9 or newer required. ' + - 'Please install the newest version of your browser.'); + 'Please install the newest version of your browser.') } if (options) { // check for deprecated options if (options.error) { - console.warn('Option "error" has been renamed to "onError"'); - options.onError = options.error; - delete options.error; + console.warn('Option "error" has been renamed to "onError"') + options.onError = options.error + delete options.error } if (options.change) { - console.warn('Option "change" has been renamed to "onChange"'); - options.onChange = options.change; - delete options.change; + console.warn('Option "change" has been renamed to "onChange"') + options.onChange = options.change + delete options.change } if (options.editable) { - console.warn('Option "editable" has been renamed to "onEditable"'); - options.onEditable = options.editable; - delete options.editable; + console.warn('Option "editable" has been renamed to "onEditable"') + options.onEditable = options.editable + delete options.editable } // warn if onChangeJSON is used when mode can be `text` or `code` @@ -131,7 +130,7 @@ function JSONEditor (container, options, json) { if (options.mode === 'text' || options.mode === 'code' || (options.modes && (options.modes.indexOf('text') !== -1 || options.modes.indexOf('code') !== -1))) { console.warn('Option "onChangeJSON" is not applicable to modes "text" and "code". ' + - 'Use "onChangeText" or "onChange" instead.'); + 'Use "onChangeText" or "onChange" instead.') } } @@ -139,14 +138,14 @@ function JSONEditor (container, options, json) { if (options) { Object.keys(options).forEach(function (option) { if (JSONEditor.VALID_OPTIONS.indexOf(option) === -1) { - console.warn('Unknown option "' + option + '". This option will be ignored'); + console.warn('Unknown option "' + option + '". This option will be ignored') } - }); + }) } } if (arguments.length) { - this._create(container, options, json); + this._create(container, options, json) } } @@ -165,13 +164,13 @@ function JSONEditor (container, options, json) { * * @type { Object. } */ -JSONEditor.modes = {}; +JSONEditor.modes = {} // debounce interval for JSON schema vaidation in milliseconds -JSONEditor.prototype.DEBOUNCE_INTERVAL = 150; +JSONEditor.prototype.DEBOUNCE_INTERVAL = 150 JSONEditor.VALID_OPTIONS = [ - 'ajv', 'schema', 'schemaRefs','templates', + 'ajv', 'schema', 'schemaRefs', 'templates', 'ace', 'theme', 'autocomplete', 'onChange', 'onChangeJSON', 'onChangeText', 'onEditable', 'onError', 'onEvent', 'onModeChange', 'onNodeName', 'onValidate', 'onCreateMenu', @@ -181,7 +180,7 @@ JSONEditor.VALID_OPTIONS = [ 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys', 'navigationBar', 'statusBar', 'mainMenuBar', 'languages', 'language', 'enableSort', 'enableTransform', 'maxVisibleChilds' -]; +] /** * Create the JSONEditor @@ -191,50 +190,50 @@ JSONEditor.VALID_OPTIONS = [ * @private */ JSONEditor.prototype._create = function (container, options, json) { - this.container = container; - this.options = options || {}; - this.json = json || {}; + this.container = container + this.options = options || {} + this.json = json || {} - var mode = this.options.mode || (this.options.modes && this.options.modes[0]) || 'tree'; - this.setMode(mode); -}; + var mode = this.options.mode || (this.options.modes && this.options.modes[0]) || 'tree' + this.setMode(mode) +} /** * Destroy the editor. Clean up DOM, event listeners, and web workers. */ -JSONEditor.prototype.destroy = function () {}; +JSONEditor.prototype.destroy = function () {} /** * Set JSON object in editor * @param {Object | undefined} json JSON data */ JSONEditor.prototype.set = function (json) { - this.json = json; -}; + this.json = json +} /** * Get JSON from the editor * @returns {Object} json */ JSONEditor.prototype.get = function () { - return this.json; -}; + return this.json +} /** * Set string containing JSON for the editor * @param {String | undefined} jsonText */ JSONEditor.prototype.setText = function (jsonText) { - this.json = util.parse(jsonText); -}; + this.json = util.parse(jsonText) +} /** * Get stringified JSON contents from the editor * @returns {String} jsonText */ JSONEditor.prototype.getText = function () { - return JSON.stringify(this.json); -}; + return JSON.stringify(this.json) +} /** * Set a field name for the root node. @@ -242,18 +241,18 @@ JSONEditor.prototype.getText = function () { */ JSONEditor.prototype.setName = function (name) { if (!this.options) { - this.options = {}; + this.options = {} } - this.options.name = name; -}; + this.options.name = name +} /** * Get the field name for the root node. * @return {String | undefined} name */ JSONEditor.prototype.getName = function () { - return this.options && this.options.name; -}; + return this.options && this.options.name +} /** * Change the mode of the editor. @@ -264,65 +263,61 @@ JSONEditor.prototype.getName = function () { JSONEditor.prototype.setMode = function (mode) { // if the mode is the same as current mode (and it's not the first time), do nothing. if (mode === this.options.mode && this.create) { - return; + return } - var container = this.container; - var options = util.extend({}, this.options); - var oldMode = options.mode; - var data; - var name; + var container = this.container + var options = util.extend({}, this.options) + var oldMode = options.mode + var data + var name - options.mode = mode; - var config = JSONEditor.modes[mode]; + options.mode = mode + var config = JSONEditor.modes[mode] if (config) { try { - var asText = (config.data == 'text'); - name = this.getName(); - data = this[asText ? 'getText' : 'get'](); // get text or json + var asText = (config.data === 'text') + name = this.getName() + data = this[asText ? 'getText' : 'get']() // get text or json - this.destroy(); - util.clear(this); - util.extend(this, config.mixin); - this.create(container, options); + this.destroy() + util.clear(this) + util.extend(this, config.mixin) + this.create(container, options) - this.setName(name); - this[asText ? 'setText' : 'set'](data); // set text or json + this.setName(name) + this[asText ? 'setText' : 'set'](data) // set text or json if (typeof config.load === 'function') { try { - config.load.call(this); - } - catch (err) { - console.error(err); + config.load.call(this) + } catch (err) { + console.error(err) } } if (typeof options.onModeChange === 'function' && mode !== oldMode) { try { - options.onModeChange(mode, oldMode); - } - catch (err) { - console.error(err); + options.onModeChange(mode, oldMode) + } catch (err) { + console.error(err) } } + } catch (err) { + this._onError(err) } - catch (err) { - this._onError(err); - } + } else { + throw new Error('Unknown mode "' + options.mode + '"') } - else { - throw new Error('Unknown mode "' + options.mode + '"'); - } -}; +} /** * Get the current mode * @return {string} */ JSONEditor.prototype.getMode = function () { - return this.options.mode; -}; + return this.options.mode +} /** * Throw an error. If an error callback is configured in options.error, this @@ -330,14 +325,13 @@ JSONEditor.prototype.getMode = function () { * @param {Error} err * @private */ -JSONEditor.prototype._onError = function(err) { +JSONEditor.prototype._onError = function (err) { if (this.options && typeof this.options.onError === 'function') { - this.options.onError(err); + this.options.onError(err) + } else { + throw err } - else { - throw err; - } -}; +} /** * Set a JSON schema for validation of the JSON object. @@ -349,60 +343,57 @@ JSONEditor.prototype._onError = function(err) { JSONEditor.prototype.setSchema = function (schema, schemaRefs) { // compile a JSON schema validator if a JSON schema is provided if (schema) { - var ajv; + var ajv try { // grab ajv from options if provided, else create a new instance if (this.options.ajv) { ajv = this.options.ajv - } - else { + } else { ajv = Ajv({ allErrors: true, verbose: true, schemaId: 'auto', $data: true - }); + }) // support both draft-04 and draft-06 alongside the latest draft-07 - ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json')); - ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json')); + ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json')) + ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json')) } - } - catch (err) { - console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.'); + } catch (err) { + console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.') } if (ajv) { - if(schemaRefs) { + if (schemaRefs) { for (var ref in schemaRefs) { - ajv.removeSchema(ref); // When updating a schema - old refs has to be removed first - if(schemaRefs[ref]) { - ajv.addSchema(schemaRefs[ref], ref); + ajv.removeSchema(ref) // When updating a schema - old refs has to be removed first + if (schemaRefs[ref]) { + ajv.addSchema(schemaRefs[ref], ref) } } - this.options.schemaRefs = schemaRefs; + this.options.schemaRefs = schemaRefs } - this.validateSchema = ajv.compile(schema); + this.validateSchema = ajv.compile(schema) // add schema to the options, so that when switching to an other mode, // the set schema is not lost - this.options.schema = schema; + this.options.schema = schema // validate now - this.validate(); + this.validate() } - this.refresh(); // update DOM - } - else { + this.refresh() // update DOM + } else { // remove current schema - this.validateSchema = null; - this.options.schema = null; - this.options.schemaRefs = null; - this.validate(); // to clear current error messages - this.refresh(); // update DOM + this.validateSchema = null + this.options.schema = null + this.options.schemaRefs = null + this.validate() // to clear current error messages + this.refresh() // update DOM } -}; +} /** * Validate current JSON object against the configured JSON schema @@ -410,14 +401,14 @@ JSONEditor.prototype.setSchema = function (schema, schemaRefs) { */ JSONEditor.prototype.validate = function () { // must be implemented by treemode and textmode -}; +} /** * Refresh the rendered contents */ JSONEditor.prototype.refresh = function () { // can be implemented by treemode and textmode -}; +} /** * Register a plugin with one ore multiple modes for the JSON Editor. @@ -439,51 +430,50 @@ JSONEditor.prototype.refresh = function () { * @param {Object | Array} mode A mode object or an array with multiple mode objects. */ JSONEditor.registerMode = function (mode) { - var i, prop; + var i, prop if (util.isArray(mode)) { // multiple modes for (i = 0; i < mode.length; i++) { - JSONEditor.registerMode(mode[i]); + JSONEditor.registerMode(mode[i]) } - } - else { + } else { // validate the new mode - if (!('mode' in mode)) throw new Error('Property "mode" missing'); - if (!('mixin' in mode)) throw new Error('Property "mixin" missing'); - if (!('data' in mode)) throw new Error('Property "data" missing'); - var name = mode.mode; + if (!('mode' in mode)) throw new Error('Property "mode" missing') + if (!('mixin' in mode)) throw new Error('Property "mixin" missing') + if (!('data' in mode)) throw new Error('Property "data" missing') + var name = mode.mode if (name in JSONEditor.modes) { - throw new Error('Mode "' + name + '" already registered'); + throw new Error('Mode "' + name + '" already registered') } // validate the mixin if (typeof mode.mixin.create !== 'function') { - throw new Error('Required function "create" missing on mixin'); + throw new Error('Required function "create" missing on mixin') } - var reserved = ['setMode', 'registerMode', 'modes']; + var reserved = ['setMode', 'registerMode', 'modes'] for (i = 0; i < reserved.length; i++) { - prop = reserved[i]; + prop = reserved[i] if (prop in mode.mixin) { - throw new Error('Reserved property "' + prop + '" not allowed in mixin'); + throw new Error('Reserved property "' + prop + '" not allowed in mixin') } } - JSONEditor.modes[name] = mode; + JSONEditor.modes[name] = mode } -}; +} // register tree, text, and preview modes -JSONEditor.registerMode(treemode); -JSONEditor.registerMode(textmode); -JSONEditor.registerMode(previewmode); +JSONEditor.registerMode(treemode) +JSONEditor.registerMode(textmode) +JSONEditor.registerMode(previewmode) // expose some of the libraries that can be used customized -JSONEditor.ace = ace; -JSONEditor.Ajv = Ajv; -JSONEditor.VanillaPicker = VanillaPicker; +JSONEditor.ace = ace +JSONEditor.Ajv = Ajv +JSONEditor.VanillaPicker = VanillaPicker // default export for TypeScript ES6 projects -JSONEditor.default = JSONEditor; +JSONEditor.default = JSONEditor -module.exports = JSONEditor; +module.exports = JSONEditor diff --git a/src/js/ModeSwitcher.js b/src/js/ModeSwitcher.js index d749daa..a6acc63 100644 --- a/src/js/ModeSwitcher.js +++ b/src/js/ModeSwitcher.js @@ -1,7 +1,7 @@ -'use strict'; +'use strict' -var ContextMenu = require('./ContextMenu'); -var translate = require('./i18n').translate; +var ContextMenu = require('./ContextMenu') +var translate = require('./i18n').translate /** * Create a select box to be used in the editor menu's, which allows to switch mode @@ -11,113 +11,113 @@ var translate = require('./i18n').translate; * @param {function(mode: string)} onSwitch Callback invoked on switch * @constructor */ -function ModeSwitcher(container, modes, current, onSwitch) { +function ModeSwitcher (container, modes, current, onSwitch) { // available modes var availableModes = { code: { - 'text': translate('modeCodeText'), - 'title': translate('modeCodeTitle'), - 'click': function () { + text: translate('modeCodeText'), + title: translate('modeCodeTitle'), + click: function () { onSwitch('code') } }, form: { - 'text': translate('modeFormText'), - 'title': translate('modeFormTitle'), - 'click': function () { - onSwitch('form'); + text: translate('modeFormText'), + title: translate('modeFormTitle'), + click: function () { + onSwitch('form') } }, text: { - 'text': translate('modeTextText'), - 'title': translate('modeTextTitle'), - 'click': function () { - onSwitch('text'); + text: translate('modeTextText'), + title: translate('modeTextTitle'), + click: function () { + onSwitch('text') } }, tree: { - 'text': translate('modeTreeText'), - 'title': translate('modeTreeTitle'), - 'click': function () { - onSwitch('tree'); + text: translate('modeTreeText'), + title: translate('modeTreeTitle'), + click: function () { + onSwitch('tree') } }, view: { - 'text': translate('modeViewText'), - 'title': translate('modeViewTitle'), - 'click': function () { - onSwitch('view'); + text: translate('modeViewText'), + title: translate('modeViewTitle'), + click: function () { + onSwitch('view') } }, preview: { - 'text': translate('modePreviewText'), - 'title': translate('modePreviewTitle'), - 'click': function () { - onSwitch('preview'); + text: translate('modePreviewText'), + title: translate('modePreviewTitle'), + click: function () { + onSwitch('preview') } } - }; + } // list the selected modes - var items = []; + var items = [] for (var i = 0; i < modes.length; i++) { - var mode = modes[i]; - var item = availableModes[mode]; + var mode = modes[i] + var item = availableModes[mode] if (!item) { - throw new Error('Unknown mode "' + mode + '"'); + throw new Error('Unknown mode "' + mode + '"') } - item.className = 'jsoneditor-type-modes' + ((current == mode) ? ' jsoneditor-selected' : ''); - items.push(item); + item.className = 'jsoneditor-type-modes' + ((current === mode) ? ' jsoneditor-selected' : '') + items.push(item) } // retrieve the title of current mode - var currentMode = availableModes[current]; + var currentMode = availableModes[current] if (!currentMode) { - throw new Error('Unknown mode "' + current + '"'); + throw new Error('Unknown mode "' + current + '"') } - var currentTitle = currentMode.text; + var currentTitle = currentMode.text // create the html element - var box = document.createElement('button'); - box.type = 'button'; - box.className = 'jsoneditor-modes jsoneditor-separator'; - box.innerHTML = currentTitle + ' ▾'; - box.title = 'Switch editor mode'; + var box = document.createElement('button') + box.type = 'button' + box.className = 'jsoneditor-modes jsoneditor-separator' + box.innerHTML = currentTitle + ' ▾' + box.title = 'Switch editor mode' box.onclick = function () { - var menu = new ContextMenu(items); - menu.show(box, container); - }; + var menu = new ContextMenu(items) + menu.show(box, container) + } - var frame = document.createElement('div'); - frame.className = 'jsoneditor-modes'; - frame.style.position = 'relative'; - frame.appendChild(box); + var frame = document.createElement('div') + frame.className = 'jsoneditor-modes' + frame.style.position = 'relative' + frame.appendChild(box) - container.appendChild(frame); + container.appendChild(frame) this.dom = { container: container, box: box, frame: frame - }; + } } /** * Set focus to switcher */ ModeSwitcher.prototype.focus = function () { - this.dom.box.focus(); -}; + this.dom.box.focus() +} /** * Destroy the ModeSwitcher, remove from DOM */ ModeSwitcher.prototype.destroy = function () { if (this.dom && this.dom.frame && this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); + this.dom.frame.parentNode.removeChild(this.dom.frame) } - this.dom = null; -}; + this.dom = null +} -module.exports = ModeSwitcher; \ No newline at end of file +module.exports = ModeSwitcher diff --git a/src/js/Node.js b/src/js/Node.js index 31c673b..c9e196b 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -1,18 +1,18 @@ -'use strict'; +'use strict' -var jmespath = require('jmespath'); -var naturalSort = require('javascript-natural-sort'); -var createAbsoluteAnchor = require('./createAbsoluteAnchor').createAbsoluteAnchor; -var ContextMenu = require('./ContextMenu'); -var appendNodeFactory = require('./appendNodeFactory'); -var showMoreNodeFactory = require('./showMoreNodeFactory'); -var showSortModal = require('./showSortModal'); -var showTransformModal = require('./showTransformModal'); -var util = require('./util'); -var translate = require('./i18n').translate; -var DEFAULT_MODAL_ANCHOR = require('./constants').DEFAULT_MODAL_ANCHOR; +var jmespath = require('jmespath') +var naturalSort = require('javascript-natural-sort') +var createAbsoluteAnchor = require('./createAbsoluteAnchor').createAbsoluteAnchor +var ContextMenu = require('./ContextMenu') +var appendNodeFactory = require('./appendNodeFactory') +var showMoreNodeFactory = require('./showMoreNodeFactory') +var showSortModal = require('./showSortModal') +var showTransformModal = require('./showTransformModal') +var util = require('./util') +var translate = require('./i18n').translate +var DEFAULT_MODAL_ANCHOR = require('./constants').DEFAULT_MODAL_ANCHOR -var YEAR_2000 = 946684800000; +var YEAR_2000 = 946684800000 /** * @constructor Node @@ -27,44 +27,43 @@ var YEAR_2000 = 946684800000; */ function Node (editor, params) { /** @type {./treemode} */ - this.editor = editor; - this.dom = {}; - this.expanded = false; + this.editor = editor + this.dom = {} + this.expanded = false - if(params && (params instanceof Object)) { - this.setField(params.field, params.fieldEditable); + if (params && (params instanceof Object)) { + this.setField(params.field, params.fieldEditable) if ('value' in params) { - this.setValue(params.value, params.type); + this.setValue(params.value, params.type) } if ('internalValue' in params) { - this.setInternalValue(params.internalValue); + this.setInternalValue(params.internalValue) } - } - else { - this.setField(''); - this.setValue(null); + } else { + this.setField('') + this.setValue(null) } - this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL); - this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL); + this._debouncedOnChangeValue = util.debounce(this._onChangeValue.bind(this), Node.prototype.DEBOUNCE_INTERVAL) + this._debouncedOnChangeField = util.debounce(this._onChangeField.bind(this), Node.prototype.DEBOUNCE_INTERVAL) // starting value for visible children - this.visibleChilds = this.getMaxVisibleChilds(); + this.visibleChilds = this.getMaxVisibleChilds() } // debounce interval for keyboard input in milliseconds -Node.prototype.DEBOUNCE_INTERVAL = 150; +Node.prototype.DEBOUNCE_INTERVAL = 150 // search will stop iterating as soon as the max is reached -Node.prototype.MAX_SEARCH_RESULTS = 999; +Node.prototype.MAX_SEARCH_RESULTS = 999 -// default number of child nodes to display -var DEFAULT_MAX_VISIBLE_CHILDS = 100; +// default number of child nodes to display +var DEFAULT_MAX_VISIBLE_CHILDS = 100 -Node.prototype.getMaxVisibleChilds = function() { +Node.prototype.getMaxVisibleChilds = function () { return (this.editor && this.editor.options && this.editor.options.maxVisibleChilds) - ? this.editor.options.maxVisibleChilds - : DEFAULT_MAX_VISIBLE_CHILDS; + ? this.editor.options.maxVisibleChilds + : DEFAULT_MAX_VISIBLE_CHILDS } /** @@ -75,11 +74,11 @@ Node.prototype._updateEditability = function () { this.editable = { field: true, value: true - }; + } if (this.editor) { - this.editable.field = this.editor.options.mode === 'tree'; - this.editable.value = this.editor.options.mode !== 'view'; + this.editable.field = this.editor.options.mode === 'tree' + this.editable.value = this.editor.options.mode !== 'view' if ((this.editor.options.mode === 'tree' || this.editor.options.mode === 'form') && (typeof this.editor.options.onEditable === 'function')) { @@ -87,19 +86,18 @@ Node.prototype._updateEditability = function () { field: this.field, value: this.value, path: this.getPath() - }); + }) if (typeof editable === 'boolean') { - this.editable.field = editable; - this.editable.value = editable; - } - else { - if (typeof editable.field === 'boolean') this.editable.field = editable.field; - if (typeof editable.value === 'boolean') this.editable.value = editable.value; + this.editable.field = editable + this.editable.value = editable + } else { + if (typeof editable.field === 'boolean') this.editable.field = editable.field + if (typeof editable.value === 'boolean') this.editable.value = editable.value } } } -}; +} /** * Get the path of this node @@ -107,45 +105,45 @@ Node.prototype._updateEditability = function () { * Element is a number if is the index of an array, a string otherwise. */ Node.prototype.getPath = function () { - var node = this; - var path = []; + var node = this + var path = [] while (node) { - var field = node.getName(); + var field = node.getName() if (field !== undefined) { - path.unshift(field); + path.unshift(field) } - node = node.parent; + node = node.parent } - return path; -}; + return path +} /** * Get the internal path of this node, a list with the child indexes. * @return {String[]} Array containing the internal path to this node */ Node.prototype.getInternalPath = function () { - var node = this; - var internalPath = []; + var node = this + var internalPath = [] while (node) { if (node.parent) { - internalPath.unshift(node.getIndex()); + internalPath.unshift(node.getIndex()) } - node = node.parent; + node = node.parent } - return internalPath; -}; + return internalPath +} /** * Get node serializable name * @returns {String|Number} */ Node.prototype.getName = function () { - return !this.parent - ? undefined // do not add an (optional) field name of the root node - : (this.parent.type != 'array') - ? this.field - : this.index; -}; + return !this.parent + ? undefined // do not add an (optional) field name of the root node + : (this.parent.type !== 'array') + ? this.field + : this.index +} /** * Find child node by serializable path @@ -153,21 +151,21 @@ Node.prototype.getName = function () { */ Node.prototype.findNodeByPath = function (path) { if (!path) { - return; + return } - if (path.length == 0) { - return this; + if (path.length === 0) { + return this } if (path.length && this.childs && this.childs.length) { - for (var i=0; i < this.childs.length; ++i) { + for (var i = 0; i < this.childs.length; ++i) { if (('' + path[0]) === ('' + this.childs[i].getName())) { - return this.childs[i].findNodeByPath(path.slice(1)); + return this.childs[i].findNodeByPath(path.slice(1)) } } } -}; +} /** * Find child node by an internal path: the indexes of the childs nodes @@ -177,17 +175,17 @@ Node.prototype.findNodeByPath = function (path) { */ Node.prototype.findNodeByInternalPath = function (internalPath) { if (!internalPath) { - return undefined; + return undefined } - var node = this; + var node = this for (var i = 0; i < internalPath.length && node; i++) { - var childIndex = internalPath[i]; - node = node.childs[childIndex]; + var childIndex = internalPath[i] + node = node.childs[childIndex] } - return node; -}; + return node +} /** * @typedef {{value: String|Object|Number|Boolean, path: Array.}} SerializableNode @@ -199,8 +197,8 @@ Node.prototype.serialize = function () { return { value: this.getValue(), path: this.getPath() - }; -}; + } +} /** * Find a Node from a JSON path like '.items[3].name' @@ -208,28 +206,27 @@ Node.prototype.serialize = function () { * @return {Node | null} Returns the Node when found, returns null if not found */ Node.prototype.findNode = function (jsonPath) { - var path = util.parsePath(jsonPath); - var node = this; + var path = util.parsePath(jsonPath) + var node = this while (node && path.length > 0) { - var prop = path.shift(); + var prop = path.shift() if (typeof prop === 'number') { if (node.type !== 'array') { - throw new Error('Cannot get child node at index ' + prop + ': node is no array'); + throw new Error('Cannot get child node at index ' + prop + ': node is no array') } - node = node.childs[prop]; - } - else { // string + node = node.childs[prop] + } else { // string if (node.type !== 'object') { - throw new Error('Cannot get child node ' + prop + ': node is no object'); + throw new Error('Cannot get child node ' + prop + ': node is no object') } node = node.childs.filter(function (child) { - return child.field === prop; - })[0]; + return child.field === prop + })[0] } } - return node; -}; + return node +} /** * Find all parents of this node. The parents are ordered from root node towards @@ -237,14 +234,14 @@ Node.prototype.findNode = function (jsonPath) { * @return {Array.} */ Node.prototype.findParents = function () { - var parents = []; - var parent = this.parent; + var parents = [] + var parent = this.parent while (parent) { - parents.unshift(parent); - parent = parent.parent; + parents.unshift(parent) + parent = parent.parent } - return parents; -}; + return parents +} /** * @@ -255,88 +252,87 @@ Node.prototype.findParents = function () { * icon will set focus to the invalid child node. */ Node.prototype.setError = function (error, child) { - this.error = error; - this.errorChild = child; + this.error = error + this.errorChild = child if (this.dom && this.dom.tr) { - this.updateError(); + this.updateError() } -}; +} /** * Render the error */ -Node.prototype.updateError = function() { - var error = this.fieldError || this.valueError || this.error; - var tdError = this.dom.tdError; +Node.prototype.updateError = function () { + var error = this.fieldError || this.valueError || this.error + var tdError = this.dom.tdError if (error && this.dom && this.dom.tr) { - util.addClassName(this.dom.tr, 'jsoneditor-validation-error'); + util.addClassName(this.dom.tr, 'jsoneditor-validation-error') if (!tdError) { - tdError = document.createElement('td'); - this.dom.tdError = tdError; - this.dom.tdValue.parentNode.appendChild(tdError); + tdError = document.createElement('td') + this.dom.tdError = tdError + this.dom.tdValue.parentNode.appendChild(tdError) } - var popover = document.createElement('div'); - popover.className = 'jsoneditor-popover jsoneditor-right'; - popover.appendChild(document.createTextNode(error.message)); + var popover = document.createElement('div') + popover.className = 'jsoneditor-popover jsoneditor-right' + popover.appendChild(document.createTextNode(error.message)) - var button = document.createElement('button'); - button.type = 'button'; - button.className = 'jsoneditor-button jsoneditor-schema-error'; - button.appendChild(popover); + var button = document.createElement('button') + button.type = 'button' + button.className = 'jsoneditor-button jsoneditor-schema-error' + button.appendChild(popover) // update the direction of the popover - button.onmouseover = button.onfocus = function updateDirection() { - var directions = ['right', 'above', 'below', 'left']; + button.onmouseover = button.onfocus = function updateDirection () { + var directions = ['right', 'above', 'below', 'left'] for (var i = 0; i < directions.length; i++) { - var direction = directions[i]; - popover.className = 'jsoneditor-popover jsoneditor-' + direction; + var direction = directions[i] + popover.className = 'jsoneditor-popover jsoneditor-' + direction - var contentRect = this.editor.content.getBoundingClientRect(); - var popoverRect = popover.getBoundingClientRect(); - var margin = 20; // account for a scroll bar - var fit = util.insideRect(contentRect, popoverRect, margin); + var contentRect = this.editor.content.getBoundingClientRect() + var popoverRect = popover.getBoundingClientRect() + var margin = 20 // account for a scroll bar + var fit = util.insideRect(contentRect, popoverRect, margin) if (fit) { - break; + break } } - }.bind(this); + }.bind(this) // when clicking the error icon, expand all nodes towards the invalid // child node, and set focus to the child node - var child = this.errorChild; + var child = this.errorChild if (child) { - button.onclick = function showInvalidNode() { + button.onclick = function showInvalidNode () { child.findParents().forEach(function (parent) { - parent.expand(false); - }); + parent.expand(false) + }) child.scrollTo(function () { - child.focus(); - }); - }; + child.focus() + }) + } } // apply the error message to the node while (tdError.firstChild) { - tdError.removeChild(tdError.firstChild); + tdError.removeChild(tdError.firstChild) } - tdError.appendChild(button); - } - else { + tdError.appendChild(button) + } else { if (this.dom.tr) { - util.removeClassName(this.dom.tr, 'jsoneditor-validation-error'); + util.removeClassName(this.dom.tr, 'jsoneditor-validation-error') } if (tdError) { - this.dom.tdError.parentNode.removeChild(this.dom.tdError); - delete this.dom.tdError; + this.dom.tdError.parentNode.removeChild(this.dom.tdError) + delete this.dom.tdError } } -}; +} /** * Get the index of this node: the index in the list of childs where this @@ -345,44 +341,43 @@ Node.prototype.updateError = function() { */ Node.prototype.getIndex = function () { if (this.parent) { - var index = this.parent.childs.indexOf(this); - return index !== -1 ? index : null; + var index = this.parent.childs.indexOf(this) + return index !== -1 ? index : null + } else { + return -1 } - else { - return -1; - } -}; +} /** * Set parent node * @param {Node} parent */ -Node.prototype.setParent = function(parent) { - this.parent = parent; -}; +Node.prototype.setParent = function (parent) { + this.parent = parent +} /** * Set field * @param {String} field * @param {boolean} [fieldEditable] */ -Node.prototype.setField = function(field, fieldEditable) { - this.field = field; - this.previousField = field; - this.fieldEditable = (fieldEditable === true); -}; +Node.prototype.setField = function (field, fieldEditable) { + this.field = field + this.previousField = field + this.fieldEditable = (fieldEditable === true) +} /** * Get field * @return {String} */ -Node.prototype.getField = function() { +Node.prototype.getField = function () { if (this.field === undefined) { - this._getDomField(); + this._getDomField() } - return this.field; -}; + return this.field +} /** * Set value. Value is a JSON structure or an element String, Boolean, etc. @@ -390,50 +385,48 @@ Node.prototype.getField = function() { * @param {String} [type] Specify the type of the value. Can be 'auto', * 'array', 'object', or 'string' */ -Node.prototype.setValue = function(value, type) { - var childValue, child, visible; - var i, j; - var notUpdateDom = false; - var previousChilds = this.childs; +Node.prototype.setValue = function (value, type) { + var childValue, child, visible + var i, j + var notUpdateDom = false + var previousChilds = this.childs - this.type = this._getType(value); + this.type = this._getType(value) // check if type corresponds with the provided type if (type && type !== this.type) { if (type === 'string' && this.type === 'auto') { - this.type = type; - } - else { + this.type = type + } else { throw new Error('Type mismatch: ' + 'cannot cast value of type "' + this.type + - ' to the specified type "' + type + '"'); + ' to the specified type "' + type + '"') } } if (this.type === 'array') { // array if (!this.childs) { - this.childs = []; + this.childs = [] } for (i = 0; i < value.length; i++) { - childValue = value[i]; + childValue = value[i] if (childValue !== undefined && !(childValue instanceof Function)) { if (i < this.childs.length) { // reuse existing child, keep its state - child = this.childs[i]; + child = this.childs[i] - child.fieldEditable = false; - child.index = i; - child.setValue(childValue); - } - else { + child.fieldEditable = false + child.index = i + child.setValue(childValue) + } else { // create a new child child = new Node(this.editor, { value: childValue - }); - visible = i < this.getMaxVisibleChilds(); - this.appendChild(child, visible, notUpdateDom); + }) + visible = i < this.getMaxVisibleChilds() + this.appendChild(child, visible, notUpdateDom) } } } @@ -441,116 +434,111 @@ Node.prototype.setValue = function(value, type) { // cleanup redundant childs // we loop backward to prevent issues with shifting index numbers for (j = this.childs.length; j >= value.length; j--) { - this.removeChild(this.childs[j], notUpdateDom); + this.removeChild(this.childs[j], notUpdateDom) } - } - else if (this.type === 'object') { + } else if (this.type === 'object') { // object if (!this.childs) { - this.childs = []; + this.childs = [] } // cleanup redundant childs // we loop backward to prevent issues with shifting index numbers for (j = this.childs.length - 1; j >= 0; j--) { - if (!value.hasOwnProperty(this.childs[j].field)) { - this.removeChild(this.childs[j], notUpdateDom); + if (!hasOwnProperty(value, this.childs[j].field)) { + this.removeChild(this.childs[j], notUpdateDom) } } - i = 0; + i = 0 for (var childField in value) { - if (value.hasOwnProperty(childField)) { - childValue = value[childField]; + if (hasOwnProperty(value, childField)) { + childValue = value[childField] if (childValue !== undefined && !(childValue instanceof Function)) { - child = this.findChildByProperty(childField); + child = this.findChildByProperty(childField) if (child) { // reuse existing child, keep its state - child.setField(childField, true); - child.setValue(childValue); - } - else { + child.setField(childField, true) + child.setValue(childValue) + } else { // create a new child child = new Node(this.editor, { field: childField, value: childValue - }); - visible = i < this.getMaxVisibleChilds(); - this.appendChild(child, visible, notUpdateDom); + }) + visible = i < this.getMaxVisibleChilds() + this.appendChild(child, visible, notUpdateDom) } } - i++; + i++ } - } - this.value = ''; + this.value = '' // sort object keys if (this.editor.options.sortObjectKeys === true) { - this.sort([], 'asc'); + this.sort([], 'asc') } - } - else { + } else { // value - this.hideChilds(); + this.hideChilds() - delete this.append; - delete this.showMore; - delete this.expanded; - delete this.childs; + delete this.append + delete this.showMore + delete this.expanded + delete this.childs - this.value = value; + this.value = value } // recreate the DOM if switching from an object/array to auto/string or vice versa // needed to recreated the expand button for example if (Array.isArray(previousChilds) !== Array.isArray(this.childs)) { - this.recreateDom(); + this.recreateDom() } - this.updateDom({'updateIndexes': true}); + this.updateDom({ updateIndexes: true }) - this.previousValue = this.value; // used only to check for changes in DOM vs JS model -}; + this.previousValue = this.value // used only to check for changes in DOM vs JS model +} /** * Set internal value * @param {*} internalValue Internal value structure keeping type, * order and duplicates in objects */ -Node.prototype.setInternalValue = function(internalValue) { - var childValue, child, visible; - var i, j; - var notUpdateDom = false; - var previousChilds = this.childs; +Node.prototype.setInternalValue = function (internalValue) { + var childValue, child, visible + var i, j + var notUpdateDom = false + var previousChilds = this.childs - this.type = internalValue.type; + this.type = internalValue.type if (internalValue.type === 'array') { // array if (!this.childs) { - this.childs = []; + this.childs = [] } for (i = 0; i < internalValue.childs.length; i++) { - childValue = internalValue.childs[i]; + childValue = internalValue.childs[i] if (childValue !== undefined && !(childValue instanceof Function)) { if (i < this.childs.length) { // reuse existing child, keep its state - child = this.childs[i]; + child = this.childs[i] - child.fieldEditable = false; - child.index = i; - child.setInternalValue(childValue); - } - else { + child.fieldEditable = false + child.index = i + child.setInternalValue(childValue) + } else { // create a new child child = new Node(this.editor, { internalValue: childValue - }); - visible = i < this.getMaxVisibleChilds(); - this.appendChild(child, visible, notUpdateDom); + }) + visible = i < this.getMaxVisibleChilds() + this.appendChild(child, visible, notUpdateDom) } } } @@ -558,34 +546,32 @@ Node.prototype.setInternalValue = function(internalValue) { // cleanup redundant childs // we loop backward to prevent issues with shifting index numbers for (j = this.childs.length; j >= internalValue.childs.length; j--) { - this.removeChild(this.childs[j], notUpdateDom); + this.removeChild(this.childs[j], notUpdateDom) } - } - else if (internalValue.type === 'object') { + } else if (internalValue.type === 'object') { // object if (!this.childs) { - this.childs = []; + this.childs = [] } for (i = 0; i < internalValue.childs.length; i++) { - childValue = internalValue.childs[i]; + childValue = internalValue.childs[i] if (childValue !== undefined && !(childValue instanceof Function)) { if (i < this.childs.length) { // reuse existing child, keep its state - child = this.childs[i]; + child = this.childs[i] - delete child.index; - child.setField(childValue.field, true); - child.setInternalValue(childValue.value); - } - else { + delete child.index + child.setField(childValue.field, true) + child.setInternalValue(childValue.value) + } else { // create a new child child = new Node(this.editor, { field: childValue.field, internalValue: childValue.value - }); - visible = i < this.getMaxVisibleChilds(); - this.appendChild(child, visible, notUpdateDom); + }) + visible = i < this.getMaxVisibleChilds() + this.appendChild(child, visible, notUpdateDom) } } } @@ -593,90 +579,85 @@ Node.prototype.setInternalValue = function(internalValue) { // cleanup redundant childs // we loop backward to prevent issues with shifting index numbers for (j = this.childs.length; j >= internalValue.childs.length; j--) { - this.removeChild(this.childs[j], notUpdateDom); + this.removeChild(this.childs[j], notUpdateDom) } - } - else { + } else { // value - this.hideChilds(); + this.hideChilds() - delete this.append; - delete this.showMore; - delete this.expanded; - delete this.childs; + delete this.append + delete this.showMore + delete this.expanded + delete this.childs - this.value = internalValue.value; + this.value = internalValue.value } // recreate the DOM if switching from an object/array to auto/string or vice versa // needed to recreated the expand button for example if (Array.isArray(previousChilds) !== Array.isArray(this.childs)) { - this.recreateDom(); + this.recreateDom() } - this.updateDom({'updateIndexes': true}); + this.updateDom({ updateIndexes: true }) - this.previousValue = this.value; // used only to check for changes in DOM vs JS model -}; + this.previousValue = this.value // used only to check for changes in DOM vs JS model +} /** * Remove the DOM of this node and it's childs and recreate it again */ -Node.prototype.recreateDom = function() { +Node.prototype.recreateDom = function () { if (this.dom && this.dom.tr && this.dom.tr.parentNode) { - var domAnchor = this._detachFromDom(); + var domAnchor = this._detachFromDom() - this.clearDom(); + this.clearDom() - this._attachToDom(domAnchor); + this._attachToDom(domAnchor) + } else { + this.clearDom() } - else { - this.clearDom(); - } -}; +} /** * Get value. Value is a JSON structure * @return {*} value */ -Node.prototype.getValue = function() { - if (this.type == 'array') { - var arr = []; - this.childs.forEach (function (child) { - arr.push(child.getValue()); - }); - return arr; - } - else if (this.type == 'object') { - var obj = {}; - this.childs.forEach (function (child) { - obj[child.getField()] = child.getValue(); - }); - return obj; - } - else { +Node.prototype.getValue = function () { + if (this.type === 'array') { + var arr = [] + this.childs.forEach(function (child) { + arr.push(child.getValue()) + }) + return arr + } else if (this.type === 'object') { + var obj = {} + this.childs.forEach(function (child) { + obj[child.getField()] = child.getValue() + }) + return obj + } else { if (this.value === undefined) { - this._getDomValue(); + this._getDomValue() } - return this.value; + return this.value } -}; +} /** * Get internal value, a structure which maintains ordering and duplicates in objects * @return {*} value */ -Node.prototype.getInternalValue = function() { +Node.prototype.getInternalValue = function () { if (this.type === 'array') { return { type: this.type, - childs: this.childs.map (function (child) { - return child.getInternalValue(); + childs: this.childs.map(function (child) { + return child.getInternalValue() }) - }; - } - else if (this.type === 'object') { + } + } else if (this.type === 'object') { return { type: this.type, childs: this.childs.map(function (child) { @@ -685,37 +666,36 @@ Node.prototype.getInternalValue = function() { value: child.getInternalValue() } }) - }; - } - else { + } + } else { if (this.value === undefined) { - this._getDomValue(); + this._getDomValue() } return { type: this.type, value: this.value - }; + } } -}; +} /** * Get the nesting level of this node * @return {Number} level */ -Node.prototype.getLevel = function() { - return (this.parent ? this.parent.getLevel() + 1 : 0); -}; +Node.prototype.getLevel = function () { + return (this.parent ? this.parent.getLevel() + 1 : 0) +} /** * Get jsonpath of the current node * @return {Node[]} Returns an array with nodes */ Node.prototype.getNodePath = function () { - var path = this.parent ? this.parent.getNodePath() : []; - path.push(this); - return path; -}; + var path = this.parent ? this.parent.getNodePath() : [] + path.push(this) + return path +} /** * Create a clone of a node @@ -723,217 +703,214 @@ Node.prototype.getNodePath = function () { * not. The DOM elements are not cloned. * @return {Node} clone */ -Node.prototype.clone = function() { - var clone = new Node(this.editor); - clone.type = this.type; - clone.field = this.field; - clone.fieldInnerText = this.fieldInnerText; - clone.fieldEditable = this.fieldEditable; - clone.previousField = this.previousField; - clone.value = this.value; - clone.valueInnerText = this.valueInnerText; - clone.previousValue = this.previousValue; - clone.expanded = this.expanded; - clone.visibleChilds = this.visibleChilds; +Node.prototype.clone = function () { + var clone = new Node(this.editor) + clone.type = this.type + clone.field = this.field + clone.fieldInnerText = this.fieldInnerText + clone.fieldEditable = this.fieldEditable + clone.previousField = this.previousField + clone.value = this.value + clone.valueInnerText = this.valueInnerText + clone.previousValue = this.previousValue + clone.expanded = this.expanded + clone.visibleChilds = this.visibleChilds if (this.childs) { // an object or array - var cloneChilds = []; + var cloneChilds = [] this.childs.forEach(function (child) { - var childClone = child.clone(); - childClone.setParent(clone); - cloneChilds.push(childClone); - }); - clone.childs = cloneChilds; - } - else { + var childClone = child.clone() + childClone.setParent(clone) + cloneChilds.push(childClone) + }) + clone.childs = cloneChilds + } else { // a value - clone.childs = undefined; + clone.childs = undefined } - return clone; -}; + return clone +} /** * Expand this node and optionally its childs. * @param {boolean} [recurse] Optional recursion, true by default. When * true, all childs will be expanded recursively */ -Node.prototype.expand = function(recurse) { +Node.prototype.expand = function (recurse) { if (!this.childs) { - return; + return } // set this node expanded - this.expanded = true; + this.expanded = true if (this.dom.expand) { - this.dom.expand.className = 'jsoneditor-button jsoneditor-expanded'; + this.dom.expand.className = 'jsoneditor-button jsoneditor-expanded' } - this.showChilds(); + this.showChilds() if (recurse !== false) { this.childs.forEach(function (child) { - child.expand(recurse); - }); + child.expand(recurse) + }) } -}; +} /** * Collapse this node and optionally its childs. * @param {boolean} [recurse] Optional recursion, true by default. When * true, all childs will be collapsed recursively */ -Node.prototype.collapse = function(recurse) { +Node.prototype.collapse = function (recurse) { if (!this.childs) { - return; + return } - this.hideChilds(); + this.hideChilds() // collapse childs in case of recurse if (recurse !== false) { this.childs.forEach(function (child) { - child.collapse(recurse); - }); - + child.collapse(recurse) + }) } // make this node collapsed if (this.dom.expand) { - this.dom.expand.className = 'jsoneditor-button jsoneditor-collapsed'; + this.dom.expand.className = 'jsoneditor-button jsoneditor-collapsed' } - this.expanded = false; -}; + this.expanded = false +} /** * Recursively show all childs when they are expanded */ -Node.prototype.showChilds = function() { - var childs = this.childs; +Node.prototype.showChilds = function () { + var childs = this.childs if (!childs) { - return; + return } if (!this.expanded) { - return; + return } - var tr = this.dom.tr; - var table = tr ? tr.parentNode : undefined; + var tr = this.dom.tr + var nextTr + var table = tr ? tr.parentNode : undefined if (table) { // show row with append button - var append = this.getAppendDom(); + var append = this.getAppendDom() if (!append.parentNode) { - var nextTr = tr.nextSibling; + nextTr = tr.nextSibling if (nextTr) { - table.insertBefore(append, nextTr); - } - else { - table.appendChild(append); + table.insertBefore(append, nextTr) + } else { + table.appendChild(append) } } // show childs - var iMax = Math.min(this.childs.length, this.visibleChilds); - var nextTr = this._getNextTr(); + var iMax = Math.min(this.childs.length, this.visibleChilds) + nextTr = this._getNextTr() for (var i = 0; i < iMax; i++) { - var child = this.childs[i]; + var child = this.childs[i] if (!child.getDom().parentNode) { - table.insertBefore(child.getDom(), nextTr); + table.insertBefore(child.getDom(), nextTr) } - child.showChilds(); + child.showChilds() } // show "show more childs" if limited - var showMore = this.getShowMoreDom(); - var nextTr = this._getNextTr(); + var showMore = this.getShowMoreDom() + nextTr = this._getNextTr() if (!showMore.parentNode) { - table.insertBefore(showMore, nextTr); + table.insertBefore(showMore, nextTr) } - this.showMore.updateDom(); // to update the counter + this.showMore.updateDom() // to update the counter } -}; +} -Node.prototype._getNextTr = function() { +Node.prototype._getNextTr = function () { if (this.showMore && this.showMore.getDom().parentNode) { - return this.showMore.getDom(); + return this.showMore.getDom() } if (this.append && this.append.getDom().parentNode) { - return this.append.getDom(); + return this.append.getDom() } -}; +} /** * Hide the node with all its childs * @param {{resetVisibleChilds: boolean}} [options] */ -Node.prototype.hide = function(options) { - var tr = this.dom.tr; - var table = tr ? tr.parentNode : undefined; +Node.prototype.hide = function (options) { + var tr = this.dom.tr + var table = tr ? tr.parentNode : undefined if (table) { - table.removeChild(tr); + table.removeChild(tr) } - this.hideChilds(options); -}; - + this.hideChilds(options) +} /** * Recursively hide all childs * @param {{resetVisibleChilds: boolean}} [options] */ -Node.prototype.hideChilds = function(options) { - var childs = this.childs; +Node.prototype.hideChilds = function (options) { + var childs = this.childs if (!childs) { - return; + return } if (!this.expanded) { - return; + return } // hide append row - var append = this.getAppendDom(); + var append = this.getAppendDom() if (append.parentNode) { - append.parentNode.removeChild(append); + append.parentNode.removeChild(append) } // hide childs this.childs.forEach(function (child) { - child.hide(); - }); + child.hide() + }) // hide "show more" row - var showMore = this.getShowMoreDom(); + var showMore = this.getShowMoreDom() if (showMore.parentNode) { - showMore.parentNode.removeChild(showMore); + showMore.parentNode.removeChild(showMore) } // reset max visible childs if (!options || options.resetVisibleChilds) { - this.visibleChilds = this.getMaxVisibleChilds(); + this.visibleChilds = this.getMaxVisibleChilds() } -}; +} /** * set custom css classes on a node */ Node.prototype._updateCssClassName = function () { - if(this.dom.field - && this.editor - && this.editor.options - && typeof this.editor.options.onClassName ==='function' - && this.dom.tree){ - util.removeAllClassNames(this.dom.tree); - var addClasses = this.editor.options.onClassName({ path: this.getPath(), field: this.field, value: this.value }) || ""; - util.addClassName(this.dom.tree, "jsoneditor-values " + addClasses); + if (this.dom.field && + this.editor && + this.editor.options && + typeof this.editor.options.onClassName === 'function' && + this.dom.tree) { + util.removeAllClassNames(this.dom.tree) + var addClasses = this.editor.options.onClassName({ path: this.getPath(), field: this.field, value: this.value }) || '' + util.addClassName(this.dom.tree, 'jsoneditor-values ' + addClasses) } -}; +} Node.prototype.recursivelyUpdateCssClassesOnNodes = function () { - this._updateCssClassName(); + this._updateCssClassName() if (Array.isArray(this.childs)) { for (var i = 0; i < this.childs.length; i++) { - this.childs[i].recursivelyUpdateCssClassesOnNodes(); + this.childs[i].recursivelyUpdateCssClassesOnNodes() } } } @@ -941,16 +918,15 @@ Node.prototype.recursivelyUpdateCssClassesOnNodes = function () { /** * Goes through the path from the node to the root and ensures that it is expanded */ -Node.prototype.expandTo = function() { - var currentNode = this.parent; +Node.prototype.expandTo = function () { + var currentNode = this.parent while (currentNode) { if (!currentNode.expanded) { - currentNode.expand(); + currentNode.expand() } - currentNode = currentNode.parent; + currentNode = currentNode.parent } -}; - +} /** * Add a new child to the node. @@ -961,41 +937,40 @@ Node.prototype.expandTo = function() { * node and appended node will be updated * (child count, indexes) */ -Node.prototype.appendChild = function(node, visible, updateDom) { +Node.prototype.appendChild = function (node, visible, updateDom) { if (this._hasChilds()) { // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - if (this.type == 'array') { - node.index = this.childs.length; + node.setParent(this) + node.fieldEditable = (this.type === 'object') + if (this.type === 'array') { + node.index = this.childs.length } - if (this.type === 'object' && node.field == undefined) { + if (this.type === 'object' && node.field === undefined) { // initialize field value if needed - node.setField(''); + node.setField('') } - this.childs.push(node); + this.childs.push(node) if (this.expanded && visible !== false) { // insert into the DOM, before the appendRow - var newTr = node.getDom(); - var nextTr = this._getNextTr(); - var table = nextTr ? nextTr.parentNode : undefined; + var newTr = node.getDom() + var nextTr = this._getNextTr() + var table = nextTr ? nextTr.parentNode : undefined if (nextTr && table) { - table.insertBefore(newTr, nextTr); + table.insertBefore(newTr, nextTr) } - node.showChilds(); + node.showChilds() - this.visibleChilds++; + this.visibleChilds++ } if (updateDom !== false) { - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); + this.updateDom({ updateIndexes: true }) + node.updateDom({ recurse: true }) } } -}; - +} /** * Move a node from its current parent to this node @@ -1003,40 +978,38 @@ Node.prototype.appendChild = function(node, visible, updateDom) { * @param {Node} node * @param {Node} beforeNode */ -Node.prototype.moveBefore = function(node, beforeNode) { +Node.prototype.moveBefore = function (node, beforeNode) { if (this._hasChilds()) { // create a temporary row, to prevent the scroll position from jumping // when removing the node - var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined; + var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined if (tbody) { - var trTemp = document.createElement('tr'); - trTemp.style.height = tbody.clientHeight + 'px'; - tbody.appendChild(trTemp); + var trTemp = document.createElement('tr') + trTemp.style.height = tbody.clientHeight + 'px' + tbody.appendChild(trTemp) } if (node.parent) { - node.parent.removeChild(node); + node.parent.removeChild(node) } if (beforeNode instanceof AppendNode || !beforeNode) { // the this.childs.length + 1 is to reckon with the node that we're about to add if (this.childs.length + 1 > this.visibleChilds) { - var lastVisibleNode = this.childs[this.visibleChilds - 1]; - this.insertBefore(node, lastVisibleNode); + var lastVisibleNode = this.childs[this.visibleChilds - 1] + this.insertBefore(node, lastVisibleNode) + } else { + this.appendChild(node) } - else { - this.appendChild(node); - } - } - else { - this.insertBefore(node, beforeNode); + } else { + this.insertBefore(node, beforeNode) } if (tbody) { - tbody.removeChild(trTemp); + tbody.removeChild(trTemp) } } -}; +} /** * Insert a new child before a given node @@ -1044,53 +1017,52 @@ Node.prototype.moveBefore = function(node, beforeNode) { * @param {Node} node * @param {Node} beforeNode */ -Node.prototype.insertBefore = function(node, beforeNode) { +Node.prototype.insertBefore = function (node, beforeNode) { if (this._hasChilds()) { - this.visibleChilds++; + this.visibleChilds++ // initialize field value if needed - if (this.type === 'object' && node.field == undefined) { - node.setField(''); + if (this.type === 'object' && node.field === undefined) { + node.setField('') } if (beforeNode === this.append) { // append to the child nodes // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - this.childs.push(node); - } - else { + node.setParent(this) + node.fieldEditable = (this.type === 'object') + this.childs.push(node) + } else { // insert before a child node - var index = this.childs.indexOf(beforeNode); - if (index == -1) { - throw new Error('Node not found'); + var index = this.childs.indexOf(beforeNode) + if (index === -1) { + throw new Error('Node not found') } // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - this.childs.splice(index, 0, node); + node.setParent(this) + node.fieldEditable = (this.type === 'object') + this.childs.splice(index, 0, node) } if (this.expanded) { // insert into the DOM - var newTr = node.getDom(); - var nextTr = beforeNode.getDom(); - var table = nextTr ? nextTr.parentNode : undefined; + var newTr = node.getDom() + var nextTr = beforeNode.getDom() + var table = nextTr ? nextTr.parentNode : undefined if (nextTr && table) { - table.insertBefore(newTr, nextTr); + table.insertBefore(newTr, nextTr) } - node.showChilds(); - this.showChilds(); + node.showChilds() + this.showChilds() } - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); + this.updateDom({ updateIndexes: true }) + node.updateDom({ recurse: true }) } -}; +} /** * Insert a new child before a given node @@ -1098,18 +1070,17 @@ Node.prototype.insertBefore = function(node, beforeNode) { * @param {Node} node * @param {Node} afterNode */ -Node.prototype.insertAfter = function(node, afterNode) { +Node.prototype.insertAfter = function (node, afterNode) { if (this._hasChilds()) { - var index = this.childs.indexOf(afterNode); - var beforeNode = this.childs[index + 1]; + var index = this.childs.indexOf(afterNode) + var beforeNode = this.childs[index + 1] if (beforeNode) { - this.insertBefore(node, beforeNode); - } - else { - this.appendChild(node); + this.insertBefore(node, beforeNode) + } else { + this.appendChild(node) } } -}; +} /** * Search in this node @@ -1119,31 +1090,31 @@ Node.prototype.insertAfter = function(node, afterNode) { * used to count and limit the results whilst iterating * @return {Node[]} results Array with nodes containing the search text */ -Node.prototype.search = function(text, results) { +Node.prototype.search = function (text, results) { if (!Array.isArray(results)) { - results = []; + results = [] } - var index; - var search = text ? text.toLowerCase() : undefined; + var index + var search = text ? text.toLowerCase() : undefined // delete old search data - delete this.searchField; - delete this.searchValue; + delete this.searchField + delete this.searchValue // search in field if (this.field !== undefined && results.length <= this.MAX_SEARCH_RESULTS) { - var field = String(this.field).toLowerCase(); - index = field.indexOf(search); + var field = String(this.field).toLowerCase() + index = field.indexOf(search) if (index !== -1) { - this.searchField = true; + this.searchField = true results.push({ - 'node': this, - 'elem': 'field' - }); + node: this, + elem: 'field' + }) } // update dom - this._updateDomField(); + this._updateDomField() } // search in value @@ -1153,68 +1124,66 @@ Node.prototype.search = function(text, results) { // search the nodes childs if (this.childs) { this.childs.forEach(function (child) { - child.search(text, results); - }); + child.search(text, results) + }) } - } - else { + } else { // string, auto - if (this.value !== undefined && results.length <= this.MAX_SEARCH_RESULTS) { - var value = String(this.value).toLowerCase(); - index = value.indexOf(search); + if (this.value !== undefined && results.length <= this.MAX_SEARCH_RESULTS) { + var value = String(this.value).toLowerCase() + index = value.indexOf(search) if (index !== -1) { - this.searchValue = true; + this.searchValue = true results.push({ - 'node': this, - 'elem': 'value' - }); + node: this, + elem: 'value' + }) } // update dom - this._updateDomValue(); + this._updateDomValue() } } - return results; -}; + return results +} /** * Move the scroll position such that this node is in the visible area. * The node will not get the focus * @param {function(boolean)} [callback] */ -Node.prototype.scrollTo = function(callback) { - this.expandPathToNode(); +Node.prototype.scrollTo = function (callback) { + this.expandPathToNode() if (this.dom.tr && this.dom.tr.parentNode) { - this.editor.scrollTo(this.dom.tr.offsetTop, callback); + this.editor.scrollTo(this.dom.tr.offsetTop, callback) } -}; +} /** * if the node is not visible, expand its parents */ Node.prototype.expandPathToNode = function () { - var node = this; - var recurse = false; + var node = this + var recurse = false while (node && node.parent) { // expand visible childs of the parent if needed var index = node.parent.type === 'array' - ? node.index - : node.parent.childs.indexOf(node); + ? node.index + : node.parent.childs.indexOf(node) while (node.parent.visibleChilds < index + 1) { - node.parent.visibleChilds += this.getMaxVisibleChilds(); + node.parent.visibleChilds += this.getMaxVisibleChilds() } // expand the parent itself - node.parent.expand(recurse); - node = node.parent; + node.parent.expand(recurse) + node = node.parent } -}; - +} // stores the element name currently having the focus -Node.focusElement = undefined; +Node.focusElement = undefined /** * Set focus to this node @@ -1222,94 +1191,83 @@ Node.focusElement = undefined; * focus available values: 'drag', 'menu', * 'expand', 'field', 'value' (default) */ -Node.prototype.focus = function(elementName) { - Node.focusElement = elementName; +Node.prototype.focus = function (elementName) { + Node.focusElement = elementName if (this.dom.tr && this.dom.tr.parentNode) { - var dom = this.dom; + var dom = this.dom switch (elementName) { case 'drag': if (dom.drag) { - dom.drag.focus(); + dom.drag.focus() + } else { + dom.menu.focus() } - else { - dom.menu.focus(); - } - break; + break case 'menu': - dom.menu.focus(); - break; + dom.menu.focus() + break case 'expand': if (this._hasChilds()) { - dom.expand.focus(); + dom.expand.focus() + } else if (dom.field && this.fieldEditable) { + dom.field.focus() + util.selectContentEditable(dom.field) + } else if (dom.value && !this._hasChilds()) { + dom.value.focus() + util.selectContentEditable(dom.value) + } else { + dom.menu.focus() } - else if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else { - dom.menu.focus(); - } - break; + break case 'field': if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); + dom.field.focus() + util.selectContentEditable(dom.field) + } else if (dom.value && !this._hasChilds()) { + dom.value.focus() + util.selectContentEditable(dom.value) + } else if (this._hasChilds()) { + dom.expand.focus() + } else { + dom.menu.focus() } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else if (this._hasChilds()) { - dom.expand.focus(); - } - else { - dom.menu.focus(); - } - break; + break case 'value': default: if (dom.select) { // enum select box - dom.select.focus(); + dom.select.focus() + } else if (dom.value && !this._hasChilds()) { + dom.value.focus() + util.selectContentEditable(dom.value) + } else if (dom.field && this.fieldEditable) { + dom.field.focus() + util.selectContentEditable(dom.field) + } else if (this._hasChilds()) { + dom.expand.focus() + } else { + dom.menu.focus() } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (this._hasChilds()) { - dom.expand.focus(); - } - else { - dom.menu.focus(); - } - break; + break } } -}; +} /** * Select all text in an editable div after a delay of 0 ms * @param {Element} editableDiv */ -Node.select = function(editableDiv) { +Node.select = function (editableDiv) { setTimeout(function () { - util.selectContentEditable(editableDiv); - }, 0); -}; + util.selectContentEditable(editableDiv) + }, 0) +} /** * Check if given node is a child. The method will check recursively to find @@ -1317,23 +1275,23 @@ Node.select = function(editableDiv) { * @param {Node} node * @return {boolean} containsNode */ -Node.prototype.containsNode = function(node) { - if (this == node) { - return true; +Node.prototype.containsNode = function (node) { + if (this === node) { + return true } - var childs = this.childs; + var childs = this.childs if (childs) { // TODO: use the js5 Array.some() here? for (var i = 0, iMax = childs.length; i < iMax; i++) { if (childs[i].containsNode(node)) { - return true; + return true } } } - return false; -}; + return false +} /** * Remove a child from the node. @@ -1344,34 +1302,34 @@ Node.prototype.containsNode = function(node) { * @return {Node | undefined} node The removed node on success, * else undefined */ -Node.prototype.removeChild = function(node, updateDom) { +Node.prototype.removeChild = function (node, updateDom) { if (this.childs) { - var index = this.childs.indexOf(node); + var index = this.childs.indexOf(node) if (index !== -1) { if (index < this.visibleChilds && this.expanded) { - this.visibleChilds--; + this.visibleChilds-- } - node.hide(); + node.hide() // delete old search results - delete node.searchField; - delete node.searchValue; + delete node.searchField + delete node.searchValue - var removedNode = this.childs.splice(index, 1)[0]; - removedNode.parent = null; + var removedNode = this.childs.splice(index, 1)[0] + removedNode.parent = null if (updateDom !== false) { - this.updateDom({'updateIndexes': true}); + this.updateDom({ updateIndexes: true }) } - return removedNode; + return removedNode } } - return undefined; -}; + return undefined +} /** * Remove a child node node from this node @@ -1381,187 +1339,179 @@ Node.prototype.removeChild = function(node, updateDom) { * @private */ Node.prototype._remove = function (node) { - this.removeChild(node); -}; + this.removeChild(node) +} /** * Change the type of the value of this Node * @param {String} newType */ Node.prototype.changeType = function (newType) { - var oldType = this.type; + var oldType = this.type - if (oldType == newType) { + if (oldType === newType) { // type is not changed - return; + return } - if ((newType == 'string' || newType == 'auto') && - (oldType == 'string' || oldType == 'auto')) { + if ((newType === 'string' || newType === 'auto') && + (oldType === 'string' || oldType === 'auto')) { // this is an easy change - this.type = newType; - } - else { + this.type = newType + } else { // change from array to object, or from string/auto to object/array - var domAnchor = this._detachFromDom(); + var domAnchor = this._detachFromDom() // delete the old DOM - this.clearDom(); + this.clearDom() // adjust the field and the value - this.type = newType; + this.type = newType // adjust childs - if (newType == 'object') { + if (newType === 'object') { if (!this.childs) { - this.childs = []; + this.childs = [] } this.childs.forEach(function (child) { - child.clearDom(); - delete child.index; - child.fieldEditable = true; - if (child.field == undefined) { - child.field = ''; + child.clearDom() + delete child.index + child.fieldEditable = true + if (child.field === undefined) { + child.field = '' } - }); + }) - if (oldType == 'string' || oldType == 'auto') { - this.expanded = true; + if (oldType === 'string' || oldType === 'auto') { + this.expanded = true } - } - else if (newType == 'array') { + } else if (newType === 'array') { if (!this.childs) { - this.childs = []; + this.childs = [] } this.childs.forEach(function (child, index) { - child.clearDom(); - child.fieldEditable = false; - child.index = index; - }); + child.clearDom() + child.fieldEditable = false + child.index = index + }) - if (oldType == 'string' || oldType == 'auto') { - this.expanded = true; + if (oldType === 'string' || oldType === 'auto') { + this.expanded = true } - } - else { - this.expanded = false; + } else { + this.expanded = false } - this._attachToDom(domAnchor); + this._attachToDom(domAnchor) } - if (newType == 'auto' || newType == 'string') { + if (newType === 'auto' || newType === 'string') { // cast value to the correct type - if (newType == 'string') { - this.value = String(this.value); - } - else { - this.value = util.parseString(String(this.value)); + if (newType === 'string') { + this.value = String(this.value) + } else { + this.value = util.parseString(String(this.value)) } - this.focus(); + this.focus() } - this.updateDom({'updateIndexes': true}); -}; + this.updateDom({ updateIndexes: true }) +} /** * Test whether the JSON contents of this node are deep equal to provided JSON object. * @param {*} json */ Node.prototype.deepEqual = function (json) { - var i; + var i if (this.type === 'array') { if (!Array.isArray(json)) { - return false; + return false } if (this.childs.length !== json.length) { - return false; + return false } for (i = 0; i < this.childs.length; i++) { if (!this.childs[i].deepEqual(json[i])) { - return false; + return false } } - } - else if (this.type === 'object') { + } else if (this.type === 'object') { if (typeof json !== 'object' || !json) { - return false; + return false } // TODO: for better efficiency, we could create a property `isDuplicate` on all of the childs // and keep that up to date. This should make deepEqual about 20% faster. - var props = {}; - var propCount = 0; + var props = {} + var propCount = 0 for (i = 0; i < this.childs.length; i++) { - var child = this.childs[i]; + var child = this.childs[i] if (!props[child.field]) { // We can have childs with duplicate field names. // We take the first, and ignore the others. - props[child.field] = true; - propCount++; + props[child.field] = true + propCount++ if (!(child.field in json)) { - return false; + return false } if (!child.deepEqual(json[child.field])) { - return false; + return false } } } if (propCount !== Object.keys(json).length) { - return false; + return false } - } - else { + } else { if (this.value !== json) { - return false; + return false } } - return true; -}; + return true +} /** * Retrieve value from DOM * @private */ -Node.prototype._getDomValue = function() { - this._clearValueError(); +Node.prototype._getDomValue = function () { + this._clearValueError() - if (this.dom.value && this.type != 'array' && this.type != 'object') { - this.valueInnerText = util.getInnerText(this.dom.value); + if (this.dom.value && this.type !== 'array' && this.type !== 'object') { + this.valueInnerText = util.getInnerText(this.dom.value) } - if (this.valueInnerText != undefined) { + if (this.valueInnerText !== undefined) { try { // retrieve the value - var value; - if (this.type == 'string') { - value = this._unescapeHTML(this.valueInnerText); - } - else { - var str = this._unescapeHTML(this.valueInnerText); - value = util.parseString(str); + var value + if (this.type === 'string') { + value = this._unescapeHTML(this.valueInnerText) + } else { + var str = this._unescapeHTML(this.valueInnerText) + value = util.parseString(str) } if (value !== this.value) { - this.value = value; - this._debouncedOnChangeValue(); + this.value = value + this._debouncedOnChangeValue() } - } - catch (err) { + } catch (err) { // keep the previous value - this._setValueError(translate('cannotParseValueError')); + this._setValueError(translate('cannotParseValueError')) } } -}; +} /** * Show a local error in case of invalid value @@ -1571,14 +1521,14 @@ Node.prototype._getDomValue = function() { Node.prototype._setValueError = function (message) { this.valueError = { message: message - }; - this.updateError(); + } + this.updateError() } Node.prototype._clearValueError = function () { if (this.valueError) { - this.valueError = null; - this.updateError(); + this.valueError = null + this.updateError() } } @@ -1590,14 +1540,14 @@ Node.prototype._clearValueError = function () { Node.prototype._setFieldError = function (message) { this.fieldError = { message: message - }; - this.updateError(); + } + this.updateError() } Node.prototype._clearFieldError = function () { if (this.fieldError) { - this.fieldError = null; - this.updateError(); + this.fieldError = null + this.updateError() } } @@ -1608,17 +1558,17 @@ Node.prototype._clearFieldError = function () { Node.prototype._onChangeValue = function () { // get current selection, then override the range such that we can select // the added/removed text on undo/redo - var oldSelection = this.editor.getDomSelection(); + var oldSelection = this.editor.getDomSelection() if (oldSelection.range) { - var undoDiff = util.textDiff(String(this.value), String(this.previousValue)); - oldSelection.range.startOffset = undoDiff.start; - oldSelection.range.endOffset = undoDiff.end; + var undoDiff = util.textDiff(String(this.value), String(this.previousValue)) + oldSelection.range.startOffset = undoDiff.start + oldSelection.range.endOffset = undoDiff.end } - var newSelection = this.editor.getDomSelection(); + var newSelection = this.editor.getDomSelection() if (newSelection.range) { - var redoDiff = util.textDiff(String(this.previousValue), String(this.value)); - newSelection.range.startOffset = redoDiff.start; - newSelection.range.endOffset = redoDiff.end; + var redoDiff = util.textDiff(String(this.previousValue), String(this.value)) + newSelection.range.startOffset = redoDiff.start + newSelection.range.endOffset = redoDiff.end } this.editor._onAction('editValue', { @@ -1627,10 +1577,10 @@ Node.prototype._onChangeValue = function () { newValue: this.value, oldSelection: oldSelection, newSelection: newSelection - }); + }) - this.previousValue = this.value; -}; + this.previousValue = this.value +} /** * Handle a changed field @@ -1639,18 +1589,18 @@ Node.prototype._onChangeValue = function () { Node.prototype._onChangeField = function () { // get current selection, then override the range such that we can select // the added/removed text on undo/redo - var oldSelection = this.editor.getDomSelection(); - var previous = this.previousField || ''; + var oldSelection = this.editor.getDomSelection() + var previous = this.previousField || '' if (oldSelection.range) { - var undoDiff = util.textDiff(this.field, previous); - oldSelection.range.startOffset = undoDiff.start; - oldSelection.range.endOffset = undoDiff.end; + var undoDiff = util.textDiff(this.field, previous) + oldSelection.range.startOffset = undoDiff.start + oldSelection.range.endOffset = undoDiff.end } - var newSelection = this.editor.getDomSelection(); + var newSelection = this.editor.getDomSelection() if (newSelection.range) { - var redoDiff = util.textDiff(previous, this.field); - newSelection.range.startOffset = redoDiff.start; - newSelection.range.endOffset = redoDiff.end; + var redoDiff = util.textDiff(previous, this.field) + newSelection.range.startOffset = redoDiff.start + newSelection.range.endOffset = redoDiff.end } this.editor._onAction('editField', { @@ -1660,10 +1610,10 @@ Node.prototype._onChangeField = function () { newValue: this.field, oldSelection: oldSelection, newSelection: newSelection - }); + }) - this.previousField = this.field; -}; + this.previousField = this.field +} /** * Update dom value: @@ -1673,124 +1623,120 @@ Node.prototype._onChangeField = function () { * @private */ Node.prototype._updateDomValue = function () { - var domValue = this.dom.value; + var domValue = this.dom.value if (domValue) { - var classNames = ['jsoneditor-value']; + var classNames = ['jsoneditor-value'] // set text color depending on value type - var value = this.value; - var type = (this.type == 'auto') ? util.type(value) : this.type; - var isUrl = type == 'string' && util.isUrl(value); - classNames.push('jsoneditor-' + type); + var value = this.value + var type = (this.type === 'auto') ? util.type(value) : this.type + var isUrl = type === 'string' && util.isUrl(value) + classNames.push('jsoneditor-' + type) if (isUrl) { - classNames.push('jsoneditor-url'); + classNames.push('jsoneditor-url') } // visual styling when empty - var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); + var isEmpty = (String(this.value) === '' && this.type !== 'array' && this.type !== 'object') if (isEmpty) { - classNames.push('jsoneditor-empty'); + classNames.push('jsoneditor-empty') } // highlight when there is a search result if (this.searchValueActive) { - classNames.push('jsoneditor-highlight-active'); + classNames.push('jsoneditor-highlight-active') } if (this.searchValue) { - classNames.push('jsoneditor-highlight'); + classNames.push('jsoneditor-highlight') } - domValue.className = classNames.join(' '); + domValue.className = classNames.join(' ') // update title - if (type == 'array' || type == 'object') { - var count = this.childs ? this.childs.length : 0; - domValue.title = this.type + ' containing ' + count + ' items'; - } - else if (isUrl && this.editable.value) { - domValue.title = translate('openUrl'); - } - else { - domValue.title = ''; + if (type === 'array' || type === 'object') { + var count = this.childs ? this.childs.length : 0 + domValue.title = this.type + ' containing ' + count + ' items' + } else if (isUrl && this.editable.value) { + domValue.title = translate('openUrl') + } else { + domValue.title = '' } // show checkbox when the value is a boolean if (type === 'boolean' && this.editable.value) { if (!this.dom.checkbox) { - this.dom.checkbox = document.createElement('input'); - this.dom.checkbox.type = 'checkbox'; - this.dom.tdCheckbox = document.createElement('td'); - this.dom.tdCheckbox.className = 'jsoneditor-tree'; - this.dom.tdCheckbox.appendChild(this.dom.checkbox); + this.dom.checkbox = document.createElement('input') + this.dom.checkbox.type = 'checkbox' + this.dom.tdCheckbox = document.createElement('td') + this.dom.tdCheckbox.className = 'jsoneditor-tree' + this.dom.tdCheckbox.appendChild(this.dom.checkbox) - this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox, this.dom.tdValue); + this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox, this.dom.tdValue) } - this.dom.checkbox.checked = this.value; - } - else { + this.dom.checkbox.checked = this.value + } else { // cleanup checkbox when displayed if (this.dom.tdCheckbox) { - this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox); - delete this.dom.tdCheckbox; - delete this.dom.checkbox; + this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox) + delete this.dom.tdCheckbox + delete this.dom.checkbox } } // create select box when this node has an enum object if (this.enum && this.editable.value) { if (!this.dom.select) { - this.dom.select = document.createElement('select'); - this.id = this.field + "_" + new Date().getUTCMilliseconds(); - this.dom.select.id = this.id; - this.dom.select.name = this.dom.select.id; + this.dom.select = document.createElement('select') + this.id = this.field + '_' + new Date().getUTCMilliseconds() + this.dom.select.id = this.id + this.dom.select.name = this.dom.select.id - //Create the default empty option - this.dom.select.option = document.createElement('option'); - this.dom.select.option.value = ''; - this.dom.select.option.innerHTML = '--'; - this.dom.select.appendChild(this.dom.select.option); + // Create the default empty option + this.dom.select.option = document.createElement('option') + this.dom.select.option.value = '' + this.dom.select.option.innerHTML = '--' + this.dom.select.appendChild(this.dom.select.option) - //Iterate all enum values and add them as options - for(var i = 0; i < this.enum.length; i++) { - this.dom.select.option = document.createElement('option'); - this.dom.select.option.value = this.enum[i]; - this.dom.select.option.innerHTML = this.enum[i]; - if(this.dom.select.option.value == this.value){ - this.dom.select.option.selected = true; + // Iterate all enum values and add them as options + for (var i = 0; i < this.enum.length; i++) { + this.dom.select.option = document.createElement('option') + this.dom.select.option.value = this.enum[i] + this.dom.select.option.innerHTML = this.enum[i] + if (this.dom.select.option.value === this.value) { + this.dom.select.option.selected = true } - this.dom.select.appendChild(this.dom.select.option); + this.dom.select.appendChild(this.dom.select.option) } - this.dom.tdSelect = document.createElement('td'); - this.dom.tdSelect.className = 'jsoneditor-tree'; - this.dom.tdSelect.appendChild(this.dom.select); - this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue); + this.dom.tdSelect = document.createElement('td') + this.dom.tdSelect.className = 'jsoneditor-tree' + this.dom.tdSelect.appendChild(this.dom.select) + this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue) } // If the enum is inside a composite type display // both the simple input and the dropdown field - if(this.schema && ( - !this.schema.hasOwnProperty("oneOf") && - !this.schema.hasOwnProperty("anyOf") && - !this.schema.hasOwnProperty("allOf")) + if (this.schema && ( + !hasOwnProperty(this.schema, 'oneOf') && + !hasOwnProperty(this.schema, 'anyOf') && + !hasOwnProperty(this.schema, 'allOf')) ) { - this.valueFieldHTML = this.dom.tdValue.innerHTML; - this.dom.tdValue.style.visibility = 'hidden'; - this.dom.tdValue.innerHTML = ''; + this.valueFieldHTML = this.dom.tdValue.innerHTML + this.dom.tdValue.style.visibility = 'hidden' + this.dom.tdValue.innerHTML = '' } else { - delete this.valueFieldHTML; + delete this.valueFieldHTML } - } - else { + } else { // cleanup select box when displayed if (this.dom.tdSelect) { - this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect); - delete this.dom.tdSelect; - delete this.dom.select; - this.dom.tdValue.innerHTML = this.valueFieldHTML; - this.dom.tdValue.style.visibility = ''; - delete this.valueFieldHTML; + this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect) + delete this.dom.tdSelect + delete this.dom.select + this.dom.tdValue.innerHTML = this.valueFieldHTML + this.dom.tdValue.style.visibility = '' + delete this.valueFieldHTML } } @@ -1799,27 +1745,25 @@ Node.prototype._updateDomValue = function () { this.editor.options.colorPicker && typeof value === 'string' && util.isValidColor(value)) { - if (!this.dom.color) { - this.dom.color = document.createElement('div'); - this.dom.color.className = 'jsoneditor-color'; + this.dom.color = document.createElement('div') + this.dom.color.className = 'jsoneditor-color' - this.dom.tdColor = document.createElement('td'); - this.dom.tdColor.className = 'jsoneditor-tree'; - this.dom.tdColor.appendChild(this.dom.color); + this.dom.tdColor = document.createElement('td') + this.dom.tdColor.className = 'jsoneditor-tree' + this.dom.tdColor.appendChild(this.dom.color) - this.dom.tdValue.parentNode.insertBefore(this.dom.tdColor, this.dom.tdValue); + this.dom.tdValue.parentNode.insertBefore(this.dom.tdColor, this.dom.tdValue) // this is a bit hacky, overriding the text color like this. find a nicer solution - this.dom.value.style.color = '#1A1A1A'; + this.dom.value.style.color = '#1A1A1A' } // update the color background - this.dom.color.style.backgroundColor = value; - } - else { + this.dom.color.style.backgroundColor = value + } else { // cleanup color picker when displayed - this._deleteDomColor(); + this._deleteDomColor() } // show date tag when value is a timestamp in milliseconds @@ -1827,38 +1771,36 @@ Node.prototype._updateDomValue = function () { typeof value === 'number' && value > YEAR_2000 && !isNaN(new Date(value).valueOf())) { - if (!this.dom.date) { - this.dom.date = document.createElement('div'); + this.dom.date = document.createElement('div') this.dom.date.className = 'jsoneditor-date' - this.dom.value.parentNode.appendChild(this.dom.date); + this.dom.value.parentNode.appendChild(this.dom.date) } - this.dom.date.innerHTML = new Date(value).toISOString(); - this.dom.date.title = new Date(value).toString(); - } - else { + this.dom.date.innerHTML = new Date(value).toISOString() + this.dom.date.title = new Date(value).toString() + } else { // cleanup date tag if (this.dom.date) { - this.dom.date.parentNode.removeChild(this.dom.date); - delete this.dom.date; + this.dom.date.parentNode.removeChild(this.dom.date) + delete this.dom.date } } // strip formatting from the contents of the editable div - util.stripFormatting(domValue); + util.stripFormatting(domValue) - this._updateDomDefault(); + this._updateDomDefault() } -}; +} Node.prototype._deleteDomColor = function () { if (this.dom.color) { - this.dom.tdColor.parentNode.removeChild(this.dom.tdColor); - delete this.dom.tdColor; - delete this.dom.color; + this.dom.tdColor.parentNode.removeChild(this.dom.tdColor) + delete this.dom.tdColor + delete this.dom.color - this.dom.value.style.color = ''; + this.dom.value.style.color = '' } } @@ -1870,40 +1812,37 @@ Node.prototype._deleteDomColor = function () { * @private */ Node.prototype._updateDomField = function () { - var domField = this.dom.field; + var domField = this.dom.field if (domField) { - var tooltip = util.makeFieldTooltip(this.schema, this.editor.options.language); + var tooltip = util.makeFieldTooltip(this.schema, this.editor.options.language) if (tooltip) { - domField.title = tooltip; + domField.title = tooltip } // make backgound color lightgray when empty - var isEmpty = (String(this.field) == '' && this.parent.type != 'array'); + var isEmpty = (String(this.field) === '' && this.parent.type !== 'array') if (isEmpty) { - util.addClassName(domField, 'jsoneditor-empty'); - } - else { - util.removeClassName(domField, 'jsoneditor-empty'); + util.addClassName(domField, 'jsoneditor-empty') + } else { + util.removeClassName(domField, 'jsoneditor-empty') } // highlight when there is a search result if (this.searchFieldActive) { - util.addClassName(domField, 'jsoneditor-highlight-active'); - } - else { - util.removeClassName(domField, 'jsoneditor-highlight-active'); + util.addClassName(domField, 'jsoneditor-highlight-active') + } else { + util.removeClassName(domField, 'jsoneditor-highlight-active') } if (this.searchField) { - util.addClassName(domField, 'jsoneditor-highlight'); - } - else { - util.removeClassName(domField, 'jsoneditor-highlight'); + util.addClassName(domField, 'jsoneditor-highlight') + } else { + util.removeClassName(domField, 'jsoneditor-highlight') } // strip formatting from the contents of the editable div - util.stripFormatting(domField); + util.stripFormatting(domField) } -}; +} /** * Retrieve field from DOM @@ -1911,48 +1850,45 @@ Node.prototype._updateDomField = function () { * into a unique name in case it is a duplicate. * @private */ -Node.prototype._getDomField = function(forceUnique) { - this._clearFieldError(); +Node.prototype._getDomField = function (forceUnique) { + this._clearFieldError() if (this.dom.field && this.fieldEditable) { - this.fieldInnerText = util.getInnerText(this.dom.field); + this.fieldInnerText = util.getInnerText(this.dom.field) } if (this.fieldInnerText !== undefined) { try { - var field = this._unescapeHTML(this.fieldInnerText); + var field = this._unescapeHTML(this.fieldInnerText) - var existingFieldNames = this.parent.getFieldNames(this); - var isDuplicate = existingFieldNames.indexOf(field) !== -1; + var existingFieldNames = this.parent.getFieldNames(this) + var isDuplicate = existingFieldNames.indexOf(field) !== -1 if (!isDuplicate) { if (field !== this.field) { - this.field = field; - this._debouncedOnChangeField(); + this.field = field + this._debouncedOnChangeField() } - } - else { + } else { if (forceUnique) { // fix duplicate field: change it into a unique name - field = util.findUniqueName(field, existingFieldNames); + field = util.findUniqueName(field, existingFieldNames) if (field !== this.field) { - this.field = field; + this.field = field // TODO: don't debounce but resolve right away, and cancel current debounce - this._debouncedOnChangeField(); + this._debouncedOnChangeField() } - } - else { - this._setFieldError(translate('duplicateFieldError')); + } else { + this._setFieldError(translate('duplicateFieldError')) } } - } - catch (err) { + } catch (err) { // keep the previous field value - this._setFieldError(translate('cannotParseFieldError')); + this._setFieldError(translate('cannotParseFieldError')) } } -}; +} /** * Update the value of the schema default element in the DOM. @@ -1962,101 +1898,101 @@ Node.prototype._getDomField = function(forceUnique) { Node.prototype._updateDomDefault = function () { // Short-circuit if schema is missing, has no default, or if Node has children if (!this.schema || this.schema.default === undefined || this._hasChilds()) { - return; + return } // select either enum dropdown (select) or input value var inputElement = this.dom.select - ? this.dom.select - : this.dom.value; + ? this.dom.select + : this.dom.value if (!inputElement) { - return; + return } if (this.value === this.schema.default) { - inputElement.title = translate('default'); - util.addClassName(inputElement, 'jsoneditor-is-default'); - util.removeClassName(inputElement, 'jsoneditor-is-not-default'); + inputElement.title = translate('default') + util.addClassName(inputElement, 'jsoneditor-is-default') + util.removeClassName(inputElement, 'jsoneditor-is-not-default') } else { - inputElement.removeAttribute('title'); - util.removeClassName(inputElement, 'jsoneditor-is-default'); - util.addClassName(inputElement, 'jsoneditor-is-not-default'); + inputElement.removeAttribute('title') + util.removeClassName(inputElement, 'jsoneditor-is-default') + util.addClassName(inputElement, 'jsoneditor-is-not-default') } -}; +} /** * Clear the dom of the node */ -Node.prototype.clearDom = function() { +Node.prototype.clearDom = function () { // TODO: hide the node first? - //this.hide(); + // this.hide(); // TODO: recursively clear dom? - this.dom = {}; -}; + this.dom = {} +} /** * Get the HTML DOM TR element of the node. * The dom will be generated when not yet created * @return {Element} tr HTML DOM TR Element */ -Node.prototype.getDom = function() { - var dom = this.dom; +Node.prototype.getDom = function () { + var dom = this.dom if (dom.tr) { - return dom.tr; + return dom.tr } - this._updateEditability(); + this._updateEditability() // create row - dom.tr = document.createElement('tr'); - dom.tr.node = this; + dom.tr = document.createElement('tr') + dom.tr.node = this if (this.editor.options.mode === 'tree') { // note: we take here the global setting - var tdDrag = document.createElement('td'); + var tdDrag = document.createElement('td') if (this.editable.field) { // create draggable area if (this.parent) { - var domDrag = document.createElement('button'); - domDrag.type = 'button'; - dom.drag = domDrag; - domDrag.className = 'jsoneditor-button jsoneditor-dragarea'; - domDrag.title = translate('drag'); - tdDrag.appendChild(domDrag); + var domDrag = document.createElement('button') + domDrag.type = 'button' + dom.drag = domDrag + domDrag.className = 'jsoneditor-button jsoneditor-dragarea' + domDrag.title = translate('drag') + tdDrag.appendChild(domDrag) } } - dom.tr.appendChild(tdDrag); + dom.tr.appendChild(tdDrag) // create context menu - var tdMenu = document.createElement('td'); - var menu = document.createElement('button'); - menu.type = 'button'; - dom.menu = menu; - menu.className = 'jsoneditor-button jsoneditor-contextmenu'; - menu.title = translate('actionsMenu'); - tdMenu.appendChild(dom.menu); - dom.tr.appendChild(tdMenu); + var tdMenu = document.createElement('td') + var menu = document.createElement('button') + menu.type = 'button' + dom.menu = menu + menu.className = 'jsoneditor-button jsoneditor-contextmenu' + menu.title = translate('actionsMenu') + tdMenu.appendChild(dom.menu) + dom.tr.appendChild(tdMenu) } // create tree and field - var tdField = document.createElement('td'); - dom.tr.appendChild(tdField); - dom.tree = this._createDomTree(); - tdField.appendChild(dom.tree); + var tdField = document.createElement('td') + dom.tr.appendChild(tdField) + dom.tree = this._createDomTree() + tdField.appendChild(dom.tree) - this.updateDom({'updateIndexes': true}); + this.updateDom({ updateIndexes: true }) - return dom.tr; -}; + return dom.tr +} /** * Test whether a Node is rendered and visible * @returns {boolean} */ Node.prototype.isVisible = function () { - return this.dom && this.dom.tr && this.dom.tr.parentNode || false -}; + return (this.dom && this.dom.tr && this.dom.tr.parentNode) || false +} /** * DragStart event, fired on mousedown on the dragarea at the left side of a Node @@ -2065,35 +2001,35 @@ Node.prototype.isVisible = function () { */ Node.onDragStart = function (nodes, event) { if (!Array.isArray(nodes)) { - return Node.onDragStart([nodes], event); + return Node.onDragStart([nodes], event) } if (nodes.length === 0) { - return; + return } - var firstNode = nodes[0]; - var lastNode = nodes[nodes.length - 1]; - var parent = firstNode.parent; - var draggedNode = Node.getNodeFromTarget(event.target); - var editor = firstNode.editor; + var firstNode = nodes[0] + var lastNode = nodes[nodes.length - 1] + var parent = firstNode.parent + var draggedNode = Node.getNodeFromTarget(event.target) + var editor = firstNode.editor // in case of multiple selected nodes, offsetY prevents the selection from // jumping when you start dragging one of the lower down nodes in the selection - var offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr); + var offsetY = util.getAbsoluteTop(draggedNode.dom.tr) - util.getAbsoluteTop(firstNode.dom.tr) if (!editor.mousemove) { editor.mousemove = util.addEventListener(window, 'mousemove', function (event) { - Node.onDrag(nodes, event); - }); + Node.onDrag(nodes, event) + }) } if (!editor.mouseup) { - editor.mouseup = util.addEventListener(window, 'mouseup',function (event ) { - Node.onDragEnd(nodes, event); - }); + editor.mouseup = util.addEventListener(window, 'mouseup', function (event) { + Node.onDragEnd(nodes, event) + }) } - editor.highlighter.lock(); + editor.highlighter.lock() editor.drag = { oldCursor: document.body.style.cursor, oldSelection: editor.getDomSelection(), @@ -2105,11 +2041,11 @@ Node.onDragStart = function (nodes, event) { mouseX: event.pageX, offsetY: offsetY, level: firstNode.getLevel() - }; - document.body.style.cursor = 'move'; + } + document.body.style.cursor = 'move' - event.preventDefault(); -}; + event.preventDefault() +} /** * Drag event, fired when moving the mouse while dragging a Node @@ -2118,148 +2054,144 @@ Node.onDragStart = function (nodes, event) { */ Node.onDrag = function (nodes, event) { if (!Array.isArray(nodes)) { - return Node.onDrag([nodes], event); + return Node.onDrag([nodes], event) } if (nodes.length === 0) { - return; + return } // TODO: this method has grown too large. Split it in a number of methods - var editor = nodes[0].editor; - var mouseY = event.pageY - editor.drag.offsetY; - var mouseX = event.pageX; - var trThis, trPrev, trNext, trFirst, trLast, trRoot; - var nodePrev, nodeNext; - var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; - var moved = false; + var editor = nodes[0].editor + var mouseY = event.pageY - editor.drag.offsetY + var mouseX = event.pageX + var trThis, trPrev, trNext, trFirst, trLast, trRoot + var nodePrev, nodeNext + var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext + var moved = false // TODO: add an ESC option, which resets to the original position // move up/down - var firstNode = nodes[0]; - trThis = firstNode.dom.tr; - topThis = util.getAbsoluteTop(trThis); - heightThis = trThis.offsetHeight; + var firstNode = nodes[0] + trThis = firstNode.dom.tr + topThis = util.getAbsoluteTop(trThis) + heightThis = trThis.offsetHeight if (mouseY < topThis) { // move up - trPrev = trThis; + trPrev = trThis do { - trPrev = trPrev.previousSibling; - nodePrev = Node.getNodeFromTarget(trPrev); - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + trPrev = trPrev.previousSibling + nodePrev = Node.getNodeFromTarget(trPrev) + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0 } - while (trPrev && mouseY < topPrev); + while (trPrev && mouseY < topPrev) if (nodePrev && !nodePrev.parent) { - nodePrev = undefined; + nodePrev = undefined } if (!nodePrev) { // move to the first node - trRoot = trThis.parentNode.firstChild; - trPrev = trRoot ? trRoot.nextSibling : undefined; - nodePrev = Node.getNodeFromTarget(trPrev); - if (nodePrev == firstNode) { - nodePrev = undefined; + trRoot = trThis.parentNode.firstChild + trPrev = trRoot ? trRoot.nextSibling : undefined + nodePrev = Node.getNodeFromTarget(trPrev) + if (nodePrev === firstNode) { + nodePrev = undefined } } if (nodePrev && nodePrev.isVisible()) { // check if mouseY is really inside the found node - trPrev = nodePrev.dom.tr; - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; + trPrev = nodePrev.dom.tr + topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0 if (mouseY > topPrev + heightThis) { - nodePrev = undefined; + nodePrev = undefined } } if (nodePrev) { nodes.forEach(function (node) { - nodePrev.parent.moveBefore(node, nodePrev); - }); - moved = true; + nodePrev.parent.moveBefore(node, nodePrev) + }) + moved = true } - } - else { + } else { // move down - var lastNode = nodes[nodes.length - 1]; - trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr; - trFirst = trLast ? trLast.nextSibling : undefined; + var lastNode = nodes[nodes.length - 1] + trLast = (lastNode.expanded && lastNode.append) ? lastNode.append.getDom() : lastNode.dom.tr + trFirst = trLast ? trLast.nextSibling : undefined if (trFirst) { - topFirst = util.getAbsoluteTop(trFirst); - trNext = trFirst; + topFirst = util.getAbsoluteTop(trFirst) + trNext = trFirst do { - nodeNext = Node.getNodeFromTarget(trNext); + nodeNext = Node.getNodeFromTarget(trNext) if (trNext) { - bottomNext = trNext.nextSibling ? - util.getAbsoluteTop(trNext.nextSibling) : 0; - heightNext = trNext ? (bottomNext - topFirst) : 0; + bottomNext = trNext.nextSibling + ? util.getAbsoluteTop(trNext.nextSibling) : 0 + heightNext = trNext ? (bottomNext - topFirst) : 0 if (nodeNext && - nodeNext.parent.childs.length == nodes.length && - nodeNext.parent.childs[nodes.length - 1] == lastNode) { + nodeNext.parent.childs.length === nodes.length && + nodeNext.parent.childs[nodes.length - 1] === lastNode) { // We are about to remove the last child of this parent, // which will make the parents appendNode visible. - topThis += 27; + topThis += 27 // TODO: dangerous to suppose the height of the appendNode a constant of 27 px. } - trNext = trNext.nextSibling; + trNext = trNext.nextSibling } } - while (trNext && mouseY > topThis + heightNext); + while (trNext && mouseY > topThis + heightNext) if (nodeNext && nodeNext.parent) { // calculate the desired level - var diffX = (mouseX - editor.drag.mouseX); - var diffLevel = Math.round(diffX / 24 / 2); - var level = editor.drag.level + diffLevel; // desired level - var levelNext = nodeNext.getLevel(); // level to be + var diffX = (mouseX - editor.drag.mouseX) + var diffLevel = Math.round(diffX / 24 / 2) + var level = editor.drag.level + diffLevel // desired level + var levelNext = nodeNext.getLevel() // level to be // find the best fitting level (move upwards over the append nodes) - trPrev = nodeNext.dom.tr && nodeNext.dom.tr.previousSibling; + trPrev = nodeNext.dom.tr && nodeNext.dom.tr.previousSibling while (levelNext < level && trPrev) { - nodePrev = Node.getNodeFromTarget(trPrev); + nodePrev = Node.getNodeFromTarget(trPrev) var isDraggedNode = nodes.some(function (node) { - return node === nodePrev || nodePrev.isDescendantOf(node); - }); + return node === nodePrev || nodePrev.isDescendantOf(node) + }) if (isDraggedNode) { // neglect the dragged nodes themselves and their childs - } - else if (nodePrev instanceof AppendNode) { - var childs = nodePrev.parent.childs; - if (childs.length != nodes.length || childs[nodes.length - 1] != lastNode) { + } else if (nodePrev instanceof AppendNode) { + var childs = nodePrev.parent.childs + if (childs.length !== nodes.length || childs[nodes.length - 1] !== lastNode) { // non-visible append node of a list of childs // consisting of not only this node (else the // append node will change into a visible "empty" // text when removing this node). - nodeNext = Node.getNodeFromTarget(trPrev); - levelNext = nodeNext.getLevel(); + nodeNext = Node.getNodeFromTarget(trPrev) + levelNext = nodeNext.getLevel() + } else { + break } - else { - break; - } - } - else { - break; + } else { + break } - trPrev = trPrev.previousSibling; + trPrev = trPrev.previousSibling } if (nodeNext instanceof AppendNode && !nodeNext.isVisible() && nodeNext.parent.showMore.isVisible()) { - nodeNext = nodeNext._nextNode(); + nodeNext = nodeNext._nextNode() } // move the node when its position is changed - if (nodeNext && nodeNext.dom.tr && trLast.nextSibling != nodeNext.dom.tr) { + if (nodeNext && nodeNext.dom.tr && trLast.nextSibling !== nodeNext.dom.tr) { nodes.forEach(function (node) { - nodeNext.parent.moveBefore(node, nodeNext); - }); - moved = true; + nodeNext.parent.moveBefore(node, nodeNext) + }) + moved = true } } } @@ -2267,15 +2199,15 @@ Node.onDrag = function (nodes, event) { if (moved) { // update the dragging parameters when moved - editor.drag.mouseX = mouseX; - editor.drag.level = firstNode.getLevel(); + editor.drag.mouseX = mouseX + editor.drag.level = firstNode.getLevel() } // auto scroll when hovering around the top of the editor - editor.startAutoScroll(mouseY); + editor.startAutoScroll(mouseY) - event.preventDefault(); -}; + event.preventDefault() +} /** * Drag event, fired on mouseup after having dragged a node @@ -2284,31 +2216,31 @@ Node.onDrag = function (nodes, event) { */ Node.onDragEnd = function (nodes, event) { if (!Array.isArray(nodes)) { - return Node.onDrag([nodes], event); + return Node.onDrag([nodes], event) } if (nodes.length === 0) { - return; + return } - var firstNode = nodes[0]; - var editor = firstNode.editor; + var firstNode = nodes[0] + var editor = firstNode.editor // set focus to the context menu button of the first node if (nodes[0]) { - nodes[0].dom.menu.focus(); + nodes[0].dom.menu.focus() } - var oldParentPath = editor.drag.oldParent.getInternalPath(); - var newParentPath = firstNode.parent.getInternalPath(); - var sameParent = editor.drag.oldParent === firstNode.parent; - var oldIndex = editor.drag.oldNextNode.getIndex(); - var newIndex = firstNode.getIndex(); - var oldParentPathRedo = editor.drag.oldParentPathRedo; + var oldParentPath = editor.drag.oldParent.getInternalPath() + var newParentPath = firstNode.parent.getInternalPath() + var sameParent = editor.drag.oldParent === firstNode.parent + var oldIndex = editor.drag.oldNextNode.getIndex() + var newIndex = firstNode.getIndex() + var oldParentPathRedo = editor.drag.oldParentPathRedo - var oldIndexRedo = editor.drag.oldIndexRedo; + var oldIndexRedo = editor.drag.oldIndexRedo var newIndexRedo = (sameParent && oldIndexRedo < newIndex) - ? (newIndex + nodes.length) - : newIndex; + ? (newIndex + nodes.length) + : newIndex if (!sameParent || oldIndexRedo !== newIndex) { // only register this action if the node is actually moved to another place @@ -2328,34 +2260,34 @@ Node.onDragEnd = function (nodes, event) { oldSelection: editor.drag.oldSelection, newSelection: editor.getDomSelection() - }); + }) } - document.body.style.cursor = editor.drag.oldCursor; - editor.highlighter.unlock(); + document.body.style.cursor = editor.drag.oldCursor + editor.highlighter.unlock() nodes.forEach(function (node) { - node.updateDom(); + node.updateDom() if (event.target !== node.dom.drag && event.target !== node.dom.menu) { - editor.highlighter.unhighlight(); + editor.highlighter.unhighlight() } - }); - delete editor.drag; + }) + delete editor.drag if (editor.mousemove) { - util.removeEventListener(window, 'mousemove', editor.mousemove); - delete editor.mousemove; + util.removeEventListener(window, 'mousemove', editor.mousemove) + delete editor.mousemove } if (editor.mouseup) { - util.removeEventListener(window, 'mouseup', editor.mouseup); - delete editor.mouseup; + util.removeEventListener(window, 'mouseup', editor.mouseup) + delete editor.mouseup } // Stop any running auto scroll - editor.stopAutoScroll(); + editor.stopAutoScroll() - event.preventDefault(); -}; + event.preventDefault() +} /** * Test if this node is a sescendant of an other node @@ -2364,16 +2296,16 @@ Node.onDragEnd = function (nodes, event) { * @private */ Node.prototype.isDescendantOf = function (node) { - var n = this.parent; + var n = this.parent while (n) { - if (n == node) { - return true; + if (n === node) { + return true } - n = n.parent; + n = n.parent } - return false; -}; + return false +} /** * Create an editable field @@ -2381,8 +2313,8 @@ Node.prototype.isDescendantOf = function (node) { * @private */ Node.prototype._createDomField = function () { - return document.createElement('div'); -}; + return document.createElement('div') +} /** * Set highlighting for this node and all its childs. @@ -2392,23 +2324,22 @@ Node.prototype._createDomField = function () { Node.prototype.setHighlight = function (highlight) { if (this.dom.tr) { if (highlight) { - util.addClassName(this.dom.tr, 'jsoneditor-highlight'); - } - else { - util.removeClassName(this.dom.tr, 'jsoneditor-highlight'); + util.addClassName(this.dom.tr, 'jsoneditor-highlight') + } else { + util.removeClassName(this.dom.tr, 'jsoneditor-highlight') } if (this.append) { - this.append.setHighlight(highlight); + this.append.setHighlight(highlight) } if (this.childs) { this.childs.forEach(function (child) { - child.setHighlight(highlight); - }); + child.setHighlight(highlight) + }) } } -}; +} /** * Select or deselect a node @@ -2416,38 +2347,36 @@ Node.prototype.setHighlight = function (highlight) { * @param {boolean} [isFirst] */ Node.prototype.setSelected = function (selected, isFirst) { - this.selected = selected; + this.selected = selected if (this.dom.tr) { if (selected) { - util.addClassName(this.dom.tr, 'jsoneditor-selected'); - } - else { - util.removeClassName(this.dom.tr, 'jsoneditor-selected'); + util.addClassName(this.dom.tr, 'jsoneditor-selected') + } else { + util.removeClassName(this.dom.tr, 'jsoneditor-selected') } if (isFirst) { - util.addClassName(this.dom.tr, 'jsoneditor-first'); - } - else { - util.removeClassName(this.dom.tr, 'jsoneditor-first'); + util.addClassName(this.dom.tr, 'jsoneditor-first') + } else { + util.removeClassName(this.dom.tr, 'jsoneditor-first') } if (this.append) { - this.append.setSelected(selected); + this.append.setSelected(selected) } if (this.showMore) { - this.showMore.setSelected(selected); + this.showMore.setSelected(selected) } if (this.childs) { this.childs.forEach(function (child) { - child.setSelected(selected); - }); + child.setSelected(selected) + }) } } -}; +} /** * Update the value of the node. Only primitive types are allowed, no Object @@ -2455,22 +2384,22 @@ Node.prototype.setSelected = function (selected, isFirst) { * @param {String | Number | Boolean | null} value */ Node.prototype.updateValue = function (value) { - this.value = value; - this.previousValue = value; - this.valueError = undefined; - this.updateDom(); -}; + this.value = value + this.previousValue = value + this.valueError = undefined + this.updateDom() +} /** * Update the field of the node. * @param {String} field */ Node.prototype.updateField = function (field) { - this.field = field; - this.previousField = field; - this.fieldError = undefined; - this.updateDom(); -}; + this.field = field + this.previousField = field + this.fieldError = undefined + this.updateDom() +} /** * Update the HTML DOM, optionally recursing through the childs @@ -2482,90 +2411,83 @@ Node.prototype.updateField = function (field) { * indexes of the node will be updated too. False by * default. */ -Node.prototype.updateDom = function(options) { +Node.prototype.updateDom = function (options) { // update level indentation - var domTree = this.dom.tree; + var domTree = this.dom.tree if (domTree) { - domTree.style.marginLeft = this.getLevel() * 24 + 'px'; + domTree.style.marginLeft = this.getLevel() * 24 + 'px' } // apply field to DOM - var domField = this.dom.field; + var domField = this.dom.field if (domField) { if (this.fieldEditable) { // parent is an object - domField.contentEditable = this.editable.field; - domField.spellcheck = false; - domField.className = 'jsoneditor-field'; - } - else { + domField.contentEditable = this.editable.field + domField.spellcheck = false + domField.className = 'jsoneditor-field' + } else { // parent is an array this is the root node - domField.contentEditable = false; - domField.className = 'jsoneditor-readonly'; + domField.contentEditable = false + domField.className = 'jsoneditor-readonly' } - var fieldText; - if (this.index != undefined) { - fieldText = this.index; - } - else if (this.field != undefined) { - fieldText = this.field; - } - else { + var fieldText + if (this.index !== undefined) { + fieldText = this.index + } else if (this.field !== undefined) { + fieldText = this.field + } else { var schema = this.editor.options.schema - ? Node._findSchema(this.editor.options.schema,this.editor.options.schemaRefs || {}, this.getPath()) - : undefined; + ? Node._findSchema(this.editor.options.schema, this.editor.options.schemaRefs || {}, this.getPath()) + : undefined if (schema && schema.title) { - fieldText = schema.title; - } - else if (this._hasChilds()) { - fieldText = this.type; - } - else { - fieldText = ''; + fieldText = schema.title + } else if (this._hasChilds()) { + fieldText = this.type + } else { + fieldText = '' } } - domField.innerHTML = this._escapeHTML(fieldText); + domField.innerHTML = this._escapeHTML(fieldText) - this._updateSchema(); + this._updateSchema() } // apply value to DOM - var domValue = this.dom.value; + var domValue = this.dom.value if (domValue) { - if (this.type == 'array') { - this.updateNodeName(); - util.addClassName(this.dom.tr, 'jsoneditor-expandable'); - } - else if (this.type == 'object') { - this.updateNodeName(); - util.addClassName(this.dom.tr, 'jsoneditor-expandable'); - } - else { - domValue.innerHTML = this._escapeHTML(this.value); - util.removeClassName(this.dom.tr, 'jsoneditor-expandable'); + if (this.type === 'array') { + this.updateNodeName() + util.addClassName(this.dom.tr, 'jsoneditor-expandable') + } else if (this.type === 'object') { + this.updateNodeName() + util.addClassName(this.dom.tr, 'jsoneditor-expandable') + } else { + domValue.innerHTML = this._escapeHTML(this.value) + util.removeClassName(this.dom.tr, 'jsoneditor-expandable') } } // update field and value - this._updateDomField(); - this._updateDomValue(); + this._updateDomField() + this._updateDomValue() - this._updateCssClassName(); + this._updateCssClassName() // update childs indexes if (options && options.updateIndexes === true) { // updateIndexes is true or undefined - this._updateDomIndexes(); + this._updateDomIndexes() } // update childs recursively if (options && options.recurse === true) { if (this.childs) { this.childs.forEach(function (child) { - child.updateDom(options); - }); + child.updateDom(options) + }) } } @@ -2576,35 +2498,34 @@ Node.prototype.updateDom = function(options) { // update row with append button if (this.append) { - this.append.updateDom(); + this.append.updateDom() } // update "show more" text at the bottom of large arrays if (this.showMore) { - this.showMore.updateDom(); + this.showMore.updateDom() } -}; +} /** * Locate the JSON schema of the node and check for any enum type * @private */ Node.prototype._updateSchema = function () { - //Locating the schema of the node and checking for any enum type - if(this.editor && this.editor.options) { + // Locating the schema of the node and checking for any enum type + if (this.editor && this.editor.options) { // find the part of the json schema matching this nodes path this.schema = this.editor.options.schema - // fix childSchema with $ref, and not display the select element on the child schema because of not found enum - ? Node._findSchema(this.editor.options.schema, this.editor.options.schemaRefs || {}, this.getPath()) - : null; + // fix childSchema with $ref, and not display the select element on the child schema because of not found enum + ? Node._findSchema(this.editor.options.schema, this.editor.options.schemaRefs || {}, this.getPath()) + : null if (this.schema) { - this.enum = Node._findEnum(this.schema); - } - else { - delete this.enum; + this.enum = Node._findEnum(this.schema) + } else { + delete this.enum } } -}; +} /** * find an enum definition in a JSON schema, as property `enum` or inside @@ -2615,19 +2536,19 @@ Node.prototype._updateSchema = function () { */ Node._findEnum = function (schema) { if (schema.enum) { - return schema.enum; + return schema.enum } - var composite = schema.oneOf || schema.anyOf || schema.allOf; + var composite = schema.oneOf || schema.anyOf || schema.allOf if (composite) { - var match = composite.filter(function (entry) {return entry.enum}); + var match = composite.filter(function (entry) { return entry.enum }) if (match.length > 0) { - return match[0].enum; + return match[0].enum } } return null -}; +} /** * Return the part of a JSON schema matching given path. @@ -2638,62 +2559,59 @@ Node._findEnum = function (schema) { * @private */ Node._findSchema = function (schema, schemaRefs, path) { - var childSchema = schema; - var foundSchema = childSchema; + var childSchema = schema + var foundSchema = childSchema - var allSchemas = schema.oneOf || schema.anyOf || schema.allOf; + var allSchemas = schema.oneOf || schema.anyOf || schema.allOf if (!allSchemas) { - allSchemas = [schema]; + allSchemas = [schema] } for (var j = 0; j < allSchemas.length; j++) { - childSchema = allSchemas[j]; + childSchema = allSchemas[j] - if ('$ref' in childSchema && typeof childSchema['$ref'] === 'string') { - childSchema = schemaRefs[childSchema['$ref']]; + if ('$ref' in childSchema && typeof childSchema.$ref === 'string') { + childSchema = schemaRefs[childSchema.$ref] if (childSchema) { - foundSchema = Node._findSchema(childSchema, schemaRefs, path); + foundSchema = Node._findSchema(childSchema, schemaRefs, path) } } for (var i = 0; i < path.length && childSchema; i++) { - var nextPath = path.slice(i + 1, path.length); - var key = path[i]; + var nextPath = path.slice(i + 1, path.length) + var key = path[i] if (typeof key === 'string' && childSchema.patternProperties && !(childSchema.properties && key in childSchema.properties)) { for (var prop in childSchema.patternProperties) { if (key.match(prop)) { - foundSchema = Node._findSchema(childSchema.patternProperties[prop], schemaRefs, nextPath); + foundSchema = Node._findSchema(childSchema.patternProperties[prop], schemaRefs, nextPath) } } - } - else if (typeof key === 'string' && childSchema.properties) { + } else if (typeof key === 'string' && childSchema.properties) { if (!(key in childSchema.properties)) { - foundSchema = null; + foundSchema = null } else { - childSchema = childSchema.properties[key]; + childSchema = childSchema.properties[key] if (childSchema) { - foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath); + foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath) } } - } - else if (typeof key === 'number' && childSchema.items) { - childSchema = childSchema.items; + } else if (typeof key === 'number' && childSchema.items) { + childSchema = childSchema.items if (childSchema) { - foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath); + foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath) } } } - } // If the found schema is the input schema, the schema does not have the given path if (foundSchema === schema && path.length > 0) { - return null; + return null } return foundSchema -}; +} /** * Update the DOM of the childs of a node: update indexes and undefined field @@ -2702,65 +2620,61 @@ Node._findSchema = function (schema, schemaRefs, path) { * @private */ Node.prototype._updateDomIndexes = function () { - var domValue = this.dom.value; - var childs = this.childs; + var domValue = this.dom.value + var childs = this.childs if (domValue && childs) { - if (this.type == 'array') { + if (this.type === 'array') { childs.forEach(function (child, index) { - child.index = index; - var childField = child.dom.field; + child.index = index + var childField = child.dom.field if (childField) { - childField.innerHTML = index; + childField.innerHTML = index } - }); - } - else if (this.type == 'object') { + }) + } else if (this.type === 'object') { childs.forEach(function (child) { - if (child.index != undefined) { - delete child.index; + if (child.index !== undefined) { + delete child.index - if (child.field == undefined) { - child.field = ''; + if (child.field === undefined) { + child.field = '' } } - }); + }) } } -}; +} /** * Create an editable value * @private */ Node.prototype._createDomValue = function () { - var domValue; + var domValue - if (this.type == 'array') { - domValue = document.createElement('div'); - domValue.innerHTML = '[...]'; - } - else if (this.type == 'object') { - domValue = document.createElement('div'); - domValue.innerHTML = '{...}'; - } - else { + if (this.type === 'array') { + domValue = document.createElement('div') + domValue.innerHTML = '[...]' + } else if (this.type === 'object') { + domValue = document.createElement('div') + domValue.innerHTML = '{...}' + } else { if (!this.editable.value && util.isUrl(this.value)) { // create a link in case of read-only editor and value containing an url - domValue = document.createElement('a'); - domValue.href = this.value; - domValue.innerHTML = this._escapeHTML(this.value); - } - else { + domValue = document.createElement('a') + domValue.href = this.value + domValue.innerHTML = this._escapeHTML(this.value) + } else { // create an editable or read-only div - domValue = document.createElement('div'); - domValue.contentEditable = this.editable.value; - domValue.spellcheck = false; - domValue.innerHTML = this._escapeHTML(this.value); + domValue = document.createElement('div') + domValue.contentEditable = this.editable.value + domValue.spellcheck = false + domValue.innerHTML = this._escapeHTML(this.value) } } - return domValue; -}; + return domValue +} /** * Create an expand/collapse button @@ -2769,22 +2683,20 @@ Node.prototype._createDomValue = function () { */ Node.prototype._createDomExpandButton = function () { // create expand button - var expand = document.createElement('button'); - expand.type = 'button'; + var expand = document.createElement('button') + expand.type = 'button' if (this._hasChilds()) { expand.className = this.expanded - ? 'jsoneditor-button jsoneditor-expanded' - : 'jsoneditor-button jsoneditor-collapsed'; - expand.title = translate('expandTitle'); - } - else { - expand.className = 'jsoneditor-button jsoneditor-invisible'; - expand.title = ''; + ? 'jsoneditor-button jsoneditor-expanded' + : 'jsoneditor-button jsoneditor-collapsed' + expand.title = translate('expandTitle') + } else { + expand.className = 'jsoneditor-button jsoneditor-invisible' + expand.title = '' } - return expand; -}; - + return expand +} /** * Create a DOM tree element, containing the expand/collapse button @@ -2792,246 +2704,243 @@ Node.prototype._createDomExpandButton = function () { * @private */ Node.prototype._createDomTree = function () { - var dom = this.dom; - var domTree = document.createElement('table'); - var tbody = document.createElement('tbody'); - domTree.style.borderCollapse = 'collapse'; // TODO: put in css - domTree.className = 'jsoneditor-values'; - domTree.appendChild(tbody); - var tr = document.createElement('tr'); - tbody.appendChild(tr); + var dom = this.dom + var domTree = document.createElement('table') + var tbody = document.createElement('tbody') + domTree.style.borderCollapse = 'collapse' // TODO: put in css + domTree.className = 'jsoneditor-values' + domTree.appendChild(tbody) + var tr = document.createElement('tr') + tbody.appendChild(tr) // create expand button - var tdExpand = document.createElement('td'); - tdExpand.className = 'jsoneditor-tree'; - tr.appendChild(tdExpand); - dom.expand = this._createDomExpandButton(); - tdExpand.appendChild(dom.expand); - dom.tdExpand = tdExpand; + var tdExpand = document.createElement('td') + tdExpand.className = 'jsoneditor-tree' + tr.appendChild(tdExpand) + dom.expand = this._createDomExpandButton() + tdExpand.appendChild(dom.expand) + dom.tdExpand = tdExpand // create the field - var tdField = document.createElement('td'); - tdField.className = 'jsoneditor-tree'; - tr.appendChild(tdField); - dom.field = this._createDomField(); - tdField.appendChild(dom.field); - dom.tdField = tdField; + var tdField = document.createElement('td') + tdField.className = 'jsoneditor-tree' + tr.appendChild(tdField) + dom.field = this._createDomField() + tdField.appendChild(dom.field) + dom.tdField = tdField // create a separator - var tdSeparator = document.createElement('td'); - tdSeparator.className = 'jsoneditor-tree'; - tr.appendChild(tdSeparator); - if (this.type != 'object' && this.type != 'array') { - tdSeparator.appendChild(document.createTextNode(':')); - tdSeparator.className = 'jsoneditor-separator'; + var tdSeparator = document.createElement('td') + tdSeparator.className = 'jsoneditor-tree' + tr.appendChild(tdSeparator) + if (this.type !== 'object' && this.type !== 'array') { + tdSeparator.appendChild(document.createTextNode(':')) + tdSeparator.className = 'jsoneditor-separator' } - dom.tdSeparator = tdSeparator; + dom.tdSeparator = tdSeparator // create the value - var tdValue = document.createElement('td'); - tdValue.className = 'jsoneditor-tree'; - tr.appendChild(tdValue); - dom.value = this._createDomValue(); - tdValue.appendChild(dom.value); - dom.tdValue = tdValue; + var tdValue = document.createElement('td') + tdValue.className = 'jsoneditor-tree' + tr.appendChild(tdValue) + dom.value = this._createDomValue() + tdValue.appendChild(dom.value) + dom.tdValue = tdValue - return domTree; -}; + return domTree +} /** * Handle an event. The event is caught centrally by the editor * @param {Event} event */ Node.prototype.onEvent = function (event) { - var type = event.type, - target = event.target || event.srcElement, - dom = this.dom, - node = this, - expandable = this._hasChilds(); - + var type = event.type + var target = event.target || event.srcElement + var dom = this.dom + var node = this + var expandable = this._hasChilds() if (typeof this.editor.options.onEvent === 'function') { - this._onEvent(event); + this._onEvent(event) } // check if mouse is on menu or on dragarea. // If so, highlight current row and its childs - if (target == dom.drag || target == dom.menu) { - if (type == 'mouseover') { - this.editor.highlighter.highlight(this); - } - else if (type == 'mouseout') { - this.editor.highlighter.unhighlight(); + if (target === dom.drag || target === dom.menu) { + if (type === 'mouseover') { + this.editor.highlighter.highlight(this) + } else if (type === 'mouseout') { + this.editor.highlighter.unhighlight() } } // context menu events - if (type == 'click' && target == dom.menu) { - var highlighter = node.editor.highlighter; - highlighter.highlight(node); - highlighter.lock(); - util.addClassName(dom.menu, 'jsoneditor-selected'); + if (type === 'click' && target === dom.menu) { + var highlighter = node.editor.highlighter + highlighter.highlight(node) + highlighter.lock() + util.addClassName(dom.menu, 'jsoneditor-selected') this.showContextMenu(dom.menu, function () { - util.removeClassName(dom.menu, 'jsoneditor-selected'); - highlighter.unlock(); - highlighter.unhighlight(); - }); + util.removeClassName(dom.menu, 'jsoneditor-selected') + highlighter.unlock() + highlighter.unhighlight() + }) } // expand events - if (type == 'click') { - if (target == dom.expand || + if (type === 'click') { + if (target === dom.expand || ((node.editor.options.mode === 'view' || node.editor.options.mode === 'form') && target.nodeName === 'DIV')) { if (expandable) { - var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all - this._onExpand(recurse); + var recurse = event.ctrlKey // with ctrl-key, expand/collapse all + this._onExpand(recurse) } } } if (type === 'click' && (event.target === node.dom.tdColor || event.target === node.dom.color)) { - this._showColorPicker(); + this._showColorPicker() } // swap the value of a boolean when the checkbox displayed left is clicked - if (type == 'change' && target == dom.checkbox) { - this.dom.value.innerHTML = !this.value; - this._getDomValue(); - this._updateDomDefault(); + if (type === 'change' && target === dom.checkbox) { + this.dom.value.innerHTML = !this.value + this._getDomValue() + this._updateDomDefault() } // update the value of the node based on the selected option - if (type == 'change' && target == dom.select) { - this.dom.value.innerHTML = dom.select.value; - this._getDomValue(); - this._updateDomValue(); + if (type === 'change' && target === dom.select) { + this.dom.value.innerHTML = dom.select.value + this._getDomValue() + this._updateDomValue() } // value events - var domValue = dom.value; - if (target == domValue) { - //noinspection FallthroughInSwitchStatementJS + var domValue = dom.value + if (target === domValue) { + // noinspection FallthroughInSwitchStatementJS switch (type) { case 'blur': case 'change': - this._getDomValue(); - this._clearValueError(); - this._updateDomValue(); + this._getDomValue() + this._clearValueError() + this._updateDomValue() if (this.value) { - domValue.innerHTML = this._escapeHTML(this.value); + domValue.innerHTML = this._escapeHTML(this.value) } - break; + break case 'input': - //this._debouncedGetDomValue(true); // TODO - this._getDomValue(); - this._updateDomValue(); - break; + // this._debouncedGetDomValue(true); // TODO + this._getDomValue() + this._updateDomValue() + break case 'keydown': case 'mousedown': - // TODO: cleanup - this.editor.selection = this.editor.getDomSelection(); - break; + // TODO: cleanup + this.editor.selection = this.editor.getDomSelection() + break case 'click': if (event.ctrlKey && this.editable.value) { // if read-only, we use the regular click behavior of an anchor if (util.isUrl(this.value)) { - event.preventDefault(); - window.open(this.value, '_blank'); + event.preventDefault() + window.open(this.value, '_blank') } } - break; + break case 'keyup': - //this._debouncedGetDomValue(true); // TODO - this._getDomValue(); - this._updateDomValue(); - break; + // this._debouncedGetDomValue(true); // TODO + this._getDomValue() + this._updateDomValue() + break case 'cut': case 'paste': setTimeout(function () { - node._getDomValue(); - node._updateDomValue(); - }, 1); - break; + node._getDomValue() + node._updateDomValue() + }, 1) + break } } // field events - var domField = dom.field; - if (target == domField) { + var domField = dom.field + if (target === domField) { switch (type) { case 'blur': - this._getDomField(true); - this._updateDomField(); + this._getDomField(true) + this._updateDomField() if (this.field) { - domField.innerHTML = this._escapeHTML(this.field); + domField.innerHTML = this._escapeHTML(this.field) } - break; + break case 'input': - this._getDomField(); - this._updateSchema(); - this._updateDomField(); - this._updateDomValue(); - break; + this._getDomField() + this._updateSchema() + this._updateDomField() + this._updateDomValue() + break case 'keydown': case 'mousedown': - this.editor.selection = this.editor.getDomSelection(); - break; + this.editor.selection = this.editor.getDomSelection() + break case 'keyup': - this._getDomField(); - this._updateDomField(); - break; + this._getDomField() + this._updateDomField() + break case 'cut': case 'paste': setTimeout(function () { - node._getDomField(); - node._updateDomField(); - }, 1); - break; + node._getDomField() + node._updateDomField() + }, 1) + break } } // focus // when clicked in whitespace left or right from the field or value, set focus - var domTree = dom.tree; - if (domTree && target == domTree.parentNode && type == 'click' && !event.hasMoved) { - var left = (event.offsetX != undefined) ? - (event.offsetX < (this.getLevel() + 1) * 24) : - (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF + var domTree = dom.tree + if (domTree && target === domTree.parentNode && type === 'click' && !event.hasMoved) { + var left = (event.offsetX !== undefined) + ? (event.offsetX < (this.getLevel() + 1) * 24) + : (event.pageX < util.getAbsoluteLeft(dom.tdSeparator))// for FF if (left || expandable) { // node is expandable when it is an object or array if (domField) { - util.setEndOfContentEditable(domField); - domField.focus(); + util.setEndOfContentEditable(domField) + domField.focus() } - } - else { + } else { if (domValue && !this.enum) { - util.setEndOfContentEditable(domValue); - domValue.focus(); + util.setEndOfContentEditable(domValue) + domValue.focus() } } } - if (((target == dom.tdExpand && !expandable) || target == dom.tdField || target == dom.tdSeparator) && - (type == 'click' && !event.hasMoved)) { + if (((target === dom.tdExpand && !expandable) || target === dom.tdField || target === dom.tdSeparator) && + (type === 'click' && !event.hasMoved)) { if (domField) { - util.setEndOfContentEditable(domField); - domField.focus(); + util.setEndOfContentEditable(domField) + domField.focus() } } - if (type == 'keydown') { - this.onKeyDown(event); + if (type === 'keydown') { + this.onKeyDown(event) } -}; +} /** * Trigger external onEvent provided in options if node is a JSON field or @@ -3043,161 +2952,148 @@ Node.prototype.onEvent = function (event) { * @private */ Node.prototype._onEvent = function (event) { - var element = event.target; + var element = event.target if (element === this.dom.field || element === this.dom.value) { var info = { field: this.getField(), path: this.getPath() - }; - // For leaf values, include value - if (!this._hasChilds() &&element === this.dom.value) { - info.value = this.getValue(); } - this.editor.options.onEvent(info, event); + // For leaf values, include value + if (!this._hasChilds() && element === this.dom.value) { + info.value = this.getValue() + } + this.editor.options.onEvent(info, event) } -}; +} /** * Key down event handler * @param {Event} event */ Node.prototype.onKeyDown = function (event) { - var keynum = event.which || event.keyCode; - var target = event.target || event.srcElement; - var ctrlKey = event.ctrlKey; - var shiftKey = event.shiftKey; - var altKey = event.altKey; - var handled = false; - var prevNode, nextNode, nextDom, nextDom2; - var editable = this.editor.options.mode === 'tree'; - var oldSelection; - var oldNextNode; - var oldParent; - var oldIndexRedo; - var newIndexRedo; - var oldParentPathRedo; - var newParentPathRedo; - var nodes; - var multiselection; + var keynum = event.which || event.keyCode + var target = event.target || event.srcElement + var ctrlKey = event.ctrlKey + var shiftKey = event.shiftKey + var altKey = event.altKey + var handled = false + var prevNode, nextNode, nextDom, nextDom2 + var editable = this.editor.options.mode === 'tree' + var oldSelection + var oldNextNode + var oldParent + var oldIndexRedo + var newIndexRedo + var oldParentPathRedo + var newParentPathRedo + var nodes + var multiselection var selectedNodes = this.editor.multiselection.nodes.length > 0 - ? this.editor.multiselection.nodes - : [this]; - var firstNode = selectedNodes[0]; - var lastNode = selectedNodes[selectedNodes.length - 1]; + ? this.editor.multiselection.nodes + : [this] + var firstNode = selectedNodes[0] + var lastNode = selectedNodes[selectedNodes.length - 1] // console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup - if (keynum == 13) { // Enter - if (target == this.dom.value) { + if (keynum === 13) { // Enter + if (target === this.dom.value) { if (!this.editable.value || event.ctrlKey) { if (util.isUrl(this.value)) { - window.open(this.value, '_blank'); - handled = true; + window.open(this.value, '_blank') + handled = true } } - } - else if (target == this.dom.expand) { - var expandable = this._hasChilds(); + } else if (target === this.dom.expand) { + var expandable = this._hasChilds() if (expandable) { - var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all - this._onExpand(recurse); - target.focus(); - handled = true; + var recurse = event.ctrlKey // with ctrl-key, expand/collapse all + this._onExpand(recurse) + target.focus() + handled = true } } - } - else if (keynum == 68) { // D - if (ctrlKey && editable) { // Ctrl+D - Node.onDuplicate(selectedNodes); - handled = true; + } else if (keynum === 68) { // D + if (ctrlKey && editable) { // Ctrl+D + Node.onDuplicate(selectedNodes) + handled = true } - } - else if (keynum == 69) { // E - if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E - this._onExpand(shiftKey); // recurse = shiftKey - target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline) - handled = true; + } else if (keynum === 69) { // E + if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E + this._onExpand(shiftKey) // recurse = shiftKey + target.focus() // TODO: should restore focus in case of recursing expand (which takes DOM offline) + handled = true } - } - else if (keynum == 77 && editable) { // M + } else if (keynum === 77 && editable) { // M if (ctrlKey) { // Ctrl+M - this.showContextMenu(target); - handled = true; + this.showContextMenu(target) + handled = true } - } - else if (keynum == 46 && editable) { // Del - if (ctrlKey) { // Ctrl+Del - Node.onRemove(selectedNodes); - handled = true; + } else if (keynum === 46 && editable) { // Del + if (ctrlKey) { // Ctrl+Del + Node.onRemove(selectedNodes) + handled = true } - } - else if (keynum == 45 && editable) { // Ins - if (ctrlKey && !shiftKey) { // Ctrl+Ins - this._onInsertBefore(); - handled = true; + } else if (keynum === 45 && editable) { // Ins + if (ctrlKey && !shiftKey) { // Ctrl+Ins + this._onInsertBefore() + handled = true + } else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins + this._onInsertAfter() + handled = true } - else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins - this._onInsertAfter(); - handled = true; - } - } - else if (keynum == 35) { // End + } else if (keynum === 35) { // End if (altKey) { // Alt+End // find the last node - var endNode = this._lastNode(); + var endNode = this._lastNode() if (endNode) { - endNode.focus(Node.focusElement || this._getElementName(target)); + endNode.focus(Node.focusElement || this._getElementName(target)) } - handled = true; + handled = true } - } - else if (keynum == 36) { // Home + } else if (keynum === 36) { // Home if (altKey) { // Alt+Home // find the first node - var homeNode = this._firstNode(); + var homeNode = this._firstNode() if (homeNode) { - homeNode.focus(Node.focusElement || this._getElementName(target)); + homeNode.focus(Node.focusElement || this._getElementName(target)) } - handled = true; + handled = true } - } - else if (keynum == 37) { // Arrow Left - if (altKey && !shiftKey) { // Alt + Arrow Left + } else if (keynum === 37) { // Arrow Left + if (altKey && !shiftKey) { // Alt + Arrow Left // move to left element - var prevElement = this._previousElement(target); + var prevElement = this._previousElement(target) if (prevElement) { - this.focus(this._getElementName(prevElement)); + this.focus(this._getElementName(prevElement)) } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow left + handled = true + } else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow left if (lastNode.expanded) { - var appendDom = lastNode.getAppendDom(); - nextDom = appendDom ? appendDom.nextSibling : undefined; - } - else { - var dom = lastNode.getDom(); - nextDom = dom.nextSibling; + var appendDom = lastNode.getAppendDom() + nextDom = appendDom ? appendDom.nextSibling : undefined + } else { + var dom = lastNode.getDom() + nextDom = dom.nextSibling } if (nextDom) { - nextNode = Node.getNodeFromTarget(nextDom); - nextDom2 = nextDom.nextSibling; - nextNode2 = Node.getNodeFromTarget(nextDom2); + nextNode = Node.getNodeFromTarget(nextDom) + nextDom2 = nextDom.nextSibling + const nextNode2 = Node.getNodeFromTarget(nextDom2) if (nextNode && nextNode instanceof AppendNode && - !(lastNode.parent.childs.length == 1) && + !(lastNode.parent.childs.length === 1) && nextNode2 && nextNode2.parent) { - oldSelection = this.editor.getDomSelection(); - oldParent = firstNode.parent; - oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append; - oldIndexRedo = firstNode.getIndex(); - newIndexRedo = nextNode2.getIndex(); - oldParentPathRedo = oldParent.getInternalPath(); - newParentPathRedo = nextNode2.parent.getInternalPath(); + oldSelection = this.editor.getDomSelection() + oldParent = firstNode.parent + oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append + oldIndexRedo = firstNode.getIndex() + newIndexRedo = nextNode2.getIndex() + oldParentPathRedo = oldParent.getInternalPath() + newParentPathRedo = nextNode2.parent.getInternalPath() selectedNodes.forEach(function (node) { - nextNode2.parent.moveBefore(node, nextNode2); - }); - this.focus(Node.focusElement || this._getElementName(target)); - + nextNode2.parent.moveBefore(node, nextNode2) + }) + this.focus(Node.focusElement || this._getElementName(target)) this.editor._onAction('moveNodes', { count: selectedNodes.length, @@ -3215,51 +3111,48 @@ Node.prototype.onKeyDown = function (event) { oldSelection: oldSelection, newSelection: this.editor.getDomSelection() - }); + }) } } } - } - else if (keynum == 38) { // Arrow Up - if (altKey && !shiftKey) { // Alt + Arrow Up + } else if (keynum === 38) { // Arrow Up + if (altKey && !shiftKey) { // Alt + Arrow Up // find the previous node - prevNode = this._previousNode(); + prevNode = this._previousNode() if (prevNode) { - this.editor.deselect(true); - prevNode.focus(Node.focusElement || this._getElementName(target)); + this.editor.deselect(true) + prevNode.focus(Node.focusElement || this._getElementName(target)) } - handled = true; - } - else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Up + handled = true + } else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Up // select multiple nodes - prevNode = this._previousNode(); + prevNode = this._previousNode() if (prevNode) { - multiselection = this.editor.multiselection; - multiselection.start = multiselection.start || this; - multiselection.end = prevNode; - nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + multiselection = this.editor.multiselection + multiselection.start = multiselection.start || this + multiselection.end = prevNode + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end) - this.editor.select(nodes); - prevNode.focus('field'); // select field as we know this always exists + this.editor.select(nodes) + prevNode.focus('field') // select field as we know this always exists } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Up + handled = true + } else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Up // find the previous node - prevNode = firstNode._previousNode(); + prevNode = firstNode._previousNode() if (prevNode && prevNode.parent) { - oldSelection = this.editor.getDomSelection(); - oldParent = firstNode.parent; - oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append; - oldIndexRedo = firstNode.getIndex(); - newIndexRedo = prevNode.getIndex(); - oldParentPathRedo = oldParent.getInternalPath(); - newParentPathRedo = prevNode.parent.getInternalPath(); + oldSelection = this.editor.getDomSelection() + oldParent = firstNode.parent + oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append + oldIndexRedo = firstNode.getIndex() + newIndexRedo = prevNode.getIndex() + oldParentPathRedo = oldParent.getInternalPath() + newParentPathRedo = prevNode.parent.getInternalPath() selectedNodes.forEach(function (node) { - prevNode.parent.moveBefore(node, prevNode); - }); - this.focus(Node.focusElement || this._getElementName(target)); + prevNode.parent.moveBefore(node, prevNode) + }) + this.focus(Node.focusElement || this._getElementName(target)) this.editor._onAction('moveNodes', { count: selectedNodes.length, @@ -3277,38 +3170,36 @@ Node.prototype.onKeyDown = function (event) { oldSelection: oldSelection, newSelection: this.editor.getDomSelection() - }); + }) } - handled = true; + handled = true } - } - else if (keynum == 39) { // Arrow Right - if (altKey && !shiftKey) { // Alt + Arrow Right + } else if (keynum === 39) { // Arrow Right + if (altKey && !shiftKey) { // Alt + Arrow Right // move to right element - var nextElement = this._nextElement(target); + var nextElement = this._nextElement(target) if (nextElement) { - this.focus(this._getElementName(nextElement)); + this.focus(this._getElementName(nextElement)) } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Right - dom = firstNode.getDom(); - var prevDom = dom.previousSibling; + handled = true + } else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Right + dom = firstNode.getDom() + var prevDom = dom.previousSibling if (prevDom) { - prevNode = Node.getNodeFromTarget(prevDom); + prevNode = Node.getNodeFromTarget(prevDom) if (prevNode && prevNode.parent && !prevNode.isVisible()) { - oldSelection = this.editor.getDomSelection(); - oldParent = firstNode.parent; - oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append; - oldIndexRedo = firstNode.getIndex(); - newIndexRedo = prevNode.getIndex(); - oldParentPathRedo = oldParent.getInternalPath(); - newParentPathRedo = prevNode.parent.getInternalPath(); + oldSelection = this.editor.getDomSelection() + oldParent = firstNode.parent + oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append + oldIndexRedo = firstNode.getIndex() + newIndexRedo = prevNode.getIndex() + oldParentPathRedo = oldParent.getInternalPath() + newParentPathRedo = prevNode.parent.getInternalPath() selectedNodes.forEach(function (node) { - prevNode.parent.moveBefore(node, prevNode); - }); - this.focus(Node.focusElement || this._getElementName(target)); + prevNode.parent.moveBefore(node, prevNode) + }) + this.focus(Node.focusElement || this._getElementName(target)) this.editor._onAction('moveNodes', { count: selectedNodes.length, @@ -3326,67 +3217,63 @@ Node.prototype.onKeyDown = function (event) { oldSelection: oldSelection, newSelection: this.editor.getDomSelection() - }); + }) } } } - } - else if (keynum == 40) { // Arrow Down - if (altKey && !shiftKey) { // Alt + Arrow Down + } else if (keynum === 40) { // Arrow Down + if (altKey && !shiftKey) { // Alt + Arrow Down // find the next node - nextNode = this._nextNode(); + nextNode = this._nextNode() if (nextNode) { - this.editor.deselect(true); - nextNode.focus(Node.focusElement || this._getElementName(target)); + this.editor.deselect(true) + nextNode.focus(Node.focusElement || this._getElementName(target)) } - handled = true; - } - else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Down + handled = true + } else if (!altKey && ctrlKey && shiftKey && editable) { // Ctrl + Shift + Arrow Down // select multiple nodes - nextNode = this._nextNode(); + nextNode = this._nextNode() if (nextNode) { - multiselection = this.editor.multiselection; - multiselection.start = multiselection.start || this; - multiselection.end = nextNode; - nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end); + multiselection = this.editor.multiselection + multiselection.start = multiselection.start || this + multiselection.end = nextNode + nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end) - this.editor.select(nodes); - nextNode.focus('field'); // select field as we know this always exists + this.editor.select(nodes) + nextNode.focus('field') // select field as we know this always exists } - handled = true; - } - else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down + handled = true + } else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down // find the 2nd next node and move before that one if (lastNode.expanded) { - nextNode = lastNode.append ? lastNode.append._nextNode() : undefined; - } - else { - nextNode = lastNode._nextNode(); + nextNode = lastNode.append ? lastNode.append._nextNode() : undefined + } else { + nextNode = lastNode._nextNode() } // when the next node is not visible, we've reached the "showMore" buttons if (nextNode && !nextNode.isVisible()) { - nextNode = nextNode.parent.showMore; + nextNode = nextNode.parent.showMore } if (nextNode && nextNode instanceof AppendNode) { - nextNode = lastNode; + nextNode = lastNode } - var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append); + const nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append) if (nextNode2 && nextNode2.parent) { - oldSelection = this.editor.getDomSelection(); - oldParent = firstNode.parent; - oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append; - oldIndexRedo = firstNode.getIndex(); - newIndexRedo = nextNode2.getIndex(); - oldParentPathRedo = oldParent.getInternalPath(); - newParentPathRedo = nextNode2.parent.getInternalPath(); + oldSelection = this.editor.getDomSelection() + oldParent = firstNode.parent + oldNextNode = oldParent.childs[lastNode.getIndex() + 1] || oldParent.append + oldIndexRedo = firstNode.getIndex() + newIndexRedo = nextNode2.getIndex() + oldParentPathRedo = oldParent.getInternalPath() + newParentPathRedo = nextNode2.parent.getInternalPath() selectedNodes.forEach(function (node) { - nextNode2.parent.moveBefore(node, nextNode2); - }); - this.focus(Node.focusElement || this._getElementName(target)); + nextNode2.parent.moveBefore(node, nextNode2) + }) + this.focus(Node.focusElement || this._getElementName(target)) this.editor._onAction('moveNodes', { count: selectedNodes.length, @@ -3401,17 +3288,17 @@ Node.prototype.onKeyDown = function (event) { newIndex: firstNode.getIndex(), oldSelection: oldSelection, newSelection: this.editor.getDomSelection() - }); + }) } - handled = true; + handled = true } } if (handled) { - event.preventDefault(); - event.stopPropagation(); + event.preventDefault() + event.stopPropagation() } -}; +} /** * Handle the expand event, when clicked on the expand button @@ -3421,25 +3308,24 @@ Node.prototype.onKeyDown = function (event) { Node.prototype._onExpand = function (recurse) { if (recurse) { // Take the table offline - var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this - var frame = table.parentNode; - var scrollTop = frame.scrollTop; - frame.removeChild(table); + var table = this.dom.tr.parentNode // TODO: not nice to access the main table like this + var frame = table.parentNode + var scrollTop = frame.scrollTop + frame.removeChild(table) } if (this.expanded) { - this.collapse(recurse); - } - else { - this.expand(recurse); + this.collapse(recurse) + } else { + this.expand(recurse) } if (recurse) { // Put the table online again - frame.appendChild(table); - frame.scrollTop = scrollTop; + frame.appendChild(table) + frame.scrollTop = scrollTop } -}; +} /** * Open a color picker to select a new color @@ -3447,26 +3333,26 @@ Node.prototype._onExpand = function (recurse) { */ Node.prototype._showColorPicker = function () { if (typeof this.editor.options.onColorPicker === 'function' && this.dom.color) { - var node = this; + var node = this // force deleting current color picker (if any) - node._deleteDomColor(); - node.updateDom(); + node._deleteDomColor() + node.updateDom() - var colorAnchor = createAbsoluteAnchor(this.dom.color, this.editor.frame); + var colorAnchor = createAbsoluteAnchor(this.dom.color, this.editor.frame) - this.editor.options.onColorPicker(colorAnchor, this.value, function onChange(value) { + this.editor.options.onColorPicker(colorAnchor, this.value, function onChange (value) { if (typeof value === 'string' && value !== node.value) { // force recreating the color block, to cleanup any attached color picker - node._deleteDomColor(); + node._deleteDomColor() - node.value = value; - node.updateDom(); - node._debouncedOnChangeValue(); + node.value = value + node.updateDom() + node._debouncedOnChangeValue() } - }); + }) } -}; +} /** * Get all field names of an object @@ -3476,45 +3362,45 @@ Node.prototype._showColorPicker = function () { Node.prototype.getFieldNames = function (excludeNode) { if (this.type === 'object') { return this.childs - .filter(function (child) { - return child !== excludeNode; - }) - .map(function (child) { - return child.field; - }); + .filter(function (child) { + return child !== excludeNode + }) + .map(function (child) { + return child.field + }) } - return []; + return [] } /** * Remove nodes * @param {Node[] | Node} nodes */ -Node.onRemove = function(nodes) { +Node.onRemove = function (nodes) { if (!Array.isArray(nodes)) { - return Node.onRemove([nodes]); + return Node.onRemove([nodes]) } if (nodes && nodes.length > 0) { - var firstNode = nodes[0]; - var parent = firstNode.parent; - var editor = firstNode.editor; - var firstIndex = firstNode.getIndex(); - editor.highlighter.unhighlight(); + var firstNode = nodes[0] + var parent = firstNode.parent + var editor = firstNode.editor + var firstIndex = firstNode.getIndex() + editor.highlighter.unhighlight() // adjust the focus - var oldSelection = editor.getDomSelection(); - Node.blurNodes(nodes); - var newSelection = editor.getDomSelection(); + var oldSelection = editor.getDomSelection() + Node.blurNodes(nodes) + var newSelection = editor.getDomSelection() // store the paths before removing them (needed for history) - var paths = nodes.map(getInternalPath); + var paths = nodes.map(getInternalPath) // remove the nodes nodes.forEach(function (node) { - node.parent._remove(node); - }); + node.parent._remove(node) + }) // store history action editor._onAction('removeNodes', { @@ -3524,58 +3410,55 @@ Node.onRemove = function(nodes) { index: firstIndex, oldSelection: oldSelection, newSelection: newSelection - }); + }) } -}; - +} /** * Duplicate nodes * duplicated nodes will be added right after the original nodes * @param {Node[] | Node} nodes */ -Node.onDuplicate = function(nodes) { +Node.onDuplicate = function (nodes) { if (!Array.isArray(nodes)) { - return Node.onDuplicate([nodes]); + return Node.onDuplicate([nodes]) } if (nodes && nodes.length > 0) { - var lastNode = nodes[nodes.length - 1]; - var parent = lastNode.parent; - var editor = lastNode.editor; + var lastNode = nodes[nodes.length - 1] + var parent = lastNode.parent + var editor = lastNode.editor - editor.deselect(editor.multiselection.nodes); + editor.deselect(editor.multiselection.nodes) // duplicate the nodes - var oldSelection = editor.getDomSelection(); - var afterNode = lastNode; + var oldSelection = editor.getDomSelection() + var afterNode = lastNode var clones = nodes.map(function (node) { - var clone = node.clone(); + var clone = node.clone() if (node.parent.type === 'object') { - var existingFieldNames = node.parent.getFieldNames(); - clone.field = util.findUniqueName(node.field, existingFieldNames); + var existingFieldNames = node.parent.getFieldNames() + clone.field = util.findUniqueName(node.field, existingFieldNames) } - parent.insertAfter(clone, afterNode); - afterNode = clone; - return clone; - }); + parent.insertAfter(clone, afterNode) + afterNode = clone + return clone + }) // set selection to the duplicated nodes if (nodes.length === 1) { if (clones[0].parent.type === 'object') { // when duplicating a single object property, // set focus to the field and keep the original field name - clones[0].dom.field.innerHTML = nodes[0].field; - clones[0].focus('field'); - } - else { - clones[0].focus(); + clones[0].dom.field.innerHTML = nodes[0].field + clones[0].focus('field') + } else { + clones[0].focus() } + } else { + editor.select(clones) } - else { - editor.select(clones); - } - var newSelection = editor.getDomSelection(); + var newSelection = editor.getDomSelection() editor._onAction('duplicateNodes', { paths: nodes.map(getInternalPath), @@ -3584,9 +3467,9 @@ Node.onDuplicate = function(nodes) { parentPath: parent.getInternalPath(), oldSelection: oldSelection, newSelection: newSelection - }); + }) } -}; +} /** * Handle insert before event @@ -3596,21 +3479,21 @@ Node.onDuplicate = function(nodes) { * @private */ Node.prototype._onInsertBefore = function (field, value, type) { - var oldSelection = this.editor.getDomSelection(); + var oldSelection = this.editor.getDomSelection() var newNode = new Node(this.editor, { - field: (field != undefined) ? field : '', - value: (value != undefined) ? value : '', + field: (field !== undefined) ? field : '', + value: (value !== undefined) ? value : '', type: type - }); - newNode.expand(true); + }) + newNode.expand(true) - var beforePath = this.getInternalPath(); + var beforePath = this.getInternalPath() - this.parent.insertBefore(newNode, this); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getDomSelection(); + this.parent.insertBefore(newNode, this) + this.editor.highlighter.unhighlight() + newNode.focus('field') + var newSelection = this.editor.getDomSelection() this.editor._onAction('insertBeforeNodes', { nodes: [newNode], @@ -3619,8 +3502,8 @@ Node.prototype._onInsertBefore = function (field, value, type) { parentPath: this.parent.getInternalPath(), oldSelection: oldSelection, newSelection: newSelection - }); -}; + }) +} /** * Handle insert after event @@ -3630,18 +3513,18 @@ Node.prototype._onInsertBefore = function (field, value, type) { * @private */ Node.prototype._onInsertAfter = function (field, value, type) { - var oldSelection = this.editor.getDomSelection(); + var oldSelection = this.editor.getDomSelection() var newNode = new Node(this.editor, { - field: (field != undefined) ? field : '', - value: (value != undefined) ? value : '', + field: (field !== undefined) ? field : '', + value: (value !== undefined) ? value : '', type: type - }); - newNode.expand(true); - this.parent.insertAfter(newNode, this); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getDomSelection(); + }) + newNode.expand(true) + this.parent.insertAfter(newNode, this) + this.editor.highlighter.unhighlight() + newNode.focus('field') + var newSelection = this.editor.getDomSelection() this.editor._onAction('insertAfterNodes', { nodes: [newNode], @@ -3650,8 +3533,8 @@ Node.prototype._onInsertAfter = function (field, value, type) { parentPath: this.parent.getInternalPath(), oldSelection: oldSelection, newSelection: newSelection - }); -}; + }) +} /** * Handle append event @@ -3661,18 +3544,18 @@ Node.prototype._onInsertAfter = function (field, value, type) { * @private */ Node.prototype._onAppend = function (field, value, type) { - var oldSelection = this.editor.getDomSelection(); + var oldSelection = this.editor.getDomSelection() var newNode = new Node(this.editor, { - field: (field != undefined) ? field : '', - value: (value != undefined) ? value : '', + field: (field !== undefined) ? field : '', + value: (value !== undefined) ? value : '', type: type - }); - newNode.expand(true); - this.parent.appendChild(newNode); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getDomSelection(); + }) + newNode.expand(true) + this.parent.appendChild(newNode) + this.editor.highlighter.unhighlight() + newNode.focus('field') + var newSelection = this.editor.getDomSelection() this.editor._onAction('appendNodes', { nodes: [newNode], @@ -3680,8 +3563,8 @@ Node.prototype._onAppend = function (field, value, type) { parentPath: this.parent.getInternalPath(), oldSelection: oldSelection, newSelection: newSelection - }); -}; + }) +} /** * Change the type of the node's value @@ -3689,11 +3572,11 @@ Node.prototype._onAppend = function (field, value, type) { * @private */ Node.prototype._onChangeType = function (newType) { - var oldType = this.type; - if (newType != oldType) { - var oldSelection = this.editor.getDomSelection(); - this.changeType(newType); - var newSelection = this.editor.getDomSelection(); + var oldType = this.type + if (newType !== oldType) { + var oldSelection = this.editor.getDomSelection() + this.changeType(newType) + var newSelection = this.editor.getDomSelection() this.editor._onAction('changeType', { path: this.getInternalPath(), @@ -3701,9 +3584,9 @@ Node.prototype._onChangeType = function (newType) { newType: newType, oldSelection: oldSelection, newSelection: newSelection - }); + }) } -}; +} /** * Sort the child's of the node. Only applicable when the node has type 'object' @@ -3714,78 +3597,77 @@ Node.prototype._onChangeType = function (newType) { */ Node.prototype.sort = function (path, direction) { if (typeof path === 'string') { - path = util.parsePath(path); + path = util.parsePath(path) } if (!this._hasChilds()) { - return; + return } - this.hideChilds(); // sorting is faster when the childs are not attached to the dom + this.hideChilds() // sorting is faster when the childs are not attached to the dom // copy the childs array (the old one will be kept for an undo action - var oldChilds = this.childs; - this.childs = this.childs.concat(); + var oldChilds = this.childs + this.childs = this.childs.concat() // sort the childs array - var order = (direction === 'desc') ? -1 : 1; + var order = (direction === 'desc') ? -1 : 1 if (this.type === 'object') { this.childs.sort(function (a, b) { - return order * naturalSort(a.field, b.field); - }); - } - else { // this.type === 'array' + return order * naturalSort(a.field, b.field) + }) + } else { // this.type === 'array' this.childs.sort(function (a, b) { - var nodeA = a.getNestedChild(path); - var nodeB = b.getNestedChild(path); + var nodeA = a.getNestedChild(path) + var nodeB = b.getNestedChild(path) if (!nodeA) { - return order; + return order } if (!nodeB) { - return -order; + return -order } - var valueA = nodeA.value; - var valueB = nodeB.value; + var valueA = nodeA.value + var valueB = nodeB.value if (typeof valueA !== 'string' && typeof valueB !== 'string') { // both values are a number, boolean, or null -> use simple, fast sorting - return valueA > valueB ? order : valueA < valueB ? -order : 0; + return valueA > valueB ? order : valueA < valueB ? -order : 0 } - return order * naturalSort(valueA, valueB); - }); + return order * naturalSort(valueA, valueB) + }) } // update the index numbering - this._updateDomIndexes(); + this._updateDomIndexes() this.editor._onAction('sort', { path: this.getInternalPath(), oldChilds: oldChilds, newChilds: this.childs - }); + }) - this.showChilds(); -}; + this.showChilds() +} /** * Replace the value of the node, keep it's state * @param {*} newValue */ Node.prototype.update = function (newValue) { - var oldValue = this.getInternalValue(); + var oldValue = this.getInternalValue() - this.setValue(newValue); + this.setValue(newValue) this.editor._onAction('transform', { path: this.getInternalPath(), oldValue: oldValue, newValue: this.getInternalValue() - }); -}; + }) +} /** * Remove this node from the DOM @@ -3795,23 +3677,22 @@ Node.prototype.update = function (newValue) { * @private */ Node.prototype._detachFromDom = function () { - var table = this.dom.tr ? this.dom.tr.parentNode : undefined; - var lastTr; + var table = this.dom.tr ? this.dom.tr.parentNode : undefined + var lastTr if (this.expanded) { - lastTr = this.getAppendDom(); + lastTr = this.getAppendDom() + } else { + lastTr = this.getDom() } - else { - lastTr = this.getDom(); - } - var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined; + var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined - this.hide({ resetVisibleChilds: false }); + this.hide({ resetVisibleChilds: false }) return { table: table, nextTr: nextTr } -}; +} /** * Attach this node to the DOM again @@ -3822,17 +3703,16 @@ Node.prototype._detachFromDom = function () { Node.prototype._attachToDom = function (domAnchor) { if (domAnchor.table) { if (domAnchor.nextTr) { - domAnchor.table.insertBefore(this.getDom(), domAnchor.nextTr); - } - else { - domAnchor.table.appendChild(this.getDom()); + domAnchor.table.insertBefore(this.getDom(), domAnchor.nextTr) + } else { + domAnchor.table.appendChild(this.getDom()) } } if (this.expanded) { - this.showChilds(); + this.showChilds() } -}; +} /** * Transform the node given a JMESPath query. @@ -3841,60 +3721,57 @@ Node.prototype._attachToDom = function (domAnchor) { */ Node.prototype.transform = function (query) { if (!this._hasChilds()) { - return; + return } - this.hideChilds(); // sorting is faster when the childs are not attached to the dom + this.hideChilds() // sorting is faster when the childs are not attached to the dom try { - var oldInternalValue = this.getInternalValue(); + var oldInternalValue = this.getInternalValue() // apply the JMESPath query - var oldValue = this.getValue(); - var newValue = jmespath.search(oldValue, query); - this.setValue(newValue); + var oldValue = this.getValue() + var newValue = jmespath.search(oldValue, query) + this.setValue(newValue) - var newInternalValue = this.getInternalValue(); + var newInternalValue = this.getInternalValue() this.editor._onAction('transform', { path: this.getInternalPath(), oldValue: oldInternalValue, newValue: newInternalValue - }); + }) - this.showChilds(); - } - catch (err) { - this.showChilds(); + this.showChilds() + } catch (err) { + this.showChilds() - this.editor._onError(err); + this.editor._onError(err) } -}; +} /** * Make this object the root object of the ditor */ Node.prototype.extract = function () { - this.editor.node.hideChilds(); - this.hideChilds(); + this.editor.node.hideChilds() + this.hideChilds() try { - var oldInternalValue = this.editor.node.getInternalValue(); - this.editor._setRoot(this); - var newInternalValue = this.editor.node.getInternalValue(); + var oldInternalValue = this.editor.node.getInternalValue() + this.editor._setRoot(this) + var newInternalValue = this.editor.node.getInternalValue() this.editor._onAction('transform', { path: this.editor.node.getInternalPath(), oldValue: oldInternalValue, newValue: newInternalValue - }); - } - catch (err) { - this.editor._onError(err); - } - finally { - this.updateDom({ recurse: true }); - this.showChilds(); + }) + } catch (err) { + this.editor._onError(err) + } finally { + this.updateDom({ recurse: true }) + this.showChilds() } } @@ -3904,31 +3781,31 @@ Node.prototype.extract = function () { * @returns {Node} */ Node.prototype.getNestedChild = function (path) { - var i = 0; - var child = this; + var i = 0 + var child = this while (child && i < path.length) { - child = child.findChildByProperty(path[i]); - i++; + child = child.findChildByProperty(path[i]) + i++ } - return child; -}; + return child +} /** * Find a child by property name * @param {string} prop * @return {Node | undefined} Returns the child node when found, or undefined otherwise */ -Node.prototype.findChildByProperty = function(prop) { +Node.prototype.findChildByProperty = function (prop) { if (this.type !== 'object') { - return undefined; + return undefined } return this.childs.find(function (child) { - return child.field === prop; - }); -}; + return child.field === prop + }) +} /** * Create a table row with an append button. @@ -3936,11 +3813,11 @@ Node.prototype.findChildByProperty = function(prop) { */ Node.prototype.getAppendDom = function () { if (!this.append) { - this.append = new AppendNode(this.editor); - this.append.setParent(this); + this.append = new AppendNode(this.editor) + this.append.setParent(this) } - return this.append.getDom(); -}; + return this.append.getDom() +} /** * Create a table row with an showMore button and text @@ -3948,10 +3825,10 @@ Node.prototype.getAppendDom = function () { */ Node.prototype.getShowMoreDom = function () { if (!this.showMore) { - this.showMore = new ShowMoreNode(this.editor, this); + this.showMore = new ShowMoreNode(this.editor, this) } - return this.showMore.getDom(); -}; + return this.showMore.getDom() +} /** * Find the node from an event target @@ -3962,13 +3839,13 @@ Node.prototype.getShowMoreDom = function () { Node.getNodeFromTarget = function (target) { while (target) { if (target.node) { - return target.node; + return target.node } - target = target.parentNode; + target = target.parentNode } - return undefined; -}; + return undefined +} /** * Test whether target is a child of the color DOM of a node @@ -3976,20 +3853,20 @@ Node.getNodeFromTarget = function (target) { * @returns {boolean} */ Node.targetIsColorPicker = function (target) { - var node = Node.getNodeFromTarget(target); + var node = Node.getNodeFromTarget(target) if (node) { - var parent = target && target.parentNode; + var parent = target && target.parentNode while (parent) { if (parent === node.dom.color) { - return true; + return true } - parent = parent.parentNode; + parent = parent.parentNode } } - return false; -}; + return false +} /** * Remove the focus of given nodes, and move the focus to the (a) node before, @@ -3998,52 +3875,50 @@ Node.targetIsColorPicker = function (target) { */ Node.blurNodes = function (nodes) { if (!Array.isArray(nodes)) { - Node.blurNodes([nodes]); - return; + Node.blurNodes([nodes]) + return } - var firstNode = nodes[0]; - var parent = firstNode.parent; - var firstIndex = firstNode.getIndex(); + var firstNode = nodes[0] + var parent = firstNode.parent + var firstIndex = firstNode.getIndex() if (parent.childs[firstIndex + nodes.length]) { - parent.childs[firstIndex + nodes.length].focus(); + parent.childs[firstIndex + nodes.length].focus() + } else if (parent.childs[firstIndex - 1]) { + parent.childs[firstIndex - 1].focus() + } else { + parent.focus() } - else if (parent.childs[firstIndex - 1]) { - parent.childs[firstIndex - 1].focus(); - } - else { - parent.focus(); - } -}; +} /** * Get the next sibling of current node * @return {Node} nextSibling */ Node.prototype.nextSibling = function () { - var index = this.parent.childs.indexOf(this); - return this.parent.childs[index + 1] || this.parent.append; -}; + var index = this.parent.childs.indexOf(this) + return this.parent.childs[index + 1] || this.parent.append +} /** * Get the previously rendered node * @return {Node | null} previousNode */ Node.prototype._previousNode = function () { - var prevNode = null; - var dom = this.getDom(); + var prevNode = null + var dom = this.getDom() if (dom && dom.parentNode) { // find the previous field - var prevDom = dom; + var prevDom = dom do { - prevDom = prevDom.previousSibling; - prevNode = Node.getNodeFromTarget(prevDom); + prevDom = prevDom.previousSibling + prevNode = Node.getNodeFromTarget(prevDom) } - while (prevDom && prevNode && (prevNode instanceof AppendNode && !prevNode.isVisible())); + while (prevDom && prevNode && (prevNode instanceof AppendNode && !prevNode.isVisible())) } - return prevNode; -}; + return prevNode +} /** * Get the next rendered node @@ -4051,20 +3926,20 @@ Node.prototype._previousNode = function () { * @private */ Node.prototype._nextNode = function () { - var nextNode = null; - var dom = this.getDom(); + var nextNode = null + var dom = this.getDom() if (dom && dom.parentNode) { // find the previous field - var nextDom = dom; + var nextDom = dom do { - nextDom = nextDom.nextSibling; - nextNode = Node.getNodeFromTarget(nextDom); + nextDom = nextDom.nextSibling + nextNode = Node.getNodeFromTarget(nextDom) } - while (nextDom && nextNode && (nextNode instanceof AppendNode && !nextNode.isVisible())); + while (nextDom && nextNode && (nextNode instanceof AppendNode && !nextNode.isVisible())) } - return nextNode; -}; + return nextNode +} /** * Get the first rendered node @@ -4072,15 +3947,15 @@ Node.prototype._nextNode = function () { * @private */ Node.prototype._firstNode = function () { - var firstNode = null; - var dom = this.getDom(); + var firstNode = null + var dom = this.getDom() if (dom && dom.parentNode) { - var firstDom = dom.parentNode.firstChild; - firstNode = Node.getNodeFromTarget(firstDom); + var firstDom = dom.parentNode.firstChild + firstNode = Node.getNodeFromTarget(firstDom) } - return firstNode; -}; + return firstNode +} /** * Get the last rendered node @@ -4088,18 +3963,18 @@ Node.prototype._firstNode = function () { * @private */ Node.prototype._lastNode = function () { - var lastNode = null; - var dom = this.getDom(); + var lastNode = null + var dom = this.getDom() if (dom && dom.parentNode) { - var lastDom = dom.parentNode.lastChild; - lastNode = Node.getNodeFromTarget(lastDom); + var lastDom = dom.parentNode.lastChild + lastNode = Node.getNodeFromTarget(lastDom) while (lastDom && lastNode && !lastNode.isVisible()) { - lastDom = lastDom.previousSibling; - lastNode = Node.getNodeFromTarget(lastDom); + lastDom = lastDom.previousSibling + lastNode = Node.getNodeFromTarget(lastDom) } } - return lastNode; -}; + return lastNode +} /** * Get the next element which can have focus. @@ -4108,30 +3983,30 @@ Node.prototype._lastNode = function () { * @private */ Node.prototype._previousElement = function (elem) { - var dom = this.dom; + var dom = this.dom // noinspection FallthroughInSwitchStatementJS switch (elem) { case dom.value: if (this.fieldEditable) { - return dom.field; + return dom.field } // intentional fall through case dom.field: if (this._hasChilds()) { - return dom.expand; + return dom.expand } // intentional fall through case dom.expand: - return dom.menu; + return dom.menu case dom.menu: if (dom.drag) { - return dom.drag; + return dom.drag } // intentional fall through default: - return null; + return null } -}; +} /** * Get the next element which can have focus. @@ -4140,49 +4015,43 @@ Node.prototype._previousElement = function (elem) { * @private */ Node.prototype._nextElement = function (elem) { - var dom = this.dom; + var dom = this.dom // noinspection FallthroughInSwitchStatementJS switch (elem) { case dom.drag: - return dom.menu; + return dom.menu case dom.menu: if (this._hasChilds()) { - return dom.expand; + return dom.expand } // intentional fall through case dom.expand: if (this.fieldEditable) { - return dom.field; + return dom.field } // intentional fall through case dom.field: if (!this._hasChilds()) { - return dom.value; + return dom.value } + // intentional fall through default: - return null; + return null } -}; +} /** * Get the dom name of given element. returns null if not found. - * For example when element == dom.field, "field" is returned. + * For example when element === dom.field, "field" is returned. * @param {Element} element * @return {String | null} elementName Available elements with name: 'drag', * 'menu', 'expand', 'field', 'value' * @private */ Node.prototype._getElementName = function (element) { - var dom = this.dom; - for (var name in dom) { - if (dom.hasOwnProperty(name)) { - if (dom[name] == element) { - return name; - } - } - } - return null; -}; + return Object.keys(this.dom) + .find(name => this.dom[name] === element) +} /** * Test if this node has childs. This is the case when the node is an object @@ -4191,42 +4060,42 @@ Node.prototype._getElementName = function (element) { * @private */ Node.prototype._hasChilds = function () { - return this.type == 'array' || this.type == 'object'; -}; + return this.type === 'array' || this.type === 'object' +} // titles with explanation for the different types Node.TYPE_TITLES = { - 'auto': translate('autoType'), - 'object': translate('objectType'), - 'array': translate('arrayType'), - 'string': translate('stringType') -}; + auto: translate('autoType'), + object: translate('objectType'), + array: translate('arrayType'), + string: translate('stringType') +} Node.prototype.addTemplates = function (menu, append) { - var node = this; - var templates = node.editor.options.templates; - if (templates == null) return; - if (templates.length) { - // create a separator - menu.push({ - 'type': 'separator' - }); - } - var appendData = function (name, data) { - node._onAppend(name, data); - }; - var insertData = function (name, data) { - node._onInsertBefore(name, data); - }; - templates.forEach(function (template) { - menu.push({ - text: template.text, - className: (template.className || 'jsoneditor-type-object'), - title: template.title, - click: (append ? appendData.bind(this, template.field, template.value) : insertData.bind(this, template.field, template.value)) - }); - }); -}; + var node = this + var templates = node.editor.options.templates + if (templates == null) return + if (templates.length) { + // create a separator + menu.push({ + type: 'separator' + }) + } + var appendData = function (name, data) { + node._onAppend(name, data) + } + var insertData = function (name, data) { + node._onInsertBefore(name, data) + } + templates.forEach(function (template) { + menu.push({ + text: template.text, + className: (template.className || 'jsoneditor-type-object'), + title: template.title, + click: (append ? appendData.bind(this, template.field, template.value) : insertData.bind(this, template.field, template.value)) + }) + }) +} /** * Show a contextmenu for this node @@ -4236,9 +4105,9 @@ Node.prototype.addTemplates = function (menu, append) { * is being closed. */ Node.prototype.showContextMenu = function (anchor, onClose) { - var node = this; - var titles = Node.TYPE_TITLES; - var items = []; + var node = this + var titles = Node.TYPE_TITLES + var items = [] if (this.editable.value) { items.push({ @@ -4249,75 +4118,75 @@ Node.prototype.showContextMenu = function (anchor, onClose) { { text: translate('auto'), className: 'jsoneditor-type-auto' + - (this.type == 'auto' ? ' jsoneditor-selected' : ''), + (this.type === 'auto' ? ' jsoneditor-selected' : ''), title: titles.auto, click: function () { - node._onChangeType('auto'); + node._onChangeType('auto') } }, { text: translate('array'), className: 'jsoneditor-type-array' + - (this.type == 'array' ? ' jsoneditor-selected' : ''), + (this.type === 'array' ? ' jsoneditor-selected' : ''), title: titles.array, click: function () { - node._onChangeType('array'); + node._onChangeType('array') } }, { text: translate('object'), className: 'jsoneditor-type-object' + - (this.type == 'object' ? ' jsoneditor-selected' : ''), + (this.type === 'object' ? ' jsoneditor-selected' : ''), title: titles.object, click: function () { - node._onChangeType('object'); + node._onChangeType('object') } }, { text: translate('string'), className: 'jsoneditor-type-string' + - (this.type == 'string' ? ' jsoneditor-selected' : ''), + (this.type === 'string' ? ' jsoneditor-selected' : ''), title: titles.string, click: function () { - node._onChangeType('string'); + node._onChangeType('string') } } ] - }); + }) } if (this._hasChilds()) { if (this.editor.options.enableSort) { items.push({ text: translate('sort'), - title: translate('sortTitle', {type: this.type}), + title: translate('sortTitle', { type: this.type }), className: 'jsoneditor-sort-asc', click: function () { node.showSortModal() } - }); + }) } if (this.editor.options.enableTransform) { items.push({ text: translate('transform'), - title: translate('transformTitle', {type: this.type}), + title: translate('transformTitle', { type: this.type }), className: 'jsoneditor-transform', click: function () { - node.showTransformModal(); + node.showTransformModal() } - }); + }) } if (this.parent) { items.push({ text: translate('extract'), - title: translate('extractTitle', {type: this.type}), + title: translate('extractTitle', { type: this.type }), className: 'jsoneditor-extract', click: function () { - node.extract(); + node.extract() } - }); + }) } } @@ -4325,106 +4194,106 @@ Node.prototype.showContextMenu = function (anchor, onClose) { if (items.length) { // create a separator items.push({ - 'type': 'separator' - }); + type: 'separator' + }) } // create append button (for last child node only) - var childs = node.parent.childs; + var childs = node.parent.childs if (node === childs[childs.length - 1]) { - var appendSubmenu = [ - { - text: translate('auto'), - className: 'jsoneditor-type-auto', - title: titles.auto, - click: function () { - node._onAppend('', '', 'auto'); - } - }, - { - text: translate('array'), - className: 'jsoneditor-type-array', - title: titles.array, - click: function () { - node._onAppend('', []); - } - }, - { - text: translate('object'), - className: 'jsoneditor-type-object', - title: titles.object, - click: function () { - node._onAppend('', {}); - } - }, - { - text: translate('string'), - className: 'jsoneditor-type-string', - title: titles.string, - click: function () { - node._onAppend('', '', 'string'); - } - } - ]; - node.addTemplates(appendSubmenu, true); - items.push({ - text: translate('appendText'), - title: translate('appendTitle'), - submenuTitle: translate('appendSubmenuTitle'), - className: 'jsoneditor-append', - click: function () { - node._onAppend('', '', 'auto'); - }, - submenu: appendSubmenu - }); + var appendSubmenu = [ + { + text: translate('auto'), + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onAppend('', '', 'auto') + } + }, + { + text: translate('array'), + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onAppend('', []) + } + }, + { + text: translate('object'), + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onAppend('', {}) + } + }, + { + text: translate('string'), + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onAppend('', '', 'string') + } + } + ] + node.addTemplates(appendSubmenu, true) + items.push({ + text: translate('appendText'), + title: translate('appendTitle'), + submenuTitle: translate('appendSubmenuTitle'), + className: 'jsoneditor-append', + click: function () { + node._onAppend('', '', 'auto') + }, + submenu: appendSubmenu + }) } // create insert button var insertSubmenu = [ - { - text: translate('auto'), - className: 'jsoneditor-type-auto', - title: titles.auto, - click: function () { - node._onInsertBefore('', '', 'auto'); - } - }, - { - text: translate('array'), - className: 'jsoneditor-type-array', - title: titles.array, - click: function () { - node._onInsertBefore('', []); - } - }, - { - text: translate('object'), - className: 'jsoneditor-type-object', - title: titles.object, - click: function () { - node._onInsertBefore('', {}); - } - }, - { - text: translate('string'), - className: 'jsoneditor-type-string', - title: titles.string, - click: function () { - node._onInsertBefore('', '', 'string'); - } + { + text: translate('auto'), + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onInsertBefore('', '', 'auto') } - ]; - node.addTemplates(insertSubmenu, false); + }, + { + text: translate('array'), + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onInsertBefore('', []) + } + }, + { + text: translate('object'), + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onInsertBefore('', {}) + } + }, + { + text: translate('string'), + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onInsertBefore('', '', 'string') + } + } + ] + node.addTemplates(insertSubmenu, false) items.push({ text: translate('insert'), title: translate('insertTitle'), submenuTitle: translate('insertSub'), className: 'jsoneditor-insert', click: function () { - node._onInsertBefore('', '', 'auto'); + node._onInsertBefore('', '', 'auto') }, submenu: insertSubmenu - }); + }) if (this.editable.field) { // create duplicate button @@ -4433,9 +4302,9 @@ Node.prototype.showContextMenu = function (anchor, onClose) { title: translate('duplicateField'), className: 'jsoneditor-duplicate', click: function () { - Node.onDuplicate(node); + Node.onDuplicate(node) } - }); + }) // create remove button items.push({ @@ -4443,38 +4312,37 @@ Node.prototype.showContextMenu = function (anchor, onClose) { title: translate('removeField'), className: 'jsoneditor-remove', click: function () { - Node.onRemove(node); + Node.onRemove(node) } - }); + }) } } if (this.editor.options.onCreateMenu) { - var path = node.getPath(); + var path = node.getPath() - items = this.editor.options.onCreateMenu(items, { + items = this.editor.options.onCreateMenu(items, { type: 'single', path: path, paths: [path] - }); - } - - var menu = new ContextMenu(items, {close: onClose}); - menu.show(anchor, this.editor.frame); -}; + }) + } + var menu = new ContextMenu(items, { close: onClose }) + menu.show(anchor, this.editor.frame) +} /** * Show sorting modal */ Node.prototype.showSortModal = function () { - var node = this; - var container = this.editor.options.modalAnchor || DEFAULT_MODAL_ANCHOR; - var json = this.getValue(); + var node = this + var container = this.editor.options.modalAnchor || DEFAULT_MODAL_ANCHOR + var json = this.getValue() function onSort (sortedBy) { - var path = sortedBy.path; - var pathArray = util.parsePath(path); + var path = sortedBy.path + var pathArray = util.parsePath(path) node.sortedBy = sortedBy node.sort(pathArray, sortedBy.direction) @@ -4487,13 +4355,13 @@ Node.prototype.showSortModal = function () { * Show transform modal */ Node.prototype.showTransformModal = function () { - var node = this; + var node = this - var anchor = this.editor.options.modalAnchor || DEFAULT_MODAL_ANCHOR; - var json = node.getValue(); + var anchor = this.editor.options.modalAnchor || DEFAULT_MODAL_ANCHOR + var json = node.getValue() showTransformModal(anchor, json, function (query) { - node.transform(query); - }); + node.transform(query) + }) } /** @@ -4502,19 +4370,19 @@ Node.prototype.showTransformModal = function () { * @return {String} type Can be 'object', 'array', 'string', 'auto' * @private */ -Node.prototype._getType = function(value) { +Node.prototype._getType = function (value) { if (value instanceof Array) { - return 'array'; + return 'array' } if (value instanceof Object) { - return 'object'; + return 'object' } - if (typeof(value) == 'string' && typeof(util.parseString(value)) != 'string') { - return 'string'; + if (typeof (value) === 'string' && typeof (util.parseString(value)) !== 'string') { + return 'string' } - return 'auto'; -}; + return 'auto' +} /** * escape a text, such that it can be displayed safely in an HTML element @@ -4524,25 +4392,24 @@ Node.prototype._getType = function(value) { */ Node.prototype._escapeHTML = function (text) { if (typeof text !== 'string') { - return String(text); - } - else { + return String(text) + } else { var htmlEscaped = String(text) - .replace(/&/g, '&') // must be replaced first! - .replace(//g, '>') - .replace(/ /g, '  ') // replace double space with an nbsp and space - .replace(/^ /, ' ') // space at start - .replace(/ $/, ' '); // space at end + .replace(/&/g, '&') // must be replaced first! + .replace(//g, '>') + .replace(/ {2}/g, '  ') // replace double space with an nbsp and space + .replace(/^ /, ' ') // space at start + .replace(/ $/, ' ') // space at end - var json = JSON.stringify(htmlEscaped); - var html = json.substring(1, json.length - 1); + var json = JSON.stringify(htmlEscaped) + var html = json.substring(1, json.length - 1) if (this.editor.options.escapeUnicode === true) { - html = util.escapeUnicodeChars(html); + html = util.escapeUnicodeChars(html) } - return html; + return html } -}; +} /** * unescape a string. @@ -4551,15 +4418,15 @@ Node.prototype._escapeHTML = function (text) { * @private */ Node.prototype._unescapeHTML = function (escapedText) { - var json = '"' + this._escapeJSON(escapedText) + '"'; - var htmlEscaped = util.parse(json); + var json = '"' + this._escapeJSON(escapedText) + '"' + var htmlEscaped = util.parse(json) return htmlEscaped - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/ |\u00A0/g, ' ') - .replace(/&/g, '&'); // must be replaced last -}; + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/ |\u00A0/g, ' ') + .replace(/&/g, '&') // must be replaced last +} /** * escape a text to make it a valid JSON string. The method will: @@ -4572,42 +4439,39 @@ Node.prototype._unescapeHTML = function (escapedText) { */ Node.prototype._escapeJSON = function (text) { // TODO: replace with some smart regex (only when a new solution is faster!) - var escaped = ''; - var i = 0; + var escaped = '' + var i = 0 while (i < text.length) { - var c = text.charAt(i); - if (c == '\n') { - escaped += '\\n'; - } - else if (c == '\\') { - escaped += c; - i++; + var c = text.charAt(i) + if (c === '\n') { + escaped += '\\n' + } else if (c === '\\') { + escaped += c + i++ - c = text.charAt(i); - if (c === '' || '"\\/bfnrtu'.indexOf(c) == -1) { - escaped += '\\'; // no valid escape character + c = text.charAt(i) + if (c === '' || '"\\/bfnrtu'.indexOf(c) === -1) { + escaped += '\\' // no valid escape character } - escaped += c; + escaped += c + } else if (c === '"') { + escaped += '\\"' + } else { + escaped += c } - else if (c == '"') { - escaped += '\\"'; - } - else { - escaped += c; - } - i++; + i++ } - return escaped; -}; + return escaped +} /** * update the object name according to the callback onNodeName * @private */ Node.prototype.updateNodeName = function () { - var count = this.childs ? this.childs.length : 0; - var nodeName; + var count = this.childs ? this.childs.length : 0 + var nodeName if (this.type === 'object' || this.type === 'array') { if (this.editor.options.onNodeName) { try { @@ -4615,16 +4479,15 @@ Node.prototype.updateNodeName = function () { path: this.getPath(), size: count, type: this.type - }); - } - catch (err) { - console.error('Error in onNodeName callback: ', err); + }) + } catch (err) { + console.error('Error in onNodeName callback: ', err) } } this.dom.value.innerHTML = (this.type === 'object') ? ('{' + (nodeName || count) + '}') - : ('[' + (nodeName || count) + ']'); + : ('[' + (nodeName || count) + ']') } } @@ -4634,11 +4497,11 @@ Node.prototype.updateNodeName = function () { */ Node.prototype.recursivelyUpdateNodeName = function () { if (this.expanded) { - this.updateNodeName(); + this.updateNodeName() if (this.childs !== 'undefined') { - var i; + var i for (i in this.childs) { - this.childs[i].recursivelyUpdateNodeName(); + this.childs[i].recursivelyUpdateNodeName() } } } @@ -4646,17 +4509,21 @@ Node.prototype.recursivelyUpdateNodeName = function () { // helper function to get the internal path of a node function getInternalPath (node) { - return node.getInternalPath(); + return node.getInternalPath() } // helper function to get the field of a node function getField (node) { - return node.getField(); + return node.getField() +} + +function hasOwnProperty (object, key) { + return Object.prototype.hasOwnProperty.call(object, key) } // TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode // idea: introduce properties .isAppendNode and .isNode and use that instead of instanceof AppendNode checks -var AppendNode = appendNodeFactory(Node); -var ShowMoreNode = showMoreNodeFactory(Node); +var AppendNode = appendNodeFactory(Node) +var ShowMoreNode = showMoreNodeFactory(Node) -module.exports = Node; +module.exports = Node diff --git a/src/js/NodeHistory.js b/src/js/NodeHistory.js index c2625d1..c6e02fe 100644 --- a/src/js/NodeHistory.js +++ b/src/js/NodeHistory.js @@ -1,6 +1,6 @@ -'use strict'; +'use strict' -var util = require('./util'); +var util = require('./util') /** * @constructor History @@ -8,190 +8,190 @@ var util = require('./util'); * @param {JSONEditor} editor */ function NodeHistory (editor) { - this.editor = editor; - this.history = []; - this.index = -1; + this.editor = editor + this.history = [] + this.index = -1 - this.clear(); + this.clear() // helper function to find a Node from a path - function findNode(path) { + function findNode (path) { return editor.node.findNodeByInternalPath(path) } // map with all supported actions this.actions = { - 'editField': { - 'undo': function (params) { - var parentNode = findNode(params.parentPath); - var node = parentNode.childs[params.index]; - node.updateField(params.oldValue); + editField: { + undo: function (params) { + var parentNode = findNode(params.parentPath) + var node = parentNode.childs[params.index] + node.updateField(params.oldValue) }, - 'redo': function (params) { - var parentNode = findNode(params.parentPath); - var node = parentNode.childs[params.index]; - node.updateField(params.newValue); + redo: function (params) { + var parentNode = findNode(params.parentPath) + var node = parentNode.childs[params.index] + node.updateField(params.newValue) } }, - 'editValue': { - 'undo': function (params) { - findNode(params.path).updateValue(params.oldValue); + editValue: { + undo: function (params) { + findNode(params.path).updateValue(params.oldValue) }, - 'redo': function (params) { - findNode(params.path).updateValue(params.newValue); + redo: function (params) { + findNode(params.path).updateValue(params.newValue) } }, - 'changeType': { - 'undo': function (params) { - findNode(params.path).changeType(params.oldType); + changeType: { + undo: function (params) { + findNode(params.path).changeType(params.oldType) }, - 'redo': function (params) { - findNode(params.path).changeType(params.newType); + redo: function (params) { + findNode(params.path).changeType(params.newType) } }, - 'appendNodes': { - 'undo': function (params) { - var parentNode = findNode(params.parentPath); + appendNodes: { + undo: function (params) { + var parentNode = findNode(params.parentPath) params.paths.map(findNode).forEach(function (node) { - parentNode.removeChild(node); - }); - }, - 'redo': function (params) { - var parentNode = findNode(params.parentPath); - params.nodes.forEach(function (node) { - parentNode.appendChild(node); - }); - } - }, - 'insertBeforeNodes': { - 'undo': function (params) { - var parentNode = findNode(params.parentPath); - params.paths.map(findNode).forEach(function (node) { - parentNode.removeChild(node); - }); + parentNode.removeChild(node) + }) }, - 'redo': function (params) { - var parentNode = findNode(params.parentPath); - var beforeNode = findNode(params.beforePath); + redo: function (params) { + var parentNode = findNode(params.parentPath) params.nodes.forEach(function (node) { - parentNode.insertBefore(node, beforeNode); - }); + parentNode.appendChild(node) + }) } }, - 'insertAfterNodes': { - 'undo': function (params) { - var parentNode = findNode(params.parentPath); + insertBeforeNodes: { + undo: function (params) { + var parentNode = findNode(params.parentPath) params.paths.map(findNode).forEach(function (node) { - parentNode.removeChild(node); - }); + parentNode.removeChild(node) + }) }, - 'redo': function (params) { - var parentNode = findNode(params.parentPath); - var afterNode = findNode(params.afterPath); + redo: function (params) { + var parentNode = findNode(params.parentPath) + var beforeNode = findNode(params.beforePath) params.nodes.forEach(function (node) { - parentNode.insertAfter(node, afterNode); - afterNode = node; - }); + parentNode.insertBefore(node, beforeNode) + }) } }, - 'removeNodes': { - 'undo': function (params) { - var parentNode = findNode(params.parentPath); - var beforeNode = parentNode.childs[params.index] || parentNode.append; - params.nodes.forEach(function (node) { - parentNode.insertBefore(node, beforeNode); - }); - }, - 'redo': function (params) { - var parentNode = findNode(params.parentPath); + insertAfterNodes: { + undo: function (params) { + var parentNode = findNode(params.parentPath) params.paths.map(findNode).forEach(function (node) { - parentNode.removeChild(node); - }); + parentNode.removeChild(node) + }) + }, + redo: function (params) { + var parentNode = findNode(params.parentPath) + var afterNode = findNode(params.afterPath) + params.nodes.forEach(function (node) { + parentNode.insertAfter(node, afterNode) + afterNode = node + }) } }, - 'duplicateNodes': { - 'undo': function (params) { - var parentNode = findNode(params.parentPath); + removeNodes: { + undo: function (params) { + var parentNode = findNode(params.parentPath) + var beforeNode = parentNode.childs[params.index] || parentNode.append + params.nodes.forEach(function (node) { + parentNode.insertBefore(node, beforeNode) + }) + }, + redo: function (params) { + var parentNode = findNode(params.parentPath) + params.paths.map(findNode).forEach(function (node) { + parentNode.removeChild(node) + }) + } + }, + duplicateNodes: { + undo: function (params) { + var parentNode = findNode(params.parentPath) params.clonePaths.map(findNode).forEach(function (node) { - parentNode.removeChild(node); - }); + parentNode.removeChild(node) + }) }, - 'redo': function (params) { - var parentNode = findNode(params.parentPath); - var afterNode = findNode(params.afterPath); - var nodes = params.paths.map(findNode); + redo: function (params) { + var parentNode = findNode(params.parentPath) + var afterNode = findNode(params.afterPath) + var nodes = params.paths.map(findNode) nodes.forEach(function (node) { - var clone = node.clone(); + var clone = node.clone() if (parentNode.type === 'object') { - var existingFieldNames = parentNode.getFieldNames(); - clone.field = util.findUniqueName(node.field, existingFieldNames); + var existingFieldNames = parentNode.getFieldNames() + clone.field = util.findUniqueName(node.field, existingFieldNames) } - parentNode.insertAfter(clone, afterNode); - afterNode = clone; - }); + parentNode.insertAfter(clone, afterNode) + afterNode = clone + }) } }, - 'moveNodes': { - 'undo': function (params) { - var oldParentNode = findNode(params.oldParentPath); - var newParentNode = findNode(params.newParentPath); - var oldBeforeNode = oldParentNode.childs[params.oldIndex] || oldParentNode.append; + moveNodes: { + undo: function (params) { + var oldParentNode = findNode(params.oldParentPath) + var newParentNode = findNode(params.newParentPath) + var oldBeforeNode = oldParentNode.childs[params.oldIndex] || oldParentNode.append // first copy the nodes, then move them - var nodes = newParentNode.childs.slice(params.newIndex, params.newIndex + params.count); + var nodes = newParentNode.childs.slice(params.newIndex, params.newIndex + params.count) nodes.forEach(function (node, index) { - node.field = params.fieldNames[index]; - oldParentNode.moveBefore(node, oldBeforeNode); - }); + node.field = params.fieldNames[index] + oldParentNode.moveBefore(node, oldBeforeNode) + }) // This is a hack to work around an issue that we don't know tha original // path of the new parent after dragging, as the node is already moved at that time. if (params.newParentPathRedo === null) { - params.newParentPathRedo = newParentNode.getInternalPath(); + params.newParentPathRedo = newParentNode.getInternalPath() } }, - 'redo': function (params) { - var oldParentNode = findNode(params.oldParentPathRedo); - var newParentNode = findNode(params.newParentPathRedo); - var newBeforeNode = newParentNode.childs[params.newIndexRedo] || newParentNode.append; + redo: function (params) { + var oldParentNode = findNode(params.oldParentPathRedo) + var newParentNode = findNode(params.newParentPathRedo) + var newBeforeNode = newParentNode.childs[params.newIndexRedo] || newParentNode.append // first copy the nodes, then move them - var nodes = oldParentNode.childs.slice(params.oldIndexRedo, params.oldIndexRedo + params.count); + var nodes = oldParentNode.childs.slice(params.oldIndexRedo, params.oldIndexRedo + params.count) nodes.forEach(function (node, index) { - node.field = params.fieldNames[index]; - newParentNode.moveBefore(node, newBeforeNode); - }); + node.field = params.fieldNames[index] + newParentNode.moveBefore(node, newBeforeNode) + }) } }, - 'sort': { - 'undo': function (params) { - var node = findNode(params.path); - node.hideChilds(); - node.childs = params.oldChilds; - node.updateDom({updateIndexes: true}); - node.showChilds(); + sort: { + undo: function (params) { + var node = findNode(params.path) + node.hideChilds() + node.childs = params.oldChilds + node.updateDom({ updateIndexes: true }) + node.showChilds() }, - 'redo': function (params) { - var node = findNode(params.path); - node.hideChilds(); - node.childs = params.newChilds; - node.updateDom({updateIndexes: true}); - node.showChilds(); + redo: function (params) { + var node = findNode(params.path) + node.hideChilds() + node.childs = params.newChilds + node.updateDom({ updateIndexes: true }) + node.showChilds() } }, - 'transform': { - 'undo': function (params) { - findNode(params.path).setInternalValue(params.oldValue); + transform: { + undo: function (params) { + findNode(params.path).setInternalValue(params.oldValue) // TODO: would be nice to restore the state of the node and childs }, - 'redo': function (params) { - findNode(params.path).setInternalValue(params.newValue); + redo: function (params) { + findNode(params.path).setInternalValue(params.newValue) // TODO: would be nice to restore the state of the node and childs } @@ -199,14 +199,14 @@ function NodeHistory (editor) { // TODO: restore the original caret position and selection with each undo // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" - }; + } } /** * The method onChange is executed when the History is changed, and can * be overloaded. */ -NodeHistory.prototype.onChange = function () {}; +NodeHistory.prototype.onChange = function () {} /** * Add a new action to the history @@ -220,118 +220,114 @@ NodeHistory.prototype.onChange = function () {}; * needed to undo or redo the action. */ NodeHistory.prototype.add = function (action, params) { - this.index++; + this.index++ this.history[this.index] = { - 'action': action, - 'params': params, - 'timestamp': new Date() - }; + action: action, + params: params, + timestamp: new Date() + } // remove redo actions which are invalid now if (this.index < this.history.length - 1) { - this.history.splice(this.index + 1, this.history.length - this.index - 1); + this.history.splice(this.index + 1, this.history.length - this.index - 1) } // fire onchange event - this.onChange(); -}; + this.onChange() +} /** * Clear history */ NodeHistory.prototype.clear = function () { - this.history = []; - this.index = -1; + this.history = [] + this.index = -1 // fire onchange event - this.onChange(); -}; + this.onChange() +} /** * Check if there is an action available for undo * @return {Boolean} canUndo */ NodeHistory.prototype.canUndo = function () { - return (this.index >= 0); -}; + return (this.index >= 0) +} /** * Check if there is an action available for redo * @return {Boolean} canRedo */ NodeHistory.prototype.canRedo = function () { - return (this.index < this.history.length - 1); -}; + return (this.index < this.history.length - 1) +} /** * Undo the last action */ NodeHistory.prototype.undo = function () { if (this.canUndo()) { - var obj = this.history[this.index]; + var obj = this.history[this.index] if (obj) { - var action = this.actions[obj.action]; + var action = this.actions[obj.action] if (action && action.undo) { - action.undo(obj.params); + action.undo(obj.params) if (obj.params.oldSelection) { try { - this.editor.setDomSelection(obj.params.oldSelection); - } - catch (err) { - console.error(err); + this.editor.setDomSelection(obj.params.oldSelection) + } catch (err) { + console.error(err) } } - } - else { - console.error(new Error('unknown action "' + obj.action + '"')); + } else { + console.error(new Error('unknown action "' + obj.action + '"')) } } - this.index--; + this.index-- // fire onchange event - this.onChange(); + this.onChange() } -}; +} /** * Redo the last action */ NodeHistory.prototype.redo = function () { if (this.canRedo()) { - this.index++; + this.index++ - var obj = this.history[this.index]; + var obj = this.history[this.index] if (obj) { - var action = this.actions[obj.action]; + var action = this.actions[obj.action] if (action && action.redo) { - action.redo(obj.params); + action.redo(obj.params) if (obj.params.newSelection) { try { - this.editor.setDomSelection(obj.params.newSelection); - } - catch (err) { - console.error(err); + this.editor.setDomSelection(obj.params.newSelection) + } catch (err) { + console.error(err) } } - } - else { - console.error(new Error('unknown action "' + obj.action + '"')); + } else { + console.error(new Error('unknown action "' + obj.action + '"')) } } // fire onchange event - this.onChange(); + this.onChange() } -}; +} /** * Destroy history */ NodeHistory.prototype.destroy = function () { - this.editor = null; + this.editor = null - this.history = []; - this.index = -1; -}; + this.history = [] + this.index = -1 +} -module.exports = NodeHistory; +module.exports = NodeHistory diff --git a/src/js/SearchBox.js b/src/js/SearchBox.js index eb8b85e..563b6fe 100644 --- a/src/js/SearchBox.js +++ b/src/js/SearchBox.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * @constructor SearchBox @@ -7,80 +7,80 @@ * @param {Element} container HTML container element of where to * create the search box */ -function SearchBox(editor, container) { - var searchBox = this; +function SearchBox (editor, container) { + var searchBox = this - this.editor = editor; - this.timeout = undefined; - this.delay = 200; // ms - this.lastText = undefined; + this.editor = editor + this.timeout = undefined + this.delay = 200 // ms + this.lastText = undefined - this.dom = {}; - this.dom.container = container; + this.dom = {} + this.dom.container = container - var wrapper = document.createElement("div"); - this.dom.wrapper = wrapper; - wrapper.className = "jsoneditor-search"; - container.appendChild(wrapper); + var wrapper = document.createElement('div') + this.dom.wrapper = wrapper + wrapper.className = 'jsoneditor-search' + container.appendChild(wrapper) - var results = document.createElement("div"); - this.dom.results = results; - results.className = "jsoneditor-results"; - wrapper.appendChild(results); + var results = document.createElement('div') + this.dom.results = results + results.className = 'jsoneditor-results' + wrapper.appendChild(results) - var divInput = document.createElement("div"); - this.dom.input = divInput; - divInput.className = "jsoneditor-frame"; - divInput.title = "Search fields and values"; - wrapper.appendChild(divInput); + var divInput = document.createElement('div') + this.dom.input = divInput + divInput.className = 'jsoneditor-frame' + divInput.title = 'Search fields and values' + wrapper.appendChild(divInput) - var refreshSearch = document.createElement("button"); - refreshSearch.type = "button"; - refreshSearch.className = "jsoneditor-refresh"; - divInput.appendChild(refreshSearch); + var refreshSearch = document.createElement('button') + refreshSearch.type = 'button' + refreshSearch.className = 'jsoneditor-refresh' + divInput.appendChild(refreshSearch) - var search = document.createElement("input"); - search.type = "text"; - this.dom.search = search; - search.oninput = function(event) { - searchBox._onDelayedSearch(event); - }; - search.onchange = function(event) { + var search = document.createElement('input') + search.type = 'text' + this.dom.search = search + search.oninput = function (event) { + searchBox._onDelayedSearch(event) + } + search.onchange = function (event) { // For IE 9 - searchBox._onSearch(); - }; - search.onkeydown = function(event) { - searchBox._onKeyDown(event); - }; - search.onkeyup = function(event) { - searchBox._onKeyUp(event); - }; - refreshSearch.onclick = function(event) { - search.select(); - }; + searchBox._onSearch() + } + search.onkeydown = function (event) { + searchBox._onKeyDown(event) + } + search.onkeyup = function (event) { + searchBox._onKeyUp(event) + } + refreshSearch.onclick = function (event) { + search.select() + } // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 - divInput.appendChild(search); + divInput.appendChild(search) - var searchNext = document.createElement("button"); - searchNext.type = "button"; - searchNext.title = "Next result (Enter)"; - searchNext.className = "jsoneditor-next"; - searchNext.onclick = function() { - searchBox.next(); - }; + var searchNext = document.createElement('button') + searchNext.type = 'button' + searchNext.title = 'Next result (Enter)' + searchNext.className = 'jsoneditor-next' + searchNext.onclick = function () { + searchBox.next() + } - divInput.appendChild(searchNext); + divInput.appendChild(searchNext) - var searchPrevious = document.createElement("button"); - searchPrevious.type = "button"; - searchPrevious.title = "Previous result (Shift+Enter)"; - searchPrevious.className = "jsoneditor-previous"; - searchPrevious.onclick = function() { - searchBox.previous(); - }; + var searchPrevious = document.createElement('button') + searchPrevious.type = 'button' + searchPrevious.title = 'Previous result (Shift+Enter)' + searchPrevious.className = 'jsoneditor-previous' + searchPrevious.onclick = function () { + searchBox.previous() + } - divInput.appendChild(searchPrevious); + divInput.appendChild(searchPrevious) } /** @@ -88,31 +88,31 @@ function SearchBox(editor, container) { * @param {boolean} [focus] If true, focus will be set to the next result * focus is false by default. */ -SearchBox.prototype.next = function(focus) { - if (this.results != undefined) { - var index = this.resultIndex != undefined ? this.resultIndex + 1 : 0; +SearchBox.prototype.next = function (focus) { + if (this.results !== null) { + var index = this.resultIndex !== null ? this.resultIndex + 1 : 0 if (index > this.results.length - 1) { - index = 0; + index = 0 } - this._setActiveResult(index, focus); + this._setActiveResult(index, focus) } -}; +} /** * Go to the prevous search result * @param {boolean} [focus] If true, focus will be set to the next result * focus is false by default. */ -SearchBox.prototype.previous = function(focus) { - if (this.results != undefined) { - var max = this.results.length - 1; - var index = this.resultIndex != undefined ? this.resultIndex - 1 : max; +SearchBox.prototype.previous = function (focus) { + if (this.results !== null) { + var max = this.results.length - 1 + var index = this.resultIndex !== null ? this.resultIndex - 1 : max if (index < 0) { - index = max; + index = max } - this._setActiveResult(index, focus); + this._setActiveResult(index, focus) } -}; +} /** * Set new value for the current active result @@ -121,57 +121,57 @@ SearchBox.prototype.previous = function(focus) { * focus is false by default. * @private */ -SearchBox.prototype._setActiveResult = function(index, focus) { +SearchBox.prototype._setActiveResult = function (index, focus) { // de-activate current active result if (this.activeResult) { - var prevNode = this.activeResult.node; - var prevElem = this.activeResult.elem; - if (prevElem == "field") { - delete prevNode.searchFieldActive; + var prevNode = this.activeResult.node + var prevElem = this.activeResult.elem + if (prevElem === 'field') { + delete prevNode.searchFieldActive } else { - delete prevNode.searchValueActive; + delete prevNode.searchValueActive } - prevNode.updateDom(); + prevNode.updateDom() } if (!this.results || !this.results[index]) { // out of range, set to undefined - this.resultIndex = undefined; - this.activeResult = undefined; - return; + this.resultIndex = undefined + this.activeResult = undefined + return } - this.resultIndex = index; + this.resultIndex = index // set new node active - var node = this.results[this.resultIndex].node; - var elem = this.results[this.resultIndex].elem; - if (elem == "field") { - node.searchFieldActive = true; + var node = this.results[this.resultIndex].node + var elem = this.results[this.resultIndex].elem + if (elem === 'field') { + node.searchFieldActive = true } else { - node.searchValueActive = true; + node.searchValueActive = true } - this.activeResult = this.results[this.resultIndex]; - node.updateDom(); + this.activeResult = this.results[this.resultIndex] + node.updateDom() // TODO: not so nice that the focus is only set after the animation is finished - node.scrollTo(function() { + node.scrollTo(function () { if (focus) { - node.focus(elem); + node.focus(elem) } - }); -}; + }) +} /** * Cancel any running onDelayedSearch. * @private */ -SearchBox.prototype._clearDelay = function() { - if (this.timeout != undefined) { - clearTimeout(this.timeout); - delete this.timeout; +SearchBox.prototype._clearDelay = function () { + if (this.timeout !== undefined) { + clearTimeout(this.timeout) + delete this.timeout } -}; +} /** * Start a timer to execute a search after a short delay. @@ -179,15 +179,15 @@ SearchBox.prototype._clearDelay = function() { * @param {Event} event * @private */ -SearchBox.prototype._onDelayedSearch = function(event) { +SearchBox.prototype._onDelayedSearch = function (event) { // execute the search after a short delay (reduces the number of // search actions while typing in the search text box) - this._clearDelay(); - var searchBox = this; - this.timeout = setTimeout(function(event) { - searchBox._onSearch(); - }, this.delay); -}; + this._clearDelay() + var searchBox = this + this.timeout = setTimeout(function (event) { + searchBox._onSearch() + }, this.delay) +} /** * Handle onSearch event @@ -196,128 +196,128 @@ SearchBox.prototype._onDelayedSearch = function(event) { * Default is false. * @private */ -SearchBox.prototype._onSearch = function(forceSearch) { - this._clearDelay(); +SearchBox.prototype._onSearch = function (forceSearch) { + this._clearDelay() - var value = this.dom.search.value; - var text = value.length > 0 ? value : undefined; + var value = this.dom.search.value + var text = value.length > 0 ? value : undefined if (text !== this.lastText || forceSearch) { // only search again when changed - this.lastText = text; - this.results = this.editor.search(text); + this.lastText = text + this.results = this.editor.search(text) var MAX_SEARCH_RESULTS = this.results[0] ? this.results[0].node.MAX_SEARCH_RESULTS - : Infinity; + : Infinity // try to maintain the current active result if this is still part of the new search results - var activeResultIndex = 0; + var activeResultIndex = 0 if (this.activeResult) { for (var i = 0; i < this.results.length; i++) { if (this.results[i].node === this.activeResult.node) { - activeResultIndex = i; - break; + activeResultIndex = i + break } } } - this._setActiveResult(activeResultIndex, false); + this._setActiveResult(activeResultIndex, false) // display search results if (text !== undefined) { - var resultCount = this.results.length; + var resultCount = this.results.length if (resultCount === 0) { - this.dom.results.innerHTML = "no results"; + this.dom.results.innerHTML = 'no results' } else if (resultCount === 1) { - this.dom.results.innerHTML = "1 result"; + this.dom.results.innerHTML = '1 result' } else if (resultCount > MAX_SEARCH_RESULTS) { - this.dom.results.innerHTML = MAX_SEARCH_RESULTS + "+ results"; + this.dom.results.innerHTML = MAX_SEARCH_RESULTS + '+ results' } else { - this.dom.results.innerHTML = resultCount + " results"; + this.dom.results.innerHTML = resultCount + ' results' } } else { - this.dom.results.innerHTML = ""; + this.dom.results.innerHTML = '' } } -}; +} /** * Handle onKeyDown event in the input box * @param {Event} event * @private */ -SearchBox.prototype._onKeyDown = function(event) { - var keynum = event.which; - if (keynum == 27) { +SearchBox.prototype._onKeyDown = function (event) { + var keynum = event.which + if (keynum === 27) { // ESC - this.dom.search.value = ""; // clear search - this._onSearch(); - event.preventDefault(); - event.stopPropagation(); - } else if (keynum == 13) { + this.dom.search.value = '' // clear search + this._onSearch() + event.preventDefault() + event.stopPropagation() + } else if (keynum === 13) { // Enter if (event.ctrlKey) { // force to search again - this._onSearch(true); + this._onSearch(true) } else if (event.shiftKey) { // move to the previous search result - this.previous(); + this.previous() } else { // move to the next search result - this.next(); + this.next() } - event.preventDefault(); - event.stopPropagation(); + event.preventDefault() + event.stopPropagation() } -}; +} /** * Handle onKeyUp event in the input box * @param {Event} event * @private */ -SearchBox.prototype._onKeyUp = function(event) { - var keynum = event.keyCode; - if (keynum != 27 && keynum != 13) { +SearchBox.prototype._onKeyUp = function (event) { + var keynum = event.keyCode + if (keynum !== 27 && keynum !== 13) { // !show and !Enter - this._onDelayedSearch(event); // For IE 9 + this._onDelayedSearch(event) // For IE 9 } -}; +} /** * Clear the search results */ -SearchBox.prototype.clear = function() { - this.dom.search.value = ""; - this._onSearch(); -}; +SearchBox.prototype.clear = function () { + this.dom.search.value = '' + this._onSearch() +} /** * Refresh searchResults if there is a search value */ -SearchBox.prototype.forceSearch = function() { - this._onSearch(true); -}; +SearchBox.prototype.forceSearch = function () { + this._onSearch(true) +} /** * Test whether the search box value is empty * @returns {boolean} Returns true when empty. */ -SearchBox.prototype.isEmpty = function() { - return this.dom.search.value === ""; -}; +SearchBox.prototype.isEmpty = function () { + return this.dom.search.value === '' +} /** * Destroy the search box */ -SearchBox.prototype.destroy = function() { - this.editor = null; - this.dom.container.removeChild(this.dom.wrapper); - this.dom = null; +SearchBox.prototype.destroy = function () { + this.editor = null + this.dom.container.removeChild(this.dom.wrapper) + this.dom = null - this.results = null; - this.activeResult = null; + this.results = null + this.activeResult = null - this._clearDelay(); -}; + this._clearDelay() +} -module.exports = SearchBox; +module.exports = SearchBox diff --git a/src/js/TreePath.js b/src/js/TreePath.js index b03945e..fde1036 100644 --- a/src/js/TreePath.js +++ b/src/js/TreePath.js @@ -1,24 +1,24 @@ -'use strict'; +'use strict' -var ContextMenu = require('./ContextMenu'); -var translate = require('./i18n').translate; -var util = require('./util'); +var ContextMenu = require('./ContextMenu') +var translate = require('./i18n').translate +var util = require('./util') /** * Creates a component that visualize path selection in tree based editors - * @param {HTMLElement} container + * @param {HTMLElement} container * @param {HTMLElement} root * @constructor */ -function TreePath(container, root) { +function TreePath (container, root) { if (container) { - this.root = root; - this.path = document.createElement('div'); - this.path.className = 'jsoneditor-treepath'; - this.path.setAttribute('tabindex',0); - this.contentMenuClicked; - container.appendChild(this.path); - this.reset(); + this.root = root + this.path = document.createElement('div') + this.path.className = 'jsoneditor-treepath' + this.path.setAttribute('tabindex', 0) + this.contentMenuClicked = false + container.appendChild(this.path) + this.reset() } } @@ -26,98 +26,98 @@ function TreePath(container, root) { * Reset component to initial status */ TreePath.prototype.reset = function () { - this.path.innerHTML = translate('selectNode'); -}; + this.path.innerHTML = translate('selectNode') +} /** * Renders the component UI according to a given path objects * @param {Array<{name: String, childs: Array}>} pathObjs a list of path objects - * + * */ TreePath.prototype.setPath = function (pathObjs) { - var me = this; + var me = this - this.path.innerHTML = ''; + this.path.innerHTML = '' if (pathObjs && pathObjs.length) { pathObjs.forEach(function (pathObj, idx) { - var pathEl = document.createElement('span'); - var sepEl; - pathEl.className = 'jsoneditor-treepath-element'; - pathEl.innerText = pathObj.name; - pathEl.onclick = _onSegmentClick.bind(me, pathObj); - - me.path.appendChild(pathEl); + var pathEl = document.createElement('span') + var sepEl + pathEl.className = 'jsoneditor-treepath-element' + pathEl.innerText = pathObj.name + pathEl.onclick = _onSegmentClick.bind(me, pathObj) + + me.path.appendChild(pathEl) if (pathObj.children.length) { - sepEl = document.createElement('span'); - sepEl.className = 'jsoneditor-treepath-seperator'; - sepEl.innerHTML = '►'; + sepEl = document.createElement('span') + sepEl.className = 'jsoneditor-treepath-seperator' + sepEl.innerHTML = '►' sepEl.onclick = function () { - me.contentMenuClicked = true; - var items = []; + me.contentMenuClicked = true + var items = [] pathObj.children.forEach(function (child) { items.push({ - 'text': child.name, - 'className': 'jsoneditor-type-modes' + (pathObjs[idx + 1] + 1 && pathObjs[idx + 1].name === child.name ? ' jsoneditor-selected' : ''), - 'click': _onContextMenuItemClick.bind(me, pathObj, child.name) - }); - }); - var menu = new ContextMenu(items); - menu.show(sepEl, me.root, true); - }; + text: child.name, + className: 'jsoneditor-type-modes' + (pathObjs[idx + 1] + 1 && pathObjs[idx + 1].name === child.name ? ' jsoneditor-selected' : ''), + click: _onContextMenuItemClick.bind(me, pathObj, child.name) + }) + }) + var menu = new ContextMenu(items) + menu.show(sepEl, me.root, true) + } - me.path.appendChild(sepEl); + me.path.appendChild(sepEl) } - if(idx === pathObjs.length - 1) { - var leftRectPos = (sepEl || pathEl).getBoundingClientRect().right; - if(me.path.offsetWidth < leftRectPos) { - me.path.scrollLeft = leftRectPos; + if (idx === pathObjs.length - 1) { + var leftRectPos = (sepEl || pathEl).getBoundingClientRect().right + if (me.path.offsetWidth < leftRectPos) { + me.path.scrollLeft = leftRectPos } if (me.path.scrollLeft) { - var showAllBtn = document.createElement('span'); - showAllBtn.className = 'jsoneditor-treepath-show-all-btn'; - showAllBtn.title = 'show all path'; - showAllBtn.innerHTML = '...'; - showAllBtn.onclick = _onShowAllClick.bind(me, pathObjs); - me.path.insertBefore(showAllBtn, me.path.firstChild); + var showAllBtn = document.createElement('span') + showAllBtn.className = 'jsoneditor-treepath-show-all-btn' + showAllBtn.title = 'show all path' + showAllBtn.innerHTML = '...' + showAllBtn.onclick = _onShowAllClick.bind(me, pathObjs) + me.path.insertBefore(showAllBtn, me.path.firstChild) } } - }); + }) } - function _onShowAllClick(pathObjs) { - me.contentMenuClicked = false; - util.addClassName(me.path, 'show-all'); - me.path.style.width = me.path.parentNode.getBoundingClientRect().width - 10 + 'px'; - me.path.onblur = function() { + function _onShowAllClick (pathObjs) { + me.contentMenuClicked = false + util.addClassName(me.path, 'show-all') + me.path.style.width = me.path.parentNode.getBoundingClientRect().width - 10 + 'px' + me.path.onblur = function () { if (me.contentMenuClicked) { - me.contentMenuClicked = false; - me.path.focus(); - return; + me.contentMenuClicked = false + me.path.focus() + return } - util.removeClassName(me.path, 'show-all'); - me.path.onblur = undefined; - me.path.style.width = ''; - me.setPath(pathObjs); - }; + util.removeClassName(me.path, 'show-all') + me.path.onblur = undefined + me.path.style.width = '' + me.setPath(pathObjs) + } } - function _onSegmentClick(pathObj) { + function _onSegmentClick (pathObj) { if (this.selectionCallback) { - this.selectionCallback(pathObj); + this.selectionCallback(pathObj) } } - function _onContextMenuItemClick(pathObj, selection) { + function _onContextMenuItemClick (pathObj, selection) { if (this.contextMenuCallback) { - this.contextMenuCallback(pathObj, selection); + this.contextMenuCallback(pathObj, selection) } } -}; +} /** * set a callback function for selection of path section @@ -125,9 +125,9 @@ TreePath.prototype.setPath = function (pathObjs) { */ TreePath.prototype.onSectionSelected = function (callback) { if (typeof callback === 'function') { - this.selectionCallback = callback; + this.selectionCallback = callback } -}; +} /** * set a callback function for selection of path section @@ -135,8 +135,8 @@ TreePath.prototype.onSectionSelected = function (callback) { */ TreePath.prototype.onContextMenuItemSelected = function (callback) { if (typeof callback === 'function') { - this.contextMenuCallback = callback; + this.contextMenuCallback = callback } -}; +} -module.exports = TreePath; \ No newline at end of file +module.exports = TreePath diff --git a/src/js/ace/index.js b/src/js/ace/index.js index ec6541e..2affa72 100644 --- a/src/js/ace/index.js +++ b/src/js/ace/index.js @@ -2,20 +2,18 @@ var ace if (window.ace) { // use the already loaded instance of Ace ace = window.ace -} -else { +} else { try { // load brace - ace = require('brace'); + ace = require('brace') // load required Ace plugins - require('brace/mode/json'); - require('brace/ext/searchbox'); - } - catch (err) { + require('brace/mode/json') + require('brace/ext/searchbox') + } catch (err) { // failed to load brace (can be minimalist bundle). // No worries, the editor will fall back to plain text if needed. } } -module.exports = ace; +module.exports = ace diff --git a/src/js/ace/theme-jsoneditor.js b/src/js/ace/theme-jsoneditor.js index 790bfdd..086a0c1 100644 --- a/src/js/ace/theme-jsoneditor.js +++ b/src/js/ace/theme-jsoneditor.js @@ -3,7 +3,7 @@ * * Copyright (c) 2010, Ajax.org B.V. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -28,118 +28,117 @@ * * ***** END LICENSE BLOCK ***** */ -ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function(acequire, exports, module) { +window.ace.define('ace/theme/jsoneditor', ['require', 'exports', 'module', 'ace/lib/dom'], function (acequire, exports, module) { + exports.isDark = false + exports.cssClass = 'ace-jsoneditor' + exports.cssText = `.ace-jsoneditor .ace_gutter { +background: #ebebeb; +color: #333 +} -exports.isDark = false; -exports.cssClass = "ace-jsoneditor"; -exports.cssText = ".ace-jsoneditor .ace_gutter {\ -background: #ebebeb;\ -color: #333\ -}\ -\ -.ace-jsoneditor.ace_editor {\ -font-family: \"dejavu sans mono\", \"droid sans mono\", consolas, monaco, \"lucida console\", \"courier new\", courier, monospace, sans-serif;\ -line-height: 1.3;\ -background-color: #fff;\ -}\ -.ace-jsoneditor .ace_print-margin {\ -width: 1px;\ -background: #e8e8e8\ -}\ -.ace-jsoneditor .ace_scroller {\ -background-color: #FFFFFF\ -}\ -.ace-jsoneditor .ace_text-layer {\ -color: gray\ -}\ -.ace-jsoneditor .ace_variable {\ -color: #1a1a1a\ -}\ -.ace-jsoneditor .ace_cursor {\ -border-left: 2px solid #000000\ -}\ -.ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\ -border-left: 0px;\ -border-bottom: 1px solid #000000\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_selection {\ -background: lightgray\ -}\ -.ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\ -box-shadow: 0 0 3px 0px #FFFFFF;\ -border-radius: 2px\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_step {\ -background: rgb(255, 255, 0)\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_bracket {\ -margin: -1px 0 0 -1px;\ -border: 1px solid #BFBFBF\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_active-line {\ -background: #FFFBD1\ -}\ -.ace-jsoneditor .ace_gutter-active-line {\ -background-color : #dcdcdc\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_selected-word {\ -border: 1px solid lightgray\ -}\ -.ace-jsoneditor .ace_invisible {\ -color: #BFBFBF\ -}\ -.ace-jsoneditor .ace_keyword,\ -.ace-jsoneditor .ace_meta,\ -.ace-jsoneditor .ace_support.ace_constant.ace_property-value {\ -color: #AF956F\ -}\ -.ace-jsoneditor .ace_keyword.ace_operator {\ -color: #484848\ -}\ -.ace-jsoneditor .ace_keyword.ace_other.ace_unit {\ -color: #96DC5F\ -}\ -.ace-jsoneditor .ace_constant.ace_language {\ -color: darkorange\ -}\ -.ace-jsoneditor .ace_constant.ace_numeric {\ -color: red\ -}\ -.ace-jsoneditor .ace_constant.ace_character.ace_entity {\ -color: #BF78CC\ -}\ -.ace-jsoneditor .ace_invalid {\ -color: #FFFFFF;\ -background-color: #FF002A;\ -}\ -.ace-jsoneditor .ace_fold {\ -background-color: #AF956F;\ -border-color: #000000\ -}\ -.ace-jsoneditor .ace_storage,\ -.ace-jsoneditor .ace_support.ace_class,\ -.ace-jsoneditor .ace_support.ace_function,\ -.ace-jsoneditor .ace_support.ace_other,\ -.ace-jsoneditor .ace_support.ace_type {\ -color: #C52727\ -}\ -.ace-jsoneditor .ace_string {\ -color: green\ -}\ -.ace-jsoneditor .ace_comment {\ -color: #BCC8BA\ -}\ -.ace-jsoneditor .ace_entity.ace_name.ace_tag,\ -.ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\ -color: #606060\ -}\ -.ace-jsoneditor .ace_markup.ace_underline {\ -text-decoration: underline\ -}\ -.ace-jsoneditor .ace_indent-guide {\ -background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ -}"; +.ace-jsoneditor.ace_editor { +font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif; +line-height: 1.3; +background-color: #fff; +} +.ace-jsoneditor .ace_print-margin { +width: 1px; +background: #e8e8e8 +} +.ace-jsoneditor .ace_scroller { +background-color: #FFFFFF +} +.ace-jsoneditor .ace_text-layer { +color: gray +} +.ace-jsoneditor .ace_variable { +color: #1a1a1a +} +.ace-jsoneditor .ace_cursor { +border-left: 2px solid #000000 +} +.ace-jsoneditor .ace_overwrite-cursors .ace_cursor { +border-left: 0px; +border-bottom: 1px solid #000000 +} +.ace-jsoneditor .ace_marker-layer .ace_selection { +background: lightgray +} +.ace-jsoneditor.ace_multiselect .ace_selection.ace_start { +box-shadow: 0 0 3px 0px #FFFFFF; +border-radius: 2px +} +.ace-jsoneditor .ace_marker-layer .ace_step { +background: rgb(255, 255, 0) +} +.ace-jsoneditor .ace_marker-layer .ace_bracket { +margin: -1px 0 0 -1px; +border: 1px solid #BFBFBF +} +.ace-jsoneditor .ace_marker-layer .ace_active-line { +background: #FFFBD1 +} +.ace-jsoneditor .ace_gutter-active-line { +background-color : #dcdcdc +} +.ace-jsoneditor .ace_marker-layer .ace_selected-word { +border: 1px solid lightgray +} +.ace-jsoneditor .ace_invisible { +color: #BFBFBF +} +.ace-jsoneditor .ace_keyword, +.ace-jsoneditor .ace_meta, +.ace-jsoneditor .ace_support.ace_constant.ace_property-value { +color: #AF956F +} +.ace-jsoneditor .ace_keyword.ace_operator { +color: #484848 +} +.ace-jsoneditor .ace_keyword.ace_other.ace_unit { +color: #96DC5F +} +.ace-jsoneditor .ace_constant.ace_language { +color: darkorange +} +.ace-jsoneditor .ace_constant.ace_numeric { +color: red +} +.ace-jsoneditor .ace_constant.ace_character.ace_entity { +color: #BF78CC +} +.ace-jsoneditor .ace_invalid { +color: #FFFFFF; +background-color: #FF002A; +} +.ace-jsoneditor .ace_fold { +background-color: #AF956F; +border-color: #000000 +} +.ace-jsoneditor .ace_storage, +.ace-jsoneditor .ace_support.ace_class, +.ace-jsoneditor .ace_support.ace_function, +.ace-jsoneditor .ace_support.ace_other, +.ace-jsoneditor .ace_support.ace_type { +color: #C52727 +} +.ace-jsoneditor .ace_string { +color: green +} +.ace-jsoneditor .ace_comment { +color: #BCC8BA +} +.ace-jsoneditor .ace_entity.ace_name.ace_tag, +.ace-jsoneditor .ace_entity.ace_other.ace_attribute-name { +color: #606060 +} +.ace-jsoneditor .ace_markup.ace_underline { +text-decoration: underline +} +.ace-jsoneditor .ace_indent-guide { +background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y +}` -var dom = acequire("../lib/dom"); -dom.importCssString(exports.cssText, exports.cssClass); -}); + var dom = acequire('../lib/dom') + dom.importCssString(exports.cssText, exports.cssClass) +}) diff --git a/src/js/appendNodeFactory.js b/src/js/appendNodeFactory.js index fd92867..5a1b938 100644 --- a/src/js/appendNodeFactory.js +++ b/src/js/appendNodeFactory.js @@ -1,14 +1,14 @@ -'use strict'; +'use strict' -var util = require('./util'); -var ContextMenu = require('./ContextMenu'); -var translate = require('./i18n').translate; +var util = require('./util') +var ContextMenu = require('./ContextMenu') +var translate = require('./i18n').translate /** * A factory function to create an AppendNode, which depends on a Node * @param {Node} Node */ -function appendNodeFactory(Node) { +function appendNodeFactory (Node) { /** * @constructor AppendNode * @extends Node @@ -18,11 +18,11 @@ function appendNodeFactory(Node) { */ function AppendNode (editor) { /** @type {TreeEditor} */ - this.editor = editor; - this.dom = {}; + this.editor = editor + this.dom = {} } - AppendNode.prototype = new Node(); + AppendNode.prototype = new Node() /** * Return a table row with an append button. @@ -30,109 +30,108 @@ function appendNodeFactory(Node) { */ AppendNode.prototype.getDom = function () { // TODO: implement a new solution for the append node - var dom = this.dom; + var dom = this.dom if (dom.tr) { - return dom.tr; + return dom.tr } - this._updateEditability(); + this._updateEditability() // a row for the append button - var trAppend = document.createElement('tr'); - trAppend.className = 'jsoneditor-append'; - trAppend.node = this; - dom.tr = trAppend; + var trAppend = document.createElement('tr') + trAppend.className = 'jsoneditor-append' + trAppend.node = this + dom.tr = trAppend // TODO: consistent naming if (this.editor.options.mode === 'tree') { // a cell for the dragarea column - dom.tdDrag = document.createElement('td'); + dom.tdDrag = document.createElement('td') // create context menu - var tdMenu = document.createElement('td'); - dom.tdMenu = tdMenu; - var menu = document.createElement('button'); - menu.type = 'button'; - menu.className = 'jsoneditor-button jsoneditor-contextmenu'; - menu.title = 'Click to open the actions menu (Ctrl+M)'; - dom.menu = menu; - tdMenu.appendChild(dom.menu); + var tdMenu = document.createElement('td') + dom.tdMenu = tdMenu + var menu = document.createElement('button') + menu.type = 'button' + menu.className = 'jsoneditor-button jsoneditor-contextmenu' + menu.title = 'Click to open the actions menu (Ctrl+M)' + dom.menu = menu + tdMenu.appendChild(dom.menu) } // a cell for the contents (showing text 'empty') - var tdAppend = document.createElement('td'); - var domText = document.createElement('div'); - domText.innerHTML = '(' + translate('empty') + ')'; - domText.className = 'jsoneditor-readonly'; - tdAppend.appendChild(domText); - dom.td = tdAppend; - dom.text = domText; + var tdAppend = document.createElement('td') + var domText = document.createElement('div') + domText.innerHTML = '(' + translate('empty') + ')' + domText.className = 'jsoneditor-readonly' + tdAppend.appendChild(domText) + dom.td = tdAppend + dom.text = domText - this.updateDom(); + this.updateDom() - return trAppend; - }; + return trAppend + } /** * Append node doesn't have a path * @returns {null} */ - AppendNode.prototype.getPath = function() { - return null; - }; + AppendNode.prototype.getPath = function () { + return null + } /** * Append node doesn't have an index * @returns {null} */ - AppendNode.prototype.getIndex = function() { - return null; - }; + AppendNode.prototype.getIndex = function () { + return null + } /** * Update the HTML dom of the Node */ - AppendNode.prototype.updateDom = function(options) { - var dom = this.dom; - var tdAppend = dom.td; + AppendNode.prototype.updateDom = function (options) { + var dom = this.dom + var tdAppend = dom.td if (tdAppend) { - tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px'; + tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px' // TODO: not so nice hard coded offset } - var domText = dom.text; + var domText = dom.text if (domText) { - domText.innerHTML = '(' + translate('empty') + ' ' + this.parent.type + ')'; + domText.innerHTML = '(' + translate('empty') + ' ' + this.parent.type + ')' } // attach or detach the contents of the append node: // hide when the parent has childs, show when the parent has no childs - var trAppend = dom.tr; + var trAppend = dom.tr if (!this.isVisible()) { if (dom.tr.firstChild) { if (dom.tdDrag) { - trAppend.removeChild(dom.tdDrag); + trAppend.removeChild(dom.tdDrag) } if (dom.tdMenu) { - trAppend.removeChild(dom.tdMenu); + trAppend.removeChild(dom.tdMenu) } - trAppend.removeChild(tdAppend); + trAppend.removeChild(tdAppend) } - } - else { + } else { if (!dom.tr.firstChild) { if (dom.tdDrag) { - trAppend.appendChild(dom.tdDrag); + trAppend.appendChild(dom.tdDrag) } if (dom.tdMenu) { - trAppend.appendChild(dom.tdMenu); + trAppend.appendChild(dom.tdMenu) } - trAppend.appendChild(tdAppend); + trAppend.appendChild(tdAppend) } } - }; + } /** * Check whether the AppendNode is currently visible. @@ -140,8 +139,8 @@ function appendNodeFactory(Node) { * @return {boolean} isVisible */ AppendNode.prototype.isVisible = function () { - return (this.parent.childs.length == 0); - }; + return (this.parent.childs.length === 0) + } /** * Show a contextmenu for this node @@ -150,110 +149,109 @@ function appendNodeFactory(Node) { * is being closed. */ AppendNode.prototype.showContextMenu = function (anchor, onClose) { - var node = this; - var titles = Node.TYPE_TITLES; + var node = this + var titles = Node.TYPE_TITLES var appendSubmenu = [ - { - text: translate('auto'), - className: 'jsoneditor-type-auto', - title: titles.auto, - click: function () { - node._onAppend('', '', 'auto'); - } - }, - { - text: translate('array'), - className: 'jsoneditor-type-array', - title: titles.array, - click: function () { - node._onAppend('', []); - } - }, - { - text: translate('object'), - className: 'jsoneditor-type-object', - title: titles.object, - click: function () { - node._onAppend('', {}); - } - }, - { - text: translate('string'), - className: 'jsoneditor-type-string', - title: titles.string, - click: function () { - node._onAppend('', '', 'string'); - } + { + text: translate('auto'), + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { + node._onAppend('', '', 'auto') } - ]; - node.addTemplates(appendSubmenu, true); + }, + { + text: translate('array'), + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { + node._onAppend('', []) + } + }, + { + text: translate('object'), + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { + node._onAppend('', {}) + } + }, + { + text: translate('string'), + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { + node._onAppend('', '', 'string') + } + } + ] + node.addTemplates(appendSubmenu, true) var items = [ // create append button { - 'text': translate('appendText'), - 'title': translate('appendTitleAuto'), - 'submenuTitle': translate('appendSubmenuTitle'), - 'className': 'jsoneditor-insert', - 'click': function () { - node._onAppend('', '', 'auto'); + text: translate('appendText'), + title: translate('appendTitleAuto'), + submenuTitle: translate('appendSubmenuTitle'), + className: 'jsoneditor-insert', + click: function () { + node._onAppend('', '', 'auto') }, - 'submenu': appendSubmenu + submenu: appendSubmenu } - ]; - + ] + if (this.editor.options.onCreateMenu) { - var path = node.parent.getPath(); + var path = node.parent.getPath() items = this.editor.options.onCreateMenu(items, { type: 'append', path: path, paths: [path] - }); + }) } - var menu = new ContextMenu(items, {close: onClose}); - menu.show(anchor, this.editor.frame); - }; + var menu = new ContextMenu(items, { close: onClose }) + menu.show(anchor, this.editor.frame) + } /** * Handle an event. The event is caught centrally by the editor * @param {Event} event */ AppendNode.prototype.onEvent = function (event) { - var type = event.type; - var target = event.target || event.srcElement; - var dom = this.dom; + var type = event.type + var target = event.target || event.srcElement + var dom = this.dom // highlight the append nodes parent - var menu = dom.menu; - if (target == menu) { - if (type == 'mouseover') { - this.editor.highlighter.highlight(this.parent); - } - else if (type == 'mouseout') { - this.editor.highlighter.unhighlight(); + var menu = dom.menu + if (target === menu) { + if (type === 'mouseover') { + this.editor.highlighter.highlight(this.parent) + } else if (type === 'mouseout') { + this.editor.highlighter.unhighlight() } } // context menu events - if (type == 'click' && target == dom.menu) { - var highlighter = this.editor.highlighter; - highlighter.highlight(this.parent); - highlighter.lock(); - util.addClassName(dom.menu, 'jsoneditor-selected'); + if (type === 'click' && target === dom.menu) { + var highlighter = this.editor.highlighter + highlighter.highlight(this.parent) + highlighter.lock() + util.addClassName(dom.menu, 'jsoneditor-selected') this.showContextMenu(dom.menu, function () { - util.removeClassName(dom.menu, 'jsoneditor-selected'); - highlighter.unlock(); - highlighter.unhighlight(); - }); + util.removeClassName(dom.menu, 'jsoneditor-selected') + highlighter.unlock() + highlighter.unhighlight() + }) } - if (type == 'keydown') { - this.onKeyDown(event); + if (type === 'keydown') { + this.onKeyDown(event) } - }; + } - return AppendNode; + return AppendNode } -module.exports = appendNodeFactory; +module.exports = appendNodeFactory diff --git a/src/js/autocomplete.js b/src/js/autocomplete.js index e4e2640..76b28cb 100644 --- a/src/js/autocomplete.js +++ b/src/js/autocomplete.js @@ -1,396 +1,384 @@ -'use strict'; +'use strict' var defaultFilterFunction = { start: function (token, match, config) { - return match.indexOf(token) === 0; + return match.indexOf(token) === 0 }, contain: function (token, match, config) { - return match.indexOf(token) > -1; + return match.indexOf(token) > -1 } -}; - -function completely(config) { - config = config || {}; - config.filter = config.filter || 'start'; - config.trigger = config.trigger || 'keydown'; - config.confirmKeys = config.confirmKeys || [39, 35, 9] // right, end, tab - config.caseSensitive = config.caseSensitive || false // autocomplete case sensitive - - var fontSize = ''; - var fontFamily = ''; - - var wrapper = document.createElement('div'); - wrapper.style.position = 'relative'; - wrapper.style.outline = '0'; - wrapper.style.border = '0'; - wrapper.style.margin = '0'; - wrapper.style.padding = '0'; - - var dropDown = document.createElement('div'); - dropDown.className = 'autocomplete dropdown'; - dropDown.style.position = 'absolute'; - dropDown.style.visibility = 'hidden'; - - var spacer; - var leftSide; // <-- it will contain the leftSide part of the textfield (the bit that was already autocompleted) - var createDropDownController = function (elem, rs) { - var rows = []; - var ix = 0; - var oldIndex = -1; - - var onMouseOver = function () { this.style.outline = '1px solid #ddd'; } - var onMouseOut = function () { this.style.outline = '0'; } - var onMouseDown = function () { p.hide(); p.onmouseselection(this.__hint, p.rs); } - - var p = { - rs: rs, - hide: function () { - elem.style.visibility = 'hidden'; - //rs.hideDropDown(); - }, - refresh: function (token, array) { - elem.style.visibility = 'hidden'; - ix = 0; - elem.innerHTML = ''; - var vph = (window.innerHeight || document.documentElement.clientHeight); - var rect = elem.parentNode.getBoundingClientRect(); - var distanceToTop = rect.top - 6; // heuristic give 6px - var distanceToBottom = vph - rect.bottom - 6; // distance from the browser border. - - rows = []; - var filterFn = typeof config.filter === 'function' ? config.filter : defaultFilterFunction[config.filter]; - - var filtered = !filterFn ? [] : array.filter(function (match) { - return filterFn(config.caseSensitive ? token : token.toLowerCase(), config.caseSensitive ? match : match.toLowerCase(), config); - }); - - rows = filtered.map(function (row) { - var divRow = document.createElement('div'); - divRow.className = 'item'; - //divRow.style.color = config.color; - divRow.onmouseover = onMouseOver; - divRow.onmouseout = onMouseOut; - divRow.onmousedown = onMouseDown; - divRow.__hint = row; - divRow.innerHTML = row.substring(0, token.length) + '' + row.substring(token.length) + ''; - elem.appendChild(divRow); - return divRow; - }); - - if (rows.length === 0) { - return; // nothing to show. - } - if (rows.length === 1 && ( (token.toLowerCase() === rows[0].__hint.toLowerCase() && !config.caseSensitive) - ||(token === rows[0].__hint && config.caseSensitive))){ - return; // do not show the dropDown if it has only one element which matches what we have just displayed. - } - - if (rows.length < 2) return; - p.highlight(0); - - if (distanceToTop > distanceToBottom * 3) { // Heuristic (only when the distance to the to top is 4 times more than distance to the bottom - elem.style.maxHeight = distanceToTop + 'px'; // we display the dropDown on the top of the input text - elem.style.top = ''; - elem.style.bottom = '100%'; - } else { - elem.style.top = '100%'; - elem.style.bottom = ''; - elem.style.maxHeight = distanceToBottom + 'px'; - } - elem.style.visibility = 'visible'; - }, - highlight: function (index) { - if (oldIndex != -1 && rows[oldIndex]) { - rows[oldIndex].className = "item"; - } - rows[index].className = "item hover"; - oldIndex = index; - }, - move: function (step) { // moves the selection either up or down (unless it's not possible) step is either +1 or -1. - if (elem.style.visibility === 'hidden') return ''; // nothing to move if there is no dropDown. (this happens if the user hits escape and then down or up) - if (ix + step === -1 || ix + step === rows.length) return rows[ix].__hint; // NO CIRCULAR SCROLLING. - ix += step; - p.highlight(ix); - return rows[ix].__hint;//txtShadow.value = uRows[uIndex].__hint ; - }, - onmouseselection: function () { } // it will be overwritten. - }; - return p; - } - - function setEndOfContenteditable(contentEditableElement) { - var range, selection; - if (document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ - { - 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 - } - else if (document.selection)//IE 8 and lower - { - range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) - range.moveToElementText(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 - range.select();//Select the range (make it the visible selection - } - } - - function calculateWidthForText(text) { - if (spacer === undefined) { // on first call only. - spacer = document.createElement('span'); - spacer.style.visibility = 'hidden'; - spacer.style.position = 'fixed'; - spacer.style.outline = '0'; - spacer.style.margin = '0'; - spacer.style.padding = '0'; - spacer.style.border = '0'; - spacer.style.left = '0'; - spacer.style.whiteSpace = 'pre'; - spacer.style.fontSize = fontSize; - spacer.style.fontFamily = fontFamily; - spacer.style.fontWeight = 'normal'; - document.body.appendChild(spacer); - } - - // Used to encode an HTML string into a plain text. - // taken from http://stackoverflow.com/questions/1219860/javascript-jquery-html-encoding - spacer.innerHTML = String(text).replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>'); - return spacer.getBoundingClientRect().right; - } - - var rs = { - onArrowDown: function () { }, // defaults to no action. - onArrowUp: function () { }, // defaults to no action. - onEnter: function () { }, // defaults to no action. - onTab: function () { }, // defaults to no action. - startFrom: 0, - options: [], - element: null, - elementHint: null, - elementStyle: null, - wrapper: wrapper, // Only to allow easy access to the HTML elements to the final user (possibly for minor customizations) - show: function (element, startPos, options) { - this.startFrom = startPos; - this.wrapper.remove(); - if (this.elementHint) { - this.elementHint.remove(); - this.elementHint = null; - } - - if (fontSize == '') { - fontSize = window.getComputedStyle(element).getPropertyValue('font-size'); - } - if (fontFamily == '') { - fontFamily = window.getComputedStyle(element).getPropertyValue('font-family'); - } - - var w = element.getBoundingClientRect().right - element.getBoundingClientRect().left; - dropDown.style.marginLeft = '0'; - dropDown.style.marginTop = element.getBoundingClientRect().height + 'px'; - this.options = options; - - if (this.element != element) { - this.element = element; - this.elementStyle = { - zIndex: this.element.style.zIndex, - position: this.element.style.position, - backgroundColor: this.element.style.backgroundColor, - borderColor: this.element.style.borderColor - } - } - - this.element.style.zIndex = 3; - this.element.style.position = 'relative'; - this.element.style.backgroundColor = 'transparent'; - this.element.style.borderColor = 'transparent'; - - this.elementHint = element.cloneNode(); - this.elementHint.className = 'autocomplete hint'; - this.elementHint.style.zIndex = 2; - this.elementHint.style.position = 'absolute'; - this.elementHint.onfocus = function () { this.element.focus(); }.bind(this); - - - - if (this.element.addEventListener) { - this.element.removeEventListener("keydown", keyDownHandler); - this.element.addEventListener("keydown", keyDownHandler, false); - this.element.removeEventListener("blur", onBlurHandler); - this.element.addEventListener("blur", onBlurHandler, false); - } - - wrapper.appendChild(this.elementHint); - wrapper.appendChild(dropDown); - element.parentElement.appendChild(wrapper); - - - this.repaint(element); - }, - setText: function (text) { - this.element.innerText = text; - }, - getText: function () { - return this.element.innerText; - }, - hideDropDown: function () { - this.wrapper.remove(); - if (this.elementHint) { - this.elementHint.remove(); - this.elementHint = null; - dropDownController.hide(); - this.element.style.zIndex = this.elementStyle.zIndex; - this.element.style.position = this.elementStyle.position; - this.element.style.backgroundColor = this.elementStyle.backgroundColor; - this.element.style.borderColor = this.elementStyle.borderColor; - } - - }, - repaint: function (element) { - var text = element.innerText; - text = text.replace('\n', ''); - - var startFrom = this.startFrom; - var options = this.options; - var optionsLength = this.options.length; - - // breaking text in leftSide and token. - - var token = text.substring(this.startFrom); - leftSide = text.substring(0, this.startFrom); - - for (var i = 0; i < optionsLength; i++) { - var opt = this.options[i]; - if ( (!config.caseSensitive && opt.toLowerCase().indexOf(token.toLowerCase()) === 0) - || (config.caseSensitive && opt.indexOf(token) === 0)) { // <-- how about upperCase vs. lowercase - this.elementHint.innerText = leftSide + token + opt.substring(token.length); - this.elementHint.realInnerText = leftSide + opt; - break; - } - } - // moving the dropDown and refreshing it. - dropDown.style.left = calculateWidthForText(leftSide) + 'px'; - dropDownController.refresh(token, this.options); - this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + 10 + 'px' - var wasDropDownHidden = (dropDown.style.visibility == 'hidden'); - if (!wasDropDownHidden) - this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + dropDown.clientWidth + 'px'; - } - }; - - var dropDownController = createDropDownController(dropDown, rs); - - var keyDownHandler = function (e) { - //console.log("Keydown:" + e.keyCode); - e = e || window.event; - var keyCode = e.keyCode; - - if (this.elementHint == null) return; - - if (keyCode == 33) { return; } // page up (do nothing) - if (keyCode == 34) { return; } // page down (do nothing); - - if (keyCode == 27) { //escape - rs.hideDropDown(); - rs.element.focus(); - e.preventDefault(); - e.stopPropagation(); - return; - } - - var text = this.element.innerText; - text = text.replace('\n', ''); - var startFrom = this.startFrom; - - if (config.confirmKeys.indexOf(keyCode) >= 0) { // (autocomplete triggered) - if (keyCode == 9) { - if (this.elementHint.innerText.length == 0) { - rs.onTab(); - } - } - if (this.elementHint.innerText.length > 0) { // if there is a hint - if (this.element.innerText != this.elementHint.realInnerText) { - this.element.innerText = this.elementHint.realInnerText; - rs.hideDropDown(); - setEndOfContenteditable(this.element); - if (keyCode == 9) { - rs.element.focus(); - e.preventDefault(); - e.stopPropagation(); - } - } - } - return; - } - - if (keyCode == 13) { // enter (autocomplete triggered) - if (this.elementHint.innerText.length == 0) { // if there is a hint - rs.onEnter(); - } else { - var wasDropDownHidden = (dropDown.style.visibility == 'hidden'); - dropDownController.hide(); - - if (wasDropDownHidden) { - rs.hideDropDown(); - rs.element.focus(); - rs.onEnter(); - return; - } - - this.element.innerText = this.elementHint.realInnerText; - rs.hideDropDown(); - setEndOfContenteditable(this.element); - e.preventDefault(); - e.stopPropagation(); - } - return; - } - - if (keyCode == 40) { // down - var token = text.substring(this.startFrom); - var m = dropDownController.move(+1); - if (m == '') { rs.onArrowDown(); } - this.elementHint.innerText = leftSide + token + m.substring(token.length); - this.elementHint.realInnerText = leftSide + m; - e.preventDefault(); - e.stopPropagation(); - return; - } - - if (keyCode == 38) { // up - var token = text.substring(this.startFrom); - var m = dropDownController.move(-1); - if (m == '') { rs.onArrowUp(); } - this.elementHint.innerText = leftSide + token + m.substring(token.length); - this.elementHint.realInnerText = leftSide + m; - e.preventDefault(); - e.stopPropagation(); - return; - } - - }.bind(rs); - - var onBlurHandler = function (e) { - rs.hideDropDown(); - //console.log("Lost focus."); - }.bind(rs); - - dropDownController.onmouseselection = function (text, rs) { - rs.element.innerText = rs.elementHint.innerText = leftSide + text; - rs.hideDropDown(); - window.setTimeout(function () { - rs.element.focus(); - setEndOfContenteditable(rs.element); - }, 1); - }; - - return rs; } -module.exports = completely; \ No newline at end of file +function completely (config) { + config = config || {} + config.filter = config.filter || 'start' + config.trigger = config.trigger || 'keydown' + config.confirmKeys = config.confirmKeys || [39, 35, 9] // right, end, tab + config.caseSensitive = config.caseSensitive || false // autocomplete case sensitive + + var fontSize = '' + var fontFamily = '' + + var wrapper = document.createElement('div') + wrapper.style.position = 'relative' + wrapper.style.outline = '0' + wrapper.style.border = '0' + wrapper.style.margin = '0' + wrapper.style.padding = '0' + + var dropDown = document.createElement('div') + dropDown.className = 'autocomplete dropdown' + dropDown.style.position = 'absolute' + dropDown.style.visibility = 'hidden' + + var spacer + var leftSide // <-- it will contain the leftSide part of the textfield (the bit that was already autocompleted) + var createDropDownController = function (elem, rs) { + var rows = [] + var ix = 0 + var oldIndex = -1 + + var onMouseOver = function () { this.style.outline = '1px solid #ddd' } + var onMouseOut = function () { this.style.outline = '0' } + var onMouseDown = function () { p.hide(); p.onmouseselection(this.__hint, p.rs) } + + var p = { + rs: rs, + hide: function () { + elem.style.visibility = 'hidden' + // rs.hideDropDown(); + }, + refresh: function (token, array) { + elem.style.visibility = 'hidden' + ix = 0 + elem.innerHTML = '' + var vph = (window.innerHeight || document.documentElement.clientHeight) + var rect = elem.parentNode.getBoundingClientRect() + var distanceToTop = rect.top - 6 // heuristic give 6px + var distanceToBottom = vph - rect.bottom - 6 // distance from the browser border. + + rows = [] + var filterFn = typeof config.filter === 'function' ? config.filter : defaultFilterFunction[config.filter] + + var filtered = !filterFn ? [] : array.filter(function (match) { + return filterFn(config.caseSensitive ? token : token.toLowerCase(), config.caseSensitive ? match : match.toLowerCase(), config) + }) + + rows = filtered.map(function (row) { + var divRow = document.createElement('div') + divRow.className = 'item' + // divRow.style.color = config.color; + divRow.onmouseover = onMouseOver + divRow.onmouseout = onMouseOut + divRow.onmousedown = onMouseDown + divRow.__hint = row + divRow.innerHTML = row.substring(0, token.length) + '' + row.substring(token.length) + '' + elem.appendChild(divRow) + return divRow + }) + + if (rows.length === 0) { + return // nothing to show. + } + if (rows.length === 1 && ((token.toLowerCase() === rows[0].__hint.toLowerCase() && !config.caseSensitive) || + (token === rows[0].__hint && config.caseSensitive))) { + return // do not show the dropDown if it has only one element which matches what we have just displayed. + } + + if (rows.length < 2) return + p.highlight(0) + + if (distanceToTop > distanceToBottom * 3) { // Heuristic (only when the distance to the to top is 4 times more than distance to the bottom + elem.style.maxHeight = distanceToTop + 'px' // we display the dropDown on the top of the input text + elem.style.top = '' + elem.style.bottom = '100%' + } else { + elem.style.top = '100%' + elem.style.bottom = '' + elem.style.maxHeight = distanceToBottom + 'px' + } + elem.style.visibility = 'visible' + }, + highlight: function (index) { + if (oldIndex !== -1 && rows[oldIndex]) { + rows[oldIndex].className = 'item' + } + rows[index].className = 'item hover' + oldIndex = index + }, + move: function (step) { // moves the selection either up or down (unless it's not possible) step is either +1 or -1. + if (elem.style.visibility === 'hidden') return '' // nothing to move if there is no dropDown. (this happens if the user hits escape and then down or up) + if (ix + step === -1 || ix + step === rows.length) return rows[ix].__hint // NO CIRCULAR SCROLLING. + ix += step + p.highlight(ix) + return rows[ix].__hint// txtShadow.value = uRows[uIndex].__hint ; + }, + onmouseselection: function () { } // it will be overwritten. + } + return p + } + + function setEndOfContenteditable (contentEditableElement) { + var range, selection + if (document.createRange) { + // Firefox, Chrome, Opera, Safari, IE 9+ + 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 + } else if (document.selection) { + // IE 8 and lower + range = document.body.createTextRange()// Create a range (a range is a like the selection but invisible) + range.moveToElementText(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 + range.select()// Select the range (make it the visible selection + } + } + + function calculateWidthForText (text) { + if (spacer === undefined) { // on first call only. + spacer = document.createElement('span') + spacer.style.visibility = 'hidden' + spacer.style.position = 'fixed' + spacer.style.outline = '0' + spacer.style.margin = '0' + spacer.style.padding = '0' + spacer.style.border = '0' + spacer.style.left = '0' + spacer.style.whiteSpace = 'pre' + spacer.style.fontSize = fontSize + spacer.style.fontFamily = fontFamily + spacer.style.fontWeight = 'normal' + document.body.appendChild(spacer) + } + + // Used to encode an HTML string into a plain text. + // taken from http://stackoverflow.com/questions/1219860/javascript-jquery-html-encoding + spacer.innerHTML = String(text).replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + return spacer.getBoundingClientRect().right + } + + var rs = { + onArrowDown: function () { }, // defaults to no action. + onArrowUp: function () { }, // defaults to no action. + onEnter: function () { }, // defaults to no action. + onTab: function () { }, // defaults to no action. + startFrom: 0, + options: [], + element: null, + elementHint: null, + elementStyle: null, + wrapper: wrapper, // Only to allow easy access to the HTML elements to the final user (possibly for minor customizations) + show: function (element, startPos, options) { + this.startFrom = startPos + this.wrapper.remove() + if (this.elementHint) { + this.elementHint.remove() + this.elementHint = null + } + + if (fontSize === '') { + fontSize = window.getComputedStyle(element).getPropertyValue('font-size') + } + if (fontFamily === '') { + fontFamily = window.getComputedStyle(element).getPropertyValue('font-family') + } + + dropDown.style.marginLeft = '0' + dropDown.style.marginTop = element.getBoundingClientRect().height + 'px' + this.options = options + + if (this.element !== element) { + this.element = element + this.elementStyle = { + zIndex: this.element.style.zIndex, + position: this.element.style.position, + backgroundColor: this.element.style.backgroundColor, + borderColor: this.element.style.borderColor + } + } + + this.element.style.zIndex = 3 + this.element.style.position = 'relative' + this.element.style.backgroundColor = 'transparent' + this.element.style.borderColor = 'transparent' + + this.elementHint = element.cloneNode() + this.elementHint.className = 'autocomplete hint' + this.elementHint.style.zIndex = 2 + this.elementHint.style.position = 'absolute' + this.elementHint.onfocus = function () { this.element.focus() }.bind(this) + + if (this.element.addEventListener) { + this.element.removeEventListener('keydown', keyDownHandler) + this.element.addEventListener('keydown', keyDownHandler, false) + this.element.removeEventListener('blur', onBlurHandler) + this.element.addEventListener('blur', onBlurHandler, false) + } + + wrapper.appendChild(this.elementHint) + wrapper.appendChild(dropDown) + element.parentElement.appendChild(wrapper) + + this.repaint(element) + }, + setText: function (text) { + this.element.innerText = text + }, + getText: function () { + return this.element.innerText + }, + hideDropDown: function () { + this.wrapper.remove() + if (this.elementHint) { + this.elementHint.remove() + this.elementHint = null + dropDownController.hide() + this.element.style.zIndex = this.elementStyle.zIndex + this.element.style.position = this.elementStyle.position + this.element.style.backgroundColor = this.elementStyle.backgroundColor + this.element.style.borderColor = this.elementStyle.borderColor + } + }, + repaint: function (element) { + var text = element.innerText + text = text.replace('\n', '') + + var optionsLength = this.options.length + + // breaking text in leftSide and token. + + var token = text.substring(this.startFrom) + leftSide = text.substring(0, this.startFrom) + + for (var i = 0; i < optionsLength; i++) { + var opt = this.options[i] + if ((!config.caseSensitive && opt.toLowerCase().indexOf(token.toLowerCase()) === 0) || + (config.caseSensitive && opt.indexOf(token) === 0)) { // <-- how about upperCase vs. lowercase + this.elementHint.innerText = leftSide + token + opt.substring(token.length) + this.elementHint.realInnerText = leftSide + opt + break + } + } + // moving the dropDown and refreshing it. + dropDown.style.left = calculateWidthForText(leftSide) + 'px' + dropDownController.refresh(token, this.options) + this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + 10 + 'px' + var wasDropDownHidden = (dropDown.style.visibility === 'hidden') + if (!wasDropDownHidden) { this.elementHint.style.width = calculateWidthForText(this.elementHint.innerText) + dropDown.clientWidth + 'px' } + } + } + + var dropDownController = createDropDownController(dropDown, rs) + + var keyDownHandler = function (e) { + // console.log("Keydown:" + e.keyCode); + e = e || window.event + var keyCode = e.keyCode + + if (this.elementHint == null) return + + if (keyCode === 33) { return } // page up (do nothing) + if (keyCode === 34) { return } // page down (do nothing); + + if (keyCode === 27) { // escape + rs.hideDropDown() + rs.element.focus() + e.preventDefault() + e.stopPropagation() + return + } + + var text = this.element.innerText + text = text.replace('\n', '') + + if (config.confirmKeys.indexOf(keyCode) >= 0) { // (autocomplete triggered) + if (keyCode === 9) { + if (this.elementHint.innerText.length === 0) { + rs.onTab() + } + } + if (this.elementHint.innerText.length > 0) { // if there is a hint + if (this.element.innerText !== this.elementHint.realInnerText) { + this.element.innerText = this.elementHint.realInnerText + rs.hideDropDown() + setEndOfContenteditable(this.element) + if (keyCode === 9) { + rs.element.focus() + e.preventDefault() + e.stopPropagation() + } + } + } + return + } + + if (keyCode === 13) { // enter (autocomplete triggered) + if (this.elementHint.innerText.length === 0) { // if there is a hint + rs.onEnter() + } else { + var wasDropDownHidden = (dropDown.style.visibility === 'hidden') + dropDownController.hide() + + if (wasDropDownHidden) { + rs.hideDropDown() + rs.element.focus() + rs.onEnter() + return + } + + this.element.innerText = this.elementHint.realInnerText + rs.hideDropDown() + setEndOfContenteditable(this.element) + e.preventDefault() + e.stopPropagation() + } + return + } + + if (keyCode === 40) { // down + const token = text.substring(this.startFrom) + const m = dropDownController.move(+1) + if (m === '') { rs.onArrowDown() } + this.elementHint.innerText = leftSide + token + m.substring(token.length) + this.elementHint.realInnerText = leftSide + m + e.preventDefault() + e.stopPropagation() + return + } + + if (keyCode === 38) { // up + const token = text.substring(this.startFrom) + const m = dropDownController.move(-1) + if (m === '') { rs.onArrowUp() } + this.elementHint.innerText = leftSide + token + m.substring(token.length) + this.elementHint.realInnerText = leftSide + m + e.preventDefault() + e.stopPropagation() + } + }.bind(rs) + + var onBlurHandler = function (e) { + rs.hideDropDown() + // console.log("Lost focus."); + } + + dropDownController.onmouseselection = function (text, rs) { + rs.element.innerText = rs.elementHint.innerText = leftSide + text + rs.hideDropDown() + window.setTimeout(function () { + rs.element.focus() + setEndOfContenteditable(rs.element) + }, 1) + } + + return rs +} + +module.exports = completely diff --git a/src/js/constants.js b/src/js/constants.js index 7f5f469..8a11c58 100644 --- a/src/js/constants.js +++ b/src/js/constants.js @@ -1,7 +1,7 @@ -exports.DEFAULT_MODAL_ANCHOR = document.body; -exports.SIZE_LARGE = 10 * 1024 * 1024; // 10 MB +exports.DEFAULT_MODAL_ANCHOR = document.body +exports.SIZE_LARGE = 10 * 1024 * 1024 // 10 MB -exports.MAX_PREVIEW_CHARACTERS = 20000; +exports.MAX_PREVIEW_CHARACTERS = 20000 -exports.PREVIEW_HISTORY_LIMIT = 2 * 1024 * 1024 * 1024; // 2 GB +exports.PREVIEW_HISTORY_LIMIT = 2 * 1024 * 1024 * 1024 // 2 GB diff --git a/src/js/createAbsoluteAnchor.js b/src/js/createAbsoluteAnchor.js index 32bf7cf..6445b42 100644 --- a/src/js/createAbsoluteAnchor.js +++ b/src/js/createAbsoluteAnchor.js @@ -1,4 +1,4 @@ -var util = require('./util'); +var util = require('./util') /** * Create an anchor element absolutely positioned in the `parent` @@ -9,58 +9,58 @@ var util = require('./util'); * @returns {HTMLElement} */ exports.createAbsoluteAnchor = function (anchor, parent, onDestroy) { - var root = getRootNode(anchor); - var eventListeners = {}; + var root = getRootNode(anchor) + var eventListeners = {} - var anchorRect = anchor.getBoundingClientRect(); - var frameRect = parent.getBoundingClientRect(); + var anchorRect = anchor.getBoundingClientRect() + var frameRect = parent.getBoundingClientRect() - var absoluteAnchor = document.createElement('div'); - absoluteAnchor.className = 'jsoneditor-anchor'; - absoluteAnchor.style.position = 'absolute'; - absoluteAnchor.style.left = (anchorRect.left - frameRect.left) + 'px'; - absoluteAnchor.style.top = (anchorRect.top - frameRect.top) + 'px'; - absoluteAnchor.style.width = (anchorRect.width - 2) + 'px'; - absoluteAnchor.style.height = (anchorRect.height - 2) + 'px'; - absoluteAnchor.style.boxSizing = 'border-box'; - parent.appendChild(absoluteAnchor); + var absoluteAnchor = document.createElement('div') + absoluteAnchor.className = 'jsoneditor-anchor' + absoluteAnchor.style.position = 'absolute' + absoluteAnchor.style.left = (anchorRect.left - frameRect.left) + 'px' + absoluteAnchor.style.top = (anchorRect.top - frameRect.top) + 'px' + absoluteAnchor.style.width = (anchorRect.width - 2) + 'px' + absoluteAnchor.style.height = (anchorRect.height - 2) + 'px' + absoluteAnchor.style.boxSizing = 'border-box' + parent.appendChild(absoluteAnchor) function destroy () { // remove temporary absolutely positioned anchor if (absoluteAnchor && absoluteAnchor.parentNode) { - absoluteAnchor.parentNode.removeChild(absoluteAnchor); + absoluteAnchor.parentNode.removeChild(absoluteAnchor) // remove all event listeners // all event listeners are supposed to be attached to document. for (var name in eventListeners) { - if (eventListeners.hasOwnProperty(name)) { - var fn = eventListeners[name]; + if (hasOwnProperty(eventListeners, name)) { + var fn = eventListeners[name] if (fn) { - util.removeEventListener(root, name, fn); + util.removeEventListener(root, name, fn) } - delete eventListeners[name]; + delete eventListeners[name] } } if (typeof onDestroy === 'function') { - onDestroy(anchor); + onDestroy(anchor) } } } // create and attach event listeners var destroyIfOutside = function (event) { - var target = event.target; + var target = event.target if ((target !== absoluteAnchor) && !util.isChildOf(target, absoluteAnchor)) { - destroy(); + destroy() } } - eventListeners.mousedown = util.addEventListener(root, 'mousedown', destroyIfOutside); - eventListeners.mousewheel = util.addEventListener(root, 'mousewheel', destroyIfOutside); + eventListeners.mousedown = util.addEventListener(root, 'mousedown', destroyIfOutside) + eventListeners.mousewheel = util.addEventListener(root, 'mousewheel', destroyIfOutside) // eventListeners.scroll = util.addEventListener(root, 'scroll', destroyIfOutside); - absoluteAnchor.destroy = destroy; + absoluteAnchor.destroy = destroy return absoluteAnchor } @@ -70,8 +70,12 @@ exports.createAbsoluteAnchor = function (anchor, parent, onDestroy) { * @param {HTMLElement} node node to check * @return {HTMLElement} node's rootNode or `window` if there is ShadowDOM is not supported. */ -function getRootNode(node){ +function getRootNode (node) { return (typeof node.getRootNode === 'function') - ? node.getRootNode() - : window; + ? node.getRootNode() + : window +} + +function hasOwnProperty (object, key) { + return Object.prototype.hasOwnProperty.call(object, key) } diff --git a/src/js/header.js b/src/js/header.js index 6485d8c..ccb8b51 100644 --- a/src/js/header.js +++ b/src/js/header.js @@ -26,4 +26,4 @@ * @author Jos de Jong, * @version @@version * @date @@date - */ \ No newline at end of file + */ diff --git a/src/js/i18n.js b/src/js/i18n.js index b379abe..b255ecd 100644 --- a/src/js/i18n.js +++ b/src/js/i18n.js @@ -1,8 +1,10 @@ -'use strict'; +'use strict' -require('./polyfills'); +/* eslint-disable no-template-curly-in-string */ -var _locales = ['en', 'pt-BR', 'zh-CN', 'tr']; +require('./polyfills') + +var _locales = ['en', 'pt-BR', 'zh-CN', 'tr'] var _defs = { en: { array: 'Array', @@ -93,7 +95,7 @@ var _defs = { modePreviewText: 'Preview', modePreviewTitle: 'Switch to preview mode', examples: 'Examples', - default: 'Default', + default: 'Default' }, 'zh-CN': { array: '数组', @@ -184,7 +186,7 @@ var _defs = { modePreviewText: '预览', modePreviewTitle: '切换至预览模式', examples: '例子', - default: '缺省', + default: '缺省' }, 'pt-BR': { array: 'Lista', @@ -283,7 +285,7 @@ var _defs = { 'Campo do tipo nao é determinado através do seu valor, ' + 'mas sempre retornara um texto.', examples: 'Exemplos', - default: 'Revelia', + default: 'Revelia' }, tr: { array: 'Dizin', @@ -370,20 +372,20 @@ var _defs = { modeViewText: 'Görünüm', modeViewTitle: 'Ağaç görünümüne geç', examples: 'Örnekler', - default: 'Varsayılan', + default: 'Varsayılan' } -}; +} -var _defaultLang = 'en'; -var _lang; -var userLang = typeof navigator !== 'undefined' ? - navigator.language || navigator.userLanguage : - undefined; +var _defaultLang = 'en' +var _lang +var userLang = typeof navigator !== 'undefined' + ? navigator.language || navigator.userLanguage + : undefined _lang = _locales.find(function (l) { - return l === userLang; -}); + return l === userLang +}) if (!_lang) { - _lang = _defaultLang; + _lang = _defaultLang } module.exports = { @@ -393,41 +395,41 @@ module.exports = { _lang: _lang, setLanguage: function (lang) { if (!lang) { - return; + return } var langFound = _locales.find(function (l) { - return l === lang; - }); + return l === lang + }) if (langFound) { - _lang = langFound; + _lang = langFound } else { - console.error('Language not found'); + console.error('Language not found') } }, setLanguages: function (languages) { if (!languages) { - return; + return } for (var key in languages) { var langFound = _locales.find(function (l) { - return l === key; - }); + return l === key + }) if (!langFound) { - _locales.push(key); + _locales.push(key) } - _defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]); + _defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]) } }, translate: function (key, data, lang) { if (!lang) { - lang = _lang; + lang = _lang } - var text = _defs[lang][key]; + var text = _defs[lang][key] if (data) { for (key in data) { - text = text.replace('${' + key + '}', data[key]); + text = text.replace('${' + key + '}', data[key]) } } - return text || key; + return text || key } -}; \ No newline at end of file +} diff --git a/src/js/jsonUtils.js b/src/js/jsonUtils.js index 52b9e67..e3d98dd 100644 --- a/src/js/jsonUtils.js +++ b/src/js/jsonUtils.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' /** * Convert part of a JSON object to a JSON string. @@ -21,26 +21,24 @@ * * @returns {string | undefined} Returns the string representation of the JSON object. */ -function stringifyPartial(value, space, limit) { - var _space; // undefined by default +function stringifyPartial (value, space, limit) { + var _space // undefined by default if (typeof space === 'number') { if (space > 10) { - _space = repeat(' ', 10); - } - else if (space >= 1) { - _space = repeat(' ', space); + _space = repeat(' ', 10) + } else if (space >= 1) { + _space = repeat(' ', space) } // else ignore - } - else if (typeof space === 'string' && space !== '') { - _space = space; + } else if (typeof space === 'string' && space !== '') { + _space = space } - var output = stringifyValue(value, _space, '', limit); + var output = stringifyValue(value, _space, '', limit) return output.length > limit - ? (slice(output, limit) + '...') - : output; + ? (slice(output, limit) + '...') + : output } /** @@ -51,27 +49,27 @@ function stringifyPartial(value, space, limit) { * @param {number} limit * @return {string | undefined} */ -function stringifyValue(value, space, indent, limit) { +function stringifyValue (value, space, indent, limit) { // boolean, null, number, string, or date if (typeof value === 'boolean' || value instanceof Boolean || value === null || typeof value === 'number' || value instanceof Number || typeof value === 'string' || value instanceof String || value instanceof Date) { - return JSON.stringify(value); + return JSON.stringify(value) } // array if (Array.isArray(value)) { - return stringifyArray(value, space, indent, limit); + return stringifyArray(value, space, indent, limit) } // object (test lastly!) if (value && typeof value === 'object') { - return stringifyObject(value, space, indent, limit); + return stringifyObject(value, space, indent, limit) } - return undefined; + return undefined } /** @@ -82,36 +80,35 @@ function stringifyValue(value, space, indent, limit) { * @param {number} limit * @return {string} */ -function stringifyArray(array, space, indent, limit) { - var childIndent = space ? (indent + space) : undefined; - var str = space ? '[\n' : '['; +function stringifyArray (array, space, indent, limit) { + var childIndent = space ? (indent + space) : undefined + var str = space ? '[\n' : '[' for (var i = 0; i < array.length; i++) { - var item = array[i]; + var item = array[i] if (space) { - str += childIndent; + str += childIndent } if (typeof item !== 'undefined' && typeof item !== 'function') { - str += stringifyValue(item, space, childIndent, limit); - } - else { + str += stringifyValue(item, space, childIndent, limit) + } else { str += 'null' } if (i < array.length - 1) { - str += space ? ',\n' : ','; + str += space ? ',\n' : ',' } // stop as soon as we're exceeding the limit if (str.length > limit) { - return str + '...'; + return str + '...' } } - str += space ? ('\n' + indent + ']') : ']'; - return str; + str += space ? ('\n' + indent + ']') : ']' + return str } /** @@ -122,41 +119,40 @@ function stringifyArray(array, space, indent, limit) { * @param {number} limit * @return {string} */ -function stringifyObject(object, space, indent, limit) { - var childIndent = space ? (indent + space) : undefined; - var first = true; - var str = space ? '{\n' : '{'; +function stringifyObject (object, space, indent, limit) { + var childIndent = space ? (indent + space) : undefined + var first = true + var str = space ? '{\n' : '{' if (typeof object.toJSON === 'function') { - return stringifyValue(object.toJSON(), space, indent, limit); + return stringifyValue(object.toJSON(), space, indent, limit) } for (var key in object) { - if (object.hasOwnProperty(key)) { - var value = object[key]; + if (hasOwnProperty(object, key)) { + var value = object[key] if (first) { - first = false; - } - else { - str += space ? ',\n' : ','; + first = false + } else { + str += space ? ',\n' : ',' } str += space - ? (childIndent + '"' + key + '": ') - : ('"' + key + '":'); + ? (childIndent + '"' + key + '": ') + : ('"' + key + '":') - str += stringifyValue(value, space, childIndent, limit); + str += stringifyValue(value, space, childIndent, limit) // stop as soon as we're exceeding the limit if (str.length > limit) { - return str + '...'; + return str + '...' } } } - str += space ? ('\n' + indent + '}') : '}'; - return str; + str += space ? ('\n' + indent + '}') : '}' + return str } /** @@ -167,11 +163,11 @@ function stringifyObject(object, space, indent, limit) { * @return {string} */ function repeat (text, times) { - var res = ''; + var res = '' while (times-- > 0) { - res += text; + res += text } - return res; + return res } /** @@ -180,10 +176,10 @@ function repeat (text, times) { * @param {number} [limit] * @return {string} */ -function slice(text, limit) { +function slice (text, limit) { return typeof limit === 'number' - ? text.slice(0, limit) - : text; + ? text.slice(0, limit) + : text } /** @@ -196,5 +192,9 @@ function containsArray (jsonText) { return /^\s*\[/.test(jsonText) } -exports.stringifyPartial = stringifyPartial; -exports.containsArray = containsArray; +function hasOwnProperty (object, key) { + return Object.prototype.hasOwnProperty.call(object, key) +} + +exports.stringifyPartial = stringifyPartial +exports.containsArray = containsArray diff --git a/src/js/polyfills.js b/src/js/polyfills.js index db68ce5..ec444ee 100644 --- a/src/js/polyfills.js +++ b/src/js/polyfills.js @@ -3,42 +3,33 @@ if (typeof Element !== 'undefined') { // Polyfill for array remove (function () { function polyfill (item) { - if (item.hasOwnProperty('remove')) { - return; + if ('remove' in item) { + return } Object.defineProperty(item, 'remove', { configurable: true, enumerable: true, writable: true, - value: function remove() { - if (this.parentNode != null) - this.parentNode.removeChild(this); + value: function remove () { + if (this.parentNode !== undefined) { this.parentNode.removeChild(this) } } - }); + }) } - if (typeof Element !== 'undefined') { polyfill(Element.prototype); } - if (typeof CharacterData !== 'undefined') { polyfill(CharacterData.prototype); } - if (typeof DocumentType !== 'undefined') { polyfill(DocumentType.prototype); } - })(); -} - - -// Polyfill for startsWith -if (!String.prototype.startsWith) { - String.prototype.startsWith = function (searchString, position) { - position = position || 0; - return this.substr(position, searchString.length) === searchString; - }; + if (typeof window.Element !== 'undefined') { polyfill(window.Element.prototype) } + if (typeof window.CharacterData !== 'undefined') { polyfill(window.CharacterData.prototype) } + if (typeof window.DocumentType !== 'undefined') { polyfill(window.DocumentType.prototype) } + })() } // Polyfill for Array.find if (!Array.prototype.find) { - Array.prototype.find = function(callback) { + // eslint-disable-next-line no-extend-native + Array.prototype.find = function (callback) { for (var i = 0; i < this.length; i++) { - var element = this[i]; - if ( callback.call(this, element, i, this) ) { - return element; + var element = this[i] + if (callback.call(this, element, i, this)) { + return element } } } @@ -46,7 +37,8 @@ if (!Array.prototype.find) { // Polyfill for String.trim if (!String.prototype.trim) { + // eslint-disable-next-line no-extend-native String.prototype.trim = function () { - return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - }; + return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '') + } } diff --git a/src/js/previewmode.js b/src/js/previewmode.js index 7880709..e7eaac7 100644 --- a/src/js/previewmode.js +++ b/src/js/previewmode.js @@ -1,21 +1,21 @@ -'use strict'; +'use strict' -var jmespath = require('jmespath'); -var translate = require('./i18n').translate; -var ModeSwitcher = require('./ModeSwitcher'); -var ErrorTable = require('./ErrorTable'); -var textmode = require('./textmode')[0].mixin; -var showSortModal = require('./showSortModal'); -var showTransformModal = require('./showTransformModal'); -var MAX_PREVIEW_CHARACTERS = require('./constants').MAX_PREVIEW_CHARACTERS; -var DEFAULT_MODAL_ANCHOR = require('./constants').DEFAULT_MODAL_ANCHOR; -var SIZE_LARGE = require('./constants').SIZE_LARGE; -var PREVIEW_HISTORY_LIMIT = require('./constants').PREVIEW_HISTORY_LIMIT; -var util = require('./util'); -var History = require('./History'); +var jmespath = require('jmespath') +var translate = require('./i18n').translate +var ModeSwitcher = require('./ModeSwitcher') +var ErrorTable = require('./ErrorTable') +var textmode = require('./textmode')[0].mixin +var showSortModal = require('./showSortModal') +var showTransformModal = require('./showTransformModal') +var MAX_PREVIEW_CHARACTERS = require('./constants').MAX_PREVIEW_CHARACTERS +var DEFAULT_MODAL_ANCHOR = require('./constants').DEFAULT_MODAL_ANCHOR +var SIZE_LARGE = require('./constants').SIZE_LARGE +var PREVIEW_HISTORY_LIMIT = require('./constants').PREVIEW_HISTORY_LIMIT +var util = require('./util') +var History = require('./History') // create a mixin with the functions for text mode -var previewmode = {}; +var previewmode = {} /** * Create a JSON document preview, suitable for processing of large documents @@ -25,274 +25,269 @@ var previewmode = {}; */ previewmode.create = function (container, options) { // read options - options = options || {}; - + options = options || {} + if (typeof options.statusBar === 'undefined') { - options.statusBar = true; + options.statusBar = true } // setting default for previewmode - options.mainMenuBar = options.mainMenuBar !== false; - options.enableSort = options.enableSort !== false; - options.enableTransform = options.enableTransform !== false; + options.mainMenuBar = options.mainMenuBar !== false + options.enableSort = options.enableSort !== false + options.enableTransform = options.enableTransform !== false - this.options = options; + this.options = options // indentation if (options.indentation) { - this.indentation = Number(options.indentation); - } - else { - this.indentation = 2; // number of spaces + this.indentation = Number(options.indentation) + } else { + this.indentation = 2 // number of spaces } // determine mode - this.mode = 'preview'; + this.mode = 'preview' - var me = this; - this.container = container; - this.dom = {}; + var me = this + this.container = container + this.dom = {} - this.json = undefined; - this.text = ''; + this.json = undefined + this.text = '' // TODO: JSON Schema support // create a debounced validate function - this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); + this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL) - this.width = container.clientWidth; - this.height = container.clientHeight; + this.width = container.clientWidth + this.height = container.clientHeight - this.frame = document.createElement('div'); - this.frame.className = 'jsoneditor jsoneditor-mode-preview'; + this.frame = document.createElement('div') + this.frame.className = 'jsoneditor jsoneditor-mode-preview' this.frame.onclick = function (event) { // prevent default submit action when the editor is located inside a form - event.preventDefault(); - }; + event.preventDefault() + } - this.content = document.createElement('div'); - this.content.className = 'jsoneditor-outer'; + this.content = document.createElement('div') + this.content.className = 'jsoneditor-outer' this.dom.busy = document.createElement('div') - this.dom.busy.className = 'jsoneditor-busy'; - this.dom.busyContent = document.createElement('span'); - this.dom.busyContent.innerHTML = 'busy...'; - this.dom.busy.appendChild(this.dom.busyContent); - this.content.appendChild(this.dom.busy); + this.dom.busy.className = 'jsoneditor-busy' + this.dom.busyContent = document.createElement('span') + this.dom.busyContent.innerHTML = 'busy...' + this.dom.busy.appendChild(this.dom.busyContent) + this.content.appendChild(this.dom.busy) - this.dom.previewContent = document.createElement('pre'); - this.dom.previewContent.className = 'jsoneditor-preview'; - this.dom.previewText = document.createTextNode(''); - this.dom.previewContent.appendChild(this.dom.previewText); - this.content.appendChild(this.dom.previewContent); + this.dom.previewContent = document.createElement('pre') + this.dom.previewContent.className = 'jsoneditor-preview' + this.dom.previewText = document.createTextNode('') + this.dom.previewContent.appendChild(this.dom.previewText) + this.content.appendChild(this.dom.previewContent) if (this.options.mainMenuBar) { - util.addClassName(this.content, 'has-main-menu-bar'); + util.addClassName(this.content, 'has-main-menu-bar') // create menu - this.menu = document.createElement('div'); - this.menu.className = 'jsoneditor-menu'; - this.frame.appendChild(this.menu); + this.menu = document.createElement('div') + this.menu.className = 'jsoneditor-menu' + this.frame.appendChild(this.menu) // create format button - var buttonFormat = document.createElement('button'); - buttonFormat.type = 'button'; - buttonFormat.className = 'jsoneditor-format'; - buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)'; - this.menu.appendChild(buttonFormat); - buttonFormat.onclick = function handleFormat() { + var buttonFormat = document.createElement('button') + buttonFormat.type = 'button' + buttonFormat.className = 'jsoneditor-format' + buttonFormat.title = 'Format JSON data, with proper indentation and line feeds (Ctrl+\\)' + this.menu.appendChild(buttonFormat) + buttonFormat.onclick = function handleFormat () { me.executeWithBusyMessage(function () { try { - me.format(); + me.format() + } catch (err) { + me._onError(err) } - catch (err) { - me._onError(err); - } - }, 'formatting...'); - }; + }, 'formatting...') + } // create compact button - var buttonCompact = document.createElement('button'); - buttonCompact.type = 'button'; - buttonCompact.className = 'jsoneditor-compact'; - buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)'; - this.menu.appendChild(buttonCompact); - buttonCompact.onclick = function handleCompact() { + var buttonCompact = document.createElement('button') + buttonCompact.type = 'button' + buttonCompact.className = 'jsoneditor-compact' + buttonCompact.title = 'Compact JSON data, remove all whitespaces (Ctrl+Shift+\\)' + this.menu.appendChild(buttonCompact) + buttonCompact.onclick = function handleCompact () { me.executeWithBusyMessage(function () { try { - me.compact(); + me.compact() + } catch (err) { + me._onError(err) } - catch (err) { - me._onError(err); - } - }, 'compacting...'); - }; + }, 'compacting...') + } // create sort button if (this.options.enableSort) { - var sort = document.createElement('button'); - sort.type = 'button'; - sort.className = 'jsoneditor-sort'; - sort.title = translate('sortTitleShort'); + var sort = document.createElement('button') + sort.type = 'button' + sort.className = 'jsoneditor-sort' + sort.title = translate('sortTitleShort') sort.onclick = function () { - me._showSortModal(); - }; - this.menu.appendChild(sort); + me._showSortModal() + } + this.menu.appendChild(sort) } // create transform button if (this.options.enableTransform) { - var transform = document.createElement('button'); - transform.type = 'button'; - transform.title = translate('transformTitleShort'); - transform.className = 'jsoneditor-transform'; + var transform = document.createElement('button') + transform.type = 'button' + transform.title = translate('transformTitleShort') + transform.className = 'jsoneditor-transform' transform.onclick = function () { - me._showTransformModal(); - }; - this.dom.transform = transform; - this.menu.appendChild(transform); + me._showTransformModal() + } + this.dom.transform = transform + this.menu.appendChild(transform) } // create repair button - var buttonRepair = document.createElement('button'); - buttonRepair.type = 'button'; - buttonRepair.className = 'jsoneditor-repair'; - buttonRepair.title = 'Repair JSON: fix quotes and escape characters, remove comments and JSONP notation, turn JavaScript objects into JSON.'; - this.menu.appendChild(buttonRepair); + var buttonRepair = document.createElement('button') + buttonRepair.type = 'button' + buttonRepair.className = 'jsoneditor-repair' + buttonRepair.title = 'Repair JSON: fix quotes and escape characters, remove comments and JSONP notation, turn JavaScript objects into JSON.' + this.menu.appendChild(buttonRepair) buttonRepair.onclick = function () { if (me.json === undefined) { // only repair if we don't have valid JSON me.executeWithBusyMessage(function () { try { - me.repair(); + me.repair() + } catch (err) { + me._onError(err) } - catch (err) { - me._onError(err); - } - }, 'repairing...'); + }, 'repairing...') } - }; + } // create history and undo/redo buttons if (this.options.history !== false) { // default option value is true var onHistoryChange = function () { - me.dom.undo.disabled = !me.history.canUndo(); - me.dom.redo.disabled = !me.history.canRedo(); - }; - - var calculateItemSize = function (item) { - return item.text.length * 2; // times two to account for the json object + me.dom.undo.disabled = !me.history.canUndo() + me.dom.redo.disabled = !me.history.canRedo() } - this.history = new History(onHistoryChange, calculateItemSize, PREVIEW_HISTORY_LIMIT); + var calculateItemSize = function (item) { + return item.text.length * 2 // times two to account for the json object + } + + this.history = new History(onHistoryChange, calculateItemSize, PREVIEW_HISTORY_LIMIT) // create undo button - var undo = document.createElement('button'); - undo.type = 'button'; - undo.className = 'jsoneditor-undo jsoneditor-separator'; - undo.title = translate('undo'); + var undo = document.createElement('button') + undo.type = 'button' + undo.className = 'jsoneditor-undo jsoneditor-separator' + undo.title = translate('undo') undo.onclick = function () { - var action = me.history.undo(); + var action = me.history.undo() if (action) { - me._applyHistory(action); + me._applyHistory(action) } - }; - this.menu.appendChild(undo); - this.dom.undo = undo; + } + this.menu.appendChild(undo) + this.dom.undo = undo // create redo button - var redo = document.createElement('button'); - redo.type = 'button'; - redo.className = 'jsoneditor-redo'; - redo.title = translate('redo'); + var redo = document.createElement('button') + redo.type = 'button' + redo.className = 'jsoneditor-redo' + redo.title = translate('redo') redo.onclick = function () { - var action = me.history.redo(); + var action = me.history.redo() if (action) { - me._applyHistory(action); + me._applyHistory(action) } - }; - this.menu.appendChild(redo); - this.dom.redo = redo; + } + this.menu.appendChild(redo) + this.dom.redo = redo // force enabling/disabling the undo/redo button - this.history.onChange(); + this.history.onChange() } // create mode box if (this.options && this.options.modes && this.options.modes.length) { - this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch(mode) { + this.modeSwitcher = new ModeSwitcher(this.menu, this.options.modes, this.options.mode, function onSwitch (mode) { // switch mode and restore focus - me.setMode(mode); - me.modeSwitcher.focus(); - }); + me.setMode(mode) + me.modeSwitcher.focus() + }) } } this.errorTable = new ErrorTable({ errorTableVisible: true, onToggleVisibility: function () { - me.validate(); + me.validate() }, onFocusLine: null, onChangeHeight: function (height) { // TODO: change CSS to using flex box, remove setting height using JavaScript - var statusBarHeight = me.dom.statusBar ? me.dom.statusBar.clientHeight : 0; - var totalHeight = height + statusBarHeight + 1; - me.content.style.marginBottom = (-totalHeight) + 'px'; - me.content.style.paddingBottom = totalHeight + 'px'; + var statusBarHeight = me.dom.statusBar ? me.dom.statusBar.clientHeight : 0 + var totalHeight = height + statusBarHeight + 1 + me.content.style.marginBottom = (-totalHeight) + 'px' + me.content.style.paddingBottom = totalHeight + 'px' } - }); + }) - this.frame.appendChild(this.content); - this.frame.appendChild(this.errorTable.getErrorTable()); - this.container.appendChild(this.frame); + this.frame.appendChild(this.content) + this.frame.appendChild(this.errorTable.getErrorTable()) + this.container.appendChild(this.frame) if (options.statusBar) { - util.addClassName(this.content, 'has-status-bar'); + util.addClassName(this.content, 'has-status-bar') - var statusBar = document.createElement('div'); - this.dom.statusBar = statusBar; - statusBar.className = 'jsoneditor-statusbar'; - this.frame.appendChild(statusBar); + var statusBar = document.createElement('div') + this.dom.statusBar = statusBar + statusBar.className = 'jsoneditor-statusbar' + this.frame.appendChild(statusBar) - this.dom.fileSizeInfo = document.createElement('span'); - this.dom.fileSizeInfo.className = 'jsoneditor-size-info'; - this.dom.fileSizeInfo.innerText = ''; - statusBar.appendChild(this.dom.fileSizeInfo); + this.dom.fileSizeInfo = document.createElement('span') + this.dom.fileSizeInfo.className = 'jsoneditor-size-info' + this.dom.fileSizeInfo.innerText = '' + statusBar.appendChild(this.dom.fileSizeInfo) - this.dom.arrayInfo = document.createElement('span'); - this.dom.arrayInfo.className = 'jsoneditor-size-info'; - this.dom.arrayInfo.innerText = ''; - statusBar.appendChild(this.dom.arrayInfo); + this.dom.arrayInfo = document.createElement('span') + this.dom.arrayInfo.className = 'jsoneditor-size-info' + this.dom.arrayInfo.innerText = '' + statusBar.appendChild(this.dom.arrayInfo) - statusBar.appendChild(this.errorTable.getErrorCounter()); - statusBar.appendChild(this.errorTable.getWarningIcon()); - statusBar.appendChild(this.errorTable.getErrorIcon()); + statusBar.appendChild(this.errorTable.getErrorCounter()) + statusBar.appendChild(this.errorTable.getWarningIcon()) + statusBar.appendChild(this.errorTable.getErrorIcon()) } - this._renderPreview(); + this._renderPreview() - this.setSchema(this.options.schema, this.options.schemaRefs); -}; + this.setSchema(this.options.schema, this.options.schemaRefs) +} previewmode._renderPreview = function () { - var text = this.getText(); + var text = this.getText() - this.dom.previewText.nodeValue = util.limitCharacters(text, MAX_PREVIEW_CHARACTERS); + this.dom.previewText.nodeValue = util.limitCharacters(text, MAX_PREVIEW_CHARACTERS) if (this.dom.fileSizeInfo) { - this.dom.fileSizeInfo.innerText = 'Size: ' + util.formatSize(text.length); + this.dom.fileSizeInfo.innerText = 'Size: ' + util.formatSize(text.length) } if (this.dom.arrayInfo) { if (Array.isArray(this.json)) { - this.dom.arrayInfo.innerText = ('Array: ' + this.json.length + ' items'); - } - else { - this.dom.arrayInfo.innerText = ''; + this.dom.arrayInfo.innerText = ('Array: ' + this.json.length + ' items') + } else { + this.dom.arrayInfo.innerText = '' } } -}; +} /** * Handle a change: @@ -302,73 +297,70 @@ previewmode._renderPreview = function () { */ previewmode._onChange = function () { // validate JSON schema (if configured) - this._debouncedValidate(); + this._debouncedValidate() // trigger the onChange callback if (this.options.onChange) { try { - this.options.onChange(); - } - catch (err) { - console.error('Error in onChange callback: ', err); + this.options.onChange() + } catch (err) { + console.error('Error in onChange callback: ', err) } } // trigger the onChangeJSON callback if (this.options.onChangeJSON) { try { - this.options.onChangeJSON(this.get()); - } - catch (err) { - console.error('Error in onChangeJSON callback: ', err); + this.options.onChangeJSON(this.get()) + } catch (err) { + console.error('Error in onChangeJSON callback: ', err) } } // trigger the onChangeText callback if (this.options.onChangeText) { try { - this.options.onChangeText(this.getText()); - } - catch (err) { - console.error('Error in onChangeText callback: ', err); + this.options.onChangeText(this.getText()) + } catch (err) { + console.error('Error in onChangeText callback: ', err) } } -}; +} /** * Open a sort modal * @private */ previewmode._showSortModal = function () { - var me = this; + var me = this function onSort (json, sortedBy) { if (Array.isArray(json)) { - var sortedArray = util.sort(json, sortedBy.path, sortedBy.direction); + var sortedArray = util.sort(json, sortedBy.path, sortedBy.direction) me.sortedBy = sortedBy - me._setAndFireOnChange(sortedArray); + me._setAndFireOnChange(sortedArray) } if (util.isObject(json)) { - var sortedObject = util.sortObjectKeys(json, sortedBy.direction); + var sortedObject = util.sortObjectKeys(json, sortedBy.direction) - me.sortedBy = sortedBy; - me._setAndFireOnChange(sortedObject); + me.sortedBy = sortedBy + me._setAndFireOnChange(sortedObject) } } this.executeWithBusyMessage(function () { - var container = me.options.modalAnchor || DEFAULT_MODAL_ANCHOR; - var json = me.get(); - me._renderPreview(); // update array count + var container = me.options.modalAnchor || DEFAULT_MODAL_ANCHOR + var json = me.get() + me._renderPreview() // update array count showSortModal(container, json, function (sortedBy) { me.executeWithBusyMessage(function () { - onSort(json, sortedBy); - }, 'sorting...'); + onSort(json, sortedBy) + }, 'sorting...') }, me.sortedBy) - }, 'parsing...'); + }, 'parsing...') } /** @@ -376,17 +368,17 @@ previewmode._showSortModal = function () { * @private */ previewmode._showTransformModal = function () { - var me = this; + var me = this this.executeWithBusyMessage(function () { - var anchor = me.options.modalAnchor || DEFAULT_MODAL_ANCHOR; - var json = me.get(); - me._renderPreview(); // update array count + var anchor = me.options.modalAnchor || DEFAULT_MODAL_ANCHOR + var json = me.get() + me._renderPreview() // update array count showTransformModal(anchor, json, function (query) { me.executeWithBusyMessage(function () { - var updatedJson = jmespath.search(json, query); - me._setAndFireOnChange(updatedJson); + var updatedJson = jmespath.search(json, query) + me._setAndFireOnChange(updatedJson) }, 'transforming...') }) }, 'parsing...') @@ -397,51 +389,51 @@ previewmode._showTransformModal = function () { */ previewmode.destroy = function () { if (this.frame && this.container && this.frame.parentNode === this.container) { - this.container.removeChild(this.frame); + this.container.removeChild(this.frame) } if (this.modeSwitcher) { - this.modeSwitcher.destroy(); - this.modeSwitcher = null; + this.modeSwitcher.destroy() + this.modeSwitcher = null } - this._debouncedValidate = null; + this._debouncedValidate = null - this.history.clear(); - this.history = null; -}; + this.history.clear() + this.history = null +} /** * Compact the code in the text editor */ previewmode.compact = function () { - var json = this.get(); - var text = JSON.stringify(json); + var json = this.get() + var text = JSON.stringify(json) // we know that in this case the json is still the same, so we pass json too - this._setTextAndFireOnChange(text, json); -}; + this._setTextAndFireOnChange(text, json) +} /** * Format the code in the text editor */ previewmode.format = function () { - var json = this.get(); - var text = JSON.stringify(json, null, this.indentation); + var json = this.get() + var text = JSON.stringify(json, null, this.indentation) // we know that in this case the json is still the same, so we pass json too - this._setTextAndFireOnChange(text, json); -}; + this._setTextAndFireOnChange(text, json) +} /** * Repair the code in the text editor */ previewmode.repair = function () { - var text = this.getText(); - var repairedText = util.repair(text); + var text = this.getText() + var repairedText = util.repair(text) - this._setTextAndFireOnChange(repairedText); -}; + this._setTextAndFireOnChange(repairedText) +} /** * Set focus to the editor @@ -449,104 +441,104 @@ previewmode.repair = function () { previewmode.focus = function () { // we don't really have a place to focus, // let's focus on the transform button - this.dom.transform.focus(); -}; + this.dom.transform.focus() +} /** * Set json data in the editor * @param {*} json */ -previewmode.set = function(json) { +previewmode.set = function (json) { if (this.history) { - this.history.clear(); + this.history.clear() } - this._set(json); -}; + this._set(json) +} /** * Update data. Same as calling `set` in text/code mode. * @param {*} json */ -previewmode.update = function(json) { - this._set(json); -}; +previewmode.update = function (json) { + this._set(json) +} /** * Set json data * @param {*} json */ -previewmode._set = function(json) { - this.text = undefined; - this.json = json; +previewmode._set = function (json) { + this.text = undefined + this.json = json - this._renderPreview(); + this._renderPreview() - this._pushHistory(); + this._pushHistory() // validate JSON schema - this._debouncedValidate(); -}; + this._debouncedValidate() +} previewmode._setAndFireOnChange = function (json) { - this._set(json); - this._onChange(); + this._set(json) + this._onChange() } /** * Get json data * @return {*} json */ -previewmode.get = function() { +previewmode.get = function () { if (this.json === undefined) { - var text = this.getText(); + var text = this.getText() - this.json = util.parse(text); // this can throw an error + this.json = util.parse(text) // this can throw an error } - return this.json; -}; + return this.json +} /** * Get the text contents of the editor * @return {String} jsonText */ -previewmode.getText = function() { +previewmode.getText = function () { if (this.text === undefined) { - this.text = JSON.stringify(this.json, null, this.indentation); + this.text = JSON.stringify(this.json, null, this.indentation) if (this.options.escapeUnicode === true) { - this.text = util.escapeUnicodeChars(this.text); + this.text = util.escapeUnicodeChars(this.text) } } - return this.text; -}; + return this.text +} /** * Set the text contents of the editor * @param {String} jsonText */ -previewmode.setText = function(jsonText) { +previewmode.setText = function (jsonText) { if (this.history) { - this.history.clear(); + this.history.clear() } - this._setText(jsonText); -}; + this._setText(jsonText) +} /** * Update the text contents * @param {string} jsonText */ -previewmode.updateText = function(jsonText) { +previewmode.updateText = function (jsonText) { // don't update if there are no changes if (this.getText() === jsonText) { - return; + return } - this._setText(jsonText); -}; + this._setText(jsonText) +} /** * Set the text contents of the editor @@ -554,37 +546,34 @@ previewmode.updateText = function(jsonText) { * @param {*} [json] Optional JSON instance of the text * @private */ -previewmode._setText = function(jsonText, json) { +previewmode._setText = function (jsonText, json) { if (this.options.escapeUnicode === true) { - this.text = util.escapeUnicodeChars(jsonText); + this.text = util.escapeUnicodeChars(jsonText) + } else { + this.text = jsonText } - else { - this.text = jsonText; - } - this.json = json; + this.json = json - this._renderPreview(); + this._renderPreview() if (this.json === undefined) { - var me = this; + var me = this this.executeWithBusyMessage(function () { try { // force parsing the json now, else it will be done in validate without feedback - me.json = me.get(); - me._renderPreview(); - me._pushHistory(); - } - catch (err) { + me.json = me.get() + me._renderPreview() + me._pushHistory() + } catch (err) { // no need to throw an error, validation will show an error } - }, 'parsing...'); - } - else { - this._pushHistory(); + }, 'parsing...') + } else { + this._pushHistory() } - this._debouncedValidate(); -}; + this._debouncedValidate() +} /** * Set text and fire onChange callback @@ -593,8 +582,8 @@ previewmode._setText = function(jsonText, json) { * @private */ previewmode._setTextAndFireOnChange = function (jsonText, json) { - this._setText(jsonText, json); - this._onChange(); + this._setText(jsonText, json) + this._onChange() } /** @@ -603,13 +592,13 @@ previewmode._setTextAndFireOnChange = function (jsonText, json) { * @private */ previewmode._applyHistory = function (action) { - this.json = action.json; - this.text = action.text; + this.json = action.json + this.text = action.text - this._renderPreview(); + this._renderPreview() - this._debouncedValidate(); -}; + this._debouncedValidate() +} /** * Push the current state to history @@ -617,15 +606,15 @@ previewmode._applyHistory = function (action) { */ previewmode._pushHistory = function () { if (!this.history) { - return; + return } var action = { text: this.text, json: this.json - }; + } - this.history.add(action); + this.history.add(action) } /** @@ -635,23 +624,22 @@ previewmode._pushHistory = function () { * @param {string} message */ previewmode.executeWithBusyMessage = function (fn, message) { - var size = this.getText().length; + var size = this.getText().length if (size > SIZE_LARGE) { - var me = this; - util.addClassName(me.frame, 'busy'); - me.dom.busyContent.innerText = message; + var me = this + util.addClassName(me.frame, 'busy') + me.dom.busyContent.innerText = message setTimeout(function () { - fn(); - util.removeClassName(me.frame, 'busy'); - me.dom.busyContent.innerText = ''; - }, 100); + fn() + util.removeClassName(me.frame, 'busy') + me.dom.busyContent.innerText = '' + }, 100) + } else { + fn() } - else { - fn(); - } -}; +} // TODO: refactor into composable functions instead of this shaky mixin-like structure previewmode.validate = textmode.validate @@ -664,4 +652,4 @@ module.exports = [ mixin: previewmode, data: 'json' } -]; +] diff --git a/src/js/showMoreNodeFactory.js b/src/js/showMoreNodeFactory.js index c106c51..3cf0f5b 100644 --- a/src/js/showMoreNodeFactory.js +++ b/src/js/showMoreNodeFactory.js @@ -1,12 +1,12 @@ -'use strict'; +'use strict' -var translate = require('./i18n').translate; +var translate = require('./i18n').translate /** * A factory function to create an ShowMoreNode, which depends on a Node * @param {function} Node */ -function showMoreNodeFactory(Node) { +function showMoreNodeFactory (Node) { /** * @constructor ShowMoreNode * @extends Node @@ -17,12 +17,12 @@ function showMoreNodeFactory(Node) { */ function ShowMoreNode (editor, parent) { /** @type {TreeEditor} */ - this.editor = editor; - this.parent = parent; - this.dom = {}; + this.editor = editor + this.parent = parent + this.dom = {} } - ShowMoreNode.prototype = new Node(); + ShowMoreNode.prototype = new Node() /** * Return a table row with an append button. @@ -30,105 +30,104 @@ function showMoreNodeFactory(Node) { */ ShowMoreNode.prototype.getDom = function () { if (this.dom.tr) { - return this.dom.tr; + return this.dom.tr } - this._updateEditability(); + this._updateEditability() // display "show more" if (!this.dom.tr) { - var me = this; - var parent = this.parent; - var showMoreButton = document.createElement('a'); - showMoreButton.appendChild(document.createTextNode(translate('showMore'))); - showMoreButton.href = '#'; + var me = this + var parent = this.parent + var showMoreButton = document.createElement('a') + showMoreButton.appendChild(document.createTextNode(translate('showMore'))) + showMoreButton.href = '#' showMoreButton.onclick = function (event) { // TODO: use callback instead of accessing a method of the parent parent.visibleChilds = Math.floor(parent.visibleChilds / parent.getMaxVisibleChilds() + 1) * - parent.getMaxVisibleChilds(); - me.updateDom(); - parent.showChilds(); + parent.getMaxVisibleChilds() + me.updateDom() + parent.showChilds() - event.preventDefault(); - return false; - }; + event.preventDefault() + return false + } - var showAllButton = document.createElement('a'); - showAllButton.appendChild(document.createTextNode(translate('showAll'))); - showAllButton.href = '#'; + var showAllButton = document.createElement('a') + showAllButton.appendChild(document.createTextNode(translate('showAll'))) + showAllButton.href = '#' showAllButton.onclick = function (event) { // TODO: use callback instead of accessing a method of the parent - parent.visibleChilds = Infinity; - me.updateDom(); - parent.showChilds(); + parent.visibleChilds = Infinity + me.updateDom() + parent.showChilds() - event.preventDefault(); - return false; - }; - - var moreContents = document.createElement('div'); - var moreText = document.createTextNode(this._getShowMoreText()); - moreContents.className = 'jsoneditor-show-more'; - moreContents.appendChild(moreText); - moreContents.appendChild(showMoreButton); - moreContents.appendChild(document.createTextNode('. ')); - moreContents.appendChild(showAllButton); - moreContents.appendChild(document.createTextNode('. ')); - - var tdContents = document.createElement('td'); - tdContents.appendChild(moreContents); - - var moreTr = document.createElement('tr'); - if (this.editor.options.mode === 'tree') { - moreTr.appendChild(document.createElement('td')); - moreTr.appendChild(document.createElement('td')); + event.preventDefault() + return false } - moreTr.appendChild(tdContents); - moreTr.className = 'jsoneditor-show-more'; - this.dom.tr = moreTr; - this.dom.moreContents = moreContents; - this.dom.moreText = moreText; + + var moreContents = document.createElement('div') + var moreText = document.createTextNode(this._getShowMoreText()) + moreContents.className = 'jsoneditor-show-more' + moreContents.appendChild(moreText) + moreContents.appendChild(showMoreButton) + moreContents.appendChild(document.createTextNode('. ')) + moreContents.appendChild(showAllButton) + moreContents.appendChild(document.createTextNode('. ')) + + var tdContents = document.createElement('td') + tdContents.appendChild(moreContents) + + var moreTr = document.createElement('tr') + if (this.editor.options.mode === 'tree') { + moreTr.appendChild(document.createElement('td')) + moreTr.appendChild(document.createElement('td')) + } + moreTr.appendChild(tdContents) + moreTr.className = 'jsoneditor-show-more' + this.dom.tr = moreTr + this.dom.moreContents = moreContents + this.dom.moreText = moreText } - this.updateDom(); + this.updateDom() - return this.dom.tr; - }; + return this.dom.tr + } /** * Update the HTML dom of the Node */ - ShowMoreNode.prototype.updateDom = function(options) { + ShowMoreNode.prototype.updateDom = function (options) { if (this.isVisible()) { // attach to the right child node (the first non-visible child) - this.dom.tr.node = this.parent.childs[this.parent.visibleChilds]; + this.dom.tr.node = this.parent.childs[this.parent.visibleChilds] if (!this.dom.tr.parentNode) { - var nextTr = this.parent._getNextTr(); + var nextTr = this.parent._getNextTr() if (nextTr) { - nextTr.parentNode.insertBefore(this.dom.tr, nextTr); + nextTr.parentNode.insertBefore(this.dom.tr, nextTr) } } // update the counts in the text - this.dom.moreText.nodeValue = this._getShowMoreText(); + this.dom.moreText.nodeValue = this._getShowMoreText() // update left margin - this.dom.moreContents.style.marginLeft = (this.getLevel() + 1) * 24 + 'px'; - } - else { + this.dom.moreContents.style.marginLeft = (this.getLevel() + 1) * 24 + 'px' + } else { if (this.dom.tr && this.dom.tr.parentNode) { - this.dom.tr.parentNode.removeChild(this.dom.tr); + this.dom.tr.parentNode.removeChild(this.dom.tr) } } - }; + } - ShowMoreNode.prototype._getShowMoreText = function() { + ShowMoreNode.prototype._getShowMoreText = function () { return translate('showMoreStatus', { visibleChilds: this.parent.visibleChilds, totalChilds: this.parent.childs.length - }) + ' '; - }; + }) + ' ' + } /** * Check whether the ShowMoreNode is currently visible. @@ -137,21 +136,21 @@ function showMoreNodeFactory(Node) { * @return {boolean} isVisible */ ShowMoreNode.prototype.isVisible = function () { - return this.parent.expanded && this.parent.childs.length > this.parent.visibleChilds; - }; + return this.parent.expanded && this.parent.childs.length > this.parent.visibleChilds + } /** * Handle an event. The event is caught centrally by the editor * @param {Event} event */ ShowMoreNode.prototype.onEvent = function (event) { - var type = event.type; + var type = event.type if (type === 'keydown') { - this.onKeyDown(event); + this.onKeyDown(event) } - }; + } - return ShowMoreNode; + return ShowMoreNode } -module.exports = showMoreNodeFactory; +module.exports = showMoreNodeFactory diff --git a/src/js/showSortModal.js b/src/js/showSortModal.js index 19aa391..80a1bdf 100644 --- a/src/js/showSortModal.js +++ b/src/js/showSortModal.js @@ -1,6 +1,6 @@ -var picoModal = require('picomodal'); -var translate = require('./i18n').translate; -var util = require('./util'); +var picoModal = require('picomodal') +var translate = require('./i18n').translate +var util = require('./util') /** * Show advanced sorting modal @@ -17,12 +17,12 @@ var util = require('./util'); */ function showSortModal (container, json, onSort, options) { var paths = Array.isArray(json) - ? util.getChildPaths(json) - : ['']; + ? util.getChildPaths(json) + : [''] var selectedPath = options && options.path && util.contains(paths, options.path) - ? options.path - : paths[0] - var selectedDirection = options && options.direction || 'asc' + ? options.path + : paths[0] + var selectedDirection = (options && options.direction) || 'asc' var content = '
' + '
' + translate('sort') + '
' + @@ -44,7 +44,7 @@ function showSortModal (container, json, onSort, options) { '
' + '' + '' + '' + '' + - '
'; + '
' picoModal({ parent: container, content: content, overlayClass: 'jsoneditor-modal-overlay', overlayStyles: { - backgroundColor: "rgb(1,1,1)", - opacity: 0.3 + 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'); + .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; - } + 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; - } + paths.forEach(function (path) { + var option = document.createElement('option') + option.text = preprocessPath(path) + option.value = path + field.appendChild(option) }) - .afterClose(function (modal) { - modal.destroy(); - }) - .show(); + + 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; +module.exports = showSortModal diff --git a/src/js/showTransformModal.js b/src/js/showTransformModal.js index 0c8b273..d2d795d 100644 --- a/src/js/showTransformModal.js +++ b/src/js/showTransformModal.js @@ -1,11 +1,11 @@ -var jmespath = require('jmespath'); -var picoModal = require('picomodal'); -var Selectr = require('./assets/selectr/selectr'); -var translate = require('./i18n').translate; -var stringifyPartial = require('./jsonUtils').stringifyPartial; -var util = require('./util'); +var jmespath = require('jmespath') +var picoModal = require('picomodal') +var Selectr = require('./assets/selectr/selectr') +var translate = require('./i18n').translate +var stringifyPartial = require('./jsonUtils').stringifyPartial +var util = require('./util') var MAX_PREVIEW_CHARACTERS = require('./constants').MAX_PREVIEW_CHARACTERS -var debounce = util.debounce; +var debounce = util.debounce /** * Show advanced filter and transform modal using JMESPath @@ -16,7 +16,7 @@ var debounce = util.debounce; * query as callback */ function showTransformModal (container, json, onTransform) { - var value = json; + var value = json var content = '