All Downloads are FREE. Search and download functionalities are using the official Maven repository.

root.libs.composum.nodes.commons.components.js.codeEditor.js Maven / Gradle / Ivy

There is a newer version: 4.3.4
Show newest version
/**
 *
 *
 */
(function () {
    'use strict';
    CPM.namespace('core.components');

    (function (components, widgets, core) {

        /**
         * the 'code-editor-widget'
         */
        components.CodeEditorWidget = widgets.Widget.extend({

            initialize: function (options) {
                widgets.Widget.prototype.initialize.apply(this, [options]);

                this.$editor = this.$('.code-editor');
                this.$findText = this.$('.search .find-text');
                this.$findNext = this.$('.search .find-next');
                this.$findPrev = this.$('.search .find-prev');
                this.$matchCase = this.$('.match-case');
                this.$findRegEx = this.$('.find-regex');
                this.$replText = this.$('.replace .replace-text');
                this.$replCurrent = this.$('.replace .replace');
                this.$replAll = this.$('.replace .replace-all');
                this.$undo = this.$('.undo');
                this.$redo = this.$('.redo');

                this.initEditor(_.bind(function (data) {
                    this.ace.setReadOnly(true);
                    this.ace.navigateFileStart();
                }, this));
                this.$el.resize(_.bind(this.resize, this));
                this.$el.on('splitpaneresize', _.bind(this.resize, this));

                this.$('.editor-toolbar .start-editing').click(_.bind(this.openEditDialog, this));

                this.searchOptions = {
                    wrap: true,
                    caseSensitive: false,
                    regExp: false
                };
                this.$findText.on('input', _.bind(function (event) {
                    this.findText();
                }, this));
                this.$findText.keypress(_.bind(function (event) {
                    this.findText();
                }, this));
                this.$findNext.click(_.bind(this.findNext, this));
                this.$findPrev.click(_.bind(this.findPrev, this));
                this.$matchCase.change(_.bind(this.toggleCaseSensitive, this));
                this.$findRegEx.change(_.bind(this.toggleRegExp, this));
                this.$replCurrent.click(_.bind(this.replace, this));
                this.$replAll.click(_.bind(this.replaceAll, this));

                this.$undo.click(_.bind(this.undo, this));
                this.$redo.click(_.bind(this.redo, this));
            },

            initEditor: function (onSuccess) {
                this.ace = ace.edit(this.$editor[0]);
                this.ace.setTheme('ace/theme/clouds');
                var type = this.$editor.attr('data-type');
                if (type) {
                    this.ace.getSession().setMode('ace/mode/' + type);
                }
                this.loadText(onSuccess);
            },

            setSaveCommand: function (save) {
                this.ace.commands.addCommand({
                    name: 'save',
                    bindKey: {
                        win: 'Ctrl-S',
                        mac: 'Command-S'
                    },
                    exec: save
                });
            },

            getValue: function () {
                return this.ace.getValue();
            },

            setValue: function (value, triggerChange) {
                this.ace.setValue(value);
                if (triggerChange) {
                    this.$el.trigger('change', [value]);
                }
            },

            openEditDialog: function () {
                this.dialog = core.getView('#text-edit-dialog', components.CodeEditorDialog);
                this.dialog.editSource(this);
            },

            getPath: function () {
                return this.$editor.attr("data-path");
            },

            /**
             * loads the text data (jcr:data property) of the node referenced by the 'data-path' attribute
             * of the editor DOM element ($...('.text-editor .code-editor')) into the editor
             * @param event the current event object (used if target is undefined)
             * @param target the editor DOM element (can be undefined - than the events target is used to find it)
             * @param onSuccess the success callback handler (function(event,editor,data))
             */
            loadText: function (onSuccess) {
                var path = this.getPath();
                if (path) {
                    core.ajaxGet("/bin/cpm/nodes/property.bin" + core.encodePath(path), {
                            contentType: 'text/plain;charset=UTF-8',
                            dataType: 'text'
                        }, _.bind(function (data) {
                            this.ace.setValue(data);
                            this.ace.clearSelection();
                            if (_.isFunction(onSuccess)) {
                                onSuccess(data);
                            }
                        }, this),
                        _.bind(function (result) {
                            core.alert('danger', core.i18n.get('Error'),
                                core.i18n.get('Error on loading text'), result);
                        }, this));
                }
            },

            saveText: function (onSuccess) {
                var path = this.getPath();
                if (path) {
                    core.ajaxPut("/bin/cpm/nodes/property.update.bin" + core.encodePath(path), this.ace.getValue(), {
                        contentType: 'text/plain;charset=UTF-8',
                        dataType: 'text'
                    }, undefined, undefined, _.bind(function (result, x, y) {
                        if (result.status === 200) {
                            if (_.isFunction(onSuccess)) {
                                onSuccess(result);
                            }
                        } else {
                            core.alert('danger', core.i18n.get('Error'),
                                core.i18n.get('Error on updating text'), result);
                        }
                    }, this));
                }
            },

            reset: function () {
                this.ace.destroy();
            },

            resize: function () {
                this.ace.resize();
            },

            findText: function (text) {
                if (!text) {
                    text = this.$findText.val();
                }
                if (text) {
                    this.searchOptions.backwards = false;
                    this.ace.findAll(text, this.searchOptions, false);
                }
            },

            findNext: function () {
                this.searchOptions.backwards = false;
                this.ace.findNext(this.searchOptions, false);
            },

            findPrev: function () {
                this.searchOptions.backwards = true;
                this.ace.findPrevious(this.searchOptions, false);
            },

            toggleCaseSensitive: function (event) {
                this.searchOptions.caseSensitive = event
                    ? event.currentTarget.checked
                    : !this.searchOptions.caseSensitive;
                this.findText();
            },

            toggleRegExp: function (event) {
                this.searchOptions.regExp = event
                    ? event.currentTarget.checked
                    : !this.searchOptions.regExp;
                this.findText();
            },

            replace: function () {
                var text = this.$replText.val();
                if (text) {
                    this.ace.replace(text, this.searchOptions);
                }
            },

            replaceAll: function () {
                var text = this.$replText.val();
                if (text) {
                    this.ace.replaceAll(text, this.searchOptions);
                }
            },

            undo: function () {
                this.ace.undo();
            },

            redo: function () {
                this.ace.redo();
            }
        });

        widgets.register('.widget.code-editor-widget', components.CodeEditorWidget);

        components.CodeEditorDialog = components.Dialog.extend({

            initialize: function (options) {
                core.components.Dialog.prototype.initialize.apply(this, [options]);
                this.editor = core.getWidget(this.el, '.widget.code-editor-widget', components.CodeEditorWidget);
                this.$('button.save').click(_.bind(this.saveAndContinue, this));
                this.$('button.save-and-close').click(_.bind(this.saveAndClose, this));
            },

            saveAndContinue: function (event, onSuccess) {
                this.cursor = this.editor.ace.getCursorPosition();
                this.editor.saveText(_.bind(function (result) {
                    if (this.source) {
                        this.source.loadText(_.bind(function (data) {
                            this.source.ace.navigateTo(this.cursor.row, this.cursor.column);
                            this.source.ace.scrollToRow(Math.max(this.cursor.row - 2, 0));
                        }, this));
                    }
                    if (_.isFunction(onSuccess)) {
                        onSuccess();
                    }
                }, this));
            },

            saveAndClose: function (event) {
                this.saveAndContinue(event, _.bind(function () {
                    this.hide();
                }, this));
            },

            /**
             * defines the text editor dialog source component which holds the text view
             * and opens the dialog with the same text as visible in the view and with the
             * same editor state (cursor, selection)
             */
            editSource: function (source) {
                this.source = source;
                // initialize the dialog with the templates data
                var path = this.source.getPath();
                var type = this.source.$editor.attr('data-type');
                this.selection = this.source.ace.getSelectionRange();
                this.cursor = this.source.ace.getCursorPosition();
                this.doEdit(path, type, _.bind(function () {
                    this.editor.ace.setReadOnly(false);
                    this.editor.ace.scrollToRow(Math.max(this.cursor.row - 2, 0));
                    this.editor.ace.navigateTo(this.cursor.row, this.cursor.column);
                    this.editor.ace.focus();
                }, this));
            },

            /**
             * Open dialog to edit a file referenced by its path without a source view.
             */
            editFile: function (path, type) {
                this.source = undefined;
                // display the editor in the modal dialog
                this.doEdit(path, type, _.bind(function () {
                    this.editor.ace.setReadOnly(false);
                    this.editor.ace.focus();
                }, this));
            },

            doEdit: function (path, type, initAfterLoad) {
                this.$('.modal-title').text(path);
                this.editor.$editor.attr('data-path', path);
                this.editor.$editor.attr('data-type', type);
                // display the editor in the modal dialog
                this.show(_.bind(function () {
                    // initialize the editor instance
                    this.editor.initEditor(initAfterLoad);
                    this.editor.setSaveCommand(_.bind(function (editor) {
                        this.saveAndContinue();
                    }, this));
                }, this));
            },

            reset: function () {
                components.Dialog.prototype.reset.apply(this);
                this.editor.reset();
            }
        });

    })(CPM.core.components, CPM.widgets, CPM.core);

})();




© 2015 - 2025 Weber Informatics LLC | Privacy Policy