Skip to content

Instantly share code, notes, and snippets.

@AubreyHewes
Created November 4, 2014 23:15
Show Gist options
  • Save AubreyHewes/780b09c3bb6553b4d02a to your computer and use it in GitHub Desktop.
Save AubreyHewes/780b09c3bb6553b4d02a to your computer and use it in GitHub Desktop.
JSONEditor Theme: Bootstrap3 (form-horizonta)
/*jshint strict: false, -W116: false, -W098: false */
/**
* Copy of the Bootstrap 3 Theme; tweaked for horizontal form (form-horizontal)
*
* @todo remove ridiculous amount of nesting; is a lib issue; create issue?
*/
JSONEditor.defaults.themes.bootstrap3horizontal = JSONEditor.AbstractTheme.extend({
labelWidth: 3,
inputWidth: 9,
/**
* Add a constructor to create/override other JSONEditor classes
*/
init: function () {
/**
* Bootstrap 3 horizontal compatible multiple (tested on "oneOf") editor; remove proprietary fixed dom/styling (field within a form-group; styled as other fields)
*
* Unfortunately we have to overload core and copy a load of the overloaded core to get this to be compatible..
*
* @todo create lib issue
*/
JSONEditor.defaults.editors.multiple = JSONEditor.defaults.editors.multiple.extend({
build: function () {
var self = this;
var container = this.container;
this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
this.switcher = this.theme.getSelectInput(this.display_text);
container.appendChild(this.theme.getFormControl(this.label, this.switcher, this.display_text.join(', ')));
this.switcher.addEventListener('change',function(e) {
e.preventDefault();
e.stopPropagation();
self.switchEditor(self.display_text.indexOf(this.value));
self.onChange(true);
});
this.editor_holder = document.createElement('div');
container.appendChild(this.editor_holder);
this.switcher_options = this.theme.getSwitcherOptions(this.switcher);
$.each(this.types,function(i,type) {
self.editors[i] = false;
var schema;
if(typeof type === "string") {
schema = $.extend({},self.schema);
schema.type = type;
}
else {
schema = $.extend({},self.schema,type);
// If we need to merge `required` arrays
if(type.required && Array.isArray(type.required) && self.schema.required && Array.isArray(self.schema.required)) {
schema.required = self.schema.required.concat(type.required);
}
}
self.validators[i] = new JSONEditor.Validator(self.jsoneditor,schema);
});
this.switchEditor(0);
}
});
// add label "for" attribute and input "id" .. making labels clickable @note is known lib issue
$.each(JSONEditor.defaults.editors, function (name, editor) {
if (name === 'options') return; // "options" is not an editor but the global editor options
JSONEditor.defaults.editors[name] = editor.extend({
register: function () {
this._super();
// superfluous prefix (but removes any possible id conflicts)
var elId = 'jsoneditor-' + this.formname.replace(/([^\[]+)\[(.+)\]/, '$1-$2').replace(/\]\[/gim, '-');
if (this.input) this.input.setAttribute('id', elId);
if (this.switcher) this.switcher.setAttribute('id', elId);
if (this.label) this.label.setAttribute('for', elId);
}
});
});
},
getSwitcher: function(options) {
var switcher = this.getSelectInput(options);
return switcher;
},
getChildEditorHolder: function() { // removes hardcoded styling
var el = document.createElement('div');
return el;
},
getGridRow: function() { // removes hardcoded styling; still a superfluous nest
var el = document.createElement('div');
return el;
},
getSelectInput: function(options) {
var el = this._super(options);
el.className += 'form-control';
return el;
},
setGridColumnSize: function(el,size) { // not using grid; so there
//el.className = 'col-md-'+size;
},
afterInputReady: function(input) {
if(input.controlgroup) return;
input.controlgroup = this.closest(input,'.form-group');
if(this.closest(input,'.compact')) {
input.controlgroup.style.marginBottom = 0;
}
// TODO: use bootstrap slider
},
getTextareaInput: function() {
var el = document.createElement('textarea');
el.className = 'form-control';
return el;
},
getRangeInput: function(min, max, step) {
// TODO: use better slider
return this._super(min, max, step);
},
getFormInputField: function(type) {
var el = this._super(type);
if(type !== 'checkbox') {
el.className += 'form-control';
}
return el;
},
getFormControl: function(label, input, description) {
var group = document.createElement('div');
if(label && input.type === 'checkbox') { // not yet used - just removed hardcoded styles
group.className += ' checkbox';
label.appendChild(input);
//label.style.fontSize = '14px';
//group.style.marginTop = '0';
group.appendChild(label);
//input.style.position = 'relative';
//input.style.cssFloat = 'left';
if(description) group.appendChild(description);
}
else {
group.className += ' form-group';
if(label) {
label.className += ' col-xs-' + this.labelWidth + ' control-label';
label.for = "";
group.appendChild(label);
}
var container = document.createElement('div');
container.className += ' col-xs-' + this.inputWidth;
input.placeholder = description;
// set title for bootstrap tooltips
if (label && label.innerText) {
input.title = label.innerText += ': ' + description + '';
} else {
input.title = description;
}
container.appendChild(input);
group.appendChild(container);
}
return group;
},
getIndentedPanel: function() { // wells are ugly within a form; breaks the horizontal form; is superfluous nesting
var el = document.createElement('div');
//el.className = 'well well-sm';
return el;
},
getFormInputDescription: function(text) { // description is used as the placeholder/title/info
//var el = document.createElement('p');
//el.className = 'help-block';
//el.textContent = text;
//return el;
return text;
},
getHeaderButtonHolder: function() { // removed the hard styling - our json-editor-bootstrap removes all buttons after json-editor render; something the library should maybe do? otherwise pressing enter activates collapsing the object..
var el = this.getButtonHolder();
//el.style.marginLeft = '10px';
return el;
},
getButtonHolder: function() { // not yet used (so no idea)
var el = document.createElement('div');
el.className = 'btn-group';
return el;
},
getButton: function(text, icon, title) { // not yet used (so no idea)
var el = this._super(text, icon, title);
el.className += 'btn btn-default';
return el;
},
getTable: function() { // not yet used (so no idea) - just removed the hard styling
var el = document.createElement('table');
el.className = 'table table-bordered';
//el.style.width = 'auto';
//el.style.maxWidth = 'none';
return el;
},
addInputError: function(input,text) {
if(!input.controlgroup) return;
if (input.controlgroup.className.indexOf(' has-error') === -1) {
input.controlgroup.className += ' has-error';
}
if(!input.errmsg) {
input.errmsg = document.createElement('p');
input.errmsg.className = 'help-block errormsg ' +
'col-xs-offset-' + this.labelWidth + ' col-xs-' + this.inputWidth; // error is now below the field
input.controlgroup.appendChild(input.errmsg);
}
else {
input.errmsg.style.display = '';
}
input.errmsg.textContent = text;
},
removeInputError: function(input) {
if(!input.errmsg) return;
input.errmsg.style.display = 'none';
input.controlgroup.className = input.controlgroup.className.replace(/\s?has-error/g,'');
},
getTabHolder: function() { // not yet used (so no idea)
var el = document.createElement('div');
el.innerHTML = "<div class='tabs list-group col-md-2'></div><div class='col-md-10'></div>";
el.className = 'rows';
return el;
},
getTab: function(text) { // not yet used (so no idea)
var el = document.createElement('a');
el.className = 'list-group-item';
el.setAttribute('href','#');
el.appendChild(text);
return el;
},
markTabActive: function(tab) { // not yet used (so no idea)
tab.className += ' active';
},
markTabInactive: function(tab) { // not yet used (so no idea)
tab.className = tab.className.replace(/\s?active/g,'');
},
getProgressBar: function() { // not yet used (so no idea)
var min = 0, max = 100, start = 0;
var container = document.createElement('div');
container.className = 'progress';
var bar = document.createElement('div');
bar.className = 'progress-bar';
bar.setAttribute('role', 'progressbar');
bar.setAttribute('aria-valuenow', start);
bar.setAttribute('aria-valuemin', min);
bar.setAttribute('aria-valuenax', max);
bar.innerHTML = start + "%";
container.appendChild(bar);
return container;
},
updateProgressBar: function(progressBar, progress) { // not yet used (so no idea)
if (!progressBar) return;
var bar = progressBar.firstChild;
var percentage = progress + "%";
bar.setAttribute('aria-valuenow', progress);
bar.style.width = percentage;
bar.innerHTML = percentage;
},
updateProgressBarUnknown: function(progressBar) { // not yet used (so no idea)
if (!progressBar) return;
var bar = progressBar.firstChild;
progressBar.className = 'progress progress-striped active';
bar.removeAttribute('aria-valuenow');
bar.style.width = '100%';
bar.innerHTML = '';
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment