From 8e07ebb71117263bff0a40f0abc0fb1fc3eed0d7 Mon Sep 17 00:00:00 2001 From: josdejong Date: Fri, 15 Nov 2013 18:11:50 +0100 Subject: [PATCH] Switched everything to 2-space indentation --- Jakefile.js | 432 +- app/chrome/manifest.json | 44 +- app/web/ajax.js | 62 +- app/web/app.css | 294 +- app/web/app.js | 532 +- app/web/beta/index.html | 18 +- app/web/doc/doc.css | 50 +- app/web/doc/index.html | 348 +- app/web/fileretriever.css | 60 +- app/web/fileretriever.js | 762 +- app/web/hash.js | 140 +- app/web/index.html | 278 +- app/web/notify.js | 184 +- app/web/queryparams.js | 58 +- app/web/splitter.js | 204 +- app/web/test.html | 356 +- bower.json | 62 +- docs/api.md | 2 +- examples/01_basic_usage.html | 70 +- examples/02_viewer.html | 58 +- examples/03_switch_mode.html | 92 +- examples/requirejs_demo/requirejs_demo.html | 24 +- examples/requirejs_demo/scripts/main.js | 38 +- jsoneditor-min.js | 2 +- jsoneditor.css | 540 +- jsoneditor.js | 7868 +++++++++---------- jsoneditor/css/contextmenu.css | 178 +- jsoneditor/css/jsoneditor.css | 194 +- jsoneditor/css/menu.css | 98 +- jsoneditor/css/searchbox.css | 70 +- jsoneditor/js/appendnode.js | 288 +- jsoneditor/js/contextmenu.js | 682 +- jsoneditor/js/highlighter.js | 72 +- jsoneditor/js/history.js | 298 +- jsoneditor/js/jsoneditor.js | 166 +- jsoneditor/js/modebox.js | 158 +- jsoneditor/js/module.js | 62 +- jsoneditor/js/node.js | 4024 +++++----- jsoneditor/js/searchbox.js | 372 +- jsoneditor/js/texteditor.js | 374 +- jsoneditor/js/treeeditor.js | 886 +-- jsoneditor/js/util.js | 486 +- misc/screenshots/description.json | 30 +- package.json | 54 +- 44 files changed, 10535 insertions(+), 10535 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index d6112ac..1a2cdfc 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -21,7 +21,7 @@ var JSONEDITOR = './jsoneditor.js', */ desc('Execute all tasks'); task('default', ['clear', 'build', 'minify', 'zip', 'webapp', 'chromeapp'], function () { - console.log('Done'); + console.log('Done'); }); /** @@ -29,7 +29,7 @@ task('default', ['clear', 'build', 'minify', 'zip', 'webapp', 'chromeapp'], func */ desc('Clear the build directory'); task('clear', function () { - jake.rmRf(BUILD); + jake.rmRf(BUILD); }); /** @@ -37,54 +37,54 @@ task('clear', function () { */ desc('Build the library'); task('build', ['clear'], function () { - var jsoneditorSrc = './jsoneditor/'; - // concatenate the javascript files - concat({ - src: [ - jsoneditorSrc + 'js/jsoneditor.js', - jsoneditorSrc + 'js/treeeditor.js', - jsoneditorSrc + 'js/texteditor.js', - jsoneditorSrc + 'js/node.js', - jsoneditorSrc + 'js/appendnode.js', - jsoneditorSrc + 'js/contextmenu.js', - jsoneditorSrc + 'js/history.js', - jsoneditorSrc + 'js/modebox.js', - jsoneditorSrc + 'js/searchbox.js', - jsoneditorSrc + 'js/highlighter.js', - jsoneditorSrc + 'js/util.js', - jsoneditorSrc + 'js/module.js' - ], - dest: JSONEDITOR, - header: read(jsoneditorSrc +'js/header.js') + '\n' + - '(function () {\n', - separator: '\n', - footer: '\n})();\n' - }); + var jsoneditorSrc = './jsoneditor/'; + // concatenate the javascript files + concat({ + src: [ + jsoneditorSrc + 'js/jsoneditor.js', + jsoneditorSrc + 'js/treeeditor.js', + jsoneditorSrc + 'js/texteditor.js', + jsoneditorSrc + 'js/node.js', + jsoneditorSrc + 'js/appendnode.js', + jsoneditorSrc + 'js/contextmenu.js', + jsoneditorSrc + 'js/history.js', + jsoneditorSrc + 'js/modebox.js', + jsoneditorSrc + 'js/searchbox.js', + jsoneditorSrc + 'js/highlighter.js', + jsoneditorSrc + 'js/util.js', + jsoneditorSrc + 'js/module.js' + ], + dest: JSONEDITOR, + header: read(jsoneditorSrc +'js/header.js') + '\n' + + '(function () {\n', + separator: '\n', + footer: '\n})();\n' + }); - // update version number and stuff in the javascript files - replacePlaceholders(JSONEDITOR); - console.log('Created ' + JSONEDITOR); + // update version number and stuff in the javascript files + replacePlaceholders(JSONEDITOR); + console.log('Created ' + JSONEDITOR); - // concatenate and stringify the css files - concat({ - src: [ - jsoneditorSrc + 'css/jsoneditor.css', - jsoneditorSrc + 'css/contextmenu.css', - jsoneditorSrc + 'css/menu.css', - jsoneditorSrc + 'css/searchbox.css' - ], - dest: JSONEDITOR_CSS, - separator: '\n' - }); - console.log('Created ' + JSONEDITOR_CSS); + // concatenate and stringify the css files + concat({ + src: [ + jsoneditorSrc + 'css/jsoneditor.css', + jsoneditorSrc + 'css/contextmenu.css', + jsoneditorSrc + 'css/menu.css', + jsoneditorSrc + 'css/searchbox.css' + ], + dest: JSONEDITOR_CSS, + separator: '\n' + }); + console.log('Created ' + JSONEDITOR_CSS); - // minify the css file - write(JSONEDITOR_CSS_MIN, new CleanCSS().minify(String(read(JSONEDITOR_CSS)))); + // minify the css file + write(JSONEDITOR_CSS_MIN, new CleanCSS().minify(String(read(JSONEDITOR_CSS)))); - // create a folder img and copy the icons - jake.mkdirP('./img'); - jake.cpR(jsoneditorSrc + 'css/img/jsoneditor-icons.png', './img/'); - console.log('Copied jsoneditor-icons.png to ./img/'); + // create a folder img and copy the icons + jake.mkdirP('./img'); + jake.cpR(jsoneditorSrc + 'css/img/jsoneditor-icons.png', './img/'); + console.log('Copied jsoneditor-icons.png to ./img/'); }); /** @@ -92,18 +92,18 @@ task('build', ['clear'], function () { */ desc('Minify the library'); task('minify', ['build'], function () { - // minify javascript - minify({ - src: JSONEDITOR, - dest: JSONEDITOR_MIN, - header: read('./jsoneditor/js/header.js'), - separator: '\n' - }); + // minify javascript + minify({ + src: JSONEDITOR, + dest: JSONEDITOR_MIN, + header: read('./jsoneditor/js/header.js'), + separator: '\n' + }); - // update version number and stuff in the javascript files - replacePlaceholders(JSONEDITOR_MIN); + // update version number and stuff in the javascript files + replacePlaceholders(JSONEDITOR_MIN); - console.log('Created ' + JSONEDITOR_MIN); + console.log('Created ' + JSONEDITOR_MIN); }); /** @@ -111,50 +111,50 @@ task('minify', ['build'], function () { */ desc('Zip the library'); task('zip', ['build', 'minify'], {async: true}, function () { - var zipfolder = BUILD + '/lib'; - var pkg = 'jsoneditor-' + version(); - var zipfile = zipfolder + '/' + pkg + '.zip'; - jake.mkdirP(zipfolder); + var zipfolder = BUILD + '/lib'; + var pkg = 'jsoneditor-' + version(); + var zipfile = zipfolder + '/' + pkg + '.zip'; + jake.mkdirP(zipfolder); - var output = fs.createWriteStream(zipfile); - var archive = archiver('zip'); + var output = fs.createWriteStream(zipfile); + var archive = archiver('zip'); - archive.on('error', function(err) { - throw err; - }); + archive.on('error', function(err) { + throw err; + }); - archive.pipe(output); + archive.pipe(output); - var filelist = new jake.FileList(); - filelist.include([ - 'README.md', - 'NOTICE', - 'LICENSE', - 'HISTORY.md', - JSONEDITOR, - JSONEDITOR_CSS, - JSONEDITOR_MIN, - JSONEDITOR_CSS_MIN, - 'img/*.*', - 'lib/**/*.*', - 'docs/**/*.*', - 'examples/**/*.*' - ]); - var files = filelist.toArray(); - files.forEach(function (file) { - archive.append(fs.createReadStream(file), { - name: pkg + '/' + file - }) - }); + var filelist = new jake.FileList(); + filelist.include([ + 'README.md', + 'NOTICE', + 'LICENSE', + 'HISTORY.md', + JSONEDITOR, + JSONEDITOR_CSS, + JSONEDITOR_MIN, + JSONEDITOR_CSS_MIN, + 'img/*.*', + 'lib/**/*.*', + 'docs/**/*.*', + 'examples/**/*.*' + ]); + var files = filelist.toArray(); + files.forEach(function (file) { + archive.append(fs.createReadStream(file), { + name: pkg + '/' + file + }) + }); - archive.finalize(function(err, written) { - if (err) { - throw err; - } + archive.finalize(function(err, written) { + if (err) { + throw err; + } - console.log('Zipped ' + zipfile); - complete(); - }); + console.log('Zipped ' + zipfile); + complete(); + }); }); /** @@ -162,107 +162,107 @@ task('zip', ['build', 'minify'], {async: true}, function () { */ desc('Build web app'); task('webapp', ['build', 'minify'], function () { - var webAppSrc = './app/web/'; - var libSrc = './lib/'; - var webApp = BUILD + '/app/web/'; - var webAppLib = webApp + 'lib/'; - var webAppAce = webAppLib + 'ace/'; - var webAppImg = webApp + 'img/'; - var appJs = webApp + 'app.js'; - var appCss = webApp + 'app.css'; - var appCssMin = webApp + 'app-min.css'; - var appJsMin = webApp + 'app-min.js'; + var webAppSrc = './app/web/'; + var libSrc = './lib/'; + var webApp = BUILD + '/app/web/'; + var webAppLib = webApp + 'lib/'; + var webAppAce = webAppLib + 'ace/'; + var webAppImg = webApp + 'img/'; + var appJs = webApp + 'app.js'; + var appCss = webApp + 'app.css'; + var appCssMin = webApp + 'app-min.css'; + var appJsMin = webApp + 'app-min.js'; - // create directories - // TODO: should be created automatically... - jake.mkdirP(webApp); - jake.mkdirP(webAppLib); - jake.mkdirP(webAppLib + 'ace/'); - jake.mkdirP(webAppLib + 'jsoneditor/'); - jake.mkdirP(webAppLib + 'jsoneditor/img/'); - jake.mkdirP(webAppLib + 'jsonlint/'); - jake.mkdirP(webAppImg); + // create directories + // TODO: should be created automatically... + jake.mkdirP(webApp); + jake.mkdirP(webAppLib); + jake.mkdirP(webAppLib + 'ace/'); + jake.mkdirP(webAppLib + 'jsoneditor/'); + jake.mkdirP(webAppLib + 'jsoneditor/img/'); + jake.mkdirP(webAppLib + 'jsonlint/'); + jake.mkdirP(webAppImg); - // concatenate the javascript files - concat({ - src: [ - webAppSrc + 'queryparams.js', - webAppSrc + 'ajax.js', - webAppSrc + 'fileretriever.js', - webAppSrc + 'notify.js', - webAppSrc + 'splitter.js', - webAppSrc + 'app.js' - ], - dest: appJs, - separator: '\n' - }); + // concatenate the javascript files + concat({ + src: [ + webAppSrc + 'queryparams.js', + webAppSrc + 'ajax.js', + webAppSrc + 'fileretriever.js', + webAppSrc + 'notify.js', + webAppSrc + 'splitter.js', + webAppSrc + 'app.js' + ], + dest: appJs, + separator: '\n' + }); - // minify javascript - minify({ - src: appJs, - dest: appJsMin - }); + // minify javascript + minify({ + src: appJs, + dest: appJsMin + }); - // concatenate the css files - concat({ - src: [ - webAppSrc + 'fileretriever.css', - webAppSrc + 'app.css' - ], - dest: appCss, - separator: '\n' - }); + // concatenate the css files + concat({ + src: [ + webAppSrc + 'fileretriever.css', + webAppSrc + 'app.css' + ], + dest: appCss, + separator: '\n' + }); - // minify css file - write(appCssMin, new CleanCSS().minify(String(read(appCss)))); + // minify css file + write(appCssMin, new CleanCSS().minify(String(read(appCss)))); - // remove non minified javascript and css file - fs.unlinkSync(appJs); - fs.unlinkSync(appCss); + // remove non minified javascript and css file + fs.unlinkSync(appJs); + fs.unlinkSync(appCss); - // copy files - jake.cpR('./README.md', webApp); - jake.cpR('./HISTORY.md', webApp); - jake.cpR('./NOTICE', webApp); - jake.cpR('./LICENSE', webApp); - jake.cpR('./LICENSE', webApp); - jake.cpR(webAppSrc + 'cache.manifest', webApp); - jake.cpR(webAppSrc + 'robots.txt', webApp); - jake.cpR(webAppSrc + 'datapolicy.txt', webApp); - jake.cpR(webAppSrc + 'index.html', webApp); - jake.cpR(webAppSrc + 'favicon.ico', webApp); - jake.cpR(webAppSrc + 'fileretriever.php', webApp); - jake.cpR(webAppSrc + 'googlea47c4a0b36d11021.html', webApp); - jake.cpR(webAppSrc + 'img/logo.png', webAppImg); - jake.cpR(webAppSrc + 'img/header_background.png', webAppImg); - jake.cpR(webAppSrc + 'doc/', webApp); + // copy files + jake.cpR('./README.md', webApp); + jake.cpR('./HISTORY.md', webApp); + jake.cpR('./NOTICE', webApp); + jake.cpR('./LICENSE', webApp); + jake.cpR('./LICENSE', webApp); + jake.cpR(webAppSrc + 'cache.manifest', webApp); + jake.cpR(webAppSrc + 'robots.txt', webApp); + jake.cpR(webAppSrc + 'datapolicy.txt', webApp); + jake.cpR(webAppSrc + 'index.html', webApp); + jake.cpR(webAppSrc + 'favicon.ico', webApp); + jake.cpR(webAppSrc + 'fileretriever.php', webApp); + jake.cpR(webAppSrc + 'googlea47c4a0b36d11021.html', webApp); + jake.cpR(webAppSrc + 'img/logo.png', webAppImg); + jake.cpR(webAppSrc + 'img/header_background.png', webAppImg); + jake.cpR(webAppSrc + 'doc/', webApp); - // update date and verison in index.html - replacePlaceholders(webApp + 'index.html'); - replacePlaceholders(webApp + 'index.html'); // TODO: fix bug in replace, should replace all occurrences - replacePlaceholders(webApp + 'cache.manifest'); + // update date and verison in index.html + replacePlaceholders(webApp + 'index.html'); + replacePlaceholders(webApp + 'index.html'); // TODO: fix bug in replace, should replace all occurrences + replacePlaceholders(webApp + 'cache.manifest'); - // concatenate and copy ace files - concat({ - src: [ - libSrc + 'ace/ace.js', - libSrc + 'ace/mode-json.js', - libSrc + 'ace/theme-textmate.js', - libSrc + 'ace/theme-jsoneditor.js', - libSrc + 'ace/ext-searchbox.js' - ], - dest: webAppAce + 'ace-min.js', - separator: '\n' - }); - jake.cpR(libSrc + 'ace/worker-json.js', webAppAce); + // concatenate and copy ace files + concat({ + src: [ + libSrc + 'ace/ace.js', + libSrc + 'ace/mode-json.js', + libSrc + 'ace/theme-textmate.js', + libSrc + 'ace/theme-jsoneditor.js', + libSrc + 'ace/ext-searchbox.js' + ], + dest: webAppAce + 'ace-min.js', + separator: '\n' + }); + jake.cpR(libSrc + 'ace/worker-json.js', webAppAce); - // copy json lint file - jake.cpR(libSrc + 'jsonlint/jsonlint.js', webAppLib + 'jsonlint/') + // copy json lint file + jake.cpR(libSrc + 'jsonlint/jsonlint.js', webAppLib + 'jsonlint/') - // copy jsoneditor files - jake.cpR(JSONEDITOR_MIN, webAppLib + 'jsoneditor/'); - jake.cpR(JSONEDITOR_CSS_MIN, webAppLib + 'jsoneditor/'); - jake.cpR('img', webAppLib + 'jsoneditor/'); + // copy jsoneditor files + jake.cpR(JSONEDITOR_MIN, webAppLib + 'jsoneditor/'); + jake.cpR(JSONEDITOR_CSS_MIN, webAppLib + 'jsoneditor/'); + jake.cpR('img', webAppLib + 'jsoneditor/'); }); @@ -271,38 +271,38 @@ task('webapp', ['build', 'minify'], function () { */ desc('Build chrome app'); task('chromeapp', {async: true}, function () { - var folder = BUILD + '/app/'; - var file = folder + 'chrome.zip'; - jake.mkdirP(folder); + var folder = BUILD + '/app/'; + var file = folder + 'chrome.zip'; + jake.mkdirP(folder); - var output = fs.createWriteStream(file); - var archive = archiver('zip'); + var output = fs.createWriteStream(file); + var archive = archiver('zip'); - archive.on('error', function(err) { - throw err; - }); + archive.on('error', function(err) { + throw err; + }); - // create a temporary manifest file with version number - var manifestTmp = folder + 'manifest.json.tmp'; - jake.cpR('./app/chrome/manifest.json', manifestTmp); - replacePlaceholders(manifestTmp); + // create a temporary manifest file with version number + var manifestTmp = folder + 'manifest.json.tmp'; + jake.cpR('./app/chrome/manifest.json', manifestTmp); + replacePlaceholders(manifestTmp); - archive.pipe(output); - archive.append(fs.createReadStream(manifestTmp), {name: 'manifest.json'}); - archive.append(fs.createReadStream('./app/web/img/icon_16.png'), {name: 'icon_16.png'}); - archive.append(fs.createReadStream('./app/web/img/icon_128.png'), {name: 'icon_128.png'}); + archive.pipe(output); + archive.append(fs.createReadStream(manifestTmp), {name: 'manifest.json'}); + archive.append(fs.createReadStream('./app/web/img/icon_16.png'), {name: 'icon_16.png'}); + archive.append(fs.createReadStream('./app/web/img/icon_128.png'), {name: 'icon_128.png'}); - // cleanup temporary manifest file - fs.unlinkSync(manifestTmp); + // cleanup temporary manifest file + fs.unlinkSync(manifestTmp); - archive.finalize(function(err, written) { - if (err) { - throw err; - } + archive.finalize(function(err, written) { + if (err) { + throw err; + } - console.log('Created chrome app ' + file); - complete(); - }); + console.log('Created chrome app ' + file); + complete(); + }); }); /** @@ -310,11 +310,11 @@ task('chromeapp', {async: true}, function () { * @param {String} filename */ var replacePlaceholders = function (filename) { - replace({ - replacements: [ - {pattern: '@@date', replacement: today()}, - {pattern: '@@version', replacement: version()} - ], - src: filename - }); + replace({ + replacements: [ + {pattern: '@@date', replacement: today()}, + {pattern: '@@version', replacement: version()} + ], + src: filename + }); }; diff --git a/app/chrome/manifest.json b/app/chrome/manifest.json index 614666d..a7d1bcf 100644 --- a/app/chrome/manifest.json +++ b/app/chrome/manifest.json @@ -1,25 +1,25 @@ { - "manifest_version": 2, - "name": "JSON Editor", - "version": "@@version", - "description": "JSON Editor is a tool to view, edit, and format JSON. It shows your data in an editable treeview and in a code editor.", - "app": { - "urls": [ - "http://jsoneditoronline.org/", - "http://jsoneditoronline.org/index.html", - "http://jsoneditoronline.org/changelog.txt", - "http://jsoneditoronline.org/NOTICE" - ], - "launch": { - "web_url": "http://jsoneditoronline.org/index.html" - } - }, - "icons": { - "16": "icon_16.png", - "128": "icon_128.png" - }, - "permissions": [ - "unlimitedStorage" + "manifest_version": 2, + "name": "JSON Editor", + "version": "@@version", + "description": "JSON Editor is a tool to view, edit, and format JSON. It shows your data in an editable treeview and in a code editor.", + "app": { + "urls": [ + "http://jsoneditoronline.org/", + "http://jsoneditoronline.org/index.html", + "http://jsoneditoronline.org/changelog.txt", + "http://jsoneditoronline.org/NOTICE" ], - "offline_enabled": true + "launch": { + "web_url": "http://jsoneditoronline.org/index.html" + } + }, + "icons": { + "16": "icon_16.png", + "128": "icon_128.png" + }, + "permissions": [ + "unlimitedStorage" + ], + "offline_enabled": true } diff --git a/app/web/ajax.js b/app/web/ajax.js index f442f6a..e5f23fc 100644 --- a/app/web/ajax.js +++ b/app/web/ajax.js @@ -1,43 +1,43 @@ /** * ajax - * Utility to perform ajax get and post requests. Supported browsers: + * Utility to perform ajax get and post requests. Supported browsers: * Chrome, Firefox, Opera, Safari, Internet Explorer 7+. */ var ajax = (function () { - function fetch (method, url, body, headers, callback) { - try { - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - callback(xhr.responseText, xhr.status); - } - }; - xhr.open(method, url, true); - if (headers) { - for (var name in headers) { - if (headers.hasOwnProperty(name)) { - xhr.setRequestHeader(name, headers[name]); - } - } - } - xhr.send(body); + function fetch (method, url, body, headers, callback) { + try { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + callback(xhr.responseText, xhr.status); } - catch (err) { - callback(err, 0); + }; + xhr.open(method, url, true); + if (headers) { + for (var name in headers) { + if (headers.hasOwnProperty(name)) { + xhr.setRequestHeader(name, headers[name]); + } } + } + xhr.send(body); } + catch (err) { + callback(err, 0); + } + } - function get (url, headers, callback) { - fetch('GET', url, null, headers, callback); - } + function get (url, headers, callback) { + fetch('GET', url, null, headers, callback); + } - function post (url, body, headers, callback) { - fetch('POST', url, body, headers, callback) - } + function post (url, body, headers, callback) { + fetch('POST', url, body, headers, callback) + } - return { - 'fetch': fetch, - 'get': get, - 'post': post - } + return { + 'fetch': fetch, + 'get': get, + 'post': post + } })(); diff --git a/app/web/app.css b/app/web/app.css index a97f5a9..a27519b 100644 --- a/app/web/app.css +++ b/app/web/app.css @@ -1,292 +1,292 @@ body, html { - font-family: arial, sans-serif; - font-size: 11pt; + font-family: arial, sans-serif; + font-size: 11pt; - width: 100%; - height: 100%; - margin: 0; - padding: 0; + width: 100%; + height: 100%; + margin: 0; + padding: 0; - overflow: hidden; + overflow: hidden; } span.header-light { - color: gray; + color: gray; } #header { - width: 100%; - height: 40px; - /* TODO - overflow: hidden; - */ + width: 100%; + height: 40px; + /* TODO + overflow: hidden; + */ - background: #4D4D4D url('img/header_background.png'); - color: white; + background: #4D4D4D url('img/header_background.png'); + color: white; } #logo { - height: 32px; - margin: 4px 10px; - border: none; + height: 32px; + margin: 4px 10px; + border: none; } #menu { - position: absolute; - top: 5px; - right: 15px; - font-size: 11pt; + position: absolute; + top: 5px; + right: 15px; + font-size: 11pt; } #menu ul { - list-style: none; - margin: 0; - padding: 0; - clear: both; + list-style: none; + margin: 0; + padding: 0; + clear: both; } #menu ul li { - color: #e6e6e6; - background: none; - border: none; - border-right: 1px solid #737373; - height: 30px; - padding: 0; - margin: 0; - float: left; - position: relative; + color: #e6e6e6; + background: none; + border: none; + border-right: 1px solid #737373; + height: 30px; + padding: 0; + margin: 0; + float: left; + position: relative; - text-decoration: none; + text-decoration: none; } #menu ul li:first-child { - border-left: 1px solid #737373; + border-left: 1px solid #737373; } #menu ul li:hover { - color: white; - background-color: #737373; + color: white; + background-color: #737373; } #menu ul li ul { - display: none; + display: none; } #menu ul li:hover > ul { - display: block; + display: block; } #menu ul li ul { - position: absolute; - top: 30px; - left: 0; - z-index: 999; + position: absolute; + top: 30px; + left: 0; + z-index: 999; - background: #f5f5f5; - border: 1px solid lightgray; - box-shadow: 0 0 15px rgba(128, 128, 128, 0.5); + background: #f5f5f5; + border: 1px solid lightgray; + box-shadow: 0 0 15px rgba(128, 128, 128, 0.5); } #menu ul li ul li { - color: #737373; - background: none; - border: none; - margin: 0; - padding: 0; + color: #737373; + background: none; + border: none; + margin: 0; + padding: 0; } #menu ul li ul li:first-child { - border-left: none; + border-left: none; } #menu ul li ul li:hover { - background-color: white; + background-color: white; } #menu a { - padding: 6px 10px; - display: block; - cursor: pointer; - text-decoration: none; - color: white; + padding: 6px 10px; + display: block; + cursor: pointer; + text-decoration: none; + color: white; } #menu ul li ul li a { - color: #737373; - width: 80px; + color: #737373; + width: 80px; } #openMenuButton { - font-size: 75%; - margin-left: 2px; + font-size: 75%; + margin-left: 2px; } #menu #open { - cursor: default; + cursor: default; } /* TODO: enable the menu with keys (when openMenuButton is active) */ #auto { - width: 100%; - height: 100%; + width: 100%; + height: 100%; - margin: -40px 0 -24px 0; - padding: 40px 0 24px 0; + margin: -40px 0 -24px 0; + padding: 40px 0 24px 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; - overflow: hidden; + overflow: hidden; } #contents { - width: 100%; - height: 100%; - overflow: hidden; + width: 100%; + height: 100%; + overflow: hidden; } #codeEditor, #treeEditor { - height: 100%; - width: 400px; + height: 100%; + width: 400px; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; } #codeEditor { - float: left; - padding: 15px 0 15px 15px; + float: left; + padding: 15px 0 15px 15px; } #treeEditor { - float: left; - padding: 15px 15px 15px 0; + float: left; + padding: 15px 15px 15px 0; } #splitter { - text-align: center; - float: left; - height: 100%; - padding: 15px; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; + text-align: center; + float: left; + height: 100%; + padding: 15px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; } #splitter #buttons { - margin: 0 0 15px 0; + margin: 0 0 15px 0; } #splitter #toTree { - margin: 40px 0 0 0 ; + margin: 40px 0 0 0 ; } #splitter #toCode { - margin: 20px 0 0 0 ; + margin: 20px 0 0 0 ; } #splitter #drag { - font-size: 32px; - color: lightgray; - border-radius: 3px; - min-width: 24px; - cursor: col-resize; + font-size: 32px; + color: lightgray; + border-radius: 3px; + min-width: 24px; + cursor: col-resize; } #splitter #drag:hover, #splitter #drag.active { - color: gray; - background-color: #f5f5f5; + color: gray; + background-color: #f5f5f5; } #footer { - width: 100%; - height: 23px; - font-size: 10pt; + width: 100%; + height: 23px; + font-size: 10pt; - overflow: hidden; - color: #BFBFBF; - border-top: 1px solid lightgray; - text-align: center; - background-color: #F5F5F5; + overflow: hidden; + color: #BFBFBF; + border-top: 1px solid lightgray; + text-align: center; + background-color: #F5F5F5; } #footer-inner { - margin: 4px; + margin: 4px; } a.header { - color: white; - text-decoration: none; + color: white; + text-decoration: none; } a.footer { - color: #BFBFBF; - text-decoration: none; + color: #BFBFBF; + text-decoration: none; } a.footer:hover { - color: red; - text-decoration: underline; + color: red; + text-decoration: underline; } #ad { - float: right; - right: 15px; - padding: 15px 0 15px 0; - position: relative; + float: right; + right: 15px; + padding: 15px 0 15px 0; + position: relative; } #chromeAppInfo { - line-height: normal; - padding: 0 5px 20px 5px; + line-height: normal; + padding: 0 5px 20px 5px; } div.error, div.notification { - border-radius: 2px; - padding: 5px; - margin: 5px; - box-shadow: 0 0 15px rgba(128, 128, 128, 0.5); + border-radius: 2px; + padding: 5px; + margin: 5px; + box-shadow: 0 0 15px rgba(128, 128, 128, 0.5); - /* TODO: add some transition effect */ + /* TODO: add some transition effect */ } div.error { - color: red; - background-color: #FFC0CB; - border: 1px solid red; + color: red; + background-color: #FFC0CB; + border: 1px solid red; } div.notification { - color: #1a1a1a; - background-color: #FFFFAB; - border: 1px solid #e6d600; + color: #1a1a1a; + background-color: #FFFFAB; + border: 1px solid #e6d600; } pre.error { - margin: 0 0 10px 0; - white-space: pre-wrap; - font-family: droid sans mono, monospace, courier new, courier, sans-serif; - font-size: 10pt; + margin: 0 0 10px 0; + white-space: pre-wrap; + font-family: droid sans mono, monospace, courier new, courier, sans-serif; + font-size: 10pt; } a.error { - color: red; - font-size: 8pt; + color: red; + font-size: 8pt; } button.convert { - cursor: default; - padding: 2px; + cursor: default; + padding: 2px; } div.convert-right, div.convert-left { - width: 24px; - height: 24px; - margin: 0; + width: 24px; + height: 24px; + margin: 0; } div.convert-right { - background: url('lib/jsoneditor/img/jsoneditor-icons.png') -0 -48px; + background: url('lib/jsoneditor/img/jsoneditor-icons.png') -0 -48px; } div.convert-left { - background: url('lib/jsoneditor/img/jsoneditor-icons.png') -24px -48px; + background: url('lib/jsoneditor/img/jsoneditor-icons.png') -24px -48px; } diff --git a/app/web/app.js b/app/web/app.js index 85c07e6..668a2e4 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -39,24 +39,24 @@ var app = {}; * Get the JSON from the code editor and load it in the tree editor */ app.CodeToTree = function() { - try { - treeEditor.set(codeEditor.get()); - } - catch (err) { - app.notify.showError(app.formatError(err)); - } + try { + treeEditor.set(codeEditor.get()); + } + catch (err) { + app.notify.showError(app.formatError(err)); + } }; /** * Get the JSON from the tree editor and load it into the code editor */ app.treeToCode = function () { - try { - codeEditor.set(treeEditor.get()); - } - catch (err) { - app.notify.showError(app.formatError(err)); - } + try { + codeEditor.set(treeEditor.get()); + } + catch (err) { + app.notify.showError(app.formatError(err)); + } }; /** @@ -64,139 +64,139 @@ app.treeToCode = function () { */ // TODO: split the method load in multiple methods, it is too large app.load = function() { - try { - // notification handler - app.notify = new Notify(); + try { + // notification handler + app.notify = new Notify(); - // retriever for loading/saving files - app.retriever = new FileRetriever({ - scriptUrl: 'fileretriever.php', - notify: app.notify - }); + // retriever for loading/saving files + app.retriever = new FileRetriever({ + scriptUrl: 'fileretriever.php', + notify: app.notify + }); - // default json document - var json = { - "array": [1, 2, 3], - "boolean": true, - "null": null, - "number": 123, - "object": {"a": "b", "c": "d", "e": "f"}, - "string": "Hello World" - }; + // default json document + var json = { + "array": [1, 2, 3], + "boolean": true, + "null": null, + "number": 123, + "object": {"a": "b", "c": "d", "e": "f"}, + "string": "Hello World" + }; - // load url if query parameters contains a url - if (window.QueryParams) { - var qp = new QueryParams(); - var url = qp.getValue('url'); - if (url) { - json = {}; - app.openUrl(url); - } - } - - // Store whether tree editor or code editor is last changed - app.lastChanged = undefined; - - // code editor - var container = document.getElementById("codeEditor"); - codeEditor = new jsoneditor.JSONEditor(container, { - mode: 'code', - change: function () { - app.lastChanged = codeEditor; - }, - error: function (err) { - app.notify.showError(app.formatError(err)); - } - }); - codeEditor.set(json); - - // tree editor - container = document.getElementById("treeEditor"); - treeEditor = new jsoneditor.JSONEditor(container, { - mode: 'tree', - change: function () { - app.lastChanged = treeEditor; - }, - error: function (err) { - app.notify.showError(app.formatError(err)); - } - }); - treeEditor.set(json); - // TODO: automatically synchronize data of code and tree editor? (tree editor should keep its state though) - - // splitter - app.splitter = new Splitter({ - container: document.getElementById('drag'), - change: function () { - app.resize(); - } - }); - - // button Code-to-Tree - var toTree = document.getElementById('toTree'); - toTree.onclick = function () { - this.focus(); - app.CodeToTree(); - }; - - // button Tree-to-Code - var toCode = document.getElementById('toCode'); - toCode.onclick = function () { - this.focus(); - app.treeToCode(); - }; - - // web page resize handler - jsoneditor.util.addEventListener(window, 'resize', app.resize); - - // clear button - var domClear = document.getElementById('clear'); - domClear.onclick = app.clearFile; - - /* TODO: enable clicking on open to execute the default, "open file" - // open button - var domOpen = document.getElementById('open'); - var domOpenMenuButton = document.getElementById('openMenuButton'); - domOpen.onclick = function (event) { - var target = event.target || event.srcElement; - if (target == domOpenMenuButton || - (event.offsetX > domOpen.offsetWidth - domOpenMenuButton.offsetWidth)) { - // clicked on the menu button - } - else { - app.openFile(); - } - }; - */ - - // menu button open file - var domMenuOpenFile = document.getElementById('menuOpenFile'); - domMenuOpenFile.onclick = function (event) { - app.openFile(); - event.stopPropagation(); - event.preventDefault(); - }; - - // menu button open url - var domMenuOpenUrl = document.getElementById('menuOpenUrl'); - domMenuOpenUrl.onclick = function (event) { - app.openUrl(); - event.stopPropagation(); - event.preventDefault(); - }; - - // save button - var domSave = document.getElementById('save'); - domSave.onclick = app.saveFile; - - // set focus on the code editor - codeEditor.focus(); - - // enforce FireFox to not do spell checking on any input field - document.body.spellcheck = false; - } catch (err) { - app.notify.showError(err); + // load url if query parameters contains a url + if (window.QueryParams) { + var qp = new QueryParams(); + var url = qp.getValue('url'); + if (url) { + json = {}; + app.openUrl(url); + } } + + // Store whether tree editor or code editor is last changed + app.lastChanged = undefined; + + // code editor + var container = document.getElementById("codeEditor"); + codeEditor = new jsoneditor.JSONEditor(container, { + mode: 'code', + change: function () { + app.lastChanged = codeEditor; + }, + error: function (err) { + app.notify.showError(app.formatError(err)); + } + }); + codeEditor.set(json); + + // tree editor + container = document.getElementById("treeEditor"); + treeEditor = new jsoneditor.JSONEditor(container, { + mode: 'tree', + change: function () { + app.lastChanged = treeEditor; + }, + error: function (err) { + app.notify.showError(app.formatError(err)); + } + }); + treeEditor.set(json); + // TODO: automatically synchronize data of code and tree editor? (tree editor should keep its state though) + + // splitter + app.splitter = new Splitter({ + container: document.getElementById('drag'), + change: function () { + app.resize(); + } + }); + + // button Code-to-Tree + var toTree = document.getElementById('toTree'); + toTree.onclick = function () { + this.focus(); + app.CodeToTree(); + }; + + // button Tree-to-Code + var toCode = document.getElementById('toCode'); + toCode.onclick = function () { + this.focus(); + app.treeToCode(); + }; + + // web page resize handler + jsoneditor.util.addEventListener(window, 'resize', app.resize); + + // clear button + var domClear = document.getElementById('clear'); + domClear.onclick = app.clearFile; + + /* TODO: enable clicking on open to execute the default, "open file" + // open button + var domOpen = document.getElementById('open'); + var domOpenMenuButton = document.getElementById('openMenuButton'); + domOpen.onclick = function (event) { + var target = event.target || event.srcElement; + if (target == domOpenMenuButton || + (event.offsetX > domOpen.offsetWidth - domOpenMenuButton.offsetWidth)) { + // clicked on the menu button + } + else { + app.openFile(); + } + }; + */ + + // menu button open file + var domMenuOpenFile = document.getElementById('menuOpenFile'); + domMenuOpenFile.onclick = function (event) { + app.openFile(); + event.stopPropagation(); + event.preventDefault(); + }; + + // menu button open url + var domMenuOpenUrl = document.getElementById('menuOpenUrl'); + domMenuOpenUrl.onclick = function (event) { + app.openUrl(); + event.stopPropagation(); + event.preventDefault(); + }; + + // save button + var domSave = document.getElementById('save'); + domSave.onclick = app.saveFile; + + // set focus on the code editor + codeEditor.focus(); + + // enforce FireFox to not do spell checking on any input field + document.body.spellcheck = false; + } catch (err) { + app.notify.showError(err); + } }; /** @@ -205,29 +205,29 @@ app.load = function() { * @param {String} data */ app.openCallback = function (err, data) { - if (!err) { - if (data != null) { - codeEditor.setText(data); - try { - var json = jsoneditor.util.parse(data); - treeEditor.set(json); - } - catch (err) { - treeEditor.set({}); - app.notify.showError(app.formatError(err)); - } - } - } - else { - app.notify.showError(err); + if (!err) { + if (data != null) { + codeEditor.setText(data); + try { + var json = jsoneditor.util.parse(data); + treeEditor.set(json); + } + catch (err) { + treeEditor.set({}); + app.notify.showError(app.formatError(err)); + } } + } + else { + app.notify.showError(err); + } }; /** * Open a file explorer to select a file and open the file */ app.openFile = function() { - app.retriever.loadFile(app.openCallback); + app.retriever.loadFile(app.openCallback); }; /** @@ -236,37 +236,37 @@ app.openFile = function() { * @param {String} [url] */ app.openUrl = function (url) { - if (!url) { - app.retriever.loadUrlDialog(app.openCallback); - } - else { - app.retriever.loadUrl(url, app.openCallback); - } + if (!url) { + app.retriever.loadUrlDialog(app.openCallback); + } + else { + app.retriever.loadUrl(url, app.openCallback); + } }; /** * Open a file explorer to save the file. */ app.saveFile = function () { - // first synchronize both editors contents - if (app.lastChanged == treeEditor) { - app.treeToCode(); - } - /* TODO: also sync from code to tree editor? will clear the history ... - if (app.lastChanged == codeEditor) { - app.CodeToEditor(); - } - */ - app.lastChanged = undefined; + // first synchronize both editors contents + if (app.lastChanged == treeEditor) { + app.treeToCode(); + } + /* TODO: also sync from code to tree editor? will clear the history ... + if (app.lastChanged == codeEditor) { + app.CodeToEditor(); + } + */ + app.lastChanged = undefined; - // save the text from the code editor - // TODO: show a 'saving...' notification - var data = codeEditor.getText(); - app.retriever.saveFile(data, function (err) { - if (err) { - app.notify.showError(err); - } - }); + // save the text from the code editor + // TODO: show a 'saving...' notification + var data = codeEditor.getText(); + app.retriever.saveFile(data, function (err) { + if (err) { + app.notify.showError(err); + } + }); }; /** @@ -275,102 +275,102 @@ app.saveFile = function () { * @returns {string} */ app.formatError = function (err) { - var message = '
' + err.toString() + '
'; - if (typeof(jsonlint) != 'undefined') { - message += - '' + - 'validated by jsonlint' + - ''; - } - return message; + var message = '
' + err.toString() + '
'; + if (typeof(jsonlint) != 'undefined') { + message += + '' + + 'validated by jsonlint' + + ''; + } + return message; }; /** * Clear the current file */ app.clearFile = function () { - var json = {}; - codeEditor.set(json); - treeEditor.set(json); + var json = {}; + codeEditor.set(json); + treeEditor.set(json); }; app.resize = function() { - var domMenu = document.getElementById('menu'); - var domTreeEditor = document.getElementById('treeEditor'); - var domCodeEditor = document.getElementById('codeEditor'); - var domSplitter = document.getElementById('splitter'); - var domSplitterButtons = document.getElementById('buttons'); - var domSplitterDrag = document.getElementById('drag'); - var domAd = document.getElementById('ad'); + var domMenu = document.getElementById('menu'); + var domTreeEditor = document.getElementById('treeEditor'); + var domCodeEditor = document.getElementById('codeEditor'); + var domSplitter = document.getElementById('splitter'); + var domSplitterButtons = document.getElementById('buttons'); + var domSplitterDrag = document.getElementById('drag'); + var domAd = document.getElementById('ad'); - var margin = 15; - var width = (window.innerWidth || document.body.offsetWidth || - document.documentElement.offsetWidth); - var adWidth = domAd ? domAd.clientWidth : 0; + var margin = 15; + var width = (window.innerWidth || document.body.offsetWidth || + document.documentElement.offsetWidth); + var adWidth = domAd ? domAd.clientWidth : 0; + if (adWidth) { + width -= (adWidth + margin); + } + + if (app.splitter) { + app.splitter.setWidth(width); + + // calculate horizontal splitter position + var value = app.splitter.getValue(); + var showCodeEditor = (value > 0); + var showTreeEditor = (value < 1); + var showButtons = showCodeEditor && showTreeEditor; + domSplitterButtons.style.display = showButtons ? '' : 'none'; + + var splitterWidth = domSplitter.clientWidth; + var splitterLeft; + if (!showCodeEditor) { + // code editor not visible + splitterLeft = 0; + domSplitterDrag.innerHTML = '›'; + domSplitterDrag.title = 'Drag right to show the code editor'; + } + else if (!showTreeEditor) { + // tree editor not visible + splitterLeft = width * value - splitterWidth; + domSplitterDrag.innerHTML = '‹'; + domSplitterDrag.title = 'Drag left to show the tree editor'; + } + else { + // both tree and code editor visible + splitterLeft = width * value - splitterWidth / 2; + + // TODO: find a character with vertical dots that works on IE8 too, or use an image + var isIE8 = (jsoneditor.util.getInternetExplorerVersion() == 8); + domSplitterDrag.innerHTML = (!isIE8) ? '⋮' : '|'; + domSplitterDrag.title = 'Drag left or right to change the width of the panels'; + } + + // resize code editor + domCodeEditor.style.display = (value == 0) ? 'none' : ''; + domCodeEditor.style.width = Math.max(Math.round(splitterLeft), 0) + 'px'; + codeEditor.resize(); + + // resize the splitter + domSplitterDrag.style.height = (domSplitter.clientHeight - + domSplitterButtons.clientHeight - 2 * margin - + (showButtons ? margin : 0)) + 'px'; + domSplitterDrag.style.lineHeight = domSplitterDrag.style.height; + + // resize tree editor + // the width has a -1 to prevent the width from being just half a pixel + // wider than the window, causing the content elements to wrap... + domTreeEditor.style.display = (value == 1) ? 'none' : ''; + domTreeEditor.style.left = Math.round(splitterLeft + splitterWidth) + 'px'; + domTreeEditor.style.width = Math.max(Math.round(width - splitterLeft - splitterWidth - 2), 0) + 'px'; + } + + // align main menu with ads + if (domMenu) { if (adWidth) { - width -= (adWidth + margin); + domMenu.style.right = (margin + (adWidth + margin)) + 'px'; } - - if (app.splitter) { - app.splitter.setWidth(width); - - // calculate horizontal splitter position - var value = app.splitter.getValue(); - var showCodeEditor = (value > 0); - var showTreeEditor = (value < 1); - var showButtons = showCodeEditor && showTreeEditor; - domSplitterButtons.style.display = showButtons ? '' : 'none'; - - var splitterWidth = domSplitter.clientWidth; - var splitterLeft; - if (!showCodeEditor) { - // code editor not visible - splitterLeft = 0; - domSplitterDrag.innerHTML = '›'; - domSplitterDrag.title = 'Drag right to show the code editor'; - } - else if (!showTreeEditor) { - // tree editor not visible - splitterLeft = width * value - splitterWidth; - domSplitterDrag.innerHTML = '‹'; - domSplitterDrag.title = 'Drag left to show the tree editor'; - } - else { - // both tree and code editor visible - splitterLeft = width * value - splitterWidth / 2; - - // TODO: find a character with vertical dots that works on IE8 too, or use an image - var isIE8 = (jsoneditor.util.getInternetExplorerVersion() == 8); - domSplitterDrag.innerHTML = (!isIE8) ? '⋮' : '|'; - domSplitterDrag.title = 'Drag left or right to change the width of the panels'; - } - - // resize code editor - domCodeEditor.style.display = (value == 0) ? 'none' : ''; - domCodeEditor.style.width = Math.max(Math.round(splitterLeft), 0) + 'px'; - codeEditor.resize(); - - // resize the splitter - domSplitterDrag.style.height = (domSplitter.clientHeight - - domSplitterButtons.clientHeight - 2 * margin - - (showButtons ? margin : 0)) + 'px'; - domSplitterDrag.style.lineHeight = domSplitterDrag.style.height; - - // resize tree editor - // the width has a -1 to prevent the width from being just half a pixel - // wider than the window, causing the content elements to wrap... - domTreeEditor.style.display = (value == 1) ? 'none' : ''; - domTreeEditor.style.left = Math.round(splitterLeft + splitterWidth) + 'px'; - domTreeEditor.style.width = Math.max(Math.round(width - splitterLeft - splitterWidth - 2), 0) + 'px'; - } - - // align main menu with ads - if (domMenu) { - if (adWidth) { - domMenu.style.right = (margin + (adWidth + margin)) + 'px'; - } - else { - domMenu.style.right = margin + 'px'; - } + else { + domMenu.style.right = margin + 'px'; } + } }; diff --git a/app/web/beta/index.html b/app/web/beta/index.html index 973d86a..5b2adab 100644 --- a/app/web/beta/index.html +++ b/app/web/beta/index.html @@ -1,17 +1,17 @@ - JSON Editor Online - Beta - + JSON Editor Online - Beta +
-

JSON Editor Online - Beta

-

- There is currently no beta version available. -

-

- Go to the current version -

+

JSON Editor Online - Beta

+

+ There is currently no beta version available. +

+

+ Go to the current version +

\ No newline at end of file diff --git a/app/web/doc/doc.css b/app/web/doc/doc.css index 5cba1ee..bc5c50d 100644 --- a/app/web/doc/doc.css +++ b/app/web/doc/doc.css @@ -1,60 +1,60 @@ body, td, th { - font-family: arial, sans-serif; - font-size: 11pt; - color: #4d4d4d; + font-family: arial, sans-serif; + font-size: 11pt; + color: #4d4d4d; } body, html { - width: 100%; - height: 100%; - padding: 0; - margin: 0; + width: 100%; + height: 100%; + padding: 0; + margin: 0; } #container { - width: 600px; - margin: 0 auto; - padding: 20px 0 60px 0; + width: 600px; + margin: 0 auto; + padding: 20px 0 60px 0; } h1 { - font-size: 14pt; - color: #4d4d4d; + font-size: 14pt; + color: #4d4d4d; } h2 { - font-size: 11pt; - color: #97B0F8; - padding-top: 20px; + font-size: 11pt; + color: #97B0F8; + padding-top: 20px; } table { - border-collapse: collapse; + border-collapse: collapse; } th { - text-align: left; - background-color: #e5e5e5;; + text-align: left; + background-color: #e5e5e5;; } td { - vertical-align: top; + vertical-align: top; } th, td { - border: 1px solid #e5e5e5; - padding: 4px 4px; + border: 1px solid #e5e5e5; + padding: 4px 4px; } a { - color: #4183C4; + color: #4183C4; } a:hover { - color: red; + color: red; } img.icon { - vertical-align: middle; - margin: 0 5px; + vertical-align: middle; + margin: 0 5px; } \ No newline at end of file diff --git a/app/web/doc/index.html b/app/web/doc/index.html index 0948f54..1e7bf38 100644 --- a/app/web/doc/index.html +++ b/app/web/doc/index.html @@ -1,201 +1,201 @@ - JSON Editor Online - Documentation - + JSON Editor Online - Documentation +
-

JSON Editor Online - Documentation

+

JSON Editor Online - Documentation

-

Introduction

-

- JSON Editor Online is a web-based tool to view, edit, and format JSON. - It shows your data side by side in a clear, editable treeview and in - a code editor. -

-

- Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+. -

-

- Website: - http://jsoneditoronline.org. -

-

- Contents: -

- +

Introduction

+

+ JSON Editor Online is a web-based tool to view, edit, and format JSON. + It shows your data side by side in a clear, editable treeview and in + a code editor. +

+

+ Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+. +

+

+ Website: + http://jsoneditoronline.org. +

+

+ Contents: +

+ - -

- The applications main menu contains options to clear, load and save the - JSON contents of the application. Files can be loaded from disk or url, - and can be saved to disk. Please note that due to security restrictions, - the application can only open files from public websites, not from an - intranet. The data policy is described - here. -

- Main menu + +

+ The applications main menu contains options to clear, load and save the + JSON contents of the application. Files can be loaded from disk or url, + and can be saved to disk. Please note that due to security restrictions, + the application can only open files from public websites, not from an + intranet. The data policy is described + here. +

+ Main menu -

Panels

-

- The application contains two panels: a code editor on the left, - and a Tree Editor on the right. -

-

- There is a splitter between the two panels, allowing to change the - width of both panels according to ones needs. - To copy the contents from one panel to an other, the two copy buttons - between the panels can be used. -

- +

Panels

+

+ The application contains two panels: a code editor on the left, + and a Tree Editor on the right. +

+

+ There is a splitter between the two panels, allowing to change the + width of both panels according to ones needs. + To copy the contents from one panel to an other, the two copy buttons + between the panels can be used. +

+ -

Code editor

-

- The code editor displays JSON data in a code editor. - The editor is capable of formatting, compacting, and inspecting JSON. -

- -

- The menu of the code editor contains the following buttons: -

- +

Code editor

+

+ The code editor displays JSON data in a code editor. + The editor is capable of formatting, compacting, and inspecting JSON. +

+ +

+ The menu of the code editor contains the following buttons: +

+ -

Tree editor

-

- The Tree editor displays the JSON data in an editable tree. - The editor makes it easy to create, duplicate, remove fields, - and to edit the contents of the fields. -

- -

- The menu of the tree editor contains the following functions: -

- +

Tree editor

+

+ The Tree editor displays the JSON data in an editable tree. + The editor makes it easy to create, duplicate, remove fields, + and to edit the contents of the fields. +

+ +

+ The menu of the tree editor contains the following functions: +

+ -

- The field values in the editor are editable input fields. - The fields can be dragged up and down using the dragarea - - on the left side of the fields. When a field is the last item of the - childs of an array or object, the field can also be dragged horizontally - to move it in or out of the array or object. -

- -

- Right from the dragarea is a button - - to open the actions menu. - Depending on the type of field, the following functionality is - available in the actions menu: -

- -

Shortcut keys

-

- The tree editor supports shortcut keys for all available actions. - The editor can be used by just a keyboard. - The following short cut keys are available: -

+

Shortcut keys

+

+ The tree editor supports shortcut keys for all available actions. + The editor can be used by just a keyboard. + The following short cut keys are available: +

- - - - +
KeyDescription
Alt+ArrowsMove the caret up/down/left/right between fields
Shift+Alt+ArrowsMove field up/down/left/right
+ + + - - - - - - - - - - - - - - -
KeyDescription
Alt+ArrowsMove the caret up/down/left/right between fields
Shift+Alt+ArrowsMove field up/down/left/right
Ctrl+DDuplicate field
Ctrl+DelRemove field
Ctrl+EnterOpen link when on a field containing an url
Ctrl+InsInsert a new field with type auto
Ctrl+Shift+InsAppend a new field with type auto
Ctrl+EExpand or collapse field
Alt+EndMove the caret to the last field
Ctrl+FFind
F3, Ctrl+G
Find next
Shift+F3, Ctrl+Shift+GFind previous
Alt+HomeMove the caret to the first field
Ctrl+MShow actions menu
Ctrl+ZUndo last action
Ctrl+Shift+ZRedo
+ Ctrl+DDuplicate field + Ctrl+DelRemove field + Ctrl+EnterOpen link when on a field containing an url + Ctrl+InsInsert a new field with type auto + Ctrl+Shift+InsAppend a new field with type auto + Ctrl+EExpand or collapse field + Alt+EndMove the caret to the last field + Ctrl+FFind + F3, Ctrl+G
Find next + Shift+F3, Ctrl+Shift+GFind previous + Alt+HomeMove the caret to the first field + Ctrl+MShow actions menu + Ctrl+ZUndo last action + Ctrl+Shift+ZRedo +
diff --git a/app/web/fileretriever.css b/app/web/fileretriever.css index dfff42b..4f4607b 100644 --- a/app/web/fileretriever.css +++ b/app/web/fileretriever.css @@ -1,63 +1,63 @@ div.fileretriever-overlay, div.fileretriever-background { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - z-index: 999; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + z-index: 999; } div.fileretriever-overlay { - background-color: gray; - opacity: 0.2; - filter: alpha(opacity = 20); + background-color: gray; + opacity: 0.2; + filter: alpha(opacity = 20); } div.fileretriever-border { - width: 410px; - margin: 100px auto; - padding: 20px; - background-color: white; - border: 1px solid gray; - border-radius: 2px; + width: 410px; + margin: 100px auto; + padding: 20px; + background-color: white; + border: 1px solid gray; + border-radius: 2px; - -moz-box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); - -webkit-box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); - box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + -moz-box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + -webkit-box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); } form.fileretriever-form { } div.fileretriever-title { - font-weight: bold; + font-weight: bold; } div.fileretriever-description { - color: gray; - margin: 30px 0 0 0; + color: gray; + margin: 30px 0 0 0; } div.fileretriever-contents { - margin: 30px 0; + margin: 30px 0; } div.fileretriever-buttons { - text-align: right; + text-align: right; } input.fileretriever-field[type="file"] { - width: 400px; - padding: 3px; + width: 400px; + padding: 3px; } input.fileretriever-field[type="text"] { - width: 400px; - border: 1px solid lightgray; - border-radius: 2px; - padding: 3px; + width: 400px; + border: 1px solid lightgray; + border-radius: 2px; + padding: 3px; } input.fileretriever-submit, input.fileretriever-cancel { - margin-left: 10px; + margin-left: 10px; } diff --git a/app/web/fileretriever.js b/app/web/fileretriever.js index 9460a2a..4646d89 100644 --- a/app/web/fileretriever.js +++ b/app/web/fileretriever.js @@ -1,16 +1,16 @@ /** * @file fileretriever.js - * + * * FileRetriever manages client side loading and saving of files. * It requires a server script (fileretriever.php). Loading and saving * files is done purely clientside using HTML5 techniques when supported * by the browser. - * + * * Requires ajax.js. - * - * Supported browsers: Chrome, Firefox, Opera, Safari, + * + * Supported browsers: Chrome, Firefox, Opera, Safari, * Internet Explorer 8+. - * + * * Example usage: * var retriever = new FileRetriever({ * 'serverUrl': 'fileretriever.php' @@ -22,17 +22,17 @@ * console.log('url loaded:', data); * }); * retriever.saveFile("some text"); - * + * * @constructor FileRetriever * @param {String} options Available options: * {string} serverUrl Server side script for - * handling files, for + * handling files, for * example "fileretriever.php" * {Number} [maxSize] Maximum allowed file size - * in bytes. (this should - * be the same as maximum - * size allowed by the server - * side script). Default is + * in bytes. (this should + * be the same as maximum + * size allowed by the server + * side script). Default is * 1024 * 1024 bytes. * {Number} [timeout] Timeout in milliseconds. * 30000 ms by default. @@ -63,18 +63,18 @@ * @date 2013-01-01 */ var FileRetriever = function (options) { - // set options and variables - options = options || {}; - this.options = { - maxSize: ((options.maxSize != undefined) ? options.maxSize : 1024 * 1024), - html5: ((options.html5 != undefined) ? options.html5 : true) - }; - this.timeout = Number(options.timeout) || 30000; - this.headers = {'Accept': 'application/json'}; // headers for ajax requests - this.scriptUrl = options.scriptUrl || 'fileretriever.php'; - this.notify = options.notify || undefined; - this.defaultFilename = 'document.json'; - this.dom = {}; + // set options and variables + options = options || {}; + this.options = { + maxSize: ((options.maxSize != undefined) ? options.maxSize : 1024 * 1024), + html5: ((options.html5 != undefined) ? options.html5 : true) + }; + this.timeout = Number(options.timeout) || 30000; + this.headers = {'Accept': 'application/json'}; // headers for ajax requests + this.scriptUrl = options.scriptUrl || 'fileretriever.php'; + this.notify = options.notify || undefined; + this.defaultFilename = 'document.json'; + this.dom = {}; }; /** @@ -83,12 +83,12 @@ var FileRetriever = function (options) { * @private */ FileRetriever.prototype._hide = function (elem) { - elem.style.visibility = 'hidden'; - elem.style.position = 'absolute'; - elem.style.left = '-1000px'; - elem.style.top = '-1000px'; - elem.style.width = '0'; - elem.style.height = '0'; + elem.style.visibility = 'hidden'; + elem.style.position = 'absolute'; + elem.style.left = '-1000px'; + elem.style.top = '-1000px'; + elem.style.width = '0'; + elem.style.height = '0'; }; /** @@ -96,16 +96,16 @@ FileRetriever.prototype._hide = function (elem) { * The FileRetriever cannot be used after its DOM elements are deleted. */ FileRetriever.prototype.remove = function () { - var dom = this.dom; - for (var prop in dom) { - if (dom.hasOwnProperty(prop)) { - var elem = dom[prop]; - if (elem.parentNode) { - elem.parentNode.removeChild(elem); - } - } + var dom = this.dom; + for (var prop in dom) { + if (dom.hasOwnProperty(prop)) { + var elem = dom[prop]; + if (elem.parentNode) { + elem.parentNode.removeChild(elem); + } } - this.dom = {}; + } + this.dom = {}; }; /** @@ -116,8 +116,8 @@ FileRetriever.prototype.remove = function () { * @private */ FileRetriever.prototype._getFilename = function (path) { - // http://stackoverflow.com/a/423385/1262753 - return path ? path.replace(/^.*[\\\/]/, '') : ''; + // http://stackoverflow.com/a/423385/1262753 + return path ? path.replace(/^.*[\\\/]/, '') : ''; }; /** @@ -125,7 +125,7 @@ FileRetriever.prototype._getFilename = function (path) { * @param {String} url */ FileRetriever.prototype.setUrl = function (url) { - this.url = url; + this.url = url; }; /** @@ -133,7 +133,7 @@ FileRetriever.prototype.setUrl = function (url) { * @return {String} filename */ FileRetriever.prototype.getFilename = function () { - return this.defaultFilename; + return this.defaultFilename; }; /** @@ -141,7 +141,7 @@ FileRetriever.prototype.getFilename = function () { * @return {String | undefined} url */ FileRetriever.prototype.getUrl = function () { - return this.url; + return this.url; }; /** @@ -152,61 +152,61 @@ FileRetriever.prototype.getUrl = function () { * {string} data */ FileRetriever.prototype.loadUrl = function (url, callback) { - // set current filename (will be used when saving a file again) - this.setUrl(url); + // set current filename (will be used when saving a file again) + this.setUrl(url); - // loading notification - var loading = undefined; - if (this.notify) { - loading = this.notify.showNotification('loading url...'); + // loading notification + var loading = undefined; + if (this.notify) { + loading = this.notify.showNotification('loading url...'); + } + + // method to ensure the callback is only executed once + var me = this; + var callbackOnce = function (error, data) { + if (callback) { + callback(error, data); + callback = undefined; } + if (me.notify && loading) { + me.notify.removeMessage(loading); + loading = undefined; + } + }; - // method to ensure the callback is only executed once - var me = this; - var callbackOnce = function (error, data) { - if (callback) { - callback(error, data); - callback = undefined; - } - if (me.notify && loading) { - me.notify.removeMessage(loading); - loading = undefined; - } - }; - - // try to fetch to the url directly (may result in a cross-domain error) - var scriptUrl = this.scriptUrl; - ajax.get(url, me.headers, function(data, status) { + // try to fetch to the url directly (may result in a cross-domain error) + var scriptUrl = this.scriptUrl; + ajax.get(url, me.headers, function(data, status) { + if (status == 200) { + // success. great. no cross-domain error + callbackOnce(null, data); + } + else { + // cross-domain error (or other). retrieve the url via the server + var indirectUrl = scriptUrl + '?url=' + encodeURIComponent(url); + var err; + ajax.get(indirectUrl, me.headers, function(data, status) { if (status == 200) { - // success. great. no cross-domain error - callbackOnce(null, data); + callbackOnce(null, data); + } + else if (status == 404) { + console.log('Error: url "' + url + '" not found', status, data); + err = new Error('Error: url "' + url + '" not found'); + callbackOnce(err, null); } else { - // cross-domain error (or other). retrieve the url via the server - var indirectUrl = scriptUrl + '?url=' + encodeURIComponent(url); - var err; - ajax.get(indirectUrl, me.headers, function(data, status) { - if (status == 200) { - callbackOnce(null, data); - } - else if (status == 404) { - console.log('Error: url "' + url + '" not found', status, data); - err = new Error('Error: url "' + url + '" not found'); - callbackOnce(err, null); - } - else { - console.log('Error: failed to load url "' + url + '"', status, data); - err = new Error('Error: failed to load url "' + url + '"'); - callbackOnce(err, null); - } - }); + console.log('Error: failed to load url "' + url + '"', status, data); + err = new Error('Error: failed to load url "' + url + '"'); + callbackOnce(err, null); } - }); + }); + } + }); - // safety mechanism: callback after a timeout - setTimeout(function () { - callbackOnce(new Error('Error loading url (time out)')); - }, this.timeout); + // safety mechanism: callback after a timeout + setTimeout(function () { + callbackOnce(new Error('Error loading url (time out)')); + }, this.timeout); }; /** @@ -219,115 +219,115 @@ FileRetriever.prototype.loadUrl = function (url, callback) { * {string} data */ FileRetriever.prototype.loadFile = function (callback) { - // loading notification - var loading = undefined; - var me = this; + // loading notification + var loading = undefined; + var me = this; - var startLoading = function () { - if (me.notify && !loading) { - loading = me.notify.showNotification('loading file...'); - } - - // safety mechanism: callback after a timeout - setTimeout(function () { - callbackOnce(new Error('Error loading url (time out)')); - }, me.timeout); - }; - - // method to ensure the callback is only executed once - var callbackOnce = function (error, data) { - if (callback) { - callback(error, data); - callback = undefined; - } - if (me.notify && loading) { - me.notify.removeMessage(loading); - loading = undefined; - } - }; - - // create a form to select a file and submit - var useFileReader = (me.options.html5 && window.File && window.FileReader); - - if (useFileReader) { - this.prompt({ - title: 'Open file', - titleSubmit: 'Open', - description: 'Select a file on your computer.', - inputType: 'file', - inputName: 'file', - callback: function (value, field) { - if (value) { - if (useFileReader) { - // load file via HTML5 FileReader (no size limits) - var file = field.files[0]; - var reader = new FileReader(); - reader.onload = function(event) { - var data = event.target.result; - callbackOnce(null, data); - }; - - // Read in the image file as a data URL. - reader.readAsText(file); - } - - startLoading(); - } - } - }); - // TODO: handle a cancel + var startLoading = function () { + if (me.notify && !loading) { + loading = me.notify.showNotification('loading file...'); } - else { - // no html5 filereader available - // create an iframe for uploading files - // the iframe must have an unique name, allowing multiple - // FileRetrievers. The name is needed as target for the uploadForm - var iframeName = 'fileretriever-upload-' + Math.round(Math.random() * 1E15); - var iframe = document.createElement('iframe'); - iframe.name = iframeName; - me._hide(iframe); - iframe.onload = function () { - // when a downloaded file is retrieved, send a callback with - // the retrieved data - var id = iframe.contentWindow.document.body.innerHTML; - if (id) { - var url = me.scriptUrl + '?id=' + id + '&filename=' + me.getFilename(); - ajax.get(url, me.headers, function (data, status) { - if (status == 200) { - callbackOnce(null, data); - } - else { - var err = new Error('Error loading file ' + me.getFilename()); - callbackOnce(err, null); - } + // safety mechanism: callback after a timeout + setTimeout(function () { + callbackOnce(new Error('Error loading url (time out)')); + }, me.timeout); + }; - // cleanup the frame again - if (iframe.parentNode === document.body) { - document.body.removeChild(iframe); - } - }); - } - }; - document.body.appendChild(iframe); - - this.prompt({ - title: 'Open file', - titleSubmit: 'Open', - description: 'Select a file on your computer.', - inputType: 'file', - inputName: 'file', - formAction: this.scriptUrl, - formMethod: 'POST', - formTarget: iframeName, - callback: function (value) { - if (value) { - startLoading(); - } - } - }); - // TODO: handle a cancel + // method to ensure the callback is only executed once + var callbackOnce = function (error, data) { + if (callback) { + callback(error, data); + callback = undefined; } + if (me.notify && loading) { + me.notify.removeMessage(loading); + loading = undefined; + } + }; + + // create a form to select a file and submit + var useFileReader = (me.options.html5 && window.File && window.FileReader); + + if (useFileReader) { + this.prompt({ + title: 'Open file', + titleSubmit: 'Open', + description: 'Select a file on your computer.', + inputType: 'file', + inputName: 'file', + callback: function (value, field) { + if (value) { + if (useFileReader) { + // load file via HTML5 FileReader (no size limits) + var file = field.files[0]; + var reader = new FileReader(); + reader.onload = function(event) { + var data = event.target.result; + callbackOnce(null, data); + }; + + // Read in the image file as a data URL. + reader.readAsText(file); + } + + startLoading(); + } + } + }); + // TODO: handle a cancel + } + else { + // no html5 filereader available + + // create an iframe for uploading files + // the iframe must have an unique name, allowing multiple + // FileRetrievers. The name is needed as target for the uploadForm + var iframeName = 'fileretriever-upload-' + Math.round(Math.random() * 1E15); + var iframe = document.createElement('iframe'); + iframe.name = iframeName; + me._hide(iframe); + iframe.onload = function () { + // when a downloaded file is retrieved, send a callback with + // the retrieved data + var id = iframe.contentWindow.document.body.innerHTML; + if (id) { + var url = me.scriptUrl + '?id=' + id + '&filename=' + me.getFilename(); + ajax.get(url, me.headers, function (data, status) { + if (status == 200) { + callbackOnce(null, data); + } + else { + var err = new Error('Error loading file ' + me.getFilename()); + callbackOnce(err, null); + } + + // cleanup the frame again + if (iframe.parentNode === document.body) { + document.body.removeChild(iframe); + } + }); + } + }; + document.body.appendChild(iframe); + + this.prompt({ + title: 'Open file', + titleSubmit: 'Open', + description: 'Select a file on your computer.', + inputType: 'file', + inputName: 'file', + formAction: this.scriptUrl, + formMethod: 'POST', + formTarget: iframeName, + callback: function (value) { + if (value) { + startLoading(); + } + } + }); + // TODO: handle a cancel + } }; /** @@ -337,25 +337,25 @@ FileRetriever.prototype.loadFile = function (callback) { * {String} data */ FileRetriever.prototype.loadUrlDialog = function (callback) { - var me = this; - this.prompt({ - title: 'Open url', - titleSubmit: 'Open', - description: 'Enter a public url. ' + - 'Urls which need authentication or are located on an intranet cannot be loaded.', - inputType: 'text', - inputName: 'url', - inputDefault: this.getUrl(), - callback: function (url) { - if (url) { - me.loadUrl(url, callback); - } - else { - // cancel - callback(); - } - } - }); + var me = this; + this.prompt({ + title: 'Open url', + titleSubmit: 'Open', + description: 'Enter a public url. ' + + 'Urls which need authentication or are located on an intranet cannot be loaded.', + inputType: 'text', + inputName: 'url', + inputDefault: this.getUrl(), + callback: function (url) { + if (url) { + me.loadUrl(url, callback); + } + else { + // cancel + callback(); + } + } + }); }; /** @@ -379,197 +379,197 @@ FileRetriever.prototype.loadUrlDialog = function (callback) { * {function} callback */ FileRetriever.prototype.prompt = function (params) { - var removeDialog = function () { - // remove the form - if (background.parentNode) { - background.parentNode.removeChild(background); - } - if (overlay.parentNode) { - overlay.parentNode.removeChild(overlay); - } - - jsoneditor.util.removeEventListener(document, 'keydown', onKeyDown); - }; - - var onCancel = function () { - removeDialog(); - if(params.callback) { - params.callback(null); - } - }; - - var onKeyDown = jsoneditor.util.addEventListener(document, 'keydown', function (event) { - var keynum = event.which; - if (keynum == 27) { // ESC - onCancel(); - event.preventDefault(); - event.stopPropagation(); - } - }); - - var overlay = document.createElement('div'); - overlay.className = 'fileretriever-overlay'; - document.body.appendChild(overlay); - - var form = document.createElement('form'); - form.className = 'fileretriever-form'; - form.target = params.formTarget || ''; - form.action = params.formAction || ''; - form.method = params.formMethod || 'POST'; - form.enctype = 'multipart/form-data'; - form.encoding = 'multipart/form-data'; // needed for IE8 and older - form.onsubmit = function () { - if (field.value) { - setTimeout(function () { - // remove *after* the submit has taken place! - removeDialog(); - }, 0); - if (params.callback) { - params.callback(field.value, field); - } - return (params.formAction != undefined && params.formMethod != undefined); - } - else { - alert('Enter a ' + params.inputName + ' first...'); - return false; - } - }; - - var title = document.createElement('div'); - title.className = 'fileretriever-title'; - title.appendChild(document.createTextNode(params.title || 'Dialog')); - form.appendChild(title); - - if (params.description) { - var description = document.createElement('div'); - description.className = 'fileretriever-description'; - description.appendChild(document.createTextNode(params.description)); - form.appendChild(description); + var removeDialog = function () { + // remove the form + if (background.parentNode) { + background.parentNode.removeChild(background); + } + if (overlay.parentNode) { + overlay.parentNode.removeChild(overlay); } - var field = document.createElement('input'); - field.className = 'fileretriever-field'; - field.type = params.inputType || 'text'; - field.name = params.inputName || 'text'; - field.value = params.inputDefault || ''; + jsoneditor.util.removeEventListener(document, 'keydown', onKeyDown); + }; - var contents = document.createElement('div'); - contents.className = 'fileretriever-contents'; - contents.appendChild(field); - form.appendChild(contents); + var onCancel = function () { + removeDialog(); + if(params.callback) { + params.callback(null); + } + }; - var cancel = document.createElement('input'); - cancel.className = 'fileretriever-cancel'; - cancel.type = 'button'; - cancel.value = params.titleCancel || 'Cancel'; - cancel.onclick = onCancel; + var onKeyDown = jsoneditor.util.addEventListener(document, 'keydown', function (event) { + var keynum = event.which; + if (keynum == 27) { // ESC + onCancel(); + event.preventDefault(); + event.stopPropagation(); + } + }); - var submit = document.createElement('input'); - submit.className = 'fileretriever-submit'; - submit.type = 'submit'; - submit.value = params.titleSubmit || 'Ok'; + var overlay = document.createElement('div'); + overlay.className = 'fileretriever-overlay'; + document.body.appendChild(overlay); - var buttons = document.createElement('div'); - buttons.className = 'fileretriever-buttons'; - buttons.appendChild(cancel); - buttons.appendChild(submit); - form.appendChild(buttons); + var form = document.createElement('form'); + form.className = 'fileretriever-form'; + form.target = params.formTarget || ''; + form.action = params.formAction || ''; + form.method = params.formMethod || 'POST'; + form.enctype = 'multipart/form-data'; + form.encoding = 'multipart/form-data'; // needed for IE8 and older + form.onsubmit = function () { + if (field.value) { + setTimeout(function () { + // remove *after* the submit has taken place! + removeDialog(); + }, 0); + if (params.callback) { + params.callback(field.value, field); + } + return (params.formAction != undefined && params.formMethod != undefined); + } + else { + alert('Enter a ' + params.inputName + ' first...'); + return false; + } + }; - var border = document.createElement('div'); - border.className = 'fileretriever-border'; - border.appendChild(form); + var title = document.createElement('div'); + title.className = 'fileretriever-title'; + title.appendChild(document.createTextNode(params.title || 'Dialog')); + form.appendChild(title); - var background = document.createElement('div'); - background.className = 'fileretriever-background'; - background.appendChild(border); - background.onclick = function (event) { - var target = event.target; - if (target == background) { - onCancel(); - } - }; - document.body.appendChild(background); + if (params.description) { + var description = document.createElement('div'); + description.className = 'fileretriever-description'; + description.appendChild(document.createTextNode(params.description)); + form.appendChild(description); + } - field.focus(); - field.select(); + var field = document.createElement('input'); + field.className = 'fileretriever-field'; + field.type = params.inputType || 'text'; + field.name = params.inputName || 'text'; + field.value = params.inputDefault || ''; + + var contents = document.createElement('div'); + contents.className = 'fileretriever-contents'; + contents.appendChild(field); + form.appendChild(contents); + + var cancel = document.createElement('input'); + cancel.className = 'fileretriever-cancel'; + cancel.type = 'button'; + cancel.value = params.titleCancel || 'Cancel'; + cancel.onclick = onCancel; + + var submit = document.createElement('input'); + submit.className = 'fileretriever-submit'; + submit.type = 'submit'; + submit.value = params.titleSubmit || 'Ok'; + + var buttons = document.createElement('div'); + buttons.className = 'fileretriever-buttons'; + buttons.appendChild(cancel); + buttons.appendChild(submit); + form.appendChild(buttons); + + var border = document.createElement('div'); + border.className = 'fileretriever-border'; + border.appendChild(form); + + var background = document.createElement('div'); + background.className = 'fileretriever-background'; + background.appendChild(border); + background.onclick = function (event) { + var target = event.target; + if (target == background) { + onCancel(); + } + }; + document.body.appendChild(background); + + field.focus(); + field.select(); }; /** * Save data to disk * @param {String} data - * @param {function} [callback] Callback when the file is saved, called + * @param {function} [callback] Callback when the file is saved, called * with parameter: * {Error} error */ FileRetriever.prototype.saveFile = function (data, callback) { - // saving notification - var saving = undefined; - if (this.notify) { - saving = this.notify.showNotification('saving file...'); + // saving notification + var saving = undefined; + if (this.notify) { + saving = this.notify.showNotification('saving file...'); + } + + // method to ensure the callback is only executed once + var me = this; + var callbackOnce = function (error) { + if (callback) { + callback(error); + callback = undefined; } - - // method to ensure the callback is only executed once - var me = this; - var callbackOnce = function (error) { - if (callback) { - callback(error); - callback = undefined; - } - if (me.notify && saving) { - me.notify.removeMessage(saving); - saving = undefined; - } - }; - - // create an anchor to save files to disk (if supported by the browser) - // Note: save file using a.download is disabled in Firefox because of a - // a bug in Firefox, which breaks the cut/paste functionality of - // editable divs on the page. - var a = document.createElement('a'); - if (this.options.html5 && a.download != undefined && !util.isFirefox()) { - // save file directly using a data URL - a.style.display = 'none'; - a.href = 'data:application/json;charset=utf-8,' + encodeURIComponent(data); - a.download = this.getFilename(); - - // attach the element to the DOM, invoke a click action, and remove it again - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - - callbackOnce(); + if (me.notify && saving) { + me.notify.removeMessage(saving); + saving = undefined; } - else { - // save file by uploading it to the server and then downloading - // it via an iframe - if (data.length < this.options.maxSize) { - ajax.post(me.scriptUrl, data, me.headers, function(id, status) { - if (status == 200) { - var iframe = document.createElement('iframe'); - iframe.src = me.scriptUrl + '?id=' + id + '&filename=' + me.getFilename(); - me._hide(iframe); - document.body.appendChild(iframe); - /* TODO: send callback after the iframe is loaded. Problem: iframe.onload does not work on IE - iframe.onload = function () { - callbackOnce(); - }; - //*/ - callbackOnce(); - // TODO: cleanup the iframe after the file is saved. Problem: we cannot know when the save dialog is closed. - } - else { - callbackOnce(new Error('Error saving file')); - } - }); + }; + + // create an anchor to save files to disk (if supported by the browser) + // Note: save file using a.download is disabled in Firefox because of a + // a bug in Firefox, which breaks the cut/paste functionality of + // editable divs on the page. + var a = document.createElement('a'); + if (this.options.html5 && a.download != undefined && !util.isFirefox()) { + // save file directly using a data URL + a.style.display = 'none'; + a.href = 'data:application/json;charset=utf-8,' + encodeURIComponent(data); + a.download = this.getFilename(); + + // attach the element to the DOM, invoke a click action, and remove it again + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + + callbackOnce(); + } + else { + // save file by uploading it to the server and then downloading + // it via an iframe + if (data.length < this.options.maxSize) { + ajax.post(me.scriptUrl, data, me.headers, function(id, status) { + if (status == 200) { + var iframe = document.createElement('iframe'); + iframe.src = me.scriptUrl + '?id=' + id + '&filename=' + me.getFilename(); + me._hide(iframe); + document.body.appendChild(iframe); + /* TODO: send callback after the iframe is loaded. Problem: iframe.onload does not work on IE + iframe.onload = function () { + callbackOnce(); + }; + //*/ + callbackOnce(); + // TODO: cleanup the iframe after the file is saved. Problem: we cannot know when the save dialog is closed. } else { - callbackOnce(new Error('Maximum allowed file size exceeded (' + - this.options.maxSize + ' bytes)')); + callbackOnce(new Error('Error saving file')); } + }); } + else { + callbackOnce(new Error('Maximum allowed file size exceeded (' + + this.options.maxSize + ' bytes)')); + } + } - // safety mechanism: callback after a timeout - setTimeout(function () { - callbackOnce(new Error('Error saving file (time out)')); - }, this.timeout); + // safety mechanism: callback after a timeout + setTimeout(function () { + callbackOnce(new Error('Error saving file (time out)')); + }, this.timeout); }; diff --git a/app/web/hash.js b/app/web/hash.js index 29e5798..0ef51df 100644 --- a/app/web/hash.js +++ b/app/web/hash.js @@ -10,18 +10,18 @@ function Hash() {} * @return {Object} query object containing key/values */ Hash.prototype.getQuery = function () { - var hash = window.location.hash.substring(1); // skip the # character - var params = hash.split('&'); - var query = {}; - for (var i = 0, iMax = params.length; i < iMax; i++) { - var keyvalue = params[i].split('='); - if (keyvalue.length == 2) { - var key = decodeURIComponent(keyvalue[0]); - var value = decodeURIComponent(keyvalue[1]); - query[key] = value; - } + var hash = window.location.hash.substring(1); // skip the # character + var params = hash.split('&'); + var query = {}; + for (var i = 0, iMax = params.length; i < iMax; i++) { + var keyvalue = params[i].split('='); + if (keyvalue.length == 2) { + var key = decodeURIComponent(keyvalue[0]); + var value = decodeURIComponent(keyvalue[1]); + query[key] = value; } - return query; + } + return query; }; /** @@ -31,46 +31,46 @@ Hash.prototype.getQuery = function () { * @param {function} callback Will be called with the new value as parameter */ Hash.prototype.onChange = function (key, callback) { - this.prevHash = ''; - var me = this; - if (!me.callbacks) { - me.callbacks = []; - } - me.callbacks.push({ - 'key': key, - 'value': undefined, - 'callback': callback - }); + this.prevHash = ''; + var me = this; + if (!me.callbacks) { + me.callbacks = []; + } + me.callbacks.push({ + 'key': key, + 'value': undefined, + 'callback': callback + }); - function checkForChanges() { - for (var i = 0; i < me.callbacks.length; i++) { - var obj = me.callbacks[i]; - var value = me.getValue(obj.key); - var changed = (value !== obj.value); - obj.value = value; - if (changed) { - obj.callback(value); - } - } + function checkForChanges() { + for (var i = 0; i < me.callbacks.length; i++) { + var obj = me.callbacks[i]; + var value = me.getValue(obj.key); + var changed = (value !== obj.value); + obj.value = value; + if (changed) { + obj.callback(value); + } } + } - // source: http://stackoverflow.com/questions/2161906/handle-url-anchor-change-event-in-js - if ('onhashchange' in window) { - window.onhashchange = function () { - checkForChanges(); - } - } - else { - // onhashchange event not supported - me.prevHash = window.location.hash; - window.setInterval(function () { - var hash = window.location.hash; - if (hash != me.prevHash) { - me.prevHash = hash; - checkForChanges(); - } - }, 500); + // source: http://stackoverflow.com/questions/2161906/handle-url-anchor-change-event-in-js + if ('onhashchange' in window) { + window.onhashchange = function () { + checkForChanges(); } + } + else { + // onhashchange event not supported + me.prevHash = window.location.hash; + window.setInterval(function () { + var hash = window.location.hash; + if (hash != me.prevHash) { + me.prevHash = hash; + checkForChanges(); + } + }, 500); + } }; @@ -79,23 +79,23 @@ Hash.prototype.onChange = function (key, callback) { * @param {Object} query object with strings */ Hash.prototype.setQuery = function (query) { - var hash = ''; + var hash = ''; - for (var key in query) { - if (query.hasOwnProperty(key)) { - var value = query[key]; - if (value != undefined) { - if (hash.length) { - hash += '&'; - } - hash += encodeURIComponent(key); - hash += '='; - hash += encodeURIComponent(query[key]); - } + for (var key in query) { + if (query.hasOwnProperty(key)) { + var value = query[key]; + if (value != undefined) { + if (hash.length) { + hash += '&'; } + hash += encodeURIComponent(key); + hash += '='; + hash += encodeURIComponent(query[key]); + } } + } - window.location.hash = (hash.length ? ('#' + hash) : ''); + window.location.hash = (hash.length ? ('#' + hash) : ''); }; @@ -105,8 +105,8 @@ Hash.prototype.setQuery = function (query) { * @return {String | undefined} value undefined when the value is not found */ Hash.prototype.getValue = function (key) { - var query = this.getQuery(); - return query[key]; + var query = this.getQuery(); + return query[key]; }; /** @@ -115,9 +115,9 @@ Hash.prototype.getValue = function (key) { * @param {String} value */ Hash.prototype.setValue = function (key, value) { - var query = this.getQuery(); - query[key] = value; - this.setQuery(query); + var query = this.getQuery(); + query[key] = value; + this.setQuery(query); }; /** @@ -125,9 +125,9 @@ Hash.prototype.setValue = function (key, value) { * @param {String} key */ Hash.prototype.removeValue = function (key) { - var query = this.getQuery(); - if (query[key]) { - delete query[key]; - this.setQuery(query); - } + var query = this.getQuery(); + if (query[key]) { + delete query[key]; + this.setQuery(query); + } }; diff --git a/app/web/index.html b/app/web/index.html index 597134e..6dfc239 100644 --- a/app/web/index.html +++ b/app/web/index.html @@ -2,186 +2,186 @@ - + - JSON Editor Online - view, edit and format JSON online + JSON Editor Online - view, edit and format JSON online - + @author Jos de Jong, + @version @@version + @date @@date + --> - - - + + + - + - - - + + + - - - + + +