diff --git a/ui/src/app/components/ace-editor-fix.js b/ui/src/app/components/ace-editor-fix.js new file mode 100644 index 0000000000..f68767e6e3 --- /dev/null +++ b/ui/src/app/components/ace-editor-fix.js @@ -0,0 +1,45 @@ +/* + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default function fixAceEditor(aceEditor) { + aceEditor.$blockScrolling = Infinity; + aceEditor.on("showGutterTooltip", function (tooltip) { + if (!tooltip.isAttachedToBody) { + document.body.appendChild(tooltip.$element); //eslint-disable-line + tooltip.isAttachedToBody = true; + onElementRemoved(tooltip.$parentNode, () => { + if (tooltip.$element.parentNode != null) { + tooltip.$element.parentNode.removeChild(tooltip.$element); + } + }); + } + }); +} + +function onElementRemoved(element, callback) { + if (!document.body.contains(element)) { //eslint-disable-line + callback(); + } else { + var observer; + observer = new MutationObserver(function(mutations) { //eslint-disable-line + if (!document.body.contains(element)) { //eslint-disable-line + callback(); + observer.disconnect(); + } + }); + observer.observe(document.body, {childList: true}); //eslint-disable-line + } +} diff --git a/ui/src/app/components/js-func.directive.js b/ui/src/app/components/js-func.directive.js index f95d003e8a..33cebdebf0 100644 --- a/ui/src/app/components/js-func.directive.js +++ b/ui/src/app/components/js-func.directive.js @@ -22,6 +22,8 @@ import thingsboardToast from '../services/toast'; import thingsboardUtils from '../common/utils.service'; import thingsboardExpandFullscreen from './expand-fullscreen.directive'; +import fixAceEditor from './ace-editor-fix'; + /* eslint-disable import/no-unresolved, import/default */ import jsFuncTemplate from './js-func.tpl.html'; @@ -83,6 +85,7 @@ function JsFunc($compile, $templateCache, toast, utils, $translate) { scope.js_editor.session.on("change", function () { scope.cleanupJsErrors(); }); + fixAceEditor(_ace); } }; diff --git a/ui/src/app/components/json-object-edit.directive.js b/ui/src/app/components/json-object-edit.directive.js index 03ddc07db7..db0aa60bb5 100644 --- a/ui/src/app/components/json-object-edit.directive.js +++ b/ui/src/app/components/json-object-edit.directive.js @@ -19,6 +19,8 @@ import 'brace/ext/language_tools'; import 'brace/mode/json'; import 'ace-builds/src-min-noconflict/snippets/json'; +import fixAceEditor from './ace-editor-fix'; + /* eslint-disable import/no-unresolved, import/default */ import jsonObjectEditTemplate from './json-object-edit.tpl.html'; @@ -30,7 +32,7 @@ export default angular.module('thingsboard.directives.jsonObjectEdit', []) .name; /*@ngInject*/ -function JsonObjectEdit($compile, $templateCache, toast, utils) { +function JsonObjectEdit($compile, $templateCache, $document, toast, utils) { var linker = function (scope, element, attrs, ngModelCtrl) { var template = $templateCache.get(jsonObjectEditTemplate); @@ -67,6 +69,7 @@ function JsonObjectEdit($compile, $templateCache, toast, utils) { scope.json_editor.session.on("change", function () { scope.cleanupJsonErrors(); }); + fixAceEditor(_ace); } }; diff --git a/ui/src/app/components/react/json-form-ace-editor.jsx b/ui/src/app/components/react/json-form-ace-editor.jsx index 1c4c02e16f..5afd3d18f1 100644 --- a/ui/src/app/components/react/json-form-ace-editor.jsx +++ b/ui/src/app/components/react/json-form-ace-editor.jsx @@ -23,6 +23,8 @@ import FlatButton from 'material-ui/FlatButton'; import 'brace/ext/language_tools'; import 'brace/theme/github'; +import fixAceEditor from './../ace-editor-fix'; + class ThingsboardAceEditor extends React.Component { constructor(props) { @@ -31,6 +33,7 @@ class ThingsboardAceEditor extends React.Component { this.onBlur = this.onBlur.bind(this); this.onFocus = this.onFocus.bind(this); this.onTidy = this.onTidy.bind(this); + this.onLoad = this.onLoad.bind(this); var value = props.value ? props.value + '' : ''; this.state = { value: value, @@ -72,6 +75,10 @@ class ThingsboardAceEditor extends React.Component { } } + onLoad(editor) { + fixAceEditor(editor); + } + render() { const styles = reactCSS({ @@ -117,6 +124,7 @@ class ThingsboardAceEditor extends React.Component { onChange={this.onValueChanged} onFocus={this.onFocus} onBlur={this.onBlur} + onLoad={this.onLoad} name={this.props.form.title} value={this.state.value} readOnly={this.props.form.readonly} diff --git a/ui/src/app/components/widget/widget-config.directive.js b/ui/src/app/components/widget/widget-config.directive.js index d0ee6a3d04..4d4d958427 100644 --- a/ui/src/app/components/widget/widget-config.directive.js +++ b/ui/src/app/components/widget/widget-config.directive.js @@ -23,6 +23,8 @@ import thingsboardJsonForm from '../json-form.directive'; import thingsboardManageWidgetActions from './action/manage-widget-actions.directive'; import 'angular-ui-ace'; +import fixAceEditor from './../ace-editor-fix'; + import './widget-config.scss'; /* eslint-disable import/no-unresolved, import/default */ @@ -72,6 +74,9 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout enableSnippets: true, enableBasicAutocompletion: true, enableLiveAutocompletion: true + }, + onLoad: function (_ace) { + fixAceEditor(_ace); } };