http://git-wip-us.apache.org/repos/asf/zeppelin/blob/ed517a20/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index 07ebf89..971257c 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -12,35 +12,35 @@ * limitations under the License. */ -import {SpellResult} from '../../spell' -import {isParagraphRunning, ParagraphStatus} from './paragraph.status' +import {SpellResult} from '../../spell'; +import {isParagraphRunning, ParagraphStatus} from './paragraph.status'; -import moment from 'moment' +import moment from 'moment'; -require('moment-duration-format') +require('moment-duration-format'); const ParagraphExecutor = { SPELL: 'SPELL', INTERPRETER: 'INTERPRETER', NONE: '', /** meaning `DONE` */ -} +}; -angular.module('zeppelinWebApp').controller('ParagraphCtrl', ParagraphCtrl) +angular.module('zeppelinWebApp').controller('ParagraphCtrl', ParagraphCtrl); -function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $location, +function ParagraphCtrl($scope, $rootScope, $route, $window, $routeParams, $location, $timeout, $compile, $http, $q, websocketMsgSrv, baseUrlSrv, ngToast, noteVarShareService, heliumService) { - 'ngInject' + 'ngInject'; - let ANGULAR_FUNCTION_OBJECT_NAME_PREFIX = '_Z_ANGULAR_FUNC_' - $rootScope.keys = Object.keys - $scope.parentNote = null - $scope.paragraph = {} - $scope.paragraph.results = {} - $scope.paragraph.results.msg = [] - $scope.originalText = '' - $scope.editor = null + let ANGULAR_FUNCTION_OBJECT_NAME_PREFIX = '_Z_ANGULAR_FUNC_'; + $rootScope.keys = Object.keys; + $scope.parentNote = null; + $scope.paragraph = {}; + $scope.paragraph.results = {}; + $scope.paragraph.results.msg = []; + $scope.originalText = ''; + $scope.editor = null; // transactional info for spell execution $scope.spellTransaction = { @@ -49,161 +49,161 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca propagated: false, resultsMsg: [], paragraphText: '', - } + }; - let searchRanges = [] + let searchRanges = []; const getCurrentRangeDefault = function() { - return {id: -1, markerId: -1} - } - let currentRange = getCurrentRangeDefault() + return {id: -1, markerId: -1}; + }; + let currentRange = getCurrentRangeDefault(); - let editorSetting = {} + let editorSetting = {}; // flag that is used to set editor setting on paste percent sign - let pastePercentSign = false + let pastePercentSign = false; // flag that is used to set editor setting on save interpreter bindings - let setInterpreterBindings = false - let paragraphScope = $rootScope.$new(true, $rootScope) + let setInterpreterBindings = false; + let paragraphScope = $rootScope.$new(true, $rootScope); // to keep backward compatibility - $scope.compiledScope = paragraphScope + $scope.compiledScope = paragraphScope; paragraphScope.z = { // z.runParagraph('20150213-231621_168813393') - runParagraph: function (paragraphId) { + runParagraph: function(paragraphId) { if (paragraphId) { - let filtered = $scope.parentNote.paragraphs.filter(function (x) { - return x.id === paragraphId - }) + let filtered = $scope.parentNote.paragraphs.filter(function(x) { + return x.id === paragraphId; + }); if (filtered.length === 1) { - let paragraph = filtered[0] + let paragraph = filtered[0]; websocketMsgSrv.runParagraph(paragraph.id, paragraph.title, paragraph.text, - paragraph.config, paragraph.settings.params) + paragraph.config, paragraph.settings.params); } else { ngToast.danger({ content: 'Cannot find a paragraph with id \'' + paragraphId + '\'', verticalPosition: 'top', - dismissOnTimeout: false - }) + dismissOnTimeout: false, + }); } } else { ngToast.danger({ content: 'Please provide a \'paragraphId\' when calling z.runParagraph(paragraphId)', verticalPosition: 'top', - dismissOnTimeout: false - }) + dismissOnTimeout: false, + }); } }, // Example: z.angularBind('my_var', 'Test Value', '20150213-231621_168813393') - angularBind: function (varName, value, paragraphId) { + angularBind: function(varName, value, paragraphId) { // Only push to server if there paragraphId is defined if (paragraphId) { - websocketMsgSrv.clientBindAngularObject($routeParams.noteId, varName, value, paragraphId) + websocketMsgSrv.clientBindAngularObject($routeParams.noteId, varName, value, paragraphId); } else { ngToast.danger({ content: 'Please provide a \'paragraphId\' when calling ' + 'z.angularBind(varName, value, \'PUT_HERE_PARAGRAPH_ID\')', verticalPosition: 'top', - dismissOnTimeout: false - }) + dismissOnTimeout: false, + }); } }, // Example: z.angularUnBind('my_var', '20150213-231621_168813393') - angularUnbind: function (varName, paragraphId) { + angularUnbind: function(varName, paragraphId) { // Only push to server if paragraphId is defined if (paragraphId) { - websocketMsgSrv.clientUnbindAngularObject($routeParams.noteId, varName, paragraphId) + websocketMsgSrv.clientUnbindAngularObject($routeParams.noteId, varName, paragraphId); } else { ngToast.danger({ content: 'Please provide a \'paragraphId\' when calling ' + 'z.angularUnbind(varName, \'PUT_HERE_PARAGRAPH_ID\')', verticalPosition: 'top', - dismissOnTimeout: false}) + dismissOnTimeout: false}); } - } - } + }, + }; - let angularObjectRegistry = {} + let angularObjectRegistry = {}; // Controller init - $scope.init = function (newParagraph, note) { - $scope.paragraph = newParagraph - $scope.parentNote = note - $scope.originalText = angular.copy(newParagraph.text) - $scope.chart = {} - $scope.baseMapOption = ['Streets', 'Satellite', 'Hybrid', 'Topo', 'Gray', 'Oceans', 'Terrain'] - $scope.colWidthOption = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - $scope.fontSizeOption = [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] - $scope.paragraphFocused = false + $scope.init = function(newParagraph, note) { + $scope.paragraph = newParagraph; + $scope.parentNote = note; + $scope.originalText = angular.copy(newParagraph.text); + $scope.chart = {}; + $scope.baseMapOption = ['Streets', 'Satellite', 'Hybrid', 'Topo', 'Gray', 'Oceans', 'Terrain']; + $scope.colWidthOption = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + $scope.fontSizeOption = [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; + $scope.paragraphFocused = false; if (newParagraph.focus) { - $scope.paragraphFocused = true + $scope.paragraphFocused = true; } if (!$scope.paragraph.config) { - $scope.paragraph.config = {} + $scope.paragraph.config = {}; } - noteVarShareService.put($scope.paragraph.id + '_paragraphScope', paragraphScope) + noteVarShareService.put($scope.paragraph.id + '_paragraphScope', paragraphScope); - initializeDefault($scope.paragraph.config) - } + initializeDefault($scope.paragraph.config); + }; - const initializeDefault = function (config) { - let forms = $scope.paragraph.settings.forms + const initializeDefault = function(config) { + let forms = $scope.paragraph.settings.forms; if (!config.colWidth) { - config.colWidth = 12 + config.colWidth = 12; } if (!config.fontSize) { - config.fontSize = 9 + config.fontSize = 9; } if (config.enabled === undefined) { - config.enabled = true + config.enabled = true; } for (let idx in forms) { if (forms[idx]) { if (forms[idx].options) { if (config.runOnSelectionChange === undefined) { - config.runOnSelectionChange = true + config.runOnSelectionChange = true; } } } } if (!config.results) { - config.results = {} + config.results = {}; } if (!config.editorSetting) { - config.editorSetting = {} + config.editorSetting = {}; } else if (config.editorSetting.editOnDblClick) { - editorSetting.isOutputHidden = config.editorSetting.editOnDblClick + editorSetting.isOutputHidden = config.editorSetting.editOnDblClick; } - } + }; const isTabCompletion = function() { - const completionKey = $scope.paragraph.config.editorSetting.completionKey - return completionKey === 'TAB' - } + const completionKey = $scope.paragraph.config.editorSetting.completionKey; + return completionKey === 'TAB'; + }; - $scope.$on('updateParagraphOutput', function (event, data) { + $scope.$on('updateParagraphOutput', function(event, data) { if ($scope.paragraph.id === data.paragraphId) { if (!$scope.paragraph.results) { - $scope.paragraph.results = {} + $scope.paragraph.results = {}; } if (!$scope.paragraph.results.msg) { - $scope.paragraph.results.msg = [] + $scope.paragraph.results.msg = []; } - let update = ($scope.paragraph.results.msg[data.index]) ? true : false + let update = ($scope.paragraph.results.msg[data.index]) ? true : false; $scope.paragraph.results.msg[data.index] = { data: data.data, - type: data.type - } + type: data.type, + }; if (update) { $rootScope.$broadcast( @@ -211,62 +211,62 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca $scope.paragraph.results.msg[data.index], $scope.paragraph.config.results[data.index], $scope.paragraph, - data.index) + data.index); } } - }) + }); - $scope.getIframeDimensions = function () { + $scope.getIframeDimensions = function() { if ($scope.asIframe) { - let paragraphid = '#' + $routeParams.paragraphId + '_container' - let height = angular.element(paragraphid).height() - return height + let paragraphid = '#' + $routeParams.paragraphId + '_container'; + let height = angular.element(paragraphid).height(); + return height; } - return 0 - } + return 0; + }; - $scope.$watch($scope.getIframeDimensions, function (newValue, oldValue) { + $scope.$watch($scope.getIframeDimensions, function(newValue, oldValue) { if ($scope.asIframe && newValue) { - let message = {} - message.height = newValue - message.url = $location.$$absUrl - $window.parent.postMessage(angular.toJson(message), '*') + let message = {}; + message.height = newValue; + message.url = $location.$$absUrl; + $window.parent.postMessage(angular.toJson(message), '*'); } - }) + }); - $scope.getEditor = function () { - return $scope.editor - } + $scope.getEditor = function() { + return $scope.editor; + }; - $scope.$watch($scope.getEditor, function (newValue, oldValue) { + $scope.$watch($scope.getEditor, function(newValue, oldValue) { if (!$scope.editor) { - return + return; } if (newValue === null || newValue === undefined) { - console.log('editor isnt loaded yet, returning') - return + console.log('editor isnt loaded yet, returning'); + return; } if ($scope.revisionView === true) { - $scope.editor.setReadOnly(true) + $scope.editor.setReadOnly(true); } else { - $scope.editor.setReadOnly(false) + $scope.editor.setReadOnly(false); } - }) + }); - let isEmpty = function (object) { - return !object - } + let isEmpty = function(object) { + return !object; + }; - $scope.isRunning = function (paragraph) { - return isParagraphRunning(paragraph) - } + $scope.isRunning = function(paragraph) { + return isParagraphRunning(paragraph); + }; - $scope.cancelParagraph = function (paragraph) { - console.log('Cancel %o', paragraph.id) - websocketMsgSrv.cancelParagraphRun(paragraph.id) - } + $scope.cancelParagraph = function(paragraph) { + console.log('Cancel %o', paragraph.id); + websocketMsgSrv.cancelParagraphRun(paragraph.id); + }; - $scope.propagateSpellResult = function (paragraphId, paragraphTitle, + $scope.propagateSpellResult = function(paragraphId, paragraphTitle, paragraphText, paragraphResults, paragraphStatus, paragraphErrorMessage, paragraphConfig, paragraphSettingsParam, @@ -277,18 +277,18 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca paragraphStatus, paragraphErrorMessage, paragraphConfig, paragraphSettingsParam, paragraphDateStarted, paragraphDateFinished - ) - } + ); + }; - $scope.handleSpellError = function (paragraphText, error, + $scope.handleSpellError = function(paragraphText, error, digestRequired, propagated) { - const errorMessage = error.stack - $scope.paragraph.status = ParagraphStatus.ERROR - $scope.paragraph.errorMessage = errorMessage - console.error('Failed to execute interpret() in spell\n', error) + const errorMessage = error.stack; + $scope.paragraph.status = ParagraphStatus.ERROR; + $scope.paragraph.errorMessage = errorMessage; + console.error('Failed to execute interpret() in spell\n', error); if (!propagated) { - $scope.paragraph.dateFinished = $scope.getFormattedParagraphTime() + $scope.paragraph.dateFinished = $scope.getFormattedParagraphTime(); } if (!propagated) { @@ -296,547 +296,551 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca $scope.paragraph.id, $scope.paragraph.title, paragraphText, [], $scope.paragraph.status, errorMessage, $scope.paragraph.config, $scope.paragraph.settings.params, - $scope.paragraph.dateStarted, $scope.paragraph.dateFinished) + $scope.paragraph.dateStarted, $scope.paragraph.dateFinished); } - } + }; - $scope.prepareSpellTransaction = function (resultsMsg, propagated, paragraphText) { - $scope.spellTransaction.totalResultCount = resultsMsg.length - $scope.spellTransaction.renderedResultCount = 0 - $scope.spellTransaction.propagated = propagated - $scope.spellTransaction.resultsMsg = resultsMsg - $scope.spellTransaction.paragraphText = paragraphText - } + $scope.prepareSpellTransaction = function(resultsMsg, propagated, paragraphText) { + $scope.spellTransaction.totalResultCount = resultsMsg.length; + $scope.spellTransaction.renderedResultCount = 0; + $scope.spellTransaction.propagated = propagated; + $scope.spellTransaction.resultsMsg = resultsMsg; + $scope.spellTransaction.paragraphText = paragraphText; + }; /** * - update spell transaction count and * - check transaction is finished based on the result count * @returns {boolean} */ - $scope.increaseSpellTransactionResultCount = function () { - $scope.spellTransaction.renderedResultCount += 1 + $scope.increaseSpellTransactionResultCount = function() { + $scope.spellTransaction.renderedResultCount += 1; - const total = $scope.spellTransaction.totalResultCount - const current = $scope.spellTransaction.renderedResultCount - return total === current - } + const total = $scope.spellTransaction.totalResultCount; + const current = $scope.spellTransaction.renderedResultCount; + return total === current; + }; - $scope.cleanupSpellTransaction = function () { - const status = ParagraphStatus.FINISHED - $scope.paragraph.executor = ParagraphExecutor.NONE - $scope.paragraph.status = status - $scope.paragraph.results.code = status + $scope.cleanupSpellTransaction = function() { + const status = ParagraphStatus.FINISHED; + $scope.paragraph.executor = ParagraphExecutor.NONE; + $scope.paragraph.status = status; + $scope.paragraph.results.code = status; - const propagated = $scope.spellTransaction.propagated - const resultsMsg = $scope.spellTransaction.resultsMsg - const paragraphText = $scope.spellTransaction.paragraphText + const propagated = $scope.spellTransaction.propagated; + const resultsMsg = $scope.spellTransaction.resultsMsg; + const paragraphText = $scope.spellTransaction.paragraphText; if (!propagated) { - $scope.paragraph.dateFinished = $scope.getFormattedParagraphTime() + $scope.paragraph.dateFinished = $scope.getFormattedParagraphTime(); } if (!propagated) { - const propagable = SpellResult.createPropagable(resultsMsg) + const propagable = SpellResult.createPropagable(resultsMsg); $scope.propagateSpellResult( $scope.paragraph.id, $scope.paragraph.title, paragraphText, propagable, status, '', $scope.paragraph.config, $scope.paragraph.settings.params, - $scope.paragraph.dateStarted, $scope.paragraph.dateFinished) + $scope.paragraph.dateStarted, $scope.paragraph.dateFinished); } - } + }; - $scope.runParagraphUsingSpell = function (paragraphText, + $scope.runParagraphUsingSpell = function(paragraphText, magic, digestRequired, propagated) { - $scope.paragraph.status = 'RUNNING' - $scope.paragraph.executor = ParagraphExecutor.SPELL - $scope.paragraph.results = {} - $scope.paragraph.errorMessage = '' - if (digestRequired) { $scope.$digest() } + $scope.paragraph.status = 'RUNNING'; + $scope.paragraph.executor = ParagraphExecutor.SPELL; + $scope.paragraph.results = {}; + $scope.paragraph.errorMessage = ''; + if (digestRequired) { + $scope.$digest(); + } try { // remove magic from paragraphText - const splited = paragraphText.split(magic) + const splited = paragraphText.split(magic); // remove leading spaces - const textWithoutMagic = splited[1].replace(/^\s+/g, '') + const textWithoutMagic = splited[1].replace(/^\s+/g, ''); if (!propagated) { - $scope.paragraph.dateStarted = $scope.getFormattedParagraphTime() + $scope.paragraph.dateStarted = $scope.getFormattedParagraphTime(); } // handle actual result message in promise heliumService.executeSpell(magic, textWithoutMagic) - .then(resultsMsg => { - $scope.prepareSpellTransaction(resultsMsg, propagated, paragraphText) + .then((resultsMsg) => { + $scope.prepareSpellTransaction(resultsMsg, propagated, paragraphText); - $scope.paragraph.results.msg = resultsMsg - $scope.paragraph.config.tableHide = false + $scope.paragraph.results.msg = resultsMsg; + $scope.paragraph.config.tableHide = false; }) - .catch(error => { + .catch((error) => { $scope.handleSpellError(paragraphText, error, - digestRequired, propagated) - }) + digestRequired, propagated); + }); } catch (error) { $scope.handleSpellError(paragraphText, error, - digestRequired, propagated) + digestRequired, propagated); } - } + }; - $scope.runParagraphUsingBackendInterpreter = function (paragraphText) { + $scope.runParagraphUsingBackendInterpreter = function(paragraphText) { websocketMsgSrv.runParagraph($scope.paragraph.id, $scope.paragraph.title, - paragraphText, $scope.paragraph.config, $scope.paragraph.settings.params) - } + paragraphText, $scope.paragraph.config, $scope.paragraph.settings.params); + }; - $scope.bindBeforeUnload = function () { - angular.element(window).off('beforeunload') + $scope.bindBeforeUnload = function() { + angular.element(window).off('beforeunload'); - let confirmOnPageExit = function (e) { + let confirmOnPageExit = function(e) { // If we haven't been passed the event get the window.event - e = e || window.event - let message = 'Do you want to reload this site?' + e = e || window.event; + let message = 'Do you want to reload this site?'; // For IE6-8 and Firefox prior to version 4 if (e) { - e.returnValue = message + e.returnValue = message; } // For Chrome, Safari, IE8+ and Opera 12+ - return message - } - angular.element(window).on('beforeunload', confirmOnPageExit) - } + return message; + }; + angular.element(window).on('beforeunload', confirmOnPageExit); + }; - $scope.unBindBeforeUnload = function () { - angular.element(window).off('beforeunload') - } + $scope.unBindBeforeUnload = function() { + angular.element(window).off('beforeunload'); + }; - $scope.saveParagraph = function (paragraph) { - const dirtyText = paragraph.text + $scope.saveParagraph = function(paragraph) { + const dirtyText = paragraph.text; if (dirtyText === undefined || dirtyText === $scope.originalText) { - return + return; } - $scope.bindBeforeUnload() + $scope.bindBeforeUnload(); - commitParagraph(paragraph).then(function () { - $scope.originalText = dirtyText - $scope.dirtyText = undefined - $scope.unBindBeforeUnload() - }) - } + commitParagraph(paragraph).then(function() { + $scope.originalText = dirtyText; + $scope.dirtyText = undefined; + $scope.unBindBeforeUnload(); + }); + }; - $scope.toggleEnableDisable = function (paragraph) { - paragraph.config.enabled = !paragraph.config.enabled - commitParagraph(paragraph) - } + $scope.toggleEnableDisable = function(paragraph) { + paragraph.config.enabled = !paragraph.config.enabled; + commitParagraph(paragraph); + }; /** * @param paragraphText to be parsed * @param digestRequired true if calling `$digest` is required * @param propagated true if update request is sent from other client */ - $scope.runParagraph = function (paragraphText, digestRequired, propagated) { + $scope.runParagraph = function(paragraphText, digestRequired, propagated) { if (!paragraphText || $scope.isRunning($scope.paragraph)) { - return + return; } - const magic = SpellResult.extractMagic(paragraphText) + const magic = SpellResult.extractMagic(paragraphText); if (heliumService.getSpellByMagic(magic)) { - $scope.runParagraphUsingSpell(paragraphText, magic, digestRequired, propagated) + $scope.runParagraphUsingSpell(paragraphText, magic, digestRequired, propagated); } else { - $scope.runParagraphUsingBackendInterpreter(paragraphText) + $scope.runParagraphUsingBackendInterpreter(paragraphText); } - $scope.originalText = angular.copy(paragraphText) - $scope.dirtyText = undefined + $scope.originalText = angular.copy(paragraphText); + $scope.dirtyText = undefined; if ($scope.paragraph.config.editorSetting.editOnDblClick) { - closeEditorAndOpenTable($scope.paragraph) + closeEditorAndOpenTable($scope.paragraph); } else if (editorSetting.isOutputHidden && !$scope.paragraph.config.editorSetting.editOnDblClick) { // %md/%angular repl make output to be hidden by default after running // so should open output if repl changed from %md/%angular to another - openEditorAndOpenTable($scope.paragraph) + openEditorAndOpenTable($scope.paragraph); } - editorSetting.isOutputHidden = $scope.paragraph.config.editorSetting.editOnDblClick - } + editorSetting.isOutputHidden = $scope.paragraph.config.editorSetting.editOnDblClick; + }; - $scope.runParagraphFromShortcut = function (paragraphText) { + $scope.runParagraphFromShortcut = function(paragraphText) { // passing `digestRequired` as true to update view immediately // without this, results cannot be rendered in view more than once - $scope.runParagraph(paragraphText, true, false) - } + $scope.runParagraph(paragraphText, true, false); + }; - $scope.runParagraphFromButton = function () { + $scope.runParagraphFromButton = function() { // we come here from the view, so we don't need to call `$digest()` - $scope.runParagraph($scope.getEditorValue(), false, false) - } + $scope.runParagraph($scope.getEditorValue(), false, false); + }; $scope.runAllToThis = function(paragraph) { - $scope.$emit('runAllAbove', paragraph, true) - } + $scope.$emit('runAllAbove', paragraph, true); + }; $scope.runAllFromThis = function(paragraph) { - $scope.$emit('runAllBelowAndCurrent', paragraph, true) - } + $scope.$emit('runAllBelowAndCurrent', paragraph, true); + }; - $scope.runAllToOrFromThis = function (paragraph) { + $scope.runAllToOrFromThis = function(paragraph) { BootstrapDialog.show({ message: 'Run paragraphs:', title: '', buttons: [{ label: 'Close', action: function(dialog) { - dialog.close() - } + dialog.close(); + }, }, { label: 'Run all above', cssClass: 'btn-primary', action: function(dialog) { - $scope.$emit('runAllAbove', paragraph, false) - dialog.close() - } + $scope.$emit('runAllAbove', paragraph, false); + dialog.close(); + }, }, { label: 'Run current and all below', cssClass: 'btn-primary', action: function(dialog) { - $scope.$emit('runAllBelowAndCurrent', paragraph, false) - dialog.close() - } - }] - }) - } + $scope.$emit('runAllBelowAndCurrent', paragraph, false); + dialog.close(); + }, + }], + }); + }; - $scope.turnOnAutoRun = function (paragraph) { - paragraph.config.runOnSelectionChange = !paragraph.config.runOnSelectionChange - commitParagraph(paragraph) - } + $scope.turnOnAutoRun = function(paragraph) { + paragraph.config.runOnSelectionChange = !paragraph.config.runOnSelectionChange; + commitParagraph(paragraph); + }; - $scope.moveUp = function (paragraph) { - $scope.$emit('moveParagraphUp', paragraph) - } + $scope.moveUp = function(paragraph) { + $scope.$emit('moveParagraphUp', paragraph); + }; - $scope.moveDown = function (paragraph) { - $scope.$emit('moveParagraphDown', paragraph) - } + $scope.moveDown = function(paragraph) { + $scope.$emit('moveParagraphDown', paragraph); + }; - $scope.insertNew = function (position) { - $scope.$emit('insertParagraph', $scope.paragraph.id, position) - } + $scope.insertNew = function(position) { + $scope.$emit('insertParagraph', $scope.paragraph.id, position); + }; - $scope.copyPara = function (position) { - let editorValue = $scope.getEditorValue() + $scope.copyPara = function(position) { + let editorValue = $scope.getEditorValue(); if (editorValue) { - $scope.copyParagraph(editorValue, position) + $scope.copyParagraph(editorValue, position); } - } + }; - $scope.copyParagraph = function (data, position) { - let newIndex = -1 + $scope.copyParagraph = function(data, position) { + let newIndex = -1; for (let i = 0; i < $scope.note.paragraphs.length; i++) { if ($scope.note.paragraphs[i].id === $scope.paragraph.id) { // determine position of where to add new paragraph; default is below if (position === 'above') { - newIndex = i + newIndex = i; } else { - newIndex = i + 1 + newIndex = i + 1; } - break + break; } } if (newIndex < 0 || newIndex > $scope.note.paragraphs.length) { - return + return; } - let config = angular.copy($scope.paragraph.config) - config.editorHide = false + let config = angular.copy($scope.paragraph.config); + config.editorHide = false; websocketMsgSrv.copyParagraph(newIndex, $scope.paragraph.title, data, - config, $scope.paragraph.settings.params) - } + config, $scope.paragraph.settings.params); + }; - $scope.removeParagraph = function (paragraph) { + $scope.removeParagraph = function(paragraph) { if ($scope.note.paragraphs.length === 1) { BootstrapDialog.alert({ closable: true, - message: 'All the paragraphs can\'t be deleted.' - }) + message: 'All the paragraphs can\'t be deleted.', + }); } else { BootstrapDialog.confirm({ closable: true, title: '', message: 'Do you want to delete this paragraph?', - callback: function (result) { + callback: function(result) { if (result) { - console.log('Remove paragraph') - websocketMsgSrv.removeParagraph(paragraph.id) - $scope.$emit('moveFocusToNextParagraph', $scope.paragraph.id) + console.log('Remove paragraph'); + websocketMsgSrv.removeParagraph(paragraph.id); + $scope.$emit('moveFocusToNextParagraph', $scope.paragraph.id); } - } - }) + }, + }); } - } + }; - $scope.clearParagraphOutput = function (paragraph) { - websocketMsgSrv.clearParagraphOutput(paragraph.id) - } + $scope.clearParagraphOutput = function(paragraph) { + websocketMsgSrv.clearParagraphOutput(paragraph.id); + }; - $scope.toggleEditor = function (paragraph) { + $scope.toggleEditor = function(paragraph) { if (paragraph.config.editorHide) { - $scope.openEditor(paragraph) + $scope.openEditor(paragraph); } else { - $scope.closeEditor(paragraph) - } - } - - $scope.closeEditor = function (paragraph) { - console.log('close the note') - paragraph.config.editorHide = true - commitParagraph(paragraph) - } - - $scope.openEditor = function (paragraph) { - console.log('open the note') - paragraph.config.editorHide = false - commitParagraph(paragraph) - } - - $scope.closeTable = function (paragraph) { - console.log('close the output') - paragraph.config.tableHide = true - commitParagraph(paragraph) - } - - $scope.openTable = function (paragraph) { - console.log('open the output') - paragraph.config.tableHide = false - commitParagraph(paragraph) - } - - let openEditorAndCloseTable = function (paragraph) { - manageEditorAndTableState(paragraph, false, true) - } - - const closeEditorAndOpenTable = function (paragraph) { - manageEditorAndTableState(paragraph, true, false) - } - - const openEditorAndOpenTable = function (paragraph) { - manageEditorAndTableState(paragraph, false, false) - } - - const manageEditorAndTableState = function (paragraph, hideEditor, hideTable) { - paragraph.config.editorHide = hideEditor - paragraph.config.tableHide = hideTable - commitParagraph(paragraph) - } - - $scope.showTitle = function (paragraph) { - paragraph.config.title = true - commitParagraph(paragraph) - } - - $scope.hideTitle = function (paragraph) { - paragraph.config.title = false - commitParagraph(paragraph) - } - - $scope.setTitle = function (paragraph) { - commitParagraph(paragraph) - } - - $scope.showLineNumbers = function (paragraph) { + $scope.closeEditor(paragraph); + } + }; + + $scope.closeEditor = function(paragraph) { + console.log('close the note'); + paragraph.config.editorHide = true; + commitParagraph(paragraph); + }; + + $scope.openEditor = function(paragraph) { + console.log('open the note'); + paragraph.config.editorHide = false; + commitParagraph(paragraph); + }; + + $scope.closeTable = function(paragraph) { + console.log('close the output'); + paragraph.config.tableHide = true; + commitParagraph(paragraph); + }; + + $scope.openTable = function(paragraph) { + console.log('open the output'); + paragraph.config.tableHide = false; + commitParagraph(paragraph); + }; + + let openEditorAndCloseTable = function(paragraph) { + manageEditorAndTableState(paragraph, false, true); + }; + + const closeEditorAndOpenTable = function(paragraph) { + manageEditorAndTableState(paragraph, true, false); + }; + + const openEditorAndOpenTable = function(paragraph) { + manageEditorAndTableState(paragraph, false, false); + }; + + const manageEditorAndTableState = function(paragraph, hideEditor, hideTable) { + paragraph.config.editorHide = hideEditor; + paragraph.config.tableHide = hideTable; + commitParagraph(paragraph); + }; + + $scope.showTitle = function(paragraph) { + paragraph.config.title = true; + commitParagraph(paragraph); + }; + + $scope.hideTitle = function(paragraph) { + paragraph.config.title = false; + commitParagraph(paragraph); + }; + + $scope.setTitle = function(paragraph) { + commitParagraph(paragraph); + }; + + $scope.showLineNumbers = function(paragraph) { if ($scope.editor) { - paragraph.config.lineNumbers = true - $scope.editor.renderer.setShowGutter(true) - commitParagraph(paragraph) + paragraph.config.lineNumbers = true; + $scope.editor.renderer.setShowGutter(true); + commitParagraph(paragraph); } - } + }; - $scope.hideLineNumbers = function (paragraph) { + $scope.hideLineNumbers = function(paragraph) { if ($scope.editor) { - paragraph.config.lineNumbers = false - $scope.editor.renderer.setShowGutter(false) - commitParagraph(paragraph) + paragraph.config.lineNumbers = false; + $scope.editor.renderer.setShowGutter(false); + commitParagraph(paragraph); } - } + }; - $scope.columnWidthClass = function (n) { + $scope.columnWidthClass = function(n) { if ($scope.asIframe) { - return 'col-md-12' + return 'col-md-12'; } else { - return 'paragraph-col col-md-' + n + return 'paragraph-col col-md-' + n; } - } + }; - $scope.changeColWidth = function (paragraph, width) { - angular.element('.navbar-right.open').removeClass('open') - paragraph.config.colWidth = width - $scope.$broadcast('paragraphResized', $scope.paragraph.id) - commitParagraph(paragraph) - } + $scope.changeColWidth = function(paragraph, width) { + angular.element('.navbar-right.open').removeClass('open'); + paragraph.config.colWidth = width; + $scope.$broadcast('paragraphResized', $scope.paragraph.id); + commitParagraph(paragraph); + }; - $scope.changeFontSize = function (paragraph, fontSize) { - angular.element('.navbar-right.open').removeClass('open') + $scope.changeFontSize = function(paragraph, fontSize) { + angular.element('.navbar-right.open').removeClass('open'); if ($scope.editor) { $scope.editor.setOptions({ - fontSize: fontSize + 'pt' - }) - autoAdjustEditorHeight($scope.editor) - paragraph.config.fontSize = fontSize - commitParagraph(paragraph) - } - } - - $scope.toggleOutput = function (paragraph) { - paragraph.config.tableHide = !paragraph.config.tableHide - commitParagraph(paragraph) - } - - $scope.aceChanged = function (_, editor) { - let session = editor.getSession() - let dirtyText = session.getValue() - $scope.dirtyText = dirtyText + fontSize: fontSize + 'pt', + }); + autoAdjustEditorHeight($scope.editor); + paragraph.config.fontSize = fontSize; + commitParagraph(paragraph); + } + }; + + $scope.toggleOutput = function(paragraph) { + paragraph.config.tableHide = !paragraph.config.tableHide; + commitParagraph(paragraph); + }; + + $scope.aceChanged = function(_, editor) { + let session = editor.getSession(); + let dirtyText = session.getValue(); + $scope.dirtyText = dirtyText; if ($scope.dirtyText !== $scope.originalText) { - $scope.startSaveTimer() + $scope.startSaveTimer(); } - setParagraphMode(session, dirtyText, editor.getCursorPosition()) - } + setParagraphMode(session, dirtyText, editor.getCursorPosition()); + }; - $scope.aceLoaded = function (_editor) { - let langTools = ace.require('ace/ext/language_tools') - let Range = ace.require('ace/range').Range + $scope.aceLoaded = function(_editor) { + let langTools = ace.require('ace/ext/language_tools'); + let Range = ace.require('ace/range').Range; - _editor.$blockScrolling = Infinity - $scope.editor = _editor - $scope.editor.on('input', $scope.aceChanged) + _editor.$blockScrolling = Infinity; + $scope.editor = _editor; + $scope.editor.on('input', $scope.aceChanged); if (_editor.container.id !== '{{paragraph.id}}_editor') { - $scope.editor.renderer.setShowGutter($scope.paragraph.config.lineNumbers) - $scope.editor.setShowFoldWidgets(false) - $scope.editor.setHighlightActiveLine(false) - $scope.editor.getSession().setUseWrapMode(true) - $scope.editor.setTheme('ace/theme/chrome') - $scope.editor.setReadOnly($scope.isRunning($scope.paragraph)) - $scope.editor.setHighlightActiveLine($scope.paragraphFocused) + $scope.editor.renderer.setShowGutter($scope.paragraph.config.lineNumbers); + $scope.editor.setShowFoldWidgets(false); + $scope.editor.setHighlightActiveLine(false); + $scope.editor.getSession().setUseWrapMode(true); + $scope.editor.setTheme('ace/theme/chrome'); + $scope.editor.setReadOnly($scope.isRunning($scope.paragraph)); + $scope.editor.setHighlightActiveLine($scope.paragraphFocused); if ($scope.paragraphFocused) { - let prefix = '%' + getInterpreterName($scope.paragraph.text) - let paragraphText = $scope.paragraph.text ? $scope.paragraph.text.trim() : '' + let prefix = '%' + getInterpreterName($scope.paragraph.text); + let paragraphText = $scope.paragraph.text ? $scope.paragraph.text.trim() : ''; - $scope.editor.focus() - $scope.goToEnd($scope.editor) + $scope.editor.focus(); + $scope.goToEnd($scope.editor); if (prefix === paragraphText) { - $timeout(function () { - $scope.editor.gotoLine(2, 0) - }, 0) + $timeout(function() { + $scope.editor.gotoLine(2, 0); + }, 0); } } - autoAdjustEditorHeight(_editor) - angular.element(window).resize(function () { - autoAdjustEditorHeight(_editor) - }) + autoAdjustEditorHeight(_editor); + angular.element(window).resize(function() { + autoAdjustEditorHeight(_editor); + }); if (navigator.appVersion.indexOf('Mac') !== -1) { - $scope.editor.setKeyboardHandler('ace/keyboard/emacs') - $rootScope.isMac = true + $scope.editor.setKeyboardHandler('ace/keyboard/emacs'); + $rootScope.isMac = true; } else if (navigator.appVersion.indexOf('Win') !== -1 || navigator.appVersion.indexOf('X11') !== -1 || navigator.appVersion.indexOf('Linux') !== -1) { - $rootScope.isMac = false + $rootScope.isMac = false; // not applying emacs key binding while the binding override Ctrl-v. default behavior of paste text on windows. } let remoteCompleter = { getCompletions: function(editor, session, pos, prefix, callback) { - let langTools = ace.require('ace/ext/language_tools') - let defaultKeywords = new Set() + let langTools = ace.require('ace/ext/language_tools'); + let defaultKeywords = new Set(); // eslint-disable-next-line handle-callback-err let getDefaultKeywords = function(err, completions) { if (completions !== undefined) { completions.forEach(function(c) { - defaultKeywords.add(c.value) - }) + defaultKeywords.add(c.value); + }); } - } + }; if (langTools.keyWordCompleter !== undefined) { - langTools.keyWordCompleter.getCompletions(editor, session, pos, prefix, getDefaultKeywords) + langTools.keyWordCompleter.getCompletions(editor, session, pos, prefix, getDefaultKeywords); } if (!editor.isFocused()) { - return + return; } - pos = session.getTextRange(new Range(0, 0, pos.row, pos.column)).length - let buf = session.getValue() + pos = session.getTextRange(new Range(0, 0, pos.row, pos.column)).length; + let buf = session.getValue(); - websocketMsgSrv.completion($scope.paragraph.id, buf, pos) + websocketMsgSrv.completion($scope.paragraph.id, buf, pos); $scope.$on('completionList', function(event, data) { let computeCaption = function(value, meta) { - let metaLength = meta !== undefined ? meta.length : 0 - let length = 42 - let whitespaceLength = 3 - let ellipses = '...' - let maxLengthCaption = length - metaLength - whitespaceLength - ellipses.length + let metaLength = meta !== undefined ? meta.length : 0; + let length = 42; + let whitespaceLength = 3; + let ellipses = '...'; + let maxLengthCaption = length - metaLength - whitespaceLength - ellipses.length; if (value !== undefined && value.length > maxLengthCaption) { - return value.substr(0, maxLengthCaption) + ellipses + return value.substr(0, maxLengthCaption) + ellipses; } - return value - } + return value; + }; if (data.completions) { - let completions = [] + let completions = []; for (let c in data.completions) { - let v = data.completions[c] - if (v.meta !== undefined && v.meta === 'keyword' && defaultKeywords.has(v.value.trim())) { - continue + if (data.completions.hasOwnProperty(c)) { + let v = data.completions[c]; + if (v.meta !== undefined && v.meta === 'keyword' && defaultKeywords.has(v.value.trim())) { + continue; + } + completions.push({ + name: v.name, + value: v.value, + meta: v.meta, + caption: computeCaption(v.value, v.meta), + score: 300, + }); } - completions.push({ - name: v.name, - value: v.value, - meta: v.meta, - caption: computeCaption(v.value, v.meta), - score: 300 - }) } - callback(null, completions) + callback(null, completions); } - }) - } - } + }); + }, + }; langTools.setCompleters([remoteCompleter, langTools.keyWordCompleter, langTools.snippetCompleter, - langTools.textCompleter]) + langTools.textCompleter]); $scope.editor.setOptions({ fontSize: $scope.paragraph.config.fontSize + 'pt', enableBasicAutocompletion: true, enableSnippets: false, - enableLiveAutocompletion: false - }) + enableLiveAutocompletion: false, + }); - $scope.editor.on('focus', function () { - handleFocus(true) - }) + $scope.editor.on('focus', function() { + handleFocus(true); + }); - $scope.editor.on('blur', function () { - handleFocus(false) - $scope.saveParagraph($scope.paragraph) - }) + $scope.editor.on('blur', function() { + handleFocus(false); + $scope.saveParagraph($scope.paragraph); + }); - $scope.editor.on('paste', function (e) { + $scope.editor.on('paste', function(e) { if (e.text.indexOf('%') === 0) { - pastePercentSign = true + pastePercentSign = true; } - }) + }); - $scope.editor.getSession().on('change', function (e, editSession) { - autoAdjustEditorHeight(_editor) - }) + $scope.editor.getSession().on('change', function(e, editSession) { + autoAdjustEditorHeight(_editor); + }); - setParagraphMode($scope.editor.getSession(), $scope.editor.getSession().getValue()) + setParagraphMode($scope.editor.getSession(), $scope.editor.getSession().getValue()); // autocomplete on '.' /* @@ -851,29 +855,29 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca */ // remove binding - $scope.editor.commands.removeCommand('showSettingsMenu') - $scope.editor.commands.removeCommand('find') - $scope.editor.commands.removeCommand('replace') + $scope.editor.commands.removeCommand('showSettingsMenu'); + $scope.editor.commands.removeCommand('find'); + $scope.editor.commands.removeCommand('replace'); - let isOption = $rootScope.isMac ? 'option' : 'alt' + let isOption = $rootScope.isMac ? 'option' : 'alt'; - $scope.editor.commands.bindKey('ctrl-' + isOption + '-n.', null) - $scope.editor.commands.bindKey('ctrl-' + isOption + '-l', null) - $scope.editor.commands.bindKey('ctrl-' + isOption + '-w', null) - $scope.editor.commands.bindKey('ctrl-' + isOption + '-a', null) - $scope.editor.commands.bindKey('ctrl-' + isOption + '-k', null) - $scope.editor.commands.bindKey('ctrl-' + isOption + '-e', null) - $scope.editor.commands.bindKey('ctrl-' + isOption + '-t', null) - $scope.editor.commands.bindKey('ctrl-space', null) + $scope.editor.commands.bindKey('ctrl-' + isOption + '-n.', null); + $scope.editor.commands.bindKey('ctrl-' + isOption + '-l', null); + $scope.editor.commands.bindKey('ctrl-' + isOption + '-w', null); + $scope.editor.commands.bindKey('ctrl-' + isOption + '-a', null); + $scope.editor.commands.bindKey('ctrl-' + isOption + '-k', null); + $scope.editor.commands.bindKey('ctrl-' + isOption + '-e', null); + $scope.editor.commands.bindKey('ctrl-' + isOption + '-t', null); + $scope.editor.commands.bindKey('ctrl-space', null); if ($rootScope.isMac) { - $scope.editor.commands.bindKey('command-l', null) + $scope.editor.commands.bindKey('command-l', null); } else { - $scope.editor.commands.bindKey('ctrl-l', null) + $scope.editor.commands.bindKey('ctrl-l', null); } // autocomplete on 'ctrl+.' - $scope.editor.commands.bindKey('ctrl-.', 'startAutocomplete') + $scope.editor.commands.bindKey('ctrl-.', 'startAutocomplete'); // Show autocomplete on tab $scope.editor.commands.addCommand({ @@ -881,113 +885,123 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca bindKey: { win: 'tab', mac: 'tab', - sender: 'editor|cli' + sender: 'editor|cli', }, exec: function(env, args, request) { - let iCursor = $scope.editor.getCursorPosition() - let currentLine = $scope.editor.session.getLine(iCursor.row) + let iCursor = $scope.editor.getCursorPosition(); + let currentLine = $scope.editor.session.getLine(iCursor.row); let isAllTabs = currentLine.substring(0, iCursor.column - 1).split('').every(function(char) { - return (char === '\t' || char === ' ') - }) + return (char === '\t' || char === ' '); + }); // If user has pressed tab on first line char or if isTabCompletion() is false, keep existing behavior // If user has pressed tab anywhere in between and editor mode is not %md, show autocomplete if (!isAllTabs && iCursor.column && isTabCompletion()) { - $scope.editor.execCommand('startAutocomplete') + $scope.editor.execCommand('startAutocomplete'); } else { - ace.config.loadModule('ace/ext/language_tools', function () { - $scope.editor.insertSnippet('\t') - }) + ace.config.loadModule('ace/ext/language_tools', function() { + $scope.editor.insertSnippet('\t'); + }); } - } - }) + }, + }); - let keyBindingEditorFocusAction = function (scrollValue) { - let numRows = $scope.editor.getSession().getLength() - let currentRow = $scope.editor.getCursorPosition().row + let keyBindingEditorFocusAction = function(scrollValue) { + let numRows = $scope.editor.getSession().getLength(); + let currentRow = $scope.editor.getCursorPosition().row; if (currentRow === 0 && scrollValue <= 0) { // move focus to previous paragraph - $scope.$emit('moveFocusToPreviousParagraph', $scope.paragraph.id) + $scope.$emit('moveFocusToPreviousParagraph', $scope.paragraph.id); } else if (currentRow === numRows - 1 && scrollValue >= 0) { - $scope.$emit('moveFocusToNextParagraph', $scope.paragraph.id) + $scope.$emit('moveFocusToNextParagraph', $scope.paragraph.id); } else { - $scope.scrollToCursor($scope.paragraph.id, scrollValue) + $scope.scrollToCursor($scope.paragraph.id, scrollValue); } - } + }; // handle cursor moves - $scope.editor.keyBinding.origOnCommandKey = $scope.editor.keyBinding.onCommandKey - $scope.editor.keyBinding.onCommandKey = function (e, hashId, keyCode) { + $scope.editor.keyBinding.origOnCommandKey = $scope.editor.keyBinding.onCommandKey; + $scope.editor.keyBinding.onCommandKey = function(e, hashId, keyCode) { if ($scope.editor.completer && $scope.editor.completer.activated) { // if autocompleter is active } else { // fix ace editor focus issue in chrome (textarea element goes to top: -1000px after focused by cursor move) if (parseInt(angular.element('#' + $scope.paragraph.id + '_editor > textarea') .css('top').replace('px', '')) < 0) { - let position = $scope.editor.getCursorPosition() - let cursorPos = $scope.editor.renderer.$cursorLayer.getPixelPosition(position, true) - angular.element('#' + $scope.paragraph.id + '_editor > textarea').css('top', cursorPos.top) + let position = $scope.editor.getCursorPosition(); + let cursorPos = $scope.editor.renderer.$cursorLayer.getPixelPosition(position, true); + angular.element('#' + $scope.paragraph.id + '_editor > textarea').css('top', cursorPos.top); } - let ROW_UP = -1 - let ROW_DOWN = 1 + let ROW_UP = -1; + let ROW_DOWN = 1; switch (keyCode) { case 38: - if (!e.shiftKey) { keyBindingEditorFocusAction(ROW_UP) } - break + if (!e.shiftKey) { + keyBindingEditorFocusAction(ROW_UP); + } + break; case 80: - if (e.ctrlKey && !e.altKey) { keyBindingEditorFocusAction(ROW_UP) } - break + if (e.ctrlKey && !e.altKey) { + keyBindingEditorFocusAction(ROW_UP); + } + break; case 40: - if (!e.shiftKey) { keyBindingEditorFocusAction(ROW_DOWN) } - break + if (!e.shiftKey) { + keyBindingEditorFocusAction(ROW_DOWN); + } + break; case 78: - if (e.ctrlKey && !e.altKey) { keyBindingEditorFocusAction(ROW_DOWN) } - break + if (e.ctrlKey && !e.altKey) { + keyBindingEditorFocusAction(ROW_DOWN); + } + break; } } - this.origOnCommandKey(e, hashId, keyCode) - } + this.origOnCommandKey(e, hashId, keyCode); + }; } - } + }; - const handleFocus = function (focused, isDigestPass) { - $scope.paragraphFocused = focused + const handleFocus = function(focused, isDigestPass) { + $scope.paragraphFocused = focused; - if ($scope.editor) { $scope.editor.setHighlightActiveLine(focused) } + if ($scope.editor) { + $scope.editor.setHighlightActiveLine(focused); + } if (isDigestPass === false || isDigestPass === undefined) { // Protect against error in case digest is already running - $timeout(function () { + $timeout(function() { // Apply changes since they come from 3rd party library - $scope.$digest() - }) + $scope.$digest(); + }); } - } + }; - let getEditorSetting = function (paragraph, interpreterName) { - let deferred = $q.defer() + let getEditorSetting = function(paragraph, interpreterName) { + let deferred = $q.defer(); if (!$scope.revisionView) { - websocketMsgSrv.getEditorSetting(paragraph.id, interpreterName) + websocketMsgSrv.getEditorSetting(paragraph.id, interpreterName); $timeout( - $scope.$on('editorSetting', function (event, data) { + $scope.$on('editorSetting', function(event, data) { if (paragraph.id === data.paragraphId) { - deferred.resolve(data) + deferred.resolve(data); } } - ), 1000) + ), 1000); } - return deferred.promise - } + return deferred.promise; + }; - let setEditorLanguage = function (session, language) { - let mode = 'ace/mode/' - mode += language - $scope.paragraph.config.editorMode = mode - session.setMode(mode) - } + let setEditorLanguage = function(session, language) { + let mode = 'ace/mode/'; + mode += language; + $scope.paragraph.config.editorMode = mode; + session.setMode(mode); + }; - const setParagraphMode = function (session, paragraphText, pos) { + const setParagraphMode = function(session, paragraphText, pos) { // Evaluate the mode only if the the position is undefined // or the first 30 characters of the paragraph have been modified // or cursor position is at beginning of second line.(in case user hit enter after typing %magic) @@ -996,319 +1010,321 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca // If paragraph loading, use config value if exists if ((typeof pos === 'undefined') && $scope.paragraph.config.editorMode && !setInterpreterBindings) { - session.setMode($scope.paragraph.config.editorMode) + session.setMode($scope.paragraph.config.editorMode); } else { - let magic = getInterpreterName(paragraphText) + let magic = getInterpreterName(paragraphText); if (editorSetting.magic !== magic) { - editorSetting.magic = magic + editorSetting.magic = magic; getEditorSetting($scope.paragraph, magic) - .then(function (setting) { - setEditorLanguage(session, setting.editor.language) - _.merge($scope.paragraph.config.editorSetting, setting.editor) - }) + .then(function(setting) { + setEditorLanguage(session, setting.editor.language); + _.merge($scope.paragraph.config.editorSetting, setting.editor); + }); } } } - pastePercentSign = false - setInterpreterBindings = false - } + pastePercentSign = false; + setInterpreterBindings = false; + }; const getInterpreterName = function(paragraphText) { - let intpNameRegexp = /^\s*%(.+?)(\s|\()/g - let match = intpNameRegexp.exec(paragraphText) + let intpNameRegexp = /^\s*%(.+?)(\s|\()/g; + let match = intpNameRegexp.exec(paragraphText); if (match) { - return match[1].trim() + return match[1].trim(); // get default interpreter name if paragraph text doesn't start with '%' // TODO(mina): dig into the cause what makes interpreterBindings to have no element } else if ($scope.$parent.interpreterBindings && $scope.$parent.interpreterBindings.length !== 0) { - return $scope.$parent.interpreterBindings[0].name + return $scope.$parent.interpreterBindings[0].name; } - return '' - } + return ''; + }; - const autoAdjustEditorHeight = function (editor) { + const autoAdjustEditorHeight = function(editor) { let height = editor.getSession().getScreenLength() * - editor.renderer.lineHeight + editor.renderer.lineHeight; - angular.element('#' + editor.container.id).height(height.toString() + 'px') - editor.resize() - } + angular.element('#' + editor.container.id).height(height.toString() + 'px'); + editor.resize(); + }; - $rootScope.$on('scrollToCursor', function (event) { + $rootScope.$on('scrollToCursor', function(event) { // scroll on 'scrollToCursor' event only when cursor is in the last paragraph - let paragraphs = angular.element('div[id$="_paragraphColumn_main"]') + let paragraphs = angular.element('div[id$="_paragraphColumn_main"]'); if (paragraphs[paragraphs.length - 1].id.indexOf($scope.paragraph.id) === 0) { - $scope.scrollToCursor($scope.paragraph.id, 0) + $scope.scrollToCursor($scope.paragraph.id, 0); } - }) + }); /** scrollToCursor if it is necessary * when cursor touches scrollTriggerEdgeMargin from the top (or bottom) of the screen, it autoscroll to place cursor around 1/3 of screen height from the top (or bottom) * paragraphId : paragraph that has active cursor * lastCursorMove : 1(down), 0, -1(up) last cursor move event **/ - $scope.scrollToCursor = function (paragraphId, lastCursorMove) { + $scope.scrollToCursor = function(paragraphId, lastCursorMove) { if (!$scope.editor || !$scope.editor.isFocused()) { // only make sense when editor is focused - return + return; } - let lineHeight = $scope.editor.renderer.lineHeight - let headerHeight = 103 // menubar, notebook titlebar - let scrollTriggerEdgeMargin = 50 + let lineHeight = $scope.editor.renderer.lineHeight; + let headerHeight = 103; // menubar, notebook titlebar + let scrollTriggerEdgeMargin = 50; - let documentHeight = angular.element(document).height() - let windowHeight = angular.element(window).height() // actual viewport height + let documentHeight = angular.element(document).height(); + let windowHeight = angular.element(window).height(); // actual viewport height - let scrollPosition = angular.element(document).scrollTop() - let editorPosition = angular.element('#' + paragraphId + '_editor').offset() - let position = $scope.editor.getCursorPosition() - let lastCursorPosition = $scope.editor.renderer.$cursorLayer.getPixelPosition(position, true) + let scrollPosition = angular.element(document).scrollTop(); + let editorPosition = angular.element('#' + paragraphId + '_editor').offset(); + let position = $scope.editor.getCursorPosition(); + let lastCursorPosition = $scope.editor.renderer.$cursorLayer.getPixelPosition(position, true); - let calculatedCursorPosition = editorPosition.top + lastCursorPosition.top + lineHeight * lastCursorMove + let calculatedCursorPosition = editorPosition.top + lastCursorPosition.top + lineHeight * lastCursorMove; - let scrollTargetPos + let scrollTargetPos; if (calculatedCursorPosition < scrollPosition + headerHeight + scrollTriggerEdgeMargin) { - scrollTargetPos = calculatedCursorPosition - headerHeight - ((windowHeight - headerHeight) / 3) + scrollTargetPos = calculatedCursorPosition - headerHeight - ((windowHeight - headerHeight) / 3); if (scrollTargetPos < 0) { - scrollTargetPos = 0 + scrollTargetPos = 0; } } else if (calculatedCursorPosition > scrollPosition + scrollTriggerEdgeMargin + windowHeight - headerHeight) { - scrollTargetPos = calculatedCursorPosition - headerHeight - ((windowHeight - headerHeight) * 2 / 3) + scrollTargetPos = calculatedCursorPosition - headerHeight - ((windowHeight - headerHeight) * 2 / 3); if (scrollTargetPos > documentHeight) { - scrollTargetPos = documentHeight + scrollTargetPos = documentHeight; } } // cancel previous scroll animation - let bodyEl = angular.element('body') - bodyEl.stop() - bodyEl.finish() + let bodyEl = angular.element('body'); + bodyEl.stop(); + bodyEl.finish(); // scroll to scrollTargetPos - bodyEl.scrollTo(scrollTargetPos, {axis: 'y', interrupt: true, duration: 100}) - } + bodyEl.scrollTo(scrollTargetPos, {axis: 'y', interrupt: true, duration: 100}); + }; - $scope.getEditorValue = function () { - return !$scope.editor ? $scope.paragraph.text : $scope.editor.getValue() - } + $scope.getEditorValue = function() { + return !$scope.editor ? $scope.paragraph.text : $scope.editor.getValue(); + }; - $scope.getProgress = function () { - return $scope.currentProgress || 0 - } + $scope.getProgress = function() { + return $scope.currentProgress || 0; + }; $scope.getFormattedParagraphTime = () => { - return moment().toISOString() - } + return moment().toISOString(); + }; - $scope.getExecutionTime = function (pdata) { - const end = pdata.dateFinished - const start = pdata.dateStarted - let timeMs = Date.parse(end) - Date.parse(start) + $scope.getExecutionTime = function(pdata) { + const end = pdata.dateFinished; + const start = pdata.dateStarted; + let timeMs = Date.parse(end) - Date.parse(start); if (isNaN(timeMs) || timeMs < 0) { if ($scope.isResultOutdated(pdata)) { - return 'outdated' + return 'outdated'; } - return '' + return ''; } - const durationFormat = moment.duration((timeMs / 1000), 'seconds').format('h [hrs] m [min] s [sec]') - const endFormat = moment(pdata.dateFinished).format('MMMM DD YYYY, h:mm:ss A') + const durationFormat = moment.duration((timeMs / 1000), 'seconds').format('h [hrs] m [min] s [sec]'); + const endFormat = moment(pdata.dateFinished).format('MMMM DD YYYY, h:mm:ss A'); - let user = (pdata.user === undefined || pdata.user === null) ? 'anonymous' : pdata.user - let desc = `Took ${durationFormat}. Last updated by ${user} at ${endFormat}.` + let user = (pdata.user === undefined || pdata.user === null) ? 'anonymous' : pdata.user; + let desc = `Took ${durationFormat}. Last updated by ${user} at ${endFormat}.`; - if ($scope.isResultOutdated(pdata)) { desc += ' (outdated)' } + if ($scope.isResultOutdated(pdata)) { + desc += ' (outdated)'; + } - return desc - } + return desc; + }; - $scope.getElapsedTime = function (paragraph) { - return 'Started ' + moment(paragraph.dateStarted).fromNow() + '.' - } + $scope.getElapsedTime = function(paragraph) { + return 'Started ' + moment(paragraph.dateStarted).fromNow() + '.'; + }; - $scope.isResultOutdated = function (pdata) { + $scope.isResultOutdated = function(pdata) { if (pdata.dateUpdated !== undefined && Date.parse(pdata.dateUpdated) > Date.parse(pdata.dateStarted)) { - return true + return true; } - return false - } + return false; + }; - $scope.goToEnd = function (editor) { - editor.navigateFileEnd() - } + $scope.goToEnd = function(editor) { + editor.navigateFileEnd(); + }; - $scope.parseTableCell = function (cell) { + $scope.parseTableCell = function(cell) { if (!isNaN(cell)) { if (cell.length === 0 || Number(cell) > Number.MAX_SAFE_INTEGER || Number(cell) < Number.MIN_SAFE_INTEGER) { - return cell + return cell; } else { - return Number(cell) + return Number(cell); } } - let d = moment(cell) + let d = moment(cell); if (d.isValid()) { - return d + return d; } - return cell - } + return cell; + }; - const commitParagraph = function (paragraph) { + const commitParagraph = function(paragraph) { const { id, title, text, config, settings: {params}, - } = paragraph + } = paragraph; return websocketMsgSrv.commitParagraph(id, title, text, config, params, - $route.current.pathParams.noteId) - } + $route.current.pathParams.noteId); + }; /** Utility function */ - $scope.goToSingleParagraph = function () { - let noteId = $route.current.pathParams.noteId + $scope.goToSingleParagraph = function() { + let noteId = $route.current.pathParams.noteId; let redirectToUrl = location.protocol + '//' + location.host + location.pathname + '#/notebook/' + noteId + - '/paragraph/' + $scope.paragraph.id + '?asIframe' - $window.open(redirectToUrl) - } + '/paragraph/' + $scope.paragraph.id + '?asIframe'; + $window.open(redirectToUrl); + }; - $scope.showScrollDownIcon = function (id) { - let doc = angular.element('#p' + id + '_text') + $scope.showScrollDownIcon = function(id) { + let doc = angular.element('#p' + id + '_text'); if (doc[0]) { - return doc[0].scrollHeight > doc.innerHeight() + return doc[0].scrollHeight > doc.innerHeight(); } - return false - } + return false; + }; - $scope.scrollParagraphDown = function (id) { - let doc = angular.element('#p' + id + '_text') - doc.animate({scrollTop: doc[0].scrollHeight}, 500) - $scope.keepScrollDown = true - } + $scope.scrollParagraphDown = function(id) { + let doc = angular.element('#p' + id + '_text'); + doc.animate({scrollTop: doc[0].scrollHeight}, 500); + $scope.keepScrollDown = true; + }; - $scope.showScrollUpIcon = function (id) { + $scope.showScrollUpIcon = function(id) { if (angular.element('#p' + id + '_text')[0]) { - return angular.element('#p' + id + '_text')[0].scrollTop !== 0 + return angular.element('#p' + id + '_text')[0].scrollTop !== 0; } - return false - } + return false; + }; - $scope.scrollParagraphUp = function (id) { - let doc = angular.element('#p' + id + '_text') - doc.animate({scrollTop: 0}, 500) - $scope.keepScrollDown = false - } + $scope.scrollParagraphUp = function(id) { + let doc = angular.element('#p' + id + '_text'); + doc.animate({scrollTop: 0}, 500); + $scope.keepScrollDown = false; + }; - $scope.$on('angularObjectUpdate', function (event, data) { - let noteId = $route.current.pathParams.noteId + $scope.$on('angularObjectUpdate', function(event, data) { + let noteId = $route.current.pathParams.noteId; if (!data.noteId || data.noteId === noteId) { - let scope - let registry + let scope; + let registry; if (!data.paragraphId || data.paragraphId === $scope.paragraph.id) { - scope = paragraphScope - registry = angularObjectRegistry + scope = paragraphScope; + registry = angularObjectRegistry; } else { - return + return; } - let varName = data.angularObject.name + let varName = data.angularObject.name; if (angular.equals(data.angularObject.object, scope[varName])) { // return when update has no change - return + return; } if (!registry[varName]) { registry[varName] = { interpreterGroupId: data.interpreterGroupId, noteId: data.noteId, - paragraphId: data.paragraphId - } + paragraphId: data.paragraphId, + }; } else { - registry[varName].noteId = registry[varName].noteId || data.noteId - registry[varName].paragraphId = registry[varName].paragraphId || data.paragraphId + registry[varName].noteId = registry[varName].noteId || data.noteId; + registry[varName].paragraphId = registry[varName].paragraphId || data.paragraphId; } - registry[varName].skipEmit = true + registry[varName].skipEmit = true; if (!registry[varName].clearWatcher) { - registry[varName].clearWatcher = scope.$watch(varName, function (newValue, oldValue) { - console.log('angular object (paragraph) updated %o %o', varName, registry[varName]) + registry[varName].clearWatcher = scope.$watch(varName, function(newValue, oldValue) { + console.log('angular object (paragraph) updated %o %o', varName, registry[varName]); if (registry[varName].skipEmit) { - registry[varName].skipEmit = false - return + registry[varName].skipEmit = false; + return; } websocketMsgSrv.updateAngularObject( registry[varName].noteId, registry[varName].paragraphId, varName, newValue, - registry[varName].interpreterGroupId) - }) + registry[varName].interpreterGroupId); + }); } - console.log('angular object (paragraph) created %o', varName) - scope[varName] = data.angularObject.object + console.log('angular object (paragraph) created %o', varName); + scope[varName] = data.angularObject.object; // create proxy for AngularFunction if (varName.indexOf(ANGULAR_FUNCTION_OBJECT_NAME_PREFIX) === 0) { - let funcName = varName.substring((ANGULAR_FUNCTION_OBJECT_NAME_PREFIX).length) - scope[funcName] = function () { + let funcName = varName.substring((ANGULAR_FUNCTION_OBJECT_NAME_PREFIX).length); + scope[funcName] = function() { // eslint-disable-next-line prefer-rest-params - scope[varName] = arguments + scope[varName] = arguments; // eslint-disable-next-line prefer-rest-params - console.log('angular function (paragraph) invoked %o', arguments) - } + console.log('angular function (paragraph) invoked %o', arguments); + }; - console.log('angular function (paragraph) created %o', scope[funcName]) + console.log('angular function (paragraph) created %o', scope[funcName]); } } - }) + }); - $scope.$on('updateParaInfos', function (event, data) { + $scope.$on('updateParaInfos', function(event, data) { if (data.id === $scope.paragraph.id) { - $scope.paragraph.runtimeInfos = data.infos + $scope.paragraph.runtimeInfos = data.infos; } - }) + }); - $scope.$on('angularObjectRemove', function (event, data) { - let noteId = $route.current.pathParams.noteId + $scope.$on('angularObjectRemove', function(event, data) { + let noteId = $route.current.pathParams.noteId; if (!data.noteId || data.noteId === noteId) { - let scope - let registry + let scope; + let registry; if (!data.paragraphId || data.paragraphId === $scope.paragraph.id) { - scope = paragraphScope - registry = angularObjectRegistry + scope = paragraphScope; + registry = angularObjectRegistry; } else { - return + return; } - let varName = data.name + let varName = data.name; // clear watcher if (registry[varName]) { - registry[varName].clearWatcher() - registry[varName] = undefined + registry[varName].clearWatcher(); + registry[varName] = undefined; } // remove scope variable - scope[varName] = undefined + scope[varName] = undefined; // remove proxy for AngularFunction if (varName.indexOf(ANGULAR_FUNCTION_OBJECT_NAME_PREFIX) === 0) { - let funcName = varName.substring((ANGULAR_FUNCTION_OBJECT_NAME_PREFIX).length) - scope[funcName] = undefined + let funcName = varName.substring((ANGULAR_FUNCTION_OBJECT_NAME_PREFIX).length); + scope[funcName] = undefined; } } - }) + }); /** * @returns {boolean} true if updated is needed */ - function isUpdateRequired (oldPara, newPara) { + function isUpdateRequired(oldPara, newPara) { return (newPara.id === oldPara.id && (newPara.dateCreated !== oldPara.dateCreated || newPara.text !== oldPara.text || @@ -1322,453 +1338,457 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca newPara.errorMessage !== oldPara.errorMessage || !angular.equals(newPara.settings, oldPara.settings) || !angular.equals(newPara.config, oldPara.config) || - !angular.equals(newPara.runtimeInfos, oldPara.runtimeInfos))) + !angular.equals(newPara.runtimeInfos, oldPara.runtimeInfos))); } - $scope.updateAllScopeTexts = function (oldPara, newPara) { + $scope.updateAllScopeTexts = function(oldPara, newPara) { if (oldPara.text !== newPara.text) { if ($scope.dirtyText) { // check if editor has local update if ($scope.dirtyText === newPara.text) { // when local update is the same from remote, clear local update - $scope.paragraph.text = newPara.text - $scope.dirtyText = undefined - $scope.originalText = angular.copy(newPara.text) + $scope.paragraph.text = newPara.text; + $scope.dirtyText = undefined; + $scope.originalText = angular.copy(newPara.text); } else { // if there're local update, keep it. - $scope.paragraph.text = newPara.text + $scope.paragraph.text = newPara.text; } } else { - $scope.paragraph.text = newPara.text - $scope.originalText = angular.copy(newPara.text) + $scope.paragraph.text = newPara.text; + $scope.originalText = angular.copy(newPara.text); } } - } + }; - $scope.updateParagraphObjectWhenUpdated = function (newPara) { + $scope.updateParagraphObjectWhenUpdated = function(newPara) { // resize col width if ($scope.paragraph.config.colWidth !== newPara.config.colWidth) { - $scope.$broadcast('paragraphResized', $scope.paragraph.id) + $scope.$broadcast('paragraphResized', $scope.paragraph.id); } if ($scope.paragraph.config.fontSize !== newPara.config.fontSize) { - $rootScope.$broadcast('fontSizeChanged', newPara.config.fontSize) + $rootScope.$broadcast('fontSizeChanged', newPara.config.fontSize); } /** push the rest */ - $scope.paragraph.aborted = newPara.aborted - $scope.paragraph.user = newPara.user - $scope.paragraph.dateUpdated = newPara.dateUpdated - $scope.paragraph.dateCreated = newPara.dateCreated - $scope.paragraph.dateFinished = newPara.dateFinished - $scope.paragraph.dateStarted = newPara.dateStarted - $scope.paragraph.errorMessage = newPara.errorMessage - $scope.paragraph.jobName = newPara.jobName - $scope.paragraph.title = newPara.title - $scope.paragraph.lineNumbers = newPara.lineNumbers - $scope.paragraph.status = newPara.status - $scope.paragraph.fontSize = newPara.fontSize + $scope.paragraph.aborted = newPara.aborted; + $scope.paragraph.user = newPara.user; + $scope.paragraph.dateUpdated = newPara.dateUpdated; + $scope.paragraph.dateCreated = newPara.dateCreated; + $scope.paragraph.dateFinished = newPara.dateFinished; + $scope.paragraph.dateStarted = newPara.dateStarted; + $scope.paragraph.errorMessage = newPara.errorMessage; + $scope.paragraph.jobName = newPara.jobName; + $scope.paragraph.title = newPara.title; + $scope.paragraph.lineNumbers = newPara.lineNumbers; + $scope.paragraph.status = newPara.status; + $scope.paragraph.fontSize = newPara.fontSize; if (newPara.status !== ParagraphStatus.RUNNING) { - $scope.paragraph.results = newPara.results + $scope.paragraph.results = newPara.results; } - $scope.paragraph.settings = newPara.settings - $scope.paragraph.runtimeInfos = newPara.runtimeInfos + $scope.paragraph.settings = newPara.settings; + $scope.paragraph.runtimeInfos = newPara.runtimeInfos; if ($scope.editor) { - $scope.editor.setReadOnly($scope.isRunning(newPara)) + $scope.editor.setReadOnly($scope.isRunning(newPara)); } if (!$scope.asIframe) { - $scope.paragraph.config = newPara.config - initializeDefault(newPara.config) + $scope.paragraph.config = newPara.config; + initializeDefault(newPara.config); } else { - newPara.config.editorHide = true - newPara.config.tableHide = false - $scope.paragraph.config = newPara.config + newPara.config.editorHide = true; + newPara.config.tableHide = false; + $scope.paragraph.config = newPara.config; } - } + }; - $scope.updateParagraph = function (oldPara, newPara, updateCallback) { + $scope.updateParagraph = function(oldPara, newPara, updateCallback) { // 1. can't update on revision view if ($scope.revisionView === true) { - return + return; } // 2. get status, refreshed - const statusChanged = (newPara.status !== oldPara.status) + const statusChanged = (newPara.status !== oldPara.status); const resultRefreshed = (newPara.dateFinished !== oldPara.dateFinished) || isEmpty(newPara.results) !== isEmpty(oldPara.results) || newPara.status === ParagraphStatus.ERROR || - (newPara.status === ParagraphStatus.FINISHED && statusChanged) + (newPara.status === ParagraphStatus.FINISHED && statusChanged); // 3. update texts managed by $scope - $scope.updateAllScopeTexts(oldPara, newPara) + $scope.updateAllScopeTexts(oldPara, newPara); // 4. execute callback to update result - updateCallback() + updateCallback(); // 5. update remaining paragraph objects - $scope.updateParagraphObjectWhenUpdated(newPara) + $scope.updateParagraphObjectWhenUpdated(newPara); // 6. handle scroll down by key properly if new paragraph is added if (statusChanged || resultRefreshed) { // when last paragraph runs, zeppelin automatically appends new paragraph. // this broadcast will focus to the newly inserted paragraph - const paragraphs = angular.element('div[id$="_paragraphColumn_main"]') + const paragraphs = angular.element('div[id$="_paragraphColumn_main"]'); if (paragraphs.length >= 2 && paragraphs[paragraphs.length - 2].id.indexOf($scope.paragraph.id) === 0) { // rendering output can took some time. So delay scrolling event firing for sometime. - setTimeout(() => { $rootScope.$broadcast('scrollToCursor') }, 500) + setTimeout(() => { + $rootScope.$broadcast('scrollToCursor'); + }, 500); } } - } + }; /** $scope.$on */ - $scope.$on('runParagraphUsingSpell', function (event, data) { - const oldPara = $scope.paragraph - let newPara = data.paragraph + $scope.$on('runParagraphUsingSpell', function(event, data) { + const oldPara = $scope.paragraph; + let newPara = data.paragraph; const updateCallback = () => { - $scope.runParagraph(newPara.text, true, true) - } + $scope.runParagraph(newPara.text, true, true); + }; if (!isUpdateRequired(oldPara, newPara)) { - return + return; } - $scope.updateParagraph(oldPara, newPara, updateCallback) - }) + $scope.updateParagraph(oldPara, newPara, updateCallback); + }); - $scope.$on('updateParagraph', function (event, data) { - const oldPara = $scope.paragraph - const newPara = data.paragraph + $scope.$on('updateParagraph', function(event, data) { + const oldPara = $scope.paragraph; + const newPara = data.paragraph; if (!isUpdateRequired(oldPara, newPara)) { - return + return; } const updateCallback = () => { // broadcast `updateResult` message to trigger result update if (newPara.results && newPara.results.msg) { for (let i in newPara.results.msg) { - const newResult = newPara.results.msg ? newPara.results.msg[i] : {} - const oldResult = (oldPara.results && oldPara.results.msg) - ? oldPara.results.msg[i] : {} - const newConfig = newPara.config.results ? newPara.config.results[i] : {} - const oldConfig = oldPara.config.results ? oldPara.config.results[i] : {} - if (!angular.equals(newResult, oldResult) || - !angular.equals(newConfig, oldConfig)) { - $rootScope.$broadcast('updateResult', newResult, newConfig, newPara, parseInt(i)) + if (newPara.results.msg.hasOwnProperty(i)) { + const newResult = newPara.results.msg ? newPara.results.msg[i] : {}; + const oldResult = (oldPara.results && oldPara.results.msg) + ? oldPara.results.msg[i] : {}; + const newConfig = newPara.config.results ? newPara.config.results[i] : {}; + const oldConfig = oldPara.config.results ? oldPara.config.results[i] : {}; + if (!angular.equals(newResult, oldResult) || + !angular.equals(newConfig, oldConfig)) { + $rootScope.$broadcast('updateResult', newResult, newConfig, newPara, parseInt(i)); + } } } } - } + }; - $scope.updateParagraph(oldPara, newPara, updateCallback) - }) + $scope.updateParagraph(oldPara, newPara, updateCallback); + }); - $scope.$on('updateProgress', function (event, data) { + $scope.$on('updateProgress', function(event, data) { if (data.id === $scope.paragraph.id) { - $scope.currentProgress = data.progress + $scope.currentProgress = data.progress; } - }) + }); - $scope.$on('appendParagraphOutput', function (event, data) { + $scope.$on('appendParagraphOutput', function(event, data) { if (data.paragraphId === $scope.paragraph.id) { if (!$scope.paragraph.results) { - $scope.paragraph.results = {} + $scope.paragraph.results = {}; if (!$scope.paragraph.results.msg) { - $scope.paragraph.results.msg = [] + $scope.paragraph.results.msg = []; } $scope.paragraph.results.msg[data.index] = { data: data.data, - type: data.type - } + type: data.type, + }; $rootScope.$broadcast( 'updateResult', $scope.paragraph.results.msg[data.index], $scope.paragraph.config.results[data.index], $scope.paragraph, - data.index) + data.index); } } - }) + }); - $scope.$on('keyEvent', function (event, keyEvent) { + $scope.$on('keyEvent', function(event, keyEvent) { if ($scope.paragraphFocused) { - let paragraphId = $scope.paragraph.id - let keyCode = keyEvent.keyCode - let noShortcutDefined = false - let editorHide = $scope.paragraph.config.editorHide + let paragraphId = $scope.paragraph.id; + let keyCode = keyEvent.keyCode; + let noShortcutDefined = false; + let editorHide = $scope.paragraph.config.editorHide; if (editorHide && (keyCode === 38 || (keyCode === 80 && keyEvent.ctrlKey && !keyEvent.altKey))) { // up // move focus to previous paragraph - $scope.$emit('moveFocusToPreviousParagraph', paragraphId) + $scope.$emit('moveFocusToPreviousParagraph', paragraphId); } else if (editorHide && (keyCode === 40 || (keyCode === 78 && keyEvent.ctrlKey && !keyEvent.altKey))) { // down // move focus to next paragraph // $timeout stops chaining effect of focus propogation - $timeout(() => $scope.$emit('moveFocusToNextParagraph', paragraphId)) + $timeout(() => $scope.$emit('moveFocusToNextParagraph', paragraphId)); } else if (!keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 13) { // Shift + Enter - $scope.runParagraphFromShortcut($scope.getEditorValue()) + $scope.runParagraphFromShortcut($scope.getEditorValue()); } else if (keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 13) { // Ctrl + Shift + Enter - $scope.runAllToOrFromThis($scope.paragraph) + $scope.runAllToOrFromThis($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 67) { // Ctrl + Alt + c - $scope.cancelParagraph($scope.paragraph) + $scope.cancelParagraph($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 68) { // Ctrl + Alt + d - $scope.removeParagraph($scope.paragraph) + $scope.removeParagraph($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 75) { // Ctrl + Alt + k - $scope.moveUp($scope.paragraph) + $scope.moveUp($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 74) { // Ctrl + Alt + j - $scope.moveDown($scope.paragraph) + $scope.moveDown($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 65) { // Ctrl + Alt + a - $scope.insertNew('above') + $scope.insertNew('above'); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 66) { // Ctrl + Alt + b - $scope.insertNew('below') + $scope.insertNew('below'); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 79) { // Ctrl + Alt + o - $scope.toggleOutput($scope.paragraph) + $scope.toggleOutput($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 82) { // Ctrl + Alt + r - $scope.toggleEnableDisable($scope.paragraph) + $scope.toggleEnableDisable($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 69) { // Ctrl + Alt + e - $scope.toggleEditor($scope.paragraph) + $scope.toggleEditor($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 77) { // Ctrl + Alt + m if ($scope.paragraph.config.lineNumbers) { - $scope.hideLineNumbers($scope.paragraph) + $scope.hideLineNumbers($scope.paragraph); } else { - $scope.showLineNumbers($scope.paragraph) + $scope.showLineNumbers($scope.paragraph); } } else if (keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 189) { // Ctrl + Shift + - - $scope.changeColWidth($scope.paragraph, Math.max(1, $scope.paragraph.config.colWidth - 1)) + $scope.changeColWidth($scope.paragraph, Math.max(1, $scope.paragraph.config.colWidth - 1)); } else if (keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 187) { // Ctrl + Shift + = - $scope.changeColWidth($scope.paragraph, Math.min(12, $scope.paragraph.config.colWidth + 1)) + $scope.changeColWidth($scope.paragraph, Math.min(12, $scope.paragraph.config.colWidth + 1)); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 84) { // Ctrl + Alt + t if ($scope.paragraph.config.title) { - $scope.hideTitle($scope.paragraph) + $scope.hideTitle($scope.paragraph); } else { - $scope.showTitle($scope.paragraph) + $scope.showTitle($scope.paragraph); } } else if (keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 67) { // Ctrl + Alt + c - $scope.copyPara('below') + $scope.copyPara('below'); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 76) { // Ctrl + Alt + l - $scope.clearParagraphOutput($scope.paragraph) + $scope.clearParagraphOutput($scope.paragraph); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 87) { // Ctrl + Alt + w - $scope.goToSingleParagraph() + $scope.goToSingleParagraph(); } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 70) { // Ctrl + f - $scope.$emit('toggleSearchBox') + $scope.$emit('toggleSearchBox'); } else { - noShortcutDefined = true + noShortcutDefined = true; } if (!noShortcutDefined) { - keyEvent.preventDefault() + keyEvent.preventDefault(); } } - }) + }); - $scope.$on('focusParagraph', function (event, paragraphId, cursorPosRow, cursorPosCol, mouseEvent) { + $scope.$on('focusParagraph', function(event, paragraphId, cursorPosRow, cursorPosCol, mouseEvent) { if (cursorPosCol === null || cursorPosCol === undefined) { - cursorPosCol = 0 + cursorPosCol = 0; } if ($scope.paragraph.id === paragraphId) { // focus editor if (!$scope.paragraph.config.editorHide) { if (!mouseEvent) { - $scope.editor.focus() + $scope.editor.focus(); // move cursor to the first row (or the last row) - let row + let row; if (cursorPosRow >= 0) { - row = cursorPosRow - $scope.editor.gotoLine(row, cursorPosCol) + row = cursorPosRow; + $scope.editor.gotoLine(row, cursorPosCol); } else { -
<TRUNCATED>