Commit 38d56377 authored by Rebecca Blundell's avatar Rebecca Blundell Committed by Rebecca Blundell

Bug 1635503: Add JSON editor for SmartEvidence

This adds a visual JSON editor for SmartEvidence
frameworks allowing site administrators to create
such frameworks more easily by copying and pasting
rather than needing to know the JSON file syntax.

behatnotneeded

Change-Id: Ief74375a6c5d23ab05e12f08d07dd3209e89c948
parent 2c82fcdd
The MIT License (MIT)
Copyright (c) 2013 Jeremy Dorn
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
JSONeditor in Mahara
=================
Website: https://github.com/json-editor/json-editor/
Version: 1.3
This library is used by SmartEvidence, to provide a user-friendly way
of editing a framework, without relying on a json upload.
In order to work, the JSONeditor needs a dist folder with jsoneditor.js and
jsoneditor.js.map in it.
It's not in the github repo for some reason, but can be found here:
https://www.jsdelivr.com/package/npm/@json-editor/json-editor?path=dist&version=1.3.0
Changes:
Removed .github, tests and docs folders; Gruntfile.js, package.json,
package-lock.json, .gitattributes, .gitignore, npmignore, .npmrc and travis.yml
From src/iconlibs, removed bootstrap2.js, foundation2-3.js, materialicons.js
src/styles
src/templates - all but default
src/themes bootstrap2.js, foundation.js, materialize.js
To allow changing of the text on the Edit JSON button:
in src/defaults.js, added:
/**
* Title on Edit JSON buttons
*/
button_edit : "Edit raw"
in src/dist/jsoneditor.js
replaced this.editjson_button = this.getButton('JSON','edit','Edit JSON');
with this.editjson_button = this.getButton('','edit', this.translate('button_edit'));
added button_edit: "Edit raw", to the JSONEditor.defualts.languages.en JSON
To stop the editor displaying undefined in the Standard Elements header when the parent
id is undefined:
in src/dist/jsoneditor.js - added the asterisked line to the following:
// The compiled function
return function(vars) {
var ret = template+"";
var r;
for(i=0; i<l; i++) {
r = replacements[i];
ret = ret.replace(r.s, r.r(vars));
}
* ret = ret.replace(/undefined\./gi, '');
return ret;
Because Mahara requires just an initial capital letter on titles, added the asterisked
lines to the JSONEditor.defaults.translate function:
if(variables) {
for(var i=0; i<variables.length; i++) {
string = string.replace(new RegExp('\\{\\{'+i+'}}','g'),variables[i]);
* string = string.toLowerCase();
* string = string.charAt(0).toUpperCase() + string.slice(1);
}
}
JSON Editor
===========
[![Build Status](https://travis-ci.org/json-editor/json-editor.svg?branch=master)](https://travis-ci.org/json-editor/json-editor)
Fork of the inactive [jdorn/json-editor](https://github.com/jdorn/json-editor) using the updated fork [json-editor/json-editor](https://github.com/json-editor/json-editor).
Some pull requests added from the original repo.
![JSON Schema -> HTML Editor -> JSON](./docs/images/jsoneditor.png)
JSON Editor takes a JSON Schema and uses it to generate an HTML form.
It has full support for JSON Schema version 3 and 4 and can integrate with several popular CSS frameworks (bootstrap, foundation, and jQueryUI).
Check out an interactive demo (demo.html): https://json-editor.github.io/json-editor/
Install
-----------------
Install package
npm install @json-editor/json-editor
Using a CDN
<script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor/dist/jsoneditor.min.js"></script>
For local usage download the [production version](https://cdn.jsdelivr.net/npm/@json-editor/json-editor/dist/jsoneditor.min.js) or the [development version](https://cdn.jsdelivr.net/npm/@json-editor/json-editor/dist/jsoneditor.js)
Requirements
-----------------
JSON Editor has no dependencies. It only needs a modern browser (tested in Chrome and Firefox).
### Optional Requirements
The following are not required, but can improve the style and usability of JSON Editor when present.
* A compatible JS template engine (Mustache, Underscore, Hogan, Handlebars, Swig, Markup, or EJS)
* A compatible CSS framework for styling (bootstrap 2/3, foundation 3/4/5, or jqueryui)
* A compatible icon library (bootstrap 2/3 glyphicons, foundation icons 2/3, jqueryui, or font awesome 3/4)
* [SCEditor](http://www.sceditor.com/) for WYSIWYG editing of HTML or BBCode content
* [SimpleMDE](https://simplemde.com/) for editing of Markdown content
* [Ace Editor](http://ace.c9.io/) for editing code
* [Select2](http://ivaynberg.github.io/select2/) for nicer Select boxes
* [Selectize](https://selectize.github.io/selectize.js/) for nicer Select & Array boxes
* [math.js](http://mathjs.org/) for more accurate floating point math (multipleOf, divisibleBy, etc.)
Usage
--------------
If you learn best by example, check these out:
* Basic Usage Example - http://rawgithub.com/jdorn/json-editor/master/examples/basic.html
* Advanced Usage Example - http://rawgithub.com/jdorn/json-editor/master/examples/advanced.html
* CSS Integration Example - http://rawgithub.com/jdorn/json-editor/master/examples/css_integration.html
The rest of this README contains detailed documentation about every aspect of JSON Editor. For more under-the-hood documentation, check the wiki.
### Initialize
```js
var element = document.getElementById('editor_holder');
var editor = new JSONEditor(element, options);
```
#### Options
Options can be set globally or on a per-instance basis during instantiation.
```js
// Set an option globally
JSONEditor.defaults.options.theme = 'bootstrap2';
// Set an option during instantiation
var editor = new JSONEditor(element, {
//...
theme: 'bootstrap2'
});
```
Here are all the available options:
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
<th>Default Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>ajax</td>
<td>If <code>true</code>, JSON Editor will load external URLs in <code>$ref</code> via ajax.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>disable_array_add</td>
<td>If <code>true</code>, remove all "add row" buttons from arrays.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>disable_array_delete</td>
<td>If <code>true</code>, remove all "delete row" buttons from arrays.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>disable_array_reorder</td>
<td>If <code>true</code>, remove all "move up" and "move down" buttons from arrays.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>disable_collapse</td>
<td>If <code>true</code>, remove all collapse buttons from objects and arrays.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>disable_edit_json</td>
<td>If <code>true</code>, remove all Edit JSON buttons from objects.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>disable_properties</td>
<td>If <code>true</code>, remove all Edit Properties buttons from objects.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>form_name_root</td>
<td>The first part of the `name` attribute of form inputs in the editor. An full example name is `root[person][name]` where "root" is the form_name_root.</td>
<td>root</td>
</tr>
<tr>
<td>iconlib</td>
<td>The icon library to use for the editor. See the <strong>CSS Integration</strong> section below for more info.</td>
<td><code>null</code></td>
</tr>
<tr>
<td>no_additional_properties</td>
<td>If <code>true</code>, objects can only contain properties defined with the <code>properties</code> keyword.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>refs</td>
<td>An object containing schema definitions for URLs. Allows you to pre-define external schemas.</td>
<td><code>{}</code></td>
</tr>
<tr>
<td>required_by_default</td>
<td>If <code>true</code>, all schemas that don't explicitly set the <code>required</code> property will be required.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>keep_oneof_values</td>
<td>If <code>true</code>, makes oneOf copy properties over when switching.</td>
<td><code>true</code></td>
</tr>
<tr>
<td>schema</td>
<td>A valid JSON Schema to use for the editor. Version 3 and Version 4 of the draft specification are supported.</td>
<td><code>{}</code></td>
</tr>
<tr>
<td>show_errors</td>
<td>When to show validation errors in the UI. Valid values are <code>interaction</code>, <code>change</code>, <code>always</code>, and <code>never</code>.</td>
<td><code>"interaction"</code></td>
</tr>
<tr>
<td>startval</td>
<td>Seed the editor with an initial value. This should be valid against the editor's schema.</td>
<td><code>null</code></td>
</tr>
<tr>
<td>template</td>
<td>The JS template engine to use. See the <strong>Templates and Variables</strong> section below for more info.</td>
<td><code>default</code></td>
</tr>
<tr>
<td>theme</td>
<td>The CSS theme to use. See the <strong>CSS Integration</strong> section below for more info.</td>
<td><code>html</code></td>
</tr>
<tr>
<td>display_required_only</td>
<td>If <code>true</code>, only required properties will be included by default.</td>
<td><code>false</code></td>
</tr>
<tr>
<td>prompt_before_delete</td>
<td>If <code>true</code>, displays a dialog box with a confirmation message before node deletion.</td>
<td><code>true</code></td>
</tr>
</tbody>
</table>
__*Note__ If the `ajax` property is `true` and JSON Editor needs to fetch an external url, the api methods won't be available immediately.
Listen for the `ready` event before calling them.
```js
editor.on('ready',function() {
// Now the api methods will be available
editor.validate();
});
```
### Get/Set Value
```js
editor.setValue({name: "John Smith"});
var value = editor.getValue();
console.log(value.name) // Will log "John Smith"
```
Instead of getting/setting the value of the entire editor, you can also work on individual parts of the schema:
```js
// Get a reference to a node within the editor
var name = editor.getEditor('root.name');
// `getEditor` will return null if the path is invalid
if(name) {
name.setValue("John Smith");
console.log(name.getValue());
}
```
### Validate
When feasible, JSON Editor won't let users enter invalid data. This is done by
using input masks and intelligently enabling/disabling controls.
However, in some cases it is still possible to enter data that doesn't validate against the schema.
You can use the `validate` method to check if the data is valid or not.
```javascript
// Validate the editor's current value against the schema
var errors = editor.validate();
if(errors.length) {
// errors is an array of objects, each with a `path`, `property`, and `message` parameter
// `property` is the schema keyword that triggered the validation error (e.g. "minLength")
// `path` is a dot separated path into the JSON object (e.g. "root.path.to.field")
console.log(errors);
}
else {
// It's valid!
}
```
By default, this will do the validation with the editor's current value.
If you want to use a different value, you can pass it in as a parameter.
```javascript
// Validate an arbitrary value against the editor's schema
var errors = editor.validate({
value: {
to: "test"
}
});
```
### Listen for Changes
The `change` event is fired whenever the editor's value changes.
```javascript
editor.on('change',function() {
// Do something
});
editor.off('change',function_reference);
```
You can also watch a specific field for changes:
```javascript
editor.watch('path.to.field',function() {
// Do something
});
editor.unwatch('path.to.field',function_reference);
```
### Enable and Disable the Editor
This lets you disable editing for the entire form or part of the form.
```js
// Disable entire form
editor.disable();
// Disable part of the form
editor.getEditor('root.location').disable();
// Enable entire form
editor.enable();
// Enable part of the form
editor.getEditor('root.location').enable();
// Check if form is currently enabled
if(editor.isEnabled()) alert("It's editable!");
```
### Destroy
This removes the editor HTML from the DOM and frees up resources.
```javascript
editor.destroy();
```
CSS Integration
----------------
JSON Editor can integrate with several popular CSS frameworks out of the box.
The currently supported themes are:
* barebones
* html (the default)
* bootstrap2
* bootstrap3
* bootstrap4
* foundation3
* foundation4
* foundation5
* foundation6
* jqueryui
The default theme is `html`, which does not rely on an external framework.
This default can be changed by setting the `JSONEditor.defaults.options.theme` variable.
If you want to specify your own styles with CSS, you can use `barebones`, which includes almost no classes or inline styles.
```javascript
JSONEditor.defaults.options.theme = 'foundation5';
```
You can override this default on a per-instance basis by passing a `theme` parameter in when initializing:
```js
var editor = new JSONEditor(element,{
schema: schema,
theme: 'jqueryui'
});
```
### Icon Libraries
JSON Editor also supports several popular icon libraries. The icon library must be set independently of the theme, even though there is some overlap.
The supported icon libs are:
* bootstrap2 (glyphicons)
* bootstrap3 (glyphicons)
* foundation2
* foundation3
* jqueryui
* fontawesome3
* fontawesome4
By default, no icons are used. Just like the CSS theme, you can set the icon lib globally or when initializing:
```js
// Set the global default
JSONEditor.defaults.options.iconlib = "bootstrap2";
// Set the icon lib during initialization
var editor = new JSONEditor(element,{
schema: schema,
iconlib: "fontawesome4"
});
```
It's possible to create your own custom themes and/or icon libs as well. Look at any of the existing classes for examples.
JSON Schema Support
-----------------
JSON Editor fully supports version 3 and 4 of the JSON Schema [core][core] and [validation][validation] specifications.
Some of The [hyper-schema][hyper] specification is supported as well.
[core]: http://json-schema.org/latest/json-schema-core.html
[validation]: http://json-schema.org/latest/json-schema-validation.html
[hyper]: http://json-schema.org/latest/json-schema-hypermedia.html
### $ref and definitions
JSON Editor supports schema references to external URLs and local definitions. Here's an example showing both:
```json
{
"type": "object",
"properties": {
"name": {
"title": "Full Name",
"$ref": "#/definitions/name"
},
"location": {
"$ref": "http://mydomain.com/geo.json"
}
},
"definitions": {
"name": {
"type": "string",
"minLength": 5
}
}
}
```
Local references must point to the `definitions` object of the root node of the schema.
So, `#/customkey/name` will throw an exception.
If loading an external url via Ajax, the url must either be on the same domain or return the correct HTTP cross domain headers.
If your URLs don't meet this requirement, you can pass in the references to JSON Editor during initialization (see Usage section above).
Self-referential $refs are supported. Check out `examples/recursive.html` for usage examples.
### hyper-schema links
The `links` keyword from the hyper-schema specification can be used to add links to related documents.
JSON Editor will use the `mediaType` property of the links to determine how best to display them.
Image, audio, and video links will display the media inline as well as providing a text link.
Here are a couple examples:
Simple text link
```js+jinja
{
"title": "Blog Post Id",
"type": "integer",
"links": [
{
"rel": "comments",
"href": "/posts/{{self}}/comments/",
// Optional - set CSS classes for the link
"class": "comment-link open-in-modal primary-text"
}
]
}
```
Make link download when clicked
```js+jinja
{
"title": "Document filename",
"type": "string",
"links": [
{
"rel": "Download File",
"href": "/documents/{{self}}",
// Can also set `download` to a string as per the HTML5 spec
"download": true
}
]
}
```
Show a video preview (using HTML5 video)
```js+jinja
{
"title": "Video filename",
"type": "string",
"links": [
{
"href": "/videos/{{self}}.mp4",
"mediaType": "video/mp4"
}
]
}
```
The `href` property is a template that gets re-evaluated every time the value changes.
The variable `self` is always available. Look at the __Dependencies__ section below for how to include other fields or use a custom template engine.
### Property Ordering
There is no way to specify property ordering in JSON Schema (although this may change in v5 of the spec).
JSON Editor introduces a new keyword `propertyOrder` for this purpose. The default property order if unspecified is 1000. Properties with the same order will use normal JSON key ordering.
```json
{
"type": "object",
"properties": {
"prop1": {
"type": "string"
},
"prop2": {
"type": "string",
"propertyOrder": 10
},
"prop3": {
"type": "string",
"propertyOrder": 1001
},
"prop4": {
"type": "string",
"propertyOrder": 1
}
}
}
```
In the above example schema, `prop1` does not have an order specified, so it will default to 1000.
So, the final order of properties in the form (and in returned JSON data) will be:
1. prop4 (order 1)
2. prop2 (order 10)
3. prop1 (order 1000)
4. prop3 (order 1001)
### Default Properties
The default behavior of JSON Editor is to include all object properties defined with the `properties` keyword.
To override this behaviour, you can use the keyword `defaultProperties` to set which ones are included:
```json
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"defaultProperties": ["name"]
}
```
Now, only the `name` property above will be included by default. You can use the "Object Properties" button
to add the "age" property back in.
### format
JSON Editor supports many different formats for schemas of type `string`. They will work with schemas of type `integer` and `number` as well, but some formats may produce weird results.
If the `enum` property is specified, `format` will be ignored.
JSON Editor uses HTML5 input types, so some of these may render as basic text input in older browsers:
* color
* date
* datetime
* datetime-local