/** * @file app.js * * @brief * JSONEditor is an editor to display and edit JSON data in a treeview. * * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ * * @license * This json editor is open sourced with the intention to use the editor as * a component in your own application. Not to just copy and monetize the editor * as it is. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * Copyright (C) 2011-2012 Jos de Jong, http://jsoneditoronline.org * * @author Jos de Jong, * @date 2012-11-03 */ var editor = null; var formatter = null; var app = {}; /** * Get the JSON from the formatter and load it in the editor */ app.formatterToEditor = function() { try { editor.set(formatter.get()); } catch (err) { app.notify.showError(err); } }; /** * Get the JSON from the editor and load it into the formatter */ app.editorToFormatter = function () { try { formatter.set(editor.get()); } catch (err) { app.notify.showError(err); } }; /** * Load the interface (editor, formatter, splitter) */ // TODO: split the method load in multiple methods, it is too large app.load = function() { try { // notification handler app.notify = new Notify(); // retriever for loading/saving files app.retriever = new FileRetriever({ scriptUrl: 'fileretriever.php', notify: app.notify }); // default json document var json = { "name": "John Smith", "age": 32, "employed": true, "address": { "street": "701 First Ave.", "city": "Sunnyvale, CA 95125", "country": "United States" }, "children": [ { "name": "Richard", "age": 7 }, { "name": "Susan", "age": 4 }, { "name": "James", "age": 3 } ] }; // load url if hash contains a url if (window.Hash) { var hash = new Hash(); var url = hash.getValue('url'); if (url) { json = {}; app.openUrl(url); } } // Store whether editor or formatter is last changed app.lastChanged = undefined; // formatter var container = document.getElementById("jsonformatter"); formatter = new JSONFormatter(container, { change: function () { app.lastChanged = formatter; } }); formatter.set(json); formatter.onError = function (err) { app.notify.showError(err); }; // editor container = document.getElementById("jsoneditor"); editor = new JSONEditor(container, { change: function () { app.lastChanged = editor; } }); editor.set(json); // TODO: automatically synchronize data of formatter and editor? (editor should keep its state though) // splitter var domSplitter = document.getElementById('splitter'); app.splitter = new Splitter({ container: domSplitter, change: function () { app.resize(); } }); // button Formatter-to-Editor domSplitter.appendChild(document.createElement('br')); domSplitter.appendChild(document.createElement('br')); domSplitter.appendChild(document.createElement('br')); var toForm = document.createElement('button'); toForm.id = 'toForm'; toForm.title = 'JSON to Editor'; toForm.className = 'convert'; toForm.innerHTML = '
'; toForm.onclick = function () { this.focus(); app.formatterToEditor(); }; domSplitter.appendChild(toForm); // button Editor-to-Formatter domSplitter.appendChild(document.createElement('br')); domSplitter.appendChild(document.createElement('br')); var toJSON = document.createElement('button'); toJSON.id = 'toJSON'; toJSON.title = 'Editor to JSON'; toJSON.className = 'convert'; toJSON.innerHTML = '
'; toJSON.onclick = function () { this.focus(); app.editorToFormatter(); }; domSplitter.appendChild(toJSON); // web page resize handler JSONEditor.Events.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) { event = event || window.event; // for IE8 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(); JSONEditor.Events.stopPropagation(event); JSONEditor.Events.preventDefault(event); }; // menu button open url var domMenuOpenUrl = document.getElementById('menuOpenUrl'); domMenuOpenUrl.onclick = function (event) { app.openUrl(); JSONEditor.Events.stopPropagation(event); JSONEditor.Events.preventDefault(event); }; // save button var domSave = document.getElementById('save'); domSave.onclick = app.saveFile; // TODO: implement a focus method formatter.textarea.focus(); // enforce FireFox to not do spell checking on any input field document.body.spellcheck = false; } catch (err) { app.notify.showError(err); } }; /** * Callback method called when a file or url is opened. * @param {Error} err * @param {String} data */ app.openCallback = function (err, data) { if (!err) { if (data != undefined) { formatter.setText(data); try { var json = JSONEditor.parse(data); editor.set(json); } catch (err) { editor.set({}); app.notify.showError(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); }; /** * Open a url. If no url is provided as parameter, a dialog will be opened * to select a url. * @param {String} [url] */ app.openUrl = function (url) { 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 the editors and formatters contents if (app.lastChanged == editor) { app.editorToFormatter(); } /* TODO: also sync from formatter to editor? will clear the history ... if (app.lastChanged == formatter) { app.formatterToEditor(); } */ app.lastChanged = undefined; // save the text from the formatter // TODO: show a 'saving...' notification var data = formatter.getText(); app.retriever.saveFile(data, function (err) { if (err) { app.notify.showError(err); } }); }; /** * Clear the current file */ app.clearFile = function () { var json = {}; formatter.set(json); editor.set(json); app.retriever.removeUrl(); }; app.resize = function() { var domEditor = document.getElementById('jsoneditor'); var domFormatter = document.getElementById('jsonformatter'); var domSplitter = document.getElementById('splitter'); var domAd = document.getElementById('ad'); var domAdInfo = document.getElementById('adInfo'); var width = window.innerWidth || document.body.offsetWidth || document.documentElement.offsetWidth; var height = window.innerHeight || document.body.offsetHeight || document.documentElement.offsetHeight; var adWidth = domAd ? domAd.clientWidth : 0; var splitterWidth = domSplitter.clientWidth; if (adWidth) { width -= (adWidth + 15); // Not so nice, +15 here for the margin } var splitterLeft = width * app.splitter.getValue(); // resize formatter domFormatter.style.width = Math.round(splitterLeft) + 'px'; // resize 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... domEditor.style.left = Math.round(splitterLeft + splitterWidth) + 'px'; domEditor.style.width = Math.round(width - splitterLeft - splitterWidth - 1) + 'px'; // resize ad text if (domAdInfo && domAd) { var infoHeight = domAdInfo.clientHeight; domAd.style.paddingTop = infoHeight + 'px'; } }; /** * Hide the advertisement */ app.hideAds = function() { var domAd = document.getElementById("ad"); if (domAd) { domAd.parentNode.removeChild(domAd); app.resize(); } };