UNPKG

json-object-editor

Version:

JOE the Json Object Editor | Platform Edition

1,428 lines (1,178 loc) 384 kB
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } /*/--------------------------------------------------------- Craydent LLC Copyright 2014 (http://craydent.com/joe) Dual licensed under the MIT or GPL Version 2 licenses. (http://craydent.com/license) ---------------------------------------------------------/*/ //render field - self.renderObjectPropFieldUI //render list item - self.renderListItems() //single field list item -renderFieldListItem() if ($c.isMobile()) { document.getElementsByTagName('html')[0].className += ' touch joesmall-size'; } else { document.getElementsByTagName('html')[0].className += ' no-touch joelarge-size'; } window._joeEditingHash = false; var _webworkers = false; var _joeworker; if (!!window.Worker) { _webworkers = true; } var joe_web_dir = '//' + location.hostname + ':' + (location.port || (location.protocol == "https:" ? 443 : 80)) + "/JsonObjectEditor/"; if (location && location.origin == 'file://') { joe_web_dir = location.href.slice(0, location.href.lastIndexOf('/') + 1); } var __docWriter = function __docWriter(src, type, cancelWrite) { var type = type || 'js'; var html = ''; switch (type.toLowerCase()) { case 'js': case 'javascript': html += '<script type="text/javascript" src="' + src + '"></script>'; break; case 'css': case 'stylesheet': html += '<link href="' + src + '" rel="stylesheet" type="text/css">'; break; } if (!cancelWrite) { document.write(html); } return html; }; var __loadAdditionalFiles = function __loadAdditionalFiles() { var bonuses = ''; if (typeof jQuery == 'undefined') { //console.log('loading jquery'); /* bonuses+= __docWriter(joe_web_dir+"js/libs/jquery-1.11.3.min.js",'js')+ __docWriter(joe_web_dir+"js/libs/jquery-ui.min.js");*/ __docWriter(joe_web_dir + "js/libs/jquery-1.11.3.min.js", 'js') + __docWriter(joe_web_dir + "js/libs/jquery-ui.min.js"); } bonuses += __docWriter(joe_web_dir + "js/libs/jquery.ui.touch-punch.min.js"); if (typeof Craydent == 'undefined' || !Craydent.VERSION || Craydent.VERSION < '1.7.37') { bonuses += __docWriter(joe_web_dir + "js/libs/craydent-1.8.1.js", 'js', true); } /* bonuses+= __docWriter(joe_web_dir+'css/joe.css','css','css',true) +__docWriter(joe_web_dir+'js/ace/ace.js','js',true) +__docWriter(joe_web_dir+'js/plugins/tinymce.min.js','js',true); */ document.write(bonuses); }; function __require(file, callback) { var head = document.getElementsByTagName("head")[0]; var script = document.createElement('script'); script.src = file; script.type = 'text/javascript'; //real browsers script.onload = callback; //Internet explorer script.onreadystatechange = function () { if (this.readyState == 'complete') { callback(); } }; head.appendChild(script); } /*var __joeFieldTypes = [ 'text', 'select', 'code', 'rendering', 'date', 'boolean', 'geo', 'image', 'url', 'objectList', 'objectReference', 'group', 'content' ];*/ //__loadAdditionalFiles(); function JsonObjectEditor(specs) { var self = this; var htmlRef = document.getElementsByTagName('html')[0]; self.initialDocumentTitle = document.title; $c.TEMPLATE_VARS.push({ variable: '/textarea', value: '</textarea>' }, { variable: 'textarea', value: '<textarea>' }, { variable: 'SERVER', value: '//' + $c.SERVER }); var initialized = false; var colCount = 1; var listMode = false; var gridMode = false; var tableMode = false, tableSpecs; var multiEdit = false; this.VERSION = '1.0.1'; window._joes = window._joes || []; this.joe_index = window._joes.length; if (!window._joes.length) { window._joe = this; } this.Error = { log: [], add: function add(message, error, data) { var payload = { caller: arguments.callee.caller, callerargs: arguments.callee.caller.arguments, message: message, error: error, stack: new Error(error).stack, data: data, timestamp: new Date().toISOString(), _id: cuid() }; self.Error.log.push(payload); logit('[error]: ' + message); }, show: function show() { self.show(self.Error.log, { schema: { title: '${message}', idprop: '_id', listView: { title: '<joe-title>${message}</joe-title><joe-subtitle>${timestamp}</joe-subtitle>', listWindowTitle: 'Errors' }, fields: ['error:code', 'message', 'stack:code', { name: 'data', type: 'content', run: function run(data, obj) { return '<div><pre>' + tryEval(data) + '</pre></div>'; } }, 'callerargs:code', 'timestamp:guid', '_id'] } }); } }; window._joes.push(this); this.Cache = { "static": {}, list: [], lookup: {}, clear: function clear() { self.Cache.lookup = {}; self.Cache.list = []; }, remove: function remove(id) {//self.cache. }, get: function get(id, specs) { var cacheitem = self.Cache.lookup[id]; if (cacheitem && typeof cacheitem.value == "function" && cacheitem.type == "callback") { return cacheitem.value(cacheitem.data, cacheitem.id); } if (!cacheitem) { //if(autoadd){ var obj = self.search(id)[0] || false; if (obj) { self.Cache.add(obj, { id: id }); return obj; } //} return false; } return cacheitem.value; }, callback: function callback(id) { var cacheitem = self.Cache.lookup[id]; if (typeof cacheitem.value == "function") { return cacheitem.value(cacheitem.data, cacheitem.id); } else { logit('cache item is not a function'); } }, add: function add(value, specs) { var specs = specs || {}; var obj = $.extend({ id: specs.id || cuid(), value: value, parent: self.joe_index }, specs); self.Cache.list.push(obj.id); self.Cache.lookup[obj.id] = obj; return obj; } }; this.Cache.set = this.Cache.add; this.history = []; /*--------------------------------------------------------------------> 0 | CONFIG <--------------------------------------------------------------------*/ var defaults = { localStorage: false, container: 'body', joeprofile: { lockedFields: ['joeUpdated'], hiddenFields: [] }, profiles: {}, fields: {}, schemas: { 'rendering': { title: 'HTML Rendering', callback: function callback() { alert('yo'); } //fields:['id','name','thingType','legs','species','weight','color','gender'], //_listID:'id', //_listTitle:'${name} ${species}' } }, compact: false, useControlEnter: true, //to save useEscapeKey: false, //to close window autoInit: false, autosave: 2000, dynamicDisplay: $(window).height() < 800 && $c.isMobile() ? 12 : 20, sans: false, listSubMenu: true, documentTitle: false, //tmplate to set document title style: { inset: true, cards: false }, speechRecognition: false }; this.specs = $.extend({}, defaults, specs || {}); if (this.specs.localStorage && typeof Storage === "undefined") { alert('no local storage'); this.specs.LocalStorage = false; } this.Indexes = { _add: function _add(idprop, dataitem) { self.Indexes[idprop] = self.Indexes[idprop] || {}; self.Indexes[idprop][dataitem[idprop]] = dataitem; }, _usage: 0 }; this.Printer = { init: function init() { if (!document.querySelector('print-joe')) { document.body.appendChild(document.createElement("print-joe")); } }, print: function print() { self.Printer.init(); var elmnt = document.getElementsByTagName("joe-panel-content")[0]; var cln = elmnt.cloneNode(true); document.querySelector('print-joe').innerHTML = ''; document.querySelector('print-joe').appendChild(cln); var panelContent = document.querySelector('print-joe joe-panel-content'); panelContent.className = 'joe-panel-content'; var activeNodes = document.querySelectorAll('print-joe joe-panel-content .joe-content-section.active'); if (activeNodes.length) { panelContent.innerHTML = ''; for (var i = 0; i < activeNodes.length; i++) { panelContent.appendChild(activeNodes[i]); } } window.print(); document.querySelector('print-joe').innerHTML = ''; } }; this.Data = {}; this.Render = {}; //TODO: make current.clear a function //TODO: check for class/id selector this.container = $(this.specs.container); this.fields = this.specs.fields; this.Fields = { reset: function reset(propname) { var field = self.Fields.get(propname); self.current.object[propname] = field.reset; self.Fields.rerender(propname); } }; //configure schemas this.schemas = this.specs.schemas; /* this.schemas._function = { idprop:'name' };*/ for (var s in _joe.schemas) { _joe.schemas[s].__schemaname = _joe.schemas[s].name = s; _joe.schemas[s]._id = cuid(); } this.current = {}; //filters:{}, this.current.clear = function () { /*|{ featured:true, description:'cleans up variables that currently exist between a single JOE showings.', tags:'cleanup, reset', category:'core' }|*/ self.current.list = null; self.current.subsets = null; self.current.subset = null; self.current.filters = {}; self.current.fields = []; self.current.schema = null; self.current.object = null; self.current.reset = {}; self.current.cache = {}; self.current.title = null; self.current.keyword = ''; if (_joes.length == 1) { document.title = self.initialDocumentTitle; } }; //profile this.defaultProfile = this.specs.defaultProfile || this.specs.joeprofile; this.current.profile = this.defaultProfile; this.ace_editors = {}; this.Render.stripeColor = function (opt, colorfunc) { var color = self.propAsFuncOrValue(colorfunc || opt.stripecolor, opt, null, _jco()); var title = ''; if (color && $c.isObject(color)) { title = ' title="' + color.title + '" '; color = color.color; } var h = '<joe-stripe-color ' + title + (color && 'style="background-color:' + color + ';"' || '') + '></joe-stripe-color>'; return h; }; this.Render.bgColor = function (opt, colorfunc) { var color = self.propAsFuncOrValue(colorfunc || opt.bgcolor, opt, null, _jco()); if (color && $c.isObject(color)) { color = color.color; } var h = '<joe-bg-color ' + (color && 'style="background-color:' + color + ';"' || '') + '></joe-bg-color>'; return h; }; this.Render.itemCheckbox = function (listItem, schema, specs) { /*|{ description:'renders a checkbox for a lsititem', specs:,expander,gotoButton,itemMenu,schemaprop,nonclickable,bgcolor,stripecolor,action tags:'render, field list item, checkbox', }|*/ var specs = specs || {}; var checkbox = self.propAsFuncOrValue(self.getCascadingProp('checkbox', schema)); var idprop = specs.idprop || self.getIDProp(); if (checkbox) { var cbox_prop = checkbox; var cbox_percentage = null; var cbox_title = ''; if ($.type(checkbox) == "object") { cbox_prop = checkbox.prop; cbox_title = checkbox.title || cbox_prop; cbox_percentage = self.propAsFuncOrValue(checkbox.percentage, listItem); } var cb_label = self.propAsFuncOrValue(checkbox.label, listItem); var checked = [true, 'true'].contains(listItem[cbox_prop]) ? 'checked' : ''; checkbox = '<joe-checkbox title="' + cbox_title + '" ' + 'class="' + checked + '"' + 'onclick="_joe.checkItem(\'' + listItem[idprop] + '\',\'' + cbox_prop + '\',null,this)">' + (cbox_percentage !== false && checkbox.hasOwnProperty('percentage') ? '<joe-checkbox-percentage>' + Math.round(cbox_percentage * 100) + '%</joe-checkbox-percentage>' : '') + (cb_label && '<joe-checkbox-label>' + cb_label + '</joe-checkbox-label>' || '') + '</joe-checkbox>'; } else { checkbox = ''; } return checkbox; }; /*--------------------------------------------------------------------> 1 | INIT <--------------------------------------------------------------------*/ this.init = function (callback) { /*|{ featured:true, description:'primary entry point into JOE, sets up the UI necessary', tags:'init, framework', category:'core' }|*/ if (initialized) { return false; } beginLogGroup('JOE init'); self.current.clear(); var html = self.renderFramework(self.renderEditorHeader() + self.renderEditorContent() + self.renderEditorFooter()); self.container.append(html); self.overlay = $('.joe-overlay[data-joeindex=' + self.joe_index + ']'); self.panel = self.overlay.find('.joe-overlay-panel'); self.initKeyHandlers(); self.Speech.init(); //self.Autosave.init(); self.readHashLink(); window.addEventListener("hashchange", function (newH, oldH) { var useHash = $GET('!') || location.hash; if (!useHash || self.joe_index != 0 || !specs.useHashlink) { return false; } if (!window._joeEditingHash) { self.readHashLink(); } }, false); var respond_timeout; $(window).on('resize', function () { if (self.resizeOk()) { clearTimeout(respond_timeout); respond_timeout = setTimeout(self.respond, 200); } }); initialized = true; self.respond(); endLogGroup(); self.Components.init(); callback && callback(); }; this.resizeOk = function () { if (!$c.isMobile()) { return true; } if (document.activeElement.tagName == "INPUT") { return false; } return true; }; /*--------------------------------------------------------------------> INIT KEY HANDLERS <--------------------------------------------------------------------*/ this.initKeyHandlers = function () { if (self.specs.useBackButton) { window.onkeydown = function (e) { var code = e.keyCode; var nonBackElements = ['input', 'select', 'textarea']; var isInputElement = nonBackElements.indexOf(e.target.tagName.toLowerCase()) != -1; if (code == 8) { //BACKBUTTON PRESSED if (isInputElement) {//return false; } else { self.goBack(); return false; } } else if ([37, 39, 38, 40, 13, 16, 17, 27].indexOf(code) == -1) { //set focus for alphanumeric keys if (e.altKey) { //alt control switch (code) { case 70: //QUICKFIND self.quickFind(); if (e.stopPropagation) e.stopPropagation(); if (e.preventDefault) e.preventDefault(); break; case 78: //QUICKADD self.quickAdd(); if (e.stopPropagation) e.stopPropagation(); if (e.preventDefault) e.preventDefault(); break; case 80: //PRINT self.Printer.print(); if (e.stopPropagation) e.stopPropagation(); if (e.preventDefault) e.preventDefault(); break; } } else { if (listMode) { var inSearchfield = false; if ($(document.activeElement) && $(document.activeElement)[0] != $('.joe-submenu-search-field')[0]) { self.overlay.find('.joe-submenu-search-field').focus(); inSearchfield = true; $('.joe-panel-content-option.keyboard-selected').removeClass('keyboard-selected'); } } else { //NOT LIST MODE, DETAILS MODE //is control key down if (e.ctrlKey || e.metaKey) { switch (code) { case 83: //look for control save if (self.container.find('.joe-button.joe-quicksave-button').length) { self.updateObject(null, null, true); if (e.stopPropagation) e.stopPropagation(); if (e.preventDefault) e.preventDefault(); } break; } } } } } else { var keyboardSelectOption = function keyboardSelectOption(selector, top) { $(selector + '.keyboard-selected').toggleClass('keyboard-selected'); var el = $(selector).eq(keyboardSelectedIndex); el.addClass('keyboard-selected'); self.overlay.find('.joe-submenu-search-field').blur(); // $('.joe-panel-content').scrollTop($('.joe-panel-content-option.keyboard-selected').offset().top); el[0].scrollIntoView(top); //var panel_content = self.overlay.find('.joe-panel-content'); //panel_content.animate({ scrollTop: panel_content.scrollTop()-10 }); //panel_content.scrollTop(panel_content.scrollTop()-10); }; //38 up, 40 dn,13 enter,37 left, 39 right var autocompleteField = $('.joe-text-autocomplete.active').length; if (autocompleteField) { var sel = '.joe-text-autocomplete-option.visible' + '.keyboard-selected'; //$('.joe-text-autocomplete-option.visible').length(); var keyboardSelected = $(sel)[0]; var keyboardSelectedIndex = $(sel).length ? $(sel).index() : -1; switch (code) { case 38: //up keyboardSelectedIndex--; if (keyboardSelectedIndex > -1) { keyboardSelectOption('.joe-text-autocomplete-option.visible'); } break; case 40: //down keyboardSelectedIndex++; if (keyboardSelectedIndex < $('.joe-text-autocomplete-option.visible').length) { keyboardSelectOption('.joe-text-autocomplete-option.visible'); } break; case 13: //enter if (keyboardSelectedIndex != -1) { keyboardSelected.click(); } break; } } if (listMode) { if (e.altKey) { //alt control //get current index and add 1 if (self.current.subsets) { var subindex = self.current.subsets.indexOf(self.current.subset) + 1; //$('joe-subset-option.active').index()+1; switch (code) { case 38: //up $('joe-subset-option').eq(subindex - 1).click(); break; case 40: //down $('joe-subset-option').eq(subindex + 1).click(); break; } } } else { var keyboardSelectedIndex = $('.joe-panel-content-option.keyboard-selected').length ? $('.joe-panel-content-option.keyboard-selected').index() : -1; //logit(keyboardSelectedIndex); switch (code) { case 38: //up keyboardSelectedIndex--; if (keyboardSelectedIndex > -1) { keyboardSelectOption('.joe-panel-content-option', top); } break; case 40: //down keyboardSelectedIndex++; if (keyboardSelectedIndex < currentListItems.length) { keyboardSelectOption('.joe-panel-content-option', top); } break; case 13: //enter if (keyboardSelectedIndex != -1) { $('.joe-panel-content-option.keyboard-selected').find('.joe-panel-content-option-content').click(); } break; } } } else { //DETAILS MODE if (e.altKey) { switch (code) { case 219: //left case 221: //right var sside = code == 219 ? 'left' : 'right'; if (self.current.sidebars[sside].content && !self.current.sidebars[sside].hidden) { self.toggleSidebar(sside); } break; } } else if (e.ctrlKey) { switch (code) { case 37: //left self.previous(); break; case 39: //right self.next(); break; } } else if (code == 13) { //add another row on enter click var ae = $(document.activeElement); if (ae && ae.is('input')) { var fieldobj = ae.parents('.joe-object-field'); if (fieldobj.length) { try { fieldobj.find('.joe-plus-button').click(); } catch (e) { self.Error.add('adding new row to objectlist', e); } } } } } } }; } }; /*--------------------------------------------------------------------> 2 | FRAMEWORK START <--------------------------------------------------------------------*/ this.getMode = function () { if (listMode) { if (self.current.list) { return 'list'; } } if (self.current.object) { return 'details'; } if (self.current.list) { return 'list'; } else { return false; } /* if(listMode){return 'list';} return 'details';*/ }; this.renderFramework = function (content) { var style = 'style-variant1'; var html = '<joe-overlay class="joe-overlay sans cols-' + colCount + ' ' + style + ' ' + (self.specs.compact && ' compact ' || '') + (self.specs.sans && ' sans ' || '') + '" data-joeindex="' + this.joe_index + '">' + '<joe-panel class="joe-overlay-panel">' + (content || '') + '</joe-panel>' + //mini '<div class="joe-mini-panel">' + '</div>' + '</joe-overlay>'; return html; }; this.populateFramework = function (data, setts) { /*|{ featured:true, description:'primary function for populating and rendering JOE, called by goJoe and joe.show', tags:'populate, framework, core' }|*/ self.current.cache = {}; self.overlay.removeClass('multi-edit'); var joePopulateBenchmarker = new Benchmarker(); self.current.reset = self.current.reset || {}; beginLogGroup('JOE population'); //logit('------Beginning joe population'); var specs = setts || {}; self.current.specs = setts; self.current.data = data; //clean copy for later; self.current.userSpecs = $.extend({}, setts); gridMode = self.current.specs.viewMode == 'grid' ? true : false; tableMode = self.current.specs.viewMode == 'table' ? true : false; //update history 1/2 if (!self.current.specs.noHistory) { self.history.push({ /* _joeHistoryTitle:self.overlay.find('.joe-panel-title').html(), */ specs: self.current.userSpecs, data: self.current.data }); } var schema = setts.schema || ''; var profile = setts.profile || null; var callback = setts.callback || null; var datatype = setts.datatype || ''; var title = setts.title || ''; //callback if (callback) { self.current.callback = callback; } else { self.current.callback = null; } /*------------------------- String data -------------------------*/ if ($.type(data) == 'string' && datatype != "string" && self.getDataset(data, { "boolean": true })) { if (!specs.schema && self.schemas[data]) { schema = data; } data = self.getDataset(data); } /*setup schema*/ specs.schema = this.setSchema(schema); /*------------------------- Column Count -------------------------*/ colCount = self.current.specs.colCount || specs.schema && specs.schema.colCount /*|| colCount*/ || 1; if (self.sizeClass == "small-size") { colCount = 1; } /*------------------------- Preformat Functions -------------------------*/ specs.preformat = specs.schema && specs.schema.preformat || specs.preformat || function (d) { return d; }; data = specs.preformat(data); /*------------------------- Object -------------------------*/ //when object passed in if ($.type(data) == 'object' || datatype == 'object') { specs.object = data; specs.menu = specs.menu || specs.schema && specs.schema.menu || self.specs.menu || specs.multiedit && __defaultMultiButtons || __defaultObjectButtons; specs.mode = "object"; self.current.object = data; } /*------------------------- MultiEdit (Arrays) -------------------------*/ self.toggleMultiEditMode(specs, data); /*------------------------- Lists (Arrays) -------------------------*/ //when array passed in listMode = false; if ($.type(data) == 'array' || datatype == 'array') { listMode = true; specs.list = data; specs.menu = specs.listMenu || specs.schema && specs.schema.listMenu || __defaultButtons; //__defaultMultiButtons; specs.mode = "list"; //TODO: filter list items here. self.current.list = data; /*------------------------- Subsets -------------------------*/ var currentSubsets; //setup subsets currentSubsets = setts.subsets || specs.schema && specs.schema.subsets || null; if (typeof currentSubsets == 'function') { currentSubsets = currentSubsets(); } //a current subset selected if (self.current.specs.subset && currentSubsets && /*currentSubsets.where({name:specs.subset})*/ currentSubsets.where({ $or: [{ name: specs.subset }, { group_start: specs.subset }] }).length) { self.current.subset = currentSubsets.where({ $or: [{ name: specs.subset }, { group_start: specs.subset }] })[0] || false; } else { //all selected if (self.current.specs.subset == "All") { self.current.subset = { name: "All", filter: {} }; } else { //select default subset if it exists self.current.subset = currentSubsets && currentSubsets.where({ 'default': true })[0] || null; } } self.current.subsets = currentSubsets; /*------------------------- Sorting -------------------------*/ //setup sorting self.current.sorter = setts.sorter || self.current.subset && self.current.subset.sorter || specs.schema && specs.schema.sorter || 'name'; if ($.type(self.current.sorter) == 'string') { self.current.sorter = [self.current.sorter]; } //self.current.object = null; } /*------------------------- Submenu -------------------------*/ if (specs.mode == 'list') { self.current.submenu = self.current.specs.listsubmenu || self.current.specs.submenu || specs.schema && specs.schema.listSubMenu || self.specs.listSubMenu; } else { self.current.submenu = self.current.specs.submenu || specs.schema && specs.schema.subMenu || self.specs.subMenu; } if (self.current.submenu == 'none') { self.current.submenu = null; } /*------------------------- Rendering -------------------------*/ //when rendering passed in if ($.type(data) == 'string' && datatype == 'rendering') { specs.rendering = data; specs.menu = [__replaceBtn__]; specs.mode = "rendering"; self.current.rendering = specs.rendering; //specs.schema } /*------------------------- String -------------------------*/ //when string passed in else if ($.type(data) == 'string' || datatype == 'string') { specs.text = data; specs.menu = __defaultButtons; //specs.menu = [{name:'save',label:'Save Object',action:'_joe.updateObject()'}]; specs.mode = "text"; self.current.text = specs.text; } //setup window title //specs.title = title || (specs.schema)? specs.schema._title : "Viewing "+specs.mode.capitalize(); specs.listWindowTitle = specs.list && (specs._listMenuTitle || //specs.listWindowTitle || specs._listWindowTitle || self.getCascadingProp('listWindowTitle') || getProperty('specs.list.windowTitle') || specs.schema && (specs.schema._listMenuTitle || specs.schema._listWindowTitle)) || false; specs.title = specs.listWindowTitle || title || specs.schema && (specs.schema.title || specs.schema._title) || "Viewing " + (self.current.schema && self.current.schema.__schemaname || typeof self.current.userSpecs.schema == 'string' && self.current.userSpecs.schema || specs.mode).capitalize(); //setup profile specs.profile = profile ? self.specs.profiles[profile] || self.specs.joeprofile : self.specs.joeprofile; self.current.profile = specs.profile; //cleanup variables self.cleanUp(); /*--------------------------------------------------------------------> Set global view mode specs <--------------------------------------------------------------------*/ if (self.current.schema && (self.current.schema.table || self.current.schema.tableView)) { tableSpecs = $.extend({ cols: ['name', self.getIDProp()] }, self.current.schema && (self.current.schema.table || self.current.schema.tableView) // &&(self.current.schema.table||self.current.schema.tableView).cols || {}); } else { tableSpecs = null; } /*--------------------------------------------------------------------> Framework Rendering <--------------------------------------------------------------------*/ var contentBM = new Benchmarker(); beginLogGroup('Content'); var content = self.renderEditorContent(specs); endLogGroup(); _bmResponse(contentBM, 'JOE [Content]'); var chromeBM = new Benchmarker(); var html = self.renderEditorHeader(specs) + self.renderEditorSubmenu(specs) + content + self.renderEditorFooter(specs) + self.renderMessageContainer(); _bmResponse(chromeBM, 'JOE [overlay-chrome]'); self.overlay.find('.joe-overlay-panel').html(html); //$('.joe-overlay-panel').html(html); //update history 2/2 - add title if (!self.current.specs.noHistory && self.history.length) { $.extend(self.history[self.history.length - 1], { _joeHistoryTitle: self.overlay.find('.joe-panel-title').html() }); } //clear ace_editors /* for (var p in _joe.ace_editors){ _joe.ace_editors[p].destroy(); } _joe.ace_editors = {};*/ //update hashlink self.updateHashLink(); //logit('Joe Populated in '+joePopulateBenchmarker.stop()+' seconds'); _bmResponse(joePopulateBenchmarker, '----Joe Populated'); endLogGroup(); return html; }; /*--------------------------------------------------------------------> 2e | FRAMEWORK END <--------------------------------------------------------------------*/ this.toggleMultiEditMode = function (specs, data) { multiEdit = self.current.userSpecs && self.current.userSpecs.multiedit || false; }; /*-----------------------------> A | Header <-----------------------------*/ function createTitleObject(specs) { var specs = specs || {}; var titleObj = $.extend({}, self.current.object); var list = specs.list || self.current.list; if (list) { var lcount = list.length; if (self.current.subset) { lcount = list.where(self.current.subset.filter).length; } titleObj._listCount = lcount || '0'; titleObj._subsetName = self.current.subset && self.current.subset.name + ' ' || ''; } self.current.title = specs.title || self.getCascadingProp('title') || self.current.schema && "new " + self.current.schema.__schemaname || 'Json Object Editor'; self.current.subtitle = specs.subtitle || self.getCascadingProp('subtitle'); var title = fillTemplate(self.propAsFuncOrValue(self.current.title), titleObj); var subtitle = fillTemplate(self.propAsFuncOrValue(self.current.subtitle), titleObj); titleObj.docTitle = title; titleObj.subTitle = subtitle; return titleObj; } this.Header = {}; this.toggleHelpMenu = function (show, target) {}; this.Header.Render = this.renderEditorHeader = function (specs) { var BM = new Benchmarker(); var specs = specs || {}; var titleObj = createTitleObject(specs); var title = titleObj.docTitle || self.current.schema && "new " + self.current.schema.__schemaname; var subtitle = titleObj.subTitle; //show doctitle if (self.specs.documentTitle) { var doctitle = self.specs.documentTitle === true ? self.current.title : self.propAsFuncOrValue(self.specs.documentTitle, self.current.title); document.title = fillTemplate(self.propAsFuncOrValue(doctitle), titleObj); } var close_action = specs.close_action || 'onclick="getJoe(' + self.joe_index + ').closeButtonAction()"'; var reload_action = specs.reload_action || 'onclick="getJoe(' + self.joe_index + ').reload()"'; function renderHeaderBackButton() { var html = ''; if (self.history.length > 1 /*&& specs.useHeaderBackBtn*/ ) { html += '<div class="jif-header-back-btn jif-panel-header-button standard-button" onclick="window.history.back()" title="back">' + self.SVG.icon.left //+'<span class="jif-arrow-left"></span>' + '</div>'; } return html; } function renderHelpButton() { var html = ''; if (specs.minimode) { return ''; } html += '<div class="jif-panel-header-button joe-panel-help" onclick="_joe.toggleHelpMenu()" title="help">' + self.SVG.icon.help + '</div>'; return html; } var help_button = renderHelpButton(); function renderUnsavedIcon() { var html = ''; if (specs.minimode) { return ''; } html += '<div class="jif-panel-header-button joe-panel-unsaved" onclick="_joe.updateObject(this,null,true);" title="unsaved changes">' + self.SVG.icon.unsaved + '</div>'; return html; } var unsaved_icon = renderUnsavedIcon(); var speech_action = specs.speech_action || 'onclick="getJoe(' + self.joe_index + ').Speech()"'; var reload_button = specs.minimode ? '' : '<div class="jif-panel-header-button joe-panel-reload" title="reload" ' + reload_action + '><span class="jif-reload"></span></div>'; var mic_button = !self.specs.speechRecognition || specs.minimode ? '' : '<div class="jif-panel-header-button joe-panel-speech" title="speech" id="speech-button-' + self.joe_index + '">M</div>'; var close_button = '<div class="jif-panel-header-button joe-panel-close" title="close" ' + close_action + '>' + self.SVG.icon.close //+'<span class="jif-close"></span>'+ + '</div>'; // var schema_button = (!specs.minimode && (self.current.schema && self.current.schema.menuicon && // '<joe-schema-icon class="clickable" title="'+self.current.schema.__schemaname+'" onclick="goJoe(_joe.getDataset(\''+self.current.schema.__schemaname+'\'),{schema:\''+self.current.schema.__schemaname+'\'})">'+self.current.schema.menuicon+'</joe-schema-icon>')||''); var schema_button = !specs.minimode && self.current.schema && self.current.schema.menuicon && '<joe-schema-icon class="clickable" title="' + self.current.schema.__schemaname + '" onclick="goJoe(\'' + self.current.schema.__schemaname + '\')">' + self.current.schema.menuicon + '</joe-schema-icon>' || ''; var back_button = !specs.minimode && renderHeaderBackButton() || ''; var left_buttons = [back_button, schema_button]; var right_buttons = [close_button, mic_button, reload_button, //help_button, TODO: add help button. unsaved_icon]; var html = //'<div class="joe-panel-header">'+ '<joe-panel-header >' + (specs.schema && specs.schema.subsets && self.renderSubsetselector(specs.schema) || specs.subsets && self.renderSubsetselector(specs) || '') + //'<joe-panel-header-buttons class="left-side">'+ left_buttons.join(' ') + //'</joe-panel-header>'+ '<div class="joe-vcenter joe-panel-title-holder"><span class="joe-panel-title">' + (('<div>' + title + '</div>').toDomElement().innerText || title || 'Json Object Editor') + '</span></div>' + //'<div class="joe-panel-reload joe-panel-header-button" title="reload" '+reload_action+'></div>'+ '<joe-panel-header-buttons class="right-side">' + right_buttons.join(' ') + '<div class="clear"></div>' + '</joe-panel-header-buttons>' + '<div class="clear"></div>' + '</joe-panel-header>'; _bmResponse(BM, '[Header] rendered'); return html; }; //What happens when the user clicks the close button. this.closeButtonAction = function (prechecked) { if (!this.checkChanges()) { return; } self.history = []; self.panel.addClass('centerscreen-collapse'); self.hide(500); self.current.clear(); $(self.container).trigger({ type: "hideJoe", index: self.joe_index /*, schema: self.current.specs.schema, subset: self.current.specs.subset*/ }); self.updateHashLink(); var closeAction = self.getCascadingProp('onPanelHide'); if (closeAction) { closeAction(self.getState()); } self.Autosave.deactivate(); }; var goingBackFromID; var goingBackQuery; this.goBack = function (obj) { if (!this.checkChanges()) { return; } //go back to last item and highlight if (self.current.object) { var gobackItem = self.current.object[self.getIDProp()]; if (gobackItem) { goingBackFromID = gobackItem; // logit(goingBackFromID); } } //clearTimeout(self.searchTimeout ); self.history.pop(); var joespecs = self.history.pop(); if (!joespecs) { self.closeButtonAction(true); return; } else { if (obj && $c.isArray(joespecs.data)) { var objid = obj[self.getIDProp()]; if (objid) { var query = {}; query[self.getIDProp()] = objid; var found = joespecs.data.where(query); found.length && $.extend(found[0], obj); } } if (joespecs.keyword) { goingBackQuery = joespecs.keyword; } } var specs = $.extend({}, joespecs.specs); specs.filters = joespecs.filters; self.show(joespecs.data, specs); }; /* this.clearAuxiliaryData = function(){ /!*|{ featured:true, description:'cleans up variables that currently exist between a single JOE showings.', tags:'cleanup, reset', category:'core' }|*!/ self.current.list = null; self.current.subsets = null; self.current.subset = null; self.current.filters = {}; self.current.fields = []; self.current.schema = null; self.current.object = null; self.current.reset = {}; };*/ //this.current.clear = this.clearAuxiliaryData; this.cleanUp = function () { /*|{ featured:true, description:'cleans up variables that currently exist between a single JOE showings.', tags:'cleanup, reset', category:'core' }|*/ /* if(!self._reloading){ self.current.reset = {}; }*/ self.current.fields = []; self.shiftSelecting = false; self.allSelected = false; /* for (var p in _joe.ace_editors){ _joe.ace_editors[p].destroy(); } _joe.ace_editors = {};*/ if (self.current.userSpecs && self.current.userSpecs.multiedit) { self.overlay.addClass('multi-edit'); } else { self.overlay.removeClass('multi-edit'); } }; /*-----------------------------> B | SubMenu <-----------------------------*/ function renderSubmenuButtons(buttons) { var html = ''; //<div class="joe-submenu-buttons">'; var buttons = self.propAsFuncOrValue(buttons || listMode && self.getCascadingProp('headerListMenu') || !listMode && self.getCascadingProp('headerMenu')); var content; if (buttons) { var h = self.renderMenuButtons(buttons, 'joe-submenu-button'); if (h) { content = true; } html += h; } return { html: html, content: content }; // return {html:html +'</div>',content:content}; } ; //self.current.submenuButtons; this.renderEditorSubmenu = function (specs) { beginLogGroup('Submenu'); var BM = new Benchmarker(); var sectionAnchors = renderSectionAnchors(); //submenu buttons var submenuButtons = renderSubmenuButtons(); if (!self.current.submenu && !sectionAnchors.count && !listMode && !self.getCascadingProp('headerMenu')) { return ''; } var showFilters = $c.getProperty(self.current, 'userSpecs.filters') || $c.getProperty(self.current, 'schema.filters') || $c.getProperty(self.current, 'schema.subsets') || false; var subSpecs = { search: true, itemcount: true, filters: showFilters, numCols: self.current.schema.columns || 0 }; var userSubmenu = $.type(self.current.submenu) != 'object' ? {} : self.current.submenu; $.extend(subSpecs, userSubmenu); if (specs.mode == 'list') { var filters_obj = self.Filter.getCached(); var submenu = '<div class="joe-panel-submenu">' //right side +self.Submenu.Aggregator.renderToggleButton() + self.renderViewModeButtons(subSpecs) + self.renderColumnCountSelector(subSpecs.numCols) + self.renderSorter() //left side + (subSpecs.filters && self.renderSubmenuFilters(subSpecs.filter) || '') + (subSpecs.search && self.renderSubmenuSearch(subSpecs.search) || '') + (subSpecs.itemcount && self.renderSubmenuItemcount(subSpecs.itemcount) || '') + submenuButtons.html + '</div>' + "<div class='joe-filters-holder'>" + renderSubsetsDiv() + (filters_obj && renderFiltersDiv() || '') // +'<span class="jif-arrow-left"></span>' + "</div>"; } else { var submenu = '<div class="joe-panel-submenu">' + renderSidebarToggle('left') + renderSidebarToggle('right') + submenuButtons.html + (sectionAnchors.count && sectionAnchors.code || '') + '</div>'; /* + "<div class='joe-filters-holder'>" // + renderSubsetsDiv() //+ (self.current.schema && (self.propAsFuncOrValue(self.current.schema.filters) && renderFiltersDiv()) || '') // +'<span class="jif-arrow-left"></span>' + "</div>";*/ } function renderOptStripeColor(opt) { var color = self.propAsFuncOrValue(opt.stripecolor || opt.stripeColor, null, null, opt); var title = ''; if (color && $c.isObject(color.title)) { title = ' title="' + color.title + '" '; color = color.color; } var h = '<joe-stripe-color ' + title + (color && 'style="background-color:' + color + ';"' || '') + '></joe-stripe-color>'; return h; } function renderOptBGColor(opt) { var color = self.propAsFuncOrValue(opt.bgcolor || opt.bgColor, null, null, opt); if (color && $c.isObject(color.title)) { color = color.color; } var h = '<joe-bg-color ' + (color && 'style="background-color:' + color + ';"' || '') + '></joe-bg-color>'; return h; } function renderOptBorderColor(opt) { var color = self.propAsFuncOrValue(opt.bordercolor || opt.borderColor, null, null, opt); if (color && $c.isObject(color.title)) { color = color.color; } var h = '<joe-border-color ' + (color && 'style="border:1px solid ' + color + ';"' || '') + '></joe-border-color>'; return h; } function renderOptionGroupStart(opt, childDom) { var collapsed = self.propAsFuncOrValue(opt.collapsed) ? 'collapsed' : ''; if (!opt.hasOwnProperty('filter')) { var html = '<joe-option-group id="' + opt.group_start + '-group" class="' + collapsed + '"><joe-menu-label onclick="$(this).parent().toggleClass(\'collapsed\');">' + (opt.display || opt.name || opt.group_start) + '</joe-menu-label>'; return html; } else { var optdisplay = opt.display || opt.name || opt.group_start || ''; var optname = opt.id || opt.name || opt.group_start || ''; var cbox = '', act, onclick; var dataname; if (childDom == 'joe-filter-option') { dataname = ' data-filter="' + optname + '" '; cbox = '<span class ="joe-option-checkbox"></span>'; act = self.current.filters && self.current.filters[optname] ? 'active' : ''; onclick = 'getJoe(' + self.joe_index + ').toggleFilter(\'' + optname + '\',this);_joe.Utils.stopPropagation();'; } else { dataname = ' data-subset="' + optname + '" '; act = self.current.subset && self.current.subset.name == optname || !self.current.subset && opt.name == "All" ? 'active' : ''; onclick = 'getJoe(' + self.joe_index + ').selectSubset(\'' + optname.toString().replace(/\'/g, "\\'") + '\');'; } var optiondiv = '<' + childDom + ' ' + dataname + ' class="' + childDom + ' joe-group-option ' + act + ' " onclick=' + onclick + '>' + renderOptBorderColor(opt) + renderOptBGColor(opt) + renderOptStripeColor(opt) + cbox + '<span style="position:relative;">' + optdisplay + '</span>' + '</' + childDom + '>'; var html = '<joe-option-group id="' + opt.group_start + '-group" class="' + collapsed + ' ">' + '<joe-menu-label onclick="$(this).parent().toggleClass(\'collapsed\');">' + optiondiv + '</joe-menu-label>'; return html; } } //TODO:move to subsets filter rendering function function renderSubsetsDiv() { var sh = '<div><joe-menu-label>Subsets</joe-menu-label>'; var act; var starting = []; if (!self.current.schema || !self.current.schema.hideAllSubset) { starting.push({ name: 'All', filter: {} }); } var group = null; starting.concat(_joe.current.subsets || []).map(function (opt) { if (opt.group_start) { group = opt.group_start; sh += renderOptionGroupStart(opt, 'joe-subset-option'); } else if (opt.group_end) { sh += '</joe-option-group>'; group = null; } else { var idval = opt.id || opt.name || ''; //if(!opt.condition || (typeof opt.condition == 'function' && opt.condition(self.current.object)) || (typeof opt.condition != 'function' && opt.condition)) { if (!opt.condition || self.propAsFuncOrValue(opt.condition)) { act = self.current.subset && self.current.subset.name == opt.name || !self.current.subset && opt.name == "All" ? 'active' : ''; if (act == 'active' && group) { sh = sh.replace('<joe-option-group id="' + group + '-group" class="collapsed', '<joe-option-group id="' + group + '-group" class="'); } // sh += '<joe-subset-option data-subset="'+idval+'" class="joe-subset-option ' + act + ' " onclick="getJoe(' + self.joe_index + ').selectSubset(\'' // + (opt.id || opt.name || '').toString().replace(/\'/g,"\\'") + '\');">' // +r