From b9982dcae9c479449fa368f0e04149a90fa94ee9 Mon Sep 17 00:00:00 2001 From: Ramiro Rivera Date: Fri, 19 Jan 2018 15:22:12 -0300 Subject: [PATCH 1/4] Added a scope attribute, to be executed in the parent scope in order to provide custom buttons, instead of having to stringify a factory function. When both additionalButtons and "addExtraButtons" are provided, merge both buttons. --- src/angular-markdown-editor.js | 282 +++++++++++++++++---------------- 1 file changed, 146 insertions(+), 136 deletions(-) diff --git a/src/angular-markdown-editor.js b/src/angular-markdown-editor.js index 6461791..9ebfadf 100644 --- a/src/angular-markdown-editor.js +++ b/src/angular-markdown-editor.js @@ -2,154 +2,164 @@ angular .module('angular-markdown-editor', []) .directive('markdownEditor', ['$rootScope', function ($rootScope) { return { - restrict: 'A', - require: 'ngModel', - link: function(scope, element, attrs, ngModel) { - var options = scope.$eval(attrs.markdownEditor); - - // Only initialize the $.markdown plugin once. - if (! element.hasClass('processed')) { - element.addClass('processed'); - - var markdownOptions = { - autofocus: options.autofocus || false, - saveable: options.saveable || false, - savable: options.savable || false, - iconlibrary: options.iconlibrary || 'glyph', - hideable: options.hideable || false, - width: options.width || 'inherit', - height: options.height || 'inherit', - resize: options.resize || 'none', - language: options.language || 'en', - footer: options.footer || '', - fullscreen: options.fullscreen || { enable: true, icons: {}}, - hiddenButtons: options.hiddenButtons || [], - disabledButtons: options.disabledButtons || [], - initialstate: options.initialstate || 'editor', - parser: options.parser || null, - dropZoneOptions: options.dropZoneOptions || {}, - enableDropDataUri: options.enableDropDataUri || false, - showButtons: options.showButtons || {}, - additionalButtons: options.additionalButtons || (options.addExtraButtons ? addNewButtons() : []), - - //-- Events/Hooks -- - // each of them are defined as callback available in the directive - // example: - // NOTE: If you want this one to work, you will have to manually download the JS file, not sure why but they haven't released any versions in a while - // https://github.com/toopay/bootstrap-markdown/tree/master/js - onPreview: function (e) { runScopeFunction(scope, attrs.onPreview, e); }, - onPreviewEnd: function (e) { runScopeFunction(scope, attrs.onPreviewEnd, e); }, - onSave: function (e) { runScopeFunction(scope, attrs.onSave, e); }, - onBlur: function (e) { runScopeFunction(scope, attrs.onBlur, e); }, - onFocus: function (e) { runScopeFunction(scope, attrs.onFocus, e); }, - onFullscreen: function (e) { runScopeFunction(scope, attrs.onFullscreen, e); }, - onSelect: function (e) { runScopeFunction(scope, attrs.onSelect, e); }, - onFullscreenExit: function (e) { runScopeFunction(scope, attrs.onFullscreenExit, e); }, - onChange: function(e) { - // When a change occurs, we need to update scope in case the user clicked one of the plugin buttons - // (which isn't the same as a keydown event that angular would listen for). - ngModel.$setViewValue(e.getContent()); - - runScopeFunction(scope, attrs.onChange, e); - }, - onShow: function (e) { - // keep the Markdown Object in $rootScope so that it's available also from anywhere (like in the parent controller) - // we will keep this in an object under the ngModel name so that it also works having multiple editor in same controller - $rootScope.markdownEditorObjects = $rootScope.markdownEditorObjects || {}; - $rootScope.markdownEditorObjects[ngModel.$name] = e; - - if (!!attrs.onShow) { - runScopeFunction(scope, attrs.onShow, e); - } - } - }; - - // Setup the markdown WYSIWYG. - - // if the markdown editor was added dynamically the markdown function will be undefined - // so it has to be called explicitely - if (element.markdown === undefined){ - element.data('markdown', (data = new $.fn.markdown.Constructor(element[0], markdownOptions))) - } else { - element.markdown(markdownOptions); - } + restrict: 'A', + require: 'ngModel', + scope: { + buttonsFactory: "&additionalButtonsFactory" + }, + link: function (scope, element, attrs, ngModel) { + + var options = scope.$eval(attrs.markdownEditor); + + // If the Buttons Factory was passed via attribute, execute it + var additionalButtons = scope.buttonsFactory != null ? scope.buttonsFactory() : []; + + // Only initialize the $.markdown plugin once. + if (!element.hasClass('processed')) { + element.addClass('processed'); + + var markdownOptions = { + autofocus: options.autofocus || false, + saveable: options.saveable || false, + savable: options.savable || false, + iconlibrary: options.iconlibrary || 'glyph', + hideable: options.hideable || false, + width: options.width || 'inherit', + height: options.height || 'inherit', + resize: options.resize || 'none', + language: options.language || 'en', + footer: options.footer || '', + fullscreen: options.fullscreen || { enable: true, icons: {}}, + hiddenButtons: options.hiddenButtons || [], + disabledButtons: options.disabledButtons || [], + initialstate: options.initialstate || 'editor', + parser: options.parser || null, + dropZoneOptions: options.dropZoneOptions || {}, + enableDropDataUri: options.enableDropDataUri || false, + showButtons: options.showButtons || {}, + + // Here, instead of using only externally defined buttons or the additional ones defined by angular-markdown-editor, both are merged if required. + additionalButtons: [additionalButtons.concat(options.addExtraButtons ? getNewButtons() : [])], + + //-- Events/Hooks -- + // each of them are defined as callback available in the directive + // example: + // NOTE: If you want this one to work, you will have to manually download the JS file, not sure why but they haven't released any versions in a while + // https://github.com/toopay/bootstrap-markdown/tree/master/js + onPreview: function (e) { runScopeFunction(scope, attrs.onPreview, e); }, + onPreviewEnd: function (e) { runScopeFunction(scope, attrs.onPreviewEnd, e); }, + onSave: function (e) { runScopeFunction(scope, attrs.onSave, e); }, + onBlur: function (e) { runScopeFunction(scope, attrs.onBlur, e); }, + onFocus: function (e) { runScopeFunction(scope, attrs.onFocus, e); }, + onFullscreen: function (e) { runScopeFunction(scope, attrs.onFullscreen, e); }, + onSelect: function (e) { runScopeFunction(scope, attrs.onSelect, e); }, + onFullscreenExit: function (e) { runScopeFunction(scope, attrs.onFullscreenExit, e); }, + onChange: function(e) { + // When a change occurs, we need to update scope in case the user clicked one of the plugin buttons + // (which isn't the same as a keydown event that angular would listen for). + ngModel.$setViewValue(e.getContent()); + + runScopeFunction(scope, attrs.onChange, e); + }, + onShow: function (e) { + // keep the Markdown Object in $rootScope so that it's available also from anywhere (like in the parent controller) + // we will keep this in an object under the ngModel name so that it also works having multiple editor in same controller + $rootScope.markdownEditorObjects = $rootScope.markdownEditorObjects || {}; + $rootScope.markdownEditorObjects[ngModel.$name] = e; + + if (!!attrs.onShow) { + runScopeFunction(scope, attrs.onShow, e); + } } + }; + + // Setup the markdown WYSIWYG. + + // if the markdown editor was added dynamically the markdown function will be undefined + // so it has to be called explicitely + if (element.markdown === undefined){ + element.data('markdown', (data = new $.fn.markdown.Constructor(element[0], markdownOptions))) + } else { + element.markdown(markdownOptions); + } } + } }; -}]); + }]); /** * Add new extra buttons: Strikethrough & Table * @return mixed additionButtons */ -function addNewButtons() { - return [[{ - name: "groupFont", - data: [{ - name: "cmdStrikethrough", - toggle: false, - title: "Strikethrough", - icon: { - fa: "fa fa-strikethrough", - glyph: "glyphicon glyphicon-minus" - }, - callback: function(e) { - // Give/remove ~~ surround the selection - var chunk, cursor, selected = e.getSelection(), - content = e.getContent(); - - if (selected.length === 0) { - // Give extra word - chunk = e.__localize('strikethrough'); - } else { - chunk = selected.text; - } +function getNewButtons() { + return [{ + name: "groupFont", + data: [{ + name: "cmdStrikethrough", + toggle: false, + title: "Strikethrough", + icon: { + fa: "fa fa-strikethrough", + glyph: "glyphicon glyphicon-minus" + }, + callback: function (e) { + // Give/remove ~~ surround the selection + var chunk, cursor, selected = e.getSelection(), + content = e.getContent(); + + if (selected.length === 0) { + // Give extra word + chunk = e.__localize('strikethrough'); + } else { + chunk = selected.text; + } - // transform selection and set the cursor into chunked text - if (content.substr(selected.start - 2, 2) === '~~' && - content.substr(selected.end, 2) === '~~') { - e.setSelection(selected.start - 2, selected.end + 2); - e.replaceSelection(chunk); - cursor = selected.start - 2; - } else { - e.replaceSelection('~~' + chunk + '~~'); - cursor = selected.start + 2; - } + // transform selection and set the cursor into chunked text + if (content.substr(selected.start - 2, 2) === '~~' && + content.substr(selected.end, 2) === '~~') { + e.setSelection(selected.start - 2, selected.end + 2); + e.replaceSelection(chunk); + cursor = selected.start - 2; + } else { + e.replaceSelection('~~' + chunk + '~~'); + cursor = selected.start + 2; + } - // Set the cursor - e.setSelection(cursor, cursor + chunk.length); - } - }] + // Set the cursor + e.setSelection(cursor, cursor + chunk.length); + } + }] }, { - name: "groupMisc", - data: [{ - name: "cmdTable", - toggle: false, - title: "Table", - icon: { - fa: "fa fa-table", - glyph: "glyphicon glyphicon-th" - }, - callback: function(e) { - // Replace selection with some drinks - var chunk, cursor, - selected = e.getSelection(), content = e.getContent(), - chunk = "\n| Tables | Are | Cool | \n" - + "| ------------- |:-------------:| -----:| \n" - + "| col 3 is | right-aligned | $1600 | \n" - + "| col 2 is | centered | $12 | \n" - + "| zebra stripes | are neat | $1 |" - - // transform selection and set the cursor into chunked text - e.replaceSelection(chunk) - cursor = selected.start - - // Set the cursor - e.setSelection(cursor,cursor+chunk.length); - } - }] - }]]; + name: "groupMisc", + data: [{ + name: "cmdTable", + toggle: false, + title: "Table", + icon: { + fa: "fa fa-table", + glyph: "glyphicon glyphicon-th" + }, + callback: function (e) { + // Replace selection with some drinks + var chunk, cursor, + selected = e.getSelection(), content = e.getContent(), + chunk = "\n" + + + "| Tables | Are | Cool | \n" + + "| ------------- |:-------------:| -----:| \n" + + "| col 3 is | right-aligned | $1600 | \n" + + "| col 2 is | centered | $12 | \n" + + "| zebra stripes | are neat | $1 |" + + // transform selection and set the cursor into chunked text + e.replaceSelection(chunk) + cursor = selected.start + + // Set the cursor + e.setSelection(cursor, cursor + chunk.length); + } + }] + }]; } /** Evaluate a function name passed as string and run it from the scope. From 23da37ee1bc55349ea008edb3e46113bec9979ea Mon Sep 17 00:00:00 2001 From: ramarivera Date: Sun, 21 Jan 2018 17:41:11 -0300 Subject: [PATCH 2/4] trying to fix indentation mistake --- src/angular-markdown-editor.js | 405 ++++++++++++++++++--------------- 1 file changed, 222 insertions(+), 183 deletions(-) diff --git a/src/angular-markdown-editor.js b/src/angular-markdown-editor.js index 9ebfadf..14b7d6a 100644 --- a/src/angular-markdown-editor.js +++ b/src/angular-markdown-editor.js @@ -1,194 +1,233 @@ -angular - .module('angular-markdown-editor', []) - .directive('markdownEditor', ['$rootScope', function ($rootScope) { - return { - restrict: 'A', - require: 'ngModel', - scope: { - buttonsFactory: "&additionalButtonsFactory" - }, - link: function (scope, element, attrs, ngModel) { - - var options = scope.$eval(attrs.markdownEditor); - - // If the Buttons Factory was passed via attribute, execute it - var additionalButtons = scope.buttonsFactory != null ? scope.buttonsFactory() : []; - - // Only initialize the $.markdown plugin once. - if (!element.hasClass('processed')) { - element.addClass('processed'); - - var markdownOptions = { - autofocus: options.autofocus || false, - saveable: options.saveable || false, - savable: options.savable || false, - iconlibrary: options.iconlibrary || 'glyph', - hideable: options.hideable || false, - width: options.width || 'inherit', - height: options.height || 'inherit', - resize: options.resize || 'none', - language: options.language || 'en', - footer: options.footer || '', - fullscreen: options.fullscreen || { enable: true, icons: {}}, - hiddenButtons: options.hiddenButtons || [], - disabledButtons: options.disabledButtons || [], - initialstate: options.initialstate || 'editor', - parser: options.parser || null, - dropZoneOptions: options.dropZoneOptions || {}, - enableDropDataUri: options.enableDropDataUri || false, - showButtons: options.showButtons || {}, - - // Here, instead of using only externally defined buttons or the additional ones defined by angular-markdown-editor, both are merged if required. - additionalButtons: [additionalButtons.concat(options.addExtraButtons ? getNewButtons() : [])], - - //-- Events/Hooks -- - // each of them are defined as callback available in the directive - // example: - // NOTE: If you want this one to work, you will have to manually download the JS file, not sure why but they haven't released any versions in a while - // https://github.com/toopay/bootstrap-markdown/tree/master/js - onPreview: function (e) { runScopeFunction(scope, attrs.onPreview, e); }, - onPreviewEnd: function (e) { runScopeFunction(scope, attrs.onPreviewEnd, e); }, - onSave: function (e) { runScopeFunction(scope, attrs.onSave, e); }, - onBlur: function (e) { runScopeFunction(scope, attrs.onBlur, e); }, - onFocus: function (e) { runScopeFunction(scope, attrs.onFocus, e); }, - onFullscreen: function (e) { runScopeFunction(scope, attrs.onFullscreen, e); }, - onSelect: function (e) { runScopeFunction(scope, attrs.onSelect, e); }, - onFullscreenExit: function (e) { runScopeFunction(scope, attrs.onFullscreenExit, e); }, - onChange: function(e) { - // When a change occurs, we need to update scope in case the user clicked one of the plugin buttons - // (which isn't the same as a keydown event that angular would listen for). - ngModel.$setViewValue(e.getContent()); - - runScopeFunction(scope, attrs.onChange, e); +angular.module("angular-markdown-editor", []).directive("markdownEditor", [ + "$rootScope", + function($rootScope) { + return { + restrict: "A", + require: "ngModel", + scope: { + buttonsFactory: "&additionalButtonsFactory" }, - onShow: function (e) { - // keep the Markdown Object in $rootScope so that it's available also from anywhere (like in the parent controller) - // we will keep this in an object under the ngModel name so that it also works having multiple editor in same controller - $rootScope.markdownEditorObjects = $rootScope.markdownEditorObjects || {}; - $rootScope.markdownEditorObjects[ngModel.$name] = e; - - if (!!attrs.onShow) { - runScopeFunction(scope, attrs.onShow, e); - } + link: function(scope, element, attrs, ngModel) { + var options = scope.$eval(attrs.markdownEditor); + + // If the Buttons Factory was passed via attribute, execute it + var additionalButtons = + scope.buttonsFactory != null ? scope.buttonsFactory() : []; + + // Only initialize the $.markdown plugin once. + if (!element.hasClass("processed")) { + element.addClass("processed"); + + var markdownOptions = { + autofocus: options.autofocus || false, + saveable: options.saveable || false, + savable: options.savable || false, + iconlibrary: options.iconlibrary || "glyph", + hideable: options.hideable || false, + width: options.width || "inherit", + height: options.height || "inherit", + resize: options.resize || "none", + language: options.language || "en", + footer: options.footer || "", + fullscreen: options.fullscreen || { + enable: true, + icons: {} + }, + hiddenButtons: options.hiddenButtons || [], + disabledButtons: options.disabledButtons || [], + initialstate: options.initialstate || "editor", + parser: options.parser || null, + dropZoneOptions: options.dropZoneOptions || {}, + enableDropDataUri: options.enableDropDataUri || false, + showButtons: options.showButtons || {}, + + // Here, instead of using only externally defined buttons or the additional ones defined by angular-markdown-editor, both are merged if required. + additionalButtons: [ + additionalButtons.concat( + options.addExtraButtons ? getNewButtons() : [] + ) + ], + + //-- Events/Hooks -- + // each of them are defined as callback available in the directive + // example: + // NOTE: If you want this one to work, you will have to manually download the JS file, not sure why but they haven't released any versions in a while + // https://github.com/toopay/bootstrap-markdown/tree/master/js + onPreview: function(e) { + runScopeFunction(scope, attrs.onPreview, e); + }, + onPreviewEnd: function(e) { + runScopeFunction(scope, attrs.onPreviewEnd, e); + }, + onSave: function(e) { + runScopeFunction(scope, attrs.onSave, e); + }, + onBlur: function(e) { + runScopeFunction(scope, attrs.onBlur, e); + }, + onFocus: function(e) { + runScopeFunction(scope, attrs.onFocus, e); + }, + onFullscreen: function(e) { + runScopeFunction(scope, attrs.onFullscreen, e); + }, + onSelect: function(e) { + runScopeFunction(scope, attrs.onSelect, e); + }, + onFullscreenExit: function(e) { + runScopeFunction(scope, attrs.onFullscreenExit, e); + }, + onChange: function(e) { + // When a change occurs, we need to update scope in case the user clicked one of the plugin buttons + // (which isn't the same as a keydown event that angular would listen for). + ngModel.$setViewValue(e.getContent()); + + runScopeFunction(scope, attrs.onChange, e); + }, + onShow: function(e) { + // keep the Markdown Object in $rootScope so that it's available also from anywhere (like in the parent controller) + // we will keep this in an object under the ngModel name so that it also works having multiple editor in same controller + $rootScope.markdownEditorObjects = + $rootScope.markdownEditorObjects || {}; + $rootScope.markdownEditorObjects[ngModel.$name] = e; + + if (!!attrs.onShow) { + runScopeFunction(scope, attrs.onShow, e); + } + } + }; + + // Setup the markdown WYSIWYG. + + // if the markdown editor was added dynamically the markdown function will be undefined + // so it has to be called explicitely + if (element.markdown === undefined) { + element.data( + "markdown", + (data = new $.fn.markdown.Constructor( + element[0], + markdownOptions + )) + ); + } else { + element.markdown(markdownOptions); + } + } } - }; - - // Setup the markdown WYSIWYG. - - // if the markdown editor was added dynamically the markdown function will be undefined - // so it has to be called explicitely - if (element.markdown === undefined){ - element.data('markdown', (data = new $.fn.markdown.Constructor(element[0], markdownOptions))) - } else { - element.markdown(markdownOptions); - } - } - } - }; - }]); + }; + } +]); /** * Add new extra buttons: Strikethrough & Table * @return mixed additionButtons */ function getNewButtons() { - return [{ - name: "groupFont", - data: [{ - name: "cmdStrikethrough", - toggle: false, - title: "Strikethrough", - icon: { - fa: "fa fa-strikethrough", - glyph: "glyphicon glyphicon-minus" - }, - callback: function (e) { - // Give/remove ~~ surround the selection - var chunk, cursor, selected = e.getSelection(), - content = e.getContent(); - - if (selected.length === 0) { - // Give extra word - chunk = e.__localize('strikethrough'); - } else { - chunk = selected.text; - } - - // transform selection and set the cursor into chunked text - if (content.substr(selected.start - 2, 2) === '~~' && - content.substr(selected.end, 2) === '~~') { - e.setSelection(selected.start - 2, selected.end + 2); - e.replaceSelection(chunk); - cursor = selected.start - 2; - } else { - e.replaceSelection('~~' + chunk + '~~'); - cursor = selected.start + 2; + return [{ + name: "groupFont", + data: [{ + name: "cmdStrikethrough", + toggle: false, + title: "Strikethrough", + icon: { + fa: "fa fa-strikethrough", + glyph: "glyphicon glyphicon-minus" + }, + callback: function(e) { + // Give/remove ~~ surround the selection + var chunk, + cursor, + selected = e.getSelection(), + content = e.getContent(); + + if (selected.length === 0) { + // Give extra word + chunk = e.__localize("strikethrough"); + } else { + chunk = selected.text; + } + + // transform selection and set the cursor into chunked text + if ( + content.substr(selected.start - 2, 2) === "~~" && + content.substr(selected.end, 2) === "~~" + ) { + e.setSelection(selected.start - 2, selected.end + 2); + e.replaceSelection(chunk); + cursor = selected.start - 2; + } else { + e.replaceSelection("~~" + chunk + "~~"); + cursor = selected.start + 2; + } + + // Set the cursor + e.setSelection(cursor, cursor + chunk.length); + } + }] + }, + { + name: "groupMisc", + data: [{ + name: "cmdTable", + toggle: false, + title: "Table", + icon: { + fa: "fa fa-table", + glyph: "glyphicon glyphicon-th" + }, + callback: function(e) { + // Replace selection with some drinks + var chunk, + cursor, + selected = e.getSelection(), + content = e.getContent(), + chunk = + "\n" + + +"| Tables | Are | Cool | \n" + + "| ------------- |:-------------:| -----:| \n" + + "| col 3 is | right-aligned | $1600 | \n" + + "| col 2 is | centered | $12 | \n" + + "| zebra stripes | are neat | $1 |"; + + // transform selection and set the cursor into chunked text + e.replaceSelection(chunk); + cursor = selected.start; + + // Set the cursor + e.setSelection(cursor, cursor + chunk.length); + } + }] } - - // Set the cursor - e.setSelection(cursor, cursor + chunk.length); - } - }] - }, - { - name: "groupMisc", - data: [{ - name: "cmdTable", - toggle: false, - title: "Table", - icon: { - fa: "fa fa-table", - glyph: "glyphicon glyphicon-th" - }, - callback: function (e) { - // Replace selection with some drinks - var chunk, cursor, - selected = e.getSelection(), content = e.getContent(), - chunk = "\n" + - + "| Tables | Are | Cool | \n" - + "| ------------- |:-------------:| -----:| \n" - + "| col 3 is | right-aligned | $1600 | \n" - + "| col 2 is | centered | $12 | \n" - + "| zebra stripes | are neat | $1 |" - - // transform selection and set the cursor into chunked text - e.replaceSelection(chunk) - cursor = selected.start - - // Set the cursor - e.setSelection(cursor, cursor + chunk.length); - } - }] - }]; + ]; } /** Evaluate a function name passed as string and run it from the scope. - * The function name could be passed with/without brackets "()", in any case we will run the function - * @param object self object - * @param string function passed as a string - * @param object Markdown Editor object - * @result mixed result - */ + * The function name could be passed with/without brackets "()", in any case we will run the function + * @param object self object + * @param string function passed as a string + * @param object Markdown Editor object + * @result mixed result + */ function runScopeFunction(scope, fnString, editorObject) { - if (!fnString) { - return; - } - - // Find if our function has the brackets "()" - if (/\({1}.*\){1}/gi.test(fnString)) { - // if yes then run it through $eval else find it in the scope and then run it. That is the only way to evaluate all arguments of the function - // we'll have to make the object available in the scope so that we can evaluate it inside the controller - var lastParenthese = fnString.indexOf(")"); - scope.$markdownEditorObject = editorObject; - fnString = fnString.replace(")", "$markdownEditorObject)"); - result = scope.$eval(fnString); - } else { - var fct = objectFindById(scope, fnString, '.'); - if (typeof fct === "function") { - result = fct(editorObject); + if (!fnString) { + return; + } + + // Find if our function has the brackets "()" + if (/\({1}.*\){1}/gi.test(fnString)) { + // if yes then run it through $eval else find it in the scope and then run it. That is the only way to evaluate all arguments of the function + // we'll have to make the object available in the scope so that we can evaluate it inside the controller + var lastParenthese = fnString.indexOf(")"); + scope.$markdownEditorObject = editorObject; + fnString = fnString.replace(")", "$markdownEditorObject)"); + result = scope.$eval(fnString); + } else { + var fct = objectFindById(scope, fnString, "."); + if (typeof fct === "function") { + result = fct(editorObject); + } } - } - return result; + return result; } /** Find a property inside an object. @@ -198,12 +237,12 @@ function runScopeFunction(scope, fnString, editorObject) { * @return mixed: property found */ function objectFindById(sourceObject, searchId, delimiter) { - var split = (!!delimiter) ? searchId.split(delimiter) : searchId; + var split = !!delimiter ? searchId.split(delimiter) : searchId; - for (var k = 0, kln = split.length; k < kln; k++) { - if(!!sourceObject[split[k]]) { - sourceObject = sourceObject[split[k]]; + for (var k = 0, kln = split.length; k < kln; k++) { + if (!!sourceObject[split[k]]) { + sourceObject = sourceObject[split[k]]; + } } - } - return sourceObject; + return sourceObject; } \ No newline at end of file From c7fef1b6f9e36f93560600f4d6805383a96b5fb3 Mon Sep 17 00:00:00 2001 From: Ramiro Rivera Date: Mon, 22 Jan 2018 08:16:23 -0300 Subject: [PATCH 3/4] Trying to fix indentation v2 --- src/angular-markdown-editor.js | 403 +++++++++++++++------------------ 1 file changed, 183 insertions(+), 220 deletions(-) diff --git a/src/angular-markdown-editor.js b/src/angular-markdown-editor.js index 14b7d6a..343c661 100644 --- a/src/angular-markdown-editor.js +++ b/src/angular-markdown-editor.js @@ -1,233 +1,196 @@ -angular.module("angular-markdown-editor", []).directive("markdownEditor", [ - "$rootScope", - function($rootScope) { - return { - restrict: "A", - require: "ngModel", - scope: { - buttonsFactory: "&additionalButtonsFactory" - }, - link: function(scope, element, attrs, ngModel) { - var options = scope.$eval(attrs.markdownEditor); - - // If the Buttons Factory was passed via attribute, execute it - var additionalButtons = - scope.buttonsFactory != null ? scope.buttonsFactory() : []; - - // Only initialize the $.markdown plugin once. - if (!element.hasClass("processed")) { - element.addClass("processed"); - - var markdownOptions = { - autofocus: options.autofocus || false, - saveable: options.saveable || false, - savable: options.savable || false, - iconlibrary: options.iconlibrary || "glyph", - hideable: options.hideable || false, - width: options.width || "inherit", - height: options.height || "inherit", - resize: options.resize || "none", - language: options.language || "en", - footer: options.footer || "", - fullscreen: options.fullscreen || { - enable: true, - icons: {} - }, - hiddenButtons: options.hiddenButtons || [], - disabledButtons: options.disabledButtons || [], - initialstate: options.initialstate || "editor", - parser: options.parser || null, - dropZoneOptions: options.dropZoneOptions || {}, - enableDropDataUri: options.enableDropDataUri || false, - showButtons: options.showButtons || {}, - - // Here, instead of using only externally defined buttons or the additional ones defined by angular-markdown-editor, both are merged if required. - additionalButtons: [ - additionalButtons.concat( - options.addExtraButtons ? getNewButtons() : [] - ) - ], - - //-- Events/Hooks -- - // each of them are defined as callback available in the directive - // example: - // NOTE: If you want this one to work, you will have to manually download the JS file, not sure why but they haven't released any versions in a while - // https://github.com/toopay/bootstrap-markdown/tree/master/js - onPreview: function(e) { - runScopeFunction(scope, attrs.onPreview, e); - }, - onPreviewEnd: function(e) { - runScopeFunction(scope, attrs.onPreviewEnd, e); - }, - onSave: function(e) { - runScopeFunction(scope, attrs.onSave, e); - }, - onBlur: function(e) { - runScopeFunction(scope, attrs.onBlur, e); - }, - onFocus: function(e) { - runScopeFunction(scope, attrs.onFocus, e); - }, - onFullscreen: function(e) { - runScopeFunction(scope, attrs.onFullscreen, e); - }, - onSelect: function(e) { - runScopeFunction(scope, attrs.onSelect, e); - }, - onFullscreenExit: function(e) { - runScopeFunction(scope, attrs.onFullscreenExit, e); - }, - onChange: function(e) { - // When a change occurs, we need to update scope in case the user clicked one of the plugin buttons - // (which isn't the same as a keydown event that angular would listen for). - ngModel.$setViewValue(e.getContent()); - - runScopeFunction(scope, attrs.onChange, e); - }, - onShow: function(e) { - // keep the Markdown Object in $rootScope so that it's available also from anywhere (like in the parent controller) - // we will keep this in an object under the ngModel name so that it also works having multiple editor in same controller - $rootScope.markdownEditorObjects = - $rootScope.markdownEditorObjects || {}; - $rootScope.markdownEditorObjects[ngModel.$name] = e; - - if (!!attrs.onShow) { - runScopeFunction(scope, attrs.onShow, e); - } - } - }; - - // Setup the markdown WYSIWYG. - - // if the markdown editor was added dynamically the markdown function will be undefined - // so it has to be called explicitely - if (element.markdown === undefined) { - element.data( - "markdown", - (data = new $.fn.markdown.Constructor( - element[0], - markdownOptions - )) - ); - } else { - element.markdown(markdownOptions); +angular + .module('angular-markdown-editor', []) + .directive('markdownEditor', ['$rootScope', function ($rootScope) { + return { + restrict: 'A', + require: 'ngModel', + scope: { + buttonsFactory: "&additionalButtonsFactory" + }, + link: function(scope, element, attrs, ngModel) { + var options = scope.$eval(attrs.markdownEditor); + + // If the Buttons Factory was passed via attribute, execute it + var additionalButtons = scope.buttonsFactory != null ? scope.buttonsFactory() : []; + + // Only initialize the $.markdown plugin once. + if (! element.hasClass('processed')) { + element.addClass('processed'); + + var markdownOptions = { + autofocus: options.autofocus || false, + saveable: options.saveable || false, + savable: options.savable || false, + iconlibrary: options.iconlibrary || 'glyph', + hideable: options.hideable || false, + width: options.width || 'inherit', + height: options.height || 'inherit', + resize: options.resize || 'none', + language: options.language || 'en', + footer: options.footer || '', + fullscreen: options.fullscreen || { enable: true, icons: {}}, + hiddenButtons: options.hiddenButtons || [], + disabledButtons: options.disabledButtons || [], + initialstate: options.initialstate || 'editor', + parser: options.parser || null, + dropZoneOptions: options.dropZoneOptions || {}, + enableDropDataUri: options.enableDropDataUri || false, + showButtons: options.showButtons || {}, + + // Here, instead of using only externally defined buttons or the additional ones defined by angular-markdown-editor, both are merged if required. + additionalButtons: [ + additionalButtons.concat( + options.addExtraButtons ? getNewButtons() : [] + ) + ], + + //-- Events/Hooks -- + // each of them are defined as callback available in the directive + // example: + // NOTE: If you want this one to work, you will have to manually download the JS file, not sure why but they haven't released any versions in a while + // https://github.com/toopay/bootstrap-markdown/tree/master/js + onPreview: function (e) { runScopeFunction(scope, attrs.onPreview, e); }, + onPreviewEnd: function (e) { runScopeFunction(scope, attrs.onPreviewEnd, e); }, + onSave: function (e) { runScopeFunction(scope, attrs.onSave, e); }, + onBlur: function (e) { runScopeFunction(scope, attrs.onBlur, e); }, + onFocus: function (e) { runScopeFunction(scope, attrs.onFocus, e); }, + onFullscreen: function (e) { runScopeFunction(scope, attrs.onFullscreen, e); }, + onSelect: function (e) { runScopeFunction(scope, attrs.onSelect, e); }, + onFullscreenExit: function (e) { runScopeFunction(scope, attrs.onFullscreenExit, e); }, + onChange: function(e) { + // When a change occurs, we need to update scope in case the user clicked one of the plugin buttons + // (which isn't the same as a keydown event that angular would listen for). + ngModel.$setViewValue(e.getContent()); + + runScopeFunction(scope, attrs.onChange, e); + }, + onShow: function (e) { + // keep the Markdown Object in $rootScope so that it's available also from anywhere (like in the parent controller) + // we will keep this in an object under the ngModel name so that it also works having multiple editor in same controller + $rootScope.markdownEditorObjects = $rootScope.markdownEditorObjects || {}; + $rootScope.markdownEditorObjects[ngModel.$name] = e; + + if (!!attrs.onShow) { + runScopeFunction(scope, attrs.onShow, e); } + } + }; + + // Setup the markdown WYSIWYG. + + // if the markdown editor was added dynamically the markdown function will be undefined + // so it has to be called explicitely + if (element.markdown === undefined){ + element.data('markdown', (data = new $.fn.markdown.Constructor(element[0], markdownOptions))) + } else { + element.markdown(markdownOptions); } } - }; - } -]); + } + }; +}]); /** * Add new extra buttons: Strikethrough & Table * @return mixed additionButtons */ function getNewButtons() { - return [{ - name: "groupFont", - data: [{ - name: "cmdStrikethrough", - toggle: false, - title: "Strikethrough", - icon: { - fa: "fa fa-strikethrough", - glyph: "glyphicon glyphicon-minus" - }, - callback: function(e) { - // Give/remove ~~ surround the selection - var chunk, - cursor, - selected = e.getSelection(), - content = e.getContent(); - - if (selected.length === 0) { - // Give extra word - chunk = e.__localize("strikethrough"); - } else { - chunk = selected.text; - } + return [[{ + name: "groupFont", + data: [{ + name: "cmdStrikethrough", + toggle: false, + title: "Strikethrough", + icon: { + fa: "fa fa-strikethrough", + glyph: "glyphicon glyphicon-minus" + }, + callback: function(e) { + // Give/remove ~~ surround the selection + var chunk, cursor, selected = e.getSelection(), + content = e.getContent(); + + if (selected.length === 0) { + // Give extra word + chunk = e.__localize('strikethrough'); + } else { + chunk = selected.text; + } - // transform selection and set the cursor into chunked text - if ( - content.substr(selected.start - 2, 2) === "~~" && - content.substr(selected.end, 2) === "~~" - ) { - e.setSelection(selected.start - 2, selected.end + 2); - e.replaceSelection(chunk); - cursor = selected.start - 2; - } else { - e.replaceSelection("~~" + chunk + "~~"); - cursor = selected.start + 2; - } + // transform selection and set the cursor into chunked text + if (content.substr(selected.start - 2, 2) === '~~' && + content.substr(selected.end, 2) === '~~') { + e.setSelection(selected.start - 2, selected.end + 2); + e.replaceSelection(chunk); + cursor = selected.start - 2; + } else { + e.replaceSelection('~~' + chunk + '~~'); + cursor = selected.start + 2; + } - // Set the cursor - e.setSelection(cursor, cursor + chunk.length); - } - }] - }, - { - name: "groupMisc", - data: [{ - name: "cmdTable", - toggle: false, - title: "Table", - icon: { - fa: "fa fa-table", - glyph: "glyphicon glyphicon-th" - }, - callback: function(e) { - // Replace selection with some drinks - var chunk, - cursor, - selected = e.getSelection(), - content = e.getContent(), - chunk = - "\n" + - +"| Tables | Are | Cool | \n" + - "| ------------- |:-------------:| -----:| \n" + - "| col 3 is | right-aligned | $1600 | \n" + - "| col 2 is | centered | $12 | \n" + - "| zebra stripes | are neat | $1 |"; - - // transform selection and set the cursor into chunked text - e.replaceSelection(chunk); - cursor = selected.start; - - // Set the cursor - e.setSelection(cursor, cursor + chunk.length); - } - }] - } - ]; + // Set the cursor + e.setSelection(cursor, cursor + chunk.length); + } + }] + }, + { + name: "groupMisc", + data: [{ + name: "cmdTable", + toggle: false, + title: "Table", + icon: { + fa: "fa fa-table", + glyph: "glyphicon glyphicon-th" + }, + callback: function(e) { + // Replace selection with some drinks + var chunk, cursor, + selected = e.getSelection(), content = e.getContent(), + chunk = "\n| Tables | Are | Cool | \n" + + "| ------------- |:-------------:| -----:| \n" + + "| col 3 is | right-aligned | $1600 | \n" + + "| col 2 is | centered | $12 | \n" + + "| zebra stripes | are neat | $1 |" + + // transform selection and set the cursor into chunked text + e.replaceSelection(chunk) + cursor = selected.start + + // Set the cursor + e.setSelection(cursor,cursor+chunk.length); + } + }] + }]]; } /** Evaluate a function name passed as string and run it from the scope. - * The function name could be passed with/without brackets "()", in any case we will run the function - * @param object self object - * @param string function passed as a string - * @param object Markdown Editor object - * @result mixed result - */ + * The function name could be passed with/without brackets "()", in any case we will run the function + * @param object self object + * @param string function passed as a string + * @param object Markdown Editor object + * @result mixed result + */ function runScopeFunction(scope, fnString, editorObject) { - if (!fnString) { - return; + if (!fnString) { + return; + } + + // Find if our function has the brackets "()" + if (/\({1}.*\){1}/gi.test(fnString)) { + // if yes then run it through $eval else find it in the scope and then run it. That is the only way to evaluate all arguments of the function + // we'll have to make the object available in the scope so that we can evaluate it inside the controller + var lastParenthese = fnString.indexOf(")"); + scope.$markdownEditorObject = editorObject; + fnString = fnString.replace(")", "$markdownEditorObject)"); + result = scope.$eval(fnString); + } else { + var fct = objectFindById(scope, fnString, '.'); + if (typeof fct === "function") { + result = fct(editorObject); } - - // Find if our function has the brackets "()" - if (/\({1}.*\){1}/gi.test(fnString)) { - // if yes then run it through $eval else find it in the scope and then run it. That is the only way to evaluate all arguments of the function - // we'll have to make the object available in the scope so that we can evaluate it inside the controller - var lastParenthese = fnString.indexOf(")"); - scope.$markdownEditorObject = editorObject; - fnString = fnString.replace(")", "$markdownEditorObject)"); - result = scope.$eval(fnString); - } else { - var fct = objectFindById(scope, fnString, "."); - if (typeof fct === "function") { - result = fct(editorObject); - } - } - return result; + } + return result; } /** Find a property inside an object. @@ -237,12 +200,12 @@ function runScopeFunction(scope, fnString, editorObject) { * @return mixed: property found */ function objectFindById(sourceObject, searchId, delimiter) { - var split = !!delimiter ? searchId.split(delimiter) : searchId; + var split = (!!delimiter) ? searchId.split(delimiter) : searchId; - for (var k = 0, kln = split.length; k < kln; k++) { - if (!!sourceObject[split[k]]) { - sourceObject = sourceObject[split[k]]; - } + for (var k = 0, kln = split.length; k < kln; k++) { + if(!!sourceObject[split[k]]) { + sourceObject = sourceObject[split[k]]; } - return sourceObject; + } + return sourceObject; } \ No newline at end of file From a038ff38d7f061d4b79280e9c2f385af141f907f Mon Sep 17 00:00:00 2001 From: Ramiro Rivera Date: Fri, 26 Jan 2018 09:12:43 -0300 Subject: [PATCH 4/4] Fixed bug when no additionall-buttons attribute were present. --- src/angular-markdown-editor.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/angular-markdown-editor.js b/src/angular-markdown-editor.js index 343c661..81d636f 100644 --- a/src/angular-markdown-editor.js +++ b/src/angular-markdown-editor.js @@ -5,14 +5,15 @@ angular restrict: 'A', require: 'ngModel', scope: { - buttonsFactory: "&additionalButtonsFactory" + additionalButtonsFactory: "&additionalButtons" }, link: function(scope, element, attrs, ngModel) { var options = scope.$eval(attrs.markdownEditor); - // If the Buttons Factory was passed via attribute, execute it - var additionalButtons = scope.buttonsFactory != null ? scope.buttonsFactory() : []; - + // Additional buttons were passed via attribute? + var additionalButtons = scope.additionalButtonsFactory(); + additionalButtons = additionalButtons || []; + // Only initialize the $.markdown plugin once. if (! element.hasClass('processed')) { element.addClass('processed'); @@ -95,7 +96,7 @@ angular * @return mixed additionButtons */ function getNewButtons() { - return [[{ + return [{ name: "groupFont", data: [{ name: "cmdStrikethrough", @@ -161,7 +162,7 @@ function getNewButtons() { e.setSelection(cursor,cursor+chunk.length); } }] - }]]; + }]; } /** Evaluate a function name passed as string and run it from the scope.