| // Copyright (c) 2000-2017 Ericsson Telecom AB // |
| // All rights reserved. This program and the accompanying materials are made available under the // |
| // terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| /////////////////////////////////////////////////////////////////////////////////////////////////////// |
| function CView_CodeEditor(p_viewmodels, p_viewId, p_parentId, p_options) {
|
| if (p_options.editorType == "html") {
|
| return new CView_HtmlEditor(p_viewmodels, p_viewId, p_parentId, p_options);
|
| } else if (p_options.editorType == "css") {
|
| return new CView_CssEditor(p_viewmodels, p_viewId, p_parentId, p_options);
|
| } else if (p_options.editorType == "javascript") {
|
| return new CView_JavascriptEditor(p_viewmodels, p_viewId, p_parentId, p_options);
|
| } else if (p_options.editorType == "json") {
|
| return new CView_JSONCodeEditor(p_viewmodels, p_viewId, p_parentId, p_options);
|
| } else {
|
| return new CView_BaseCodeEditor(p_viewmodels, p_viewId, p_parentId, p_options);
|
| }
|
| }
|
|
|
| CView_CodeEditor.getHelp = function() {
|
| return "A code editor view that supports validation and formatting.";
|
| };
|
|
|
| CView_CodeEditor.expectsInterface = function() {
|
| return [
|
| {
|
| "mandatory": ["setTextData", "getTextData"]
|
| }
|
| ];
|
| };
|
|
|
| CView_CodeEditor.getCustomDataSchema = function() {
|
| var schema = {
|
| "$schema": "http://json-schema.org/draft-04/schema#",
|
| "title": "Custom data for CView_CodeEditor",
|
| "type": "object",
|
| "properties": {
|
| "editorType": {
|
| "description": "The type of the editor used for syntax highlighting and formaatting.",
|
| "type": "string",
|
| "enum": ["html", "css", "javascript", "json"]
|
| },
|
| "readOnly": {
|
| "description": "Whether we want to allow editing.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "headerText": {
|
| "description": "The title of the editor.",
|
| "type": "string"
|
| },
|
| "formatAllowed": {
|
| "description": "Whether we want to allow formatting.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "manualSaveRequired": {
|
| "description": "Whether we must press the save button to save the data.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "closeable": {
|
| "description": "Whether we want to allow closing the editor.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "alwaysRefresh": {
|
| "description": "Always refresh the editor, not only on full refresh.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "disableRefreshOnFocus": {
|
| "description": "Disables refresh when focused.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "focusEditorOnOpen": {
|
| "description": "Whether we want to focus the editor when opening it.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "draggable": {
|
| "description": "Whether we want the editor to be draggable.",
|
| "type": "boolean",
|
| "format": "checkbox",
|
| "default": true
|
| },
|
| "offset": {
|
| "description": "The offset of the editor. Only works with draggable.",
|
| "type": "object",
|
| "properties": {
|
| "top": {
|
| "type": "integer"
|
| },
|
| "left": {
|
| "type": "integer"
|
| }
|
| }
|
| }
|
| },
|
| "additionalProperties": false
|
| };
|
| $.extend(true, schema, ViewUtils.commonViewSchema);
|
| return schema;
|
| };
|
|
|
| function CView_BaseCodeEditor(p_viewmodels, p_viewId, p_parentId, p_options) {
|
| "use strict";
|
| var v_parentId = p_parentId;
|
| var v_viewId = p_viewId;
|
| var v_viewmodel = ViewUtils.getViewmodelsFromExpectedInterface(p_viewmodels, CView_CodeEditor)[0];
|
| var v_options = p_options;
|
| var v_callback_onDataChanged;
|
|
|
| var v_editor;
|
| var v_editorDiv;
|
| var v_name = "";
|
| var v_enabled = true;
|
| if (v_options.headerText != undefined) {
|
| v_name = v_options.headerText;
|
| }
|
|
|
| var v_this = this;
|
|
|
| this.EDITOROPTIONS = {
|
| lineNumbers: true,
|
| smartIndent: true,
|
| indentUnit: 4,
|
| lineWrapping: false,
|
| foldGutter: true,
|
| gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
| matchBrackets: true,
|
| autoCloseBrackets: true,
|
| highlightSelectionMatches: true,
|
| styleActiveLine: true,
|
| readOnly: v_options.readOnly
|
| };
|
|
|
| this.isValid = function() {
|
| return true;
|
| };
|
|
|
| this.format = function(text) {
|
| return text;
|
| };
|
|
|
| this.applicationCreated = function() {
|
| createHtml();
|
| setupCallbacks();
|
| open();
|
| };
|
|
|
| this.onDataChanged = function(callback) {
|
| v_callback_onDataChanged = callback;
|
| }
|
|
|
| function createHtml() {
|
| $("#" + v_parentId).append('<div id="' + v_viewId + '" class="CodeEditor"></div>');
|
| v_editorDiv = $("#" + v_viewId);
|
| v_editorDiv.append(
|
| '<div id="' + v_viewId + '_Header" class="CodeEditor_Header">' +
|
| '<h3>' + v_name + '</h3>' +
|
| '<button id="' + v_viewId + '_Format" class="CodeEditor_Format">Format</button>' +
|
| '<button id="' + v_viewId + '_Save" class="CodeEditor_Save">Save</button>' +
|
| '<button id="' + v_viewId + '_Close" class="CodeEditor_Close">X</button>' +
|
| '</div>' +
|
| '<div id="' + v_viewId + '_Editor" class="CodeEditor_Editor"></div>'
|
| );
|
| v_editor = new CodeMirror(document.getElementById(v_viewId + "_Editor"), v_this.EDITOROPTIONS);
|
|
|
| if (!v_options.closeable) {
|
| $('#' + v_viewId + '_Close').hide();
|
| }
|
|
|
| if (!v_options.formatAllowed) {
|
| $('#' + v_viewId + '_Format').hide();
|
| }
|
|
|
| if (!v_options.manualSaveRequired) {
|
| $('#' + v_viewId + '_Save').hide();
|
| }
|
|
|
| v_editor.setSize("100%", "100%");
|
| }
|
|
|
| function onChanges() {
|
| var currentValue = v_editor.getValue();
|
| if (v_callback_onDataChanged) {
|
| var newValue = v_callback_onDataChanged(currentValue);
|
| if (currentValue !== newValue) {
|
| currentValue = newValue;
|
| v_editor.setValue(currentValue);
|
| return;
|
| }
|
| }
|
| var isValidJSON = v_this.isValid(currentValue);
|
| refreshBorder(isValidJSON);
|
| if (!v_options.manualSaveRequired && isValidJSON) {
|
| v_viewmodel.setTextData(currentValue);
|
| }
|
| }
|
|
|
| function setupCallbacks() {
|
| v_editor.on('changes', onChanges);
|
| v_editor.on('focus', function() {
|
| v_editorDiv.addClass('EditorFocused')
|
| if (v_options.disableRefreshOnFocus){
|
| v_enabled = false;
|
| }
|
| });
|
| v_editor.on('blur', function() {
|
| v_editorDiv.removeClass('EditorFocused')
|
| v_enabled = true;
|
| });
|
|
|
| if (v_options.formatAllowed) {
|
| $("#" + v_viewId + "_Format").click(function() {
|
| if (v_this.isValid(v_editor.getValue())) {
|
| v_editor.setValue(v_this.format(v_editor.getValue()));
|
| }
|
| });
|
| }
|
|
|
| if (v_options.manualSaveRequired) {
|
| $("#" + v_viewId + "_Save").click(function() {
|
| v_viewmodel.setTextData(v_editor.getValue());
|
| });
|
| }
|
|
|
| if (v_options.closeable) {
|
| $("#" + v_viewId + "_Close").click(function() {
|
| v_editorDiv.remove();
|
| });
|
| }
|
|
|
| if (v_options.draggable) {
|
| var handle = $("#" + v_viewId + "_Header");
|
| handle.css("cursor", "move");
|
| v_editorDiv.css("position", "absolute");
|
|
|
| v_editorDiv.draggable({
|
| containment: [$("#" + v_parentId).offset().left, $("#" + v_parentId).offset().top, 20000, 20000],
|
| scroll: true,
|
| handle: handle
|
| }).resizable({
|
| handles: "se",
|
| resize: function() {}
|
| });
|
|
|
| v_editorDiv.on({
|
| dragstop: function(event) {
|
| v_editor.focus();
|
| },
|
| click: function(event) {
|
| v_editor.focus();
|
| },
|
| keydown: function(event) {
|
| if (event.keyCode == 27) {
|
| v_editorDiv.remove();
|
| }
|
| event.stopPropagation();
|
| }
|
| });
|
| }
|
| }
|
|
|
| function changeEditor(text, color, border) {
|
| $("#" + v_viewId + "_Header > label").text(text);
|
| $("#" + v_viewId + "_Header").css("color", color);
|
| $("#" + v_viewId).css("border-color", border);
|
| }
|
|
|
| function open() {
|
| changeEditor(v_name, "black", "#DDDDDD");
|
|
|
| if (v_options.draggable && v_options.offset != undefined) {
|
| v_editorDiv.offset(v_options.offset);
|
| // in IE and chrome we need to set the offset twice so it gets calculated correctly
|
| v_editorDiv.offset(v_options.offset);
|
| }
|
|
|
| if (v_options.focusEditorOnOpen) {
|
| v_editor.focus();
|
| }
|
| };
|
|
|
| function refreshBorder(valid) {
|
| if (!valid) {
|
| changeEditor("INVALID DATA: " + v_name, "red", "red");
|
| } else {
|
| changeEditor(v_name, "black", "#DDDDDD");
|
| }
|
| }
|
|
|
| this.refresh = function(p_fullRefresh) {
|
| function valueArrived(value) {
|
| var scrollInfo = v_editor.getScrollInfo();
|
| v_editor.off('changes', onChanges);
|
| v_editor.setValue(value);
|
| v_editor.on('changes', onChanges);
|
| v_editor.scrollTo(scrollInfo.left, scrollInfo.top);
|
| refreshBorder(v_this.isValid(value));
|
| }
|
|
|
| if (v_enabled && (p_fullRefresh || v_options.alwaysRefresh)) {
|
| v_viewmodel.getTextData(valueArrived);
|
| }
|
| };
|
| }
|
|
|
| function CView_JSONCodeEditor(p_viewmodels, p_mainId, p_parentId, p_options) {
|
| "use strict";
|
| var editor = new CView_BaseCodeEditor(p_viewmodels, p_mainId, p_parentId, p_options);
|
|
|
| editor.EDITOROPTIONS.mode = "javascript";
|
|
|
| editor.format = function(text) {
|
| var rawData = JSON.parse(text);
|
| var formattedText = JSON.stringify(rawData, null, 4);
|
| return formattedText;
|
| };
|
|
|
| editor.isValid = function(text) {
|
| try {
|
| JSON.parse(text);
|
| return true;
|
| } catch (e) {
|
| return false;
|
| }
|
| };
|
|
|
| return editor;
|
| }
|
|
|
| function CView_HtmlEditor(p_viewmodels, p_mainId, p_parentId, p_options) {
|
| "use strict";
|
| var editor = new CView_BaseCodeEditor(p_viewmodels, p_mainId, p_parentId, p_options);
|
|
|
| editor.EDITOROPTIONS.mode = "xml";
|
|
|
| editor.format = function(text) {
|
| var parser = new DOMParser();
|
| var doc = parser.parseFromString('<DIV>' + text + '</DIV>', "text/xml");
|
| return doc.documentElement.innerHTML;
|
| };
|
|
|
| editor.isValid = function(text) {
|
| function hasUniqueIds(doc) {
|
| var result = true;
|
| var elements_with_id = doc.querySelectorAll("*[id]");
|
| for (var i = 0; result && (i < elements_with_id.length); i++) {
|
| if (!/\S/.test(elements_with_id[i].getAttribute("id"))) { // There is an ID that is empty.
|
| return false;
|
| }
|
| for (var j = i+1; result && (j < elements_with_id.length); j++) {
|
| result = (elements_with_id[i].getAttribute("id") !== elements_with_id[j].getAttribute("id"));
|
| }
|
| }
|
| return result;
|
| }
|
|
|
| try {
|
| var parser = new DOMParser();
|
| var doc = parser.parseFromString('<DIV>' + text + '</DIV>', "text/xml");
|
| return hasUniqueIds(doc) && doc.getElementsByTagName("parsererror").length === 0;
|
| } catch (e) {
|
| return false;
|
| }
|
| };
|
|
|
| return editor;
|
| }
|
|
|
| function CView_CssEditor(p_viewmodels, p_mainId, p_parentId, p_options) {
|
| "use strict";
|
| var editor = new CView_BaseCodeEditor(p_viewmodels, p_mainId, p_parentId, p_options);
|
| editor.EDITOROPTIONS.mode = "css";
|
| return editor;
|
| }
|
|
|
| function CView_JavascriptEditor(p_viewmodels, p_mainId, p_parentId, p_options) {
|
| "use strict";
|
| var editor = new CView_BaseCodeEditor(p_viewmodels, p_mainId, p_parentId, p_options);
|
| editor.EDITOROPTIONS.mode = "javascript";
|
| return editor;
|
| }
|
|
|
| //# sourceURL=WebApplicationFramework\Views\View_CodeEditor.js |