json-object-editor
Version:
JOE the Json Object Editor | Platform Edition
1,278 lines (1,151 loc) • 558 kB
JavaScript
/* --------------------------------------------------------
*
* JOE - v1.5.0
* Created by: Corey Hadden
*
* -------------------------------------------------------- */
/*/---------------------------------------------------------
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';
}else{
document.getElementsByTagName('html')[0].className +=' no-touch';
}
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);
}
__docWriter =function(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;
};
__loadAdditionalFiles = function(){
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;
self.initialDocumentTitle = document.title;
$c.TEMPLATE_VARS.push(
{variable:'/textarea',value:'</textarea>'},
{variable:'textarea',value:'<textarea>'},
{variable:'SERVER',value:'//'+$c.SERVER}
);
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(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(){
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(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(){
self.Cache.lookup = {};
self.Cache.list = [];
},
remove:function(id){
//self.cache.
},
get:function(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(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(value,specs){
var obj = $.extend({
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(){alert('yo');}
//fields:['id','name','thingType','legs','species','weight','color','gender'],
//_listID:'id',
//_listTitle:'${name} ${species}'
}},
compact:false,
useControlEnter:true,
useEscapeKey:false,
autoInit:false,
dynamicDisplay:($(window).height() < 800 && $c.isMobile())?12:20,
sans:false,
listSubMenu:true,
documentTitle:false,//tmplate to set document title
useInset:true,
speechRecognition:false
};
this.specs = $.extend({},defaults,specs||{});
if(this.specs.localStorage && typeof(Storage) === "undefined"){
alert('no local storage');
this.specs.LocalStorage = false;
}
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(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;
};
/*-------------------------------------------------------------------->
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.readHashLink();
/* $(window).on('hashChange',function(h,i,c){
logit(h,i,c);
});*/
window.addEventListener("hashchange", function(newH,oldH){
var useHash = $GET('!') || location.hash;
if (!useHash || self.joe_index != 0 || !specs.useHashlink) {
return false;
}
//logit(newH);
if(!window._joeEditingHash){
self.readHashLink();
//logit(useHash);
}
}, false);
var respond_timeout;
//self.respond();
$(window).on('resize',function(){
clearTimeout(respond_timeout);
respond_timeout = setTimeout(self.respond,200);
//self.respond
});
initialized = true;
self.respond();
endLogGroup();
callback && callback();
};
/*-------------------------------------------------------------------->
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].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;
}
}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{
//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 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){
$(sel).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);
}
}
}
}
}
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);
}
}
}
}
};
/*-------------------------------------------------------------------->
2 | FRAMEWORK START
<--------------------------------------------------------------------*/
this.getMode = function(){
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;
/*-------------------------
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;
/* var titleObj = /!*createTitleObject(specs);*!/$.extend({},self.current.object)
if(specs.list){
var lcount = specs.list.length;
if(self.current.subset){
lcount = specs.list.where(self.current.subset.filter).length;
}
titleObj._listCount =(lcount||'0');
}
self.current.title = specs.title || 'Json Object Editor';
var title = fillTemplate(self.propAsFuncOrValue(self.current.title),titleObj);
titleObj.docTitle = title;*/
//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="joe-header-back-btn joe-panel-header-button" onclick="getJoe('+self.joe_index+').goBack();" title="go back"> </div>';
//html+= '<div class="jif-header-back-btn jif-panel-header-button" onclick="getJoe('+self.joe_index+').goBack();" title="back"><span class="jif-arrow-left"></span></div>';
html+= '<div class="jif-header-back-btn jif-panel-header-button" onclick="window.history.back()" title="back"><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()
//.replace(/(<([^>]+)>)/ig,"");
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+'>' +
'<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 back_button = (!specs.minimode && renderHeaderBackButton() || '')
var left_buttons = [
back_button,
schema_button
];
var right_buttons = [
close_button,
mic_button,
reload_button,
help_button
];
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())}
};
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();
//self.current.schema && (self.propAsFuncOrValue(self.current.schema.filters,self.current.list)) || false;
var submenu =
'<div class="joe-panel-submenu">'
//right side
+ 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()
+ (
//( (self.current.filters && !$c.isEmpty(self.current.filters)) && renderFiltersDiv())||
(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 || '';