Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/notes.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkorelstar <korelstar@users.noreply.github.com>2018-11-29 17:59:14 +0300
committerkorelstar <korelstar@users.noreply.github.com>2018-11-29 17:59:14 +0300
commitfaefa615de5aa5635bf83855dfc50ad115fbcd64 (patch)
treeeecc534d2e11d7e797b40c34996cc20bc2af296d
parent1093583bc5ea69aa3dd9d6fc2037c023d3ec1363 (diff)
build JSv2.5.1
-rw-r--r--js/public/app.min.js2
-rw-r--r--js/public/app.min.js.map2
2 files changed, 2 insertions, 2 deletions
diff --git a/js/public/app.min.js b/js/public/app.min.js
index 43f13fe1..3fbae814 100644
--- a/js/public/app.min.js
+++ b/js/public/app.min.js
@@ -1,2 +1,2 @@
-!function(e,n,o,r,i){"use strict";var a=e.module("Notes",["restangular","ngRoute"]).config(["$provide","$routeProvider","RestangularProvider","$httpProvider","$windowProvider",function(e,t,n,r,i){r.defaults.headers.common.requesttoken=o,e.value("Constants",{saveInterval:5e3}),t.when("/notes/:noteId",{templateUrl:"note.html",controller:"NoteController",resolve:{note:["$route","$q","is","Restangular",function(e,t,n,o){var r=t.defer(),i=e.current.params.noteId;return n.loading=!0,o.one("notes",i).get().then(function(e){n.loading=!1,r.resolve(e)},function(){n.loading=!1,r.reject()}),r.promise}]}}).otherwise({redirectTo:"/"});var a=OC.generateUrl("/apps/notes");n.setBaseUrl(a)}]).run(["$rootScope","$location","NotesModel",function(e,t,o){n('link[rel="shortcut icon"]').attr("href",OC.filePath("notes","img","favicon.png")),e.$on("$routeChangeError",function(){var e=o.getAll();if(e.length>0){var n=e.sort(function(e,t){return e.modified>t.modified?1:e.modified<t.modified?-1:0}),r=e[n.length-1];t.path("/notes/"+r.id)}else t.path("/")})}]);a.controller("AppController",["$scope","$location","is",function(e,t,o){e.is=o,e.init=function(n,o,r){e.defaultTitle=document.title,0!==n&&""===t.path()&&t.path("/notes/"+n),o&&OC.Notification.showTemporary(o),r&&e.initSearch()},e.search="",e.defaultTitle=null,e.initSearch=function(){new OCA.Search(function(t){e.search=t,e.$apply(),"none"===n("#app-navigation-toggle").css("display")||n("body").hasClass("snapjs-left")||n("#app-navigation-toggle").click()},function(){e.search="",e.$apply()})}}]),a.controller("NoteController",["$routeParams","$scope","NotesModel","SaveQueue","note","debounce","$document","$timeout",function(e,o,r,i,a,c,u,l){r.updateIfExists(a),o.note=r.get(e.noteId),o.isSaving=function(){return i.isSaving()},o.isManualSaving=function(){return i.isManualSaving()},o.updateTitle=function(){var e=o.note.content;e=e.replace(/^\s*[*+-]\s+/gm,""),e=e.replace(/^#+\s+(.*?)\s*#*$/gm,"$1"),e=e.replace(/^(=+|-+)$/gm,""),e=e.replace(/(\*+|_+)(.*?)\1/gm,"$2"),e=e.replace(/[\*\|\/\\\:\"<>\?]/g,""),e=e.replace(/^[\. ]+/gm,""),o.note.title=e.trim().split(/\r?\n/,2)[0]||t("notes","New note")},o.onEdit=function(){var e=o.note;e.unsaved=!0,o.autoSave(e)},o.autoSave=c(function(e){i.add(e)},1e3),o.manualSave=function(){var e=o.note;e.error=!1,i.addManual(e)},o.editCategory=!1,o.showEditCategory=function(){n("#category").val(o.note.category),o.editCategory=!0,n("#category").autocomplete({source:r.getCategories(r.getAll(),0,!1),minLength:0,position:{my:"left bottom",at:"left top",of:"#category"},open:function(){l(function(){var e=n("form.category").innerWidth()-2;n(".ui-autocomplete.ui-menu").width(e)})}}).autocomplete("widget").addClass("category-autocomplete"),n("form.category .icon-confirm").insertAfter("#category"),l(function(){n("#category").focus(),n("#category").autocomplete("search","")})},o.saveCategory=function(){var e=n("#category").val();return o.note.category===e?void(o.editCategory=!1):(o.isCategorySaving=!0,void o.note.customPUT({category:e},"category",{},{}).then(function(n){o.note.category=n.category,e!==n.category&&OC.Notification.showTemporary(t("notes","Updating the note's category has failed. Is the target directory writable?"))},function(){OC.Notification.showTemporary(t("notes","Updating the note's category has failed."))})["finally"](function(){o.isCategorySaving=!1,o.editCategory=!1}))},u.unbind("keypress.notes.save"),u.bind("keypress.notes.save",function(e){if(e.ctrlKey||e.metaKey)switch(String.fromCharCode(e.which).toLowerCase()){case"s":e.preventDefault(),o.manualSave()}}),o.toggleDistractionFree=function(){function e(e){e.requestFullscreen?e.requestFullscreen():e.mozRequestFullScreen?e.mozRequestFullScreen():e.webkitRequestFullscreen?e.webkitRequestFullscreen():e.msRequestFullscreen&&e.msRequestFullscreen()}function t(){document.exitFullscreen?document.exitFullscreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitExitFullscreen&&document.webkitExitFullscreen()}document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement?t():e(document.getElementById("app-content"))},o.$watch(function(){return o.note.title},function(e){e?document.title=e+" - "+o.defaultTitle:document.title=o.defaultTitle})}]),a.controller("NotesController",["$routeParams","$scope","$location","Restangular","NotesModel","$window",function(e,o,r,i,a,c){o.route=e,o.notesLoaded=!1,o.notes=a.getAll(),o.folderSelectorOpen=!1,o.filterCategory=null,o.orderRecent=["-favorite","-modified"],o.orderAlpha=["category","-favorite","title"],o.filterOrder=o.orderRecent;var u=i.all("notes");u.getList().then(function(e){a.addAll(e),o.notesLoaded=!0}),o.create=function(){u.post({category:o.filterCategory}).then(function(e){a.add(e),r.path("/notes/"+e.id)})},o["delete"]=function(e){var t=a.get(e);t.remove().then(function(){a.remove(e),o.$emit("$routeChangeError")})},o.toggleFavorite=function(e,t){var n=a.get(e);n.customPUT({favorite:!n.favorite},"favorite",{},{}).then(function(e){n.favorite=!!e}),t.target.blur()},o.categories=[],o.$watch("notes",function(e){o.categories=a.getCategories(e,1,!0)},!0),o.toggleFolderSelector=function(){o.folderSelectorOpen=!o.folderSelectorOpen},o.setFilter=function(e){null===e?o.filterOrder=o.orderRecent:o.filterOrder=o.orderAlpha,o.filterCategory=e,o.folderSelectorOpen=!1,n("#app-navigation > ul").animate({scrollTop:0},"fast")},o.categoryFilter=function(e){if(null!==o.filterCategory){if(e.category===o.filterCategory)return!0;if(null!==e.category)return e.category.startsWith(o.filterCategory+"/")}return!0},o.isCategory=function(e){return"string"==typeof e},c.onbeforeunload=function(){for(var e=a.getAll(),n=0;n<e.length;n+=1)if(e[n].unsaved)return t("notes","There are unsaved notes. Leaving the page will discard all changes!");return null}}]),a.controller("NotesSettingsController",["$scope","Restangular","$document",function(n,o,r){n.extensions=[".txt",".md"],o.one("settings").get().then(function(t){e.isObject(t)?n.settings=t:n.settings=o.one("settings")}),r.on("change","#notesPath",function(){var e=t("notes","Please wait while new settings are applied…");OC.Notification.show(e),n.settings.put().then(function(){window.location.reload(!0)})}),r.on("change","#fileSuffix",function(){n.settings.put()})}]),a.filter("and",["$filter",function(e){return function(t,n){var o=n.split(" "),r=t;for(var i in o)r=e("filter")(r,o[i]);return r}}]),a.filter("categoryTitle",function(){return function(e){return e&&"string"==typeof e?e.replace(/\//g," / "):""}}),a.filter("groupNotes",function(){return function(e,t){if(t){for(var n=null,o=0;o<e.length;o+=1){var r=e[o];null!==n&&n!==r.category&&e.splice(o,0,r.category.substring(t.length+1)),n=r.category}return e}return e}}),a.filter("wordCount",function(){return function(e){if(e&&"string"==typeof e){var t=e.split(/\s+/).filter(function(e){return e.search(/[A-Za-z0-9]/)!==-1}).length;return window.n("notes","%n word","%n words",t)}return 0}}),a.directive("notesAutofocus",function(){return{restrict:"A",link:function(e,t){t.focus()}}}),a.directive("editor",["$timeout","urlFinder",function(t,o){return{restrict:"A",link:function(i,a){var c=new r({element:a[0],spellChecker:!1,autoDownloadFontAwesome:!1,toolbar:!1,status:!1,forceSync:!0}),u=n(c.codemirror.getWrapperElement());c.value(i.note.content),c.codemirror.focus(),c.codemirror.on("change",function(){t(function(){i.$apply(function(){i.note.content=c.value(),i.onEdit(),i.updateTitle()})})}),u.on("click",".cm-link, .cm-url",function(t){if(t.ctrlKey){var n=o(this);e.isDefined(n)&&window.open(n,"_blank")}})}}}]),a.directive("notesTooltip",function(){return{restrict:"A",link:function(e,t){t.tooltip({container:"body"}),t.on("$destroy",function(){t.tooltip("hide")}),t.on("click",function(){t.tooltip("hide")})}}}),a.factory("debounce",["$timeout",function(e){return function(t,n){var o;return function(){var r=this,i=arguments;o&&e.cancel(o),o=e(function(){t.apply(r,i)},n)}}}]),a.factory("is",function(){return{loading:!1}}),a.factory("NotesModel",function(){var t=function(){this.notes=[],this.notesIds={}};return t.prototype={addAll:function(e){for(var t=0;t<e.length;t+=1)this.add(e[t])},add:function(e){this.updateIfExists(e)},getAll:function(){return this.notes},get:function(e){return this.notesIds[e].error?(OC.Notification.show(this.notesIds[e].errorMessage,{type:"error"}),!1):this.notesIds[e]},updateIfExists:function(t){var n=this.notesIds[t.id];e.isDefined(n)?null===t.content&&null!==n.content||(n.title=t.title,n.modified=t.modified,n.content=t.content,n.favorite=t.favorite,n.category=t.category,n.error=t.error,n.errorMessage=t.errorMessage):(this.notes.push(t),this.notesIds[t.id]=t)},remove:function(e){for(var t=0;t<this.notes.length;t+=1){var n=this.notes[t];if(n.id===e){this.notes.splice(t,1),delete this.notesIds[e];break}}},nthIndexOf:function(e,t,n){for(var o=-1;n--&&o++<e.length&&(o=e.indexOf(t,o),!(o<0)););return o},getCategories:function(e,t,n){for(var o={},r=0;r<e.length;r+=1){var a=e[r].category;if(t>0){var c=this.nthIndexOf(a,"/",t);c>0&&(a=a.substring(0,c))}o[a]===i?o[a]=1:o[a]+=1}var u=[];for(var l in o)n?u.push({name:l,count:o[l]}):l&&u.push(l);return n||u.sort(),u}},new t}),a.factory("SaveQueue",["$q",function(e){var t=function(){this._queue={},this._flushLock=!1,this._manualSaveActive=!1};return t.prototype={add:function(e){this._queue[e.id]=e,this._flush()},addManual:function(e){this._manualSaveActive=!0,this.add(e)},_flush:function(){var t=Object.keys(this._queue);if(0!==t.length&&!this._flushLock){this._flushLock=!0;for(var n=this,o=[],r=0;r<t.length;r+=1){var i=this._queue[t[r]];o.push(i.put().then(this._noteUpdateRequest.bind(null,i))["catch"](this._saveFailed.bind(null,i)))}this._queue={},e.all(o).then(function(){n._flushLock=!1,n._flush(),n._manualSaveActive=!1})}},_noteUpdateRequest:function(e,t){e.error=!1,e.title=t.title,e.modified=t.modified,e.category=t.category,t.content===e.content&&(e.unsaved=!1)},_saveFailed:function(e){e.error=!0},isSaving:function(){return this._flushLock},isManualSaving:function(){return this._manualSaveActive}},new t}]),a.factory("urlFinder",[function(){return function(e){for(e=n(e),e.is(".cm-url.cm-formatting")&&0!==e.prev().length&&(e=e.prev());e.is(".cm-link");)e=e.next();for(;e.is(".cm-url.cm-formatting");)e=e.next();return e.is(".cm-url:not(.cm-formatting)")?e.text():i}}])}(angular,jQuery,oc_requesttoken,SimpleMDE);
+!function(e,n,o,r,i){"use strict";var a=e.module("Notes",["restangular","ngRoute"]).config(["$provide","$routeProvider","RestangularProvider","$httpProvider","$windowProvider",function(e,t,n,r,i){r.defaults.headers.common.requesttoken=o,e.value("Constants",{saveInterval:5e3}),t.when("/notes/:noteId",{templateUrl:"note.html",controller:"NoteController",resolve:{note:["$route","$q","is","Restangular",function(e,t,n,o){var r=t.defer(),i=e.current.params.noteId;return n.loading=!0,o.one("notes",i).get().then(function(e){n.loading=!1,r.resolve(e)},function(){n.loading=!1,r.reject()}),r.promise}]}}).otherwise({redirectTo:"/"});var a=OC.generateUrl("/apps/notes");n.setBaseUrl(a)}]).run(["$rootScope","$location","NotesModel",function(e,t,o){n('link[rel="shortcut icon"]').attr("href",OC.filePath("notes","img","favicon.png")),e.$on("$routeChangeError",function(){var e=o.getAll();if(e.length>0){var n=e.sort(function(e,t){return e.modified>t.modified?1:e.modified<t.modified?-1:0}),r=e[n.length-1];t.path("/notes/"+r.id)}else t.path("/")})}]);a.controller("AppController",["$scope","$location","is",function(e,t,o){e.is=o,e.init=function(n,o,r){e.defaultTitle=document.title,0!==n&&""===t.path()&&t.path("/notes/"+n),o&&OC.Notification.showTemporary(o),r&&e.initSearch()},e.search="",e.defaultTitle=null,e.initSearch=function(){new OCA.Search(function(t){e.search=t,e.$apply(),"none"===n("#app-navigation-toggle").css("display")||n("body").hasClass("snapjs-left")||n("#app-navigation-toggle").click()},function(){e.search="",e.$apply()})}}]),a.controller("NoteController",["$routeParams","$scope","NotesModel","SaveQueue","note","debounce","$document","$timeout",function(e,o,r,i,a,c,u,l){r.updateIfExists(a),o.note=r.get(e.noteId),o.isSaving=function(){return i.isSaving()},o.isManualSaving=function(){return i.isManualSaving()},o.updateTitle=function(){var e=o.note.content;e=e.replace(/^\s*[*+-]\s+/gm,""),e=e.replace(/^#+\s+(.*?)\s*#*$/gm,"$1"),e=e.replace(/^(=+|-+)$/gm,""),e=e.replace(/(\*+|_+)(.*?)\1/gm,"$2"),e=e.replace(/[\*\|\/\\\:\"<>\?]/g,""),e=e.replace(/^[\. ]+/gm,""),o.note.title=e.trim().split(/\r?\n/,2)[0]||t("notes","New note")},o.onEdit=function(){var e=o.note;e.unsaved=!0,o.autoSave(e)},o.autoSave=c(function(e){i.add(e)},1e3),o.manualSave=function(){var e=o.note;e.error=!1,i.addManual(e)},o.editCategory=!1,o.showEditCategory=function(){n("#category").val(o.note.category),o.editCategory=!0,n("#category").autocomplete({source:r.getCategories(r.getAll(),0,!1),minLength:0,position:{my:"left bottom",at:"left top",of:"#category"},open:function(){l(function(){var e=n("form.category").innerWidth()-2;n(".ui-autocomplete.ui-menu").width(e)})}}).autocomplete("widget").addClass("category-autocomplete"),n("form.category .icon-confirm").insertAfter("#category"),l(function(){n("#category").focus(),n("#category").autocomplete("search","")})},o.saveCategory=function(){var e=n("#category").val();return o.note.category===e?void(o.editCategory=!1):(o.isCategorySaving=!0,void o.note.customPUT({category:e},"category",{},{}).then(function(n){o.note.category=n.category,e!==n.category&&OC.Notification.showTemporary(t("notes","Updating the note's category has failed. Is the target directory writable?"))},function(){OC.Notification.showTemporary(t("notes","Updating the note's category has failed."))})["finally"](function(){o.isCategorySaving=!1,o.editCategory=!1}))},u.unbind("keypress.notes.save"),u.bind("keypress.notes.save",function(e){if(e.ctrlKey||e.metaKey)switch(String.fromCharCode(e.which).toLowerCase()){case"s":e.preventDefault(),o.manualSave()}}),o.toggleDistractionFree=function(){function e(e){e.requestFullscreen?e.requestFullscreen():e.mozRequestFullScreen?e.mozRequestFullScreen():e.webkitRequestFullscreen?e.webkitRequestFullscreen():e.msRequestFullscreen&&e.msRequestFullscreen()}function t(){document.exitFullscreen?document.exitFullscreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitExitFullscreen&&document.webkitExitFullscreen()}document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement?t():e(document.getElementById("app-content"))},o.$watch(function(){return o.note.title},function(e){e?document.title=e+" - "+o.defaultTitle:document.title=o.defaultTitle})}]),a.controller("NotesController",["$routeParams","$scope","$location","Restangular","NotesModel","$window",function(e,o,r,i,a,c){o.route=e,o.notesLoaded=!1,o.notes=a.getAll(),o.folderSelectorOpen=!1,o.filterCategory=null,o.orderRecent=["-favorite","-modified"],o.orderAlpha=["category","-favorite","title"],o.filterOrder=o.orderRecent;var u=i.all("notes");u.getList().then(function(e){a.addAll(e),o.notesLoaded=!0}),o.create=function(){u.post({category:o.filterCategory}).then(function(e){a.add(e),r.path("/notes/"+e.id)})},o["delete"]=function(e){var t=a.get(e);t.remove().then(function(){a.remove(e),o.$emit("$routeChangeError")})},o.toggleFavorite=function(e,t){var n=a.get(e);n.customPUT({favorite:!n.favorite},"favorite",{},{}).then(function(e){n.favorite=!!e}),t.target.blur()},o.categories=[],o.$watch("notes",function(e){o.categories=a.getCategories(e,1,!0)},!0),o.toggleFolderSelector=function(){o.folderSelectorOpen=!o.folderSelectorOpen},o.setFilter=function(e){null===e?o.filterOrder=o.orderRecent:o.filterOrder=o.orderAlpha,o.filterCategory=e,o.folderSelectorOpen=!1,n("#app-navigation > ul").animate({scrollTop:0},"fast")},o.categoryFilter=function(e){if(null!==o.filterCategory){if(e.category===o.filterCategory)return!0;if(null!==e.category)return e.category.startsWith(o.filterCategory+"/")}return!0},o.isCategory=function(e){return"string"==typeof e},c.onbeforeunload=function(){for(var e=a.getAll(),n=0;n<e.length;n+=1)if(e[n].unsaved)return t("notes","There are unsaved notes. Leaving the page will discard all changes!");return null}}]),a.controller("NotesSettingsController",["$scope","Restangular","$document",function(n,o,r){n.extensions=[".txt",".md"],o.one("settings").get().then(function(t){e.isObject(t)?n.settings=t:n.settings=o.one("settings")}),r.on("change","#notesPath",function(){var e=t("notes","Please wait while new settings are applied…");OC.Notification.show(e),n.settings.put().then(function(){window.location.reload(!0)})}),r.on("change","#fileSuffix",function(){n.settings.put()})}]),a.directive("notesAutofocus",function(){return{restrict:"A",link:function(e,t){t.focus()}}}),a.directive("editor",["$timeout","urlFinder",function(t,o){return{restrict:"A",link:function(i,a){var c=new r({element:a[0],spellChecker:!1,autoDownloadFontAwesome:!1,toolbar:!1,status:!1,forceSync:!0}),u=n(c.codemirror.getWrapperElement());c.value(i.note.content),c.codemirror.focus(),c.codemirror.on("change",function(){t(function(){i.$apply(function(){i.note.content=c.value(),i.onEdit(),i.updateTitle()})})}),u.on("click",".cm-link, .cm-url",function(t){if(t.ctrlKey){var n=o(this);e.isDefined(n)&&window.open(n,"_blank")}})}}}]),a.directive("notesTooltip",function(){return{restrict:"A",link:function(e,t){t.tooltip({container:"body"}),t.on("$destroy",function(){t.tooltip("hide")}),t.on("click",function(){t.tooltip("hide")})}}}),a.filter("and",["$filter",function(e){return function(t,n){var o=n.split(" "),r=t;for(var i in o)r=e("filter")(r,o[i]);return r}}]),a.filter("categoryTitle",function(){return function(e){return e&&"string"==typeof e?e.replace(/\//g," / "):""}}),a.filter("groupNotes",function(){return function(e,t){if(t){for(var n=null,o=0;o<e.length;o+=1){var r=e[o];null!==n&&n!==r.category&&e.splice(o,0,r.category.substring(t.length+1)),n=r.category}return e}return e}}),a.filter("wordCount",function(){return function(e){if(e&&"string"==typeof e){var t=e.split(/\s+/).filter(function(e){return e.search(/[A-Za-z0-9]/)!==-1}).length;return window.n("notes","%n word","%n words",t)}return 0}}),a.factory("debounce",["$timeout",function(e){return function(t,n){var o;return function(){var r=this,i=arguments;o&&e.cancel(o),o=e(function(){t.apply(r,i)},n)}}}]),a.factory("is",function(){return{loading:!1}}),a.factory("NotesModel",function(){var t=function(){this.notes=[],this.notesIds={}};return t.prototype={addAll:function(e){for(var t=0;t<e.length;t+=1)this.add(e[t])},add:function(e){this.updateIfExists(e)},getAll:function(){return this.notes},get:function(e){return this.notesIds[e].error?(OC.Notification.show(this.notesIds[e].errorMessage,{type:"error"}),!1):this.notesIds[e]},updateIfExists:function(t){var n=this.notesIds[t.id];e.isDefined(n)?null===t.content&&null!==n.content||(n.title=t.title,n.modified=t.modified,n.content=t.content,n.favorite=t.favorite,n.category=t.category,n.error=t.error,n.errorMessage=t.errorMessage):(this.notes.push(t),this.notesIds[t.id]=t)},remove:function(e){for(var t=0;t<this.notes.length;t+=1){var n=this.notes[t];if(n.id===e){this.notes.splice(t,1),delete this.notesIds[e];break}}},nthIndexOf:function(e,t,n){for(var o=-1;n--&&o++<e.length&&(o=e.indexOf(t,o),!(o<0)););return o},getCategories:function(e,t,n){for(var o={},r=0;r<e.length;r+=1){var a=e[r].category;if(t>0){var c=this.nthIndexOf(a,"/",t);c>0&&(a=a.substring(0,c))}o[a]===i?o[a]=1:o[a]+=1}var u=[];for(var l in o)n?u.push({name:l,count:o[l]}):l&&u.push(l);return n||u.sort(),u}},new t}),a.factory("SaveQueue",["$q",function(e){var t=function(){this._queue={},this._flushLock=!1,this._manualSaveActive=!1};return t.prototype={add:function(e){this._queue[e.id]=e,this._flush()},addManual:function(e){this._manualSaveActive=!0,this.add(e)},_flush:function(){var t=Object.keys(this._queue);if(0!==t.length&&!this._flushLock){this._flushLock=!0;for(var n=this,o=[],r=0;r<t.length;r+=1){var i=this._queue[t[r]];o.push(i.put().then(this._noteUpdateRequest.bind(null,i))["catch"](this._saveFailed.bind(null,i)))}this._queue={},e.all(o).then(function(){n._flushLock=!1,n._flush(),n._manualSaveActive=!1})}},_noteUpdateRequest:function(e,t){e.error=!1,e.title=t.title,e.modified=t.modified,e.category=t.category,t.content===e.content&&(e.unsaved=!1)},_saveFailed:function(e){e.error=!0},isSaving:function(){return this._flushLock},isManualSaving:function(){return this._manualSaveActive}},new t}]),a.factory("urlFinder",[function(){return function(e){for(e=n(e),e.is(".cm-url.cm-formatting")&&0!==e.prev().length&&(e=e.prev());e.is(".cm-link");)e=e.next();for(;e.is(".cm-url.cm-formatting");)e=e.next();return e.is(".cm-url:not(.cm-formatting)")?e.text():i}}])}(angular,jQuery,oc_requesttoken,SimpleMDE);
//# sourceMappingURL=app.min.js.map
diff --git a/js/public/app.min.js.map b/js/public/app.min.js.map
index d3859877..66a769e6 100644
--- a/js/public/app.min.js.map
+++ b/js/public/app.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["app.js","controllers/appcontroller.js","controllers/notecontroller.js","controllers/notescontroller.js","controllers/notessettingscontroller.js","app.min.js","filters/and.js","filters/categoryTitle.js","filters/groupNotes.js","filters/wordCount.js","directives/autofocus.js","directives/editor.js","directives/tooltip.js","services/debounce.js","services/is.js","services/notesmodel.js","services/savequeue.js","services/urlFinder.js"],"names":["angular","$","requestToken","SimpleMDE","undefined","app","module","config","$provide","$routeProvider","RestangularProvider","$httpProvider","$windowProvider","defaults","headers","common","requesttoken","value","saveInterval","when","templateUrl","controller","resolve","note","$route","$q","is","Restangular","deferred","defer","noteId","current","params","loading","one","get","then","reject","promise","otherwise","redirectTo","baseUrl","OC","generateUrl","setBaseUrl","run","$rootScope","$location","NotesModel","attr","filePath","$on","notes","getAll","length","sorted","sort","a","b","modified","path","id","$scope","init","lastViewedNote","errorMessage","useSearchAPI","defaultTitle","document","title","Notification","showTemporary","initSearch","search","OCA","Search","query","$apply","css","hasClass","click","$routeParams","SaveQueue","debounce","$document","$timeout","updateIfExists","isSaving","isManualSaving","updateTitle","content","replace","trim","split","t","onEdit","unsaved","autoSave","add","manualSave","error","addManual","editCategory","showEditCategory","val","category","autocomplete","source","getCategories","minLength","position","my","at","of","open","width","innerWidth","addClass","insertAfter","focus","saveCategory","isCategorySaving","customPUT","updatedNote","unbind","bind","event","ctrlKey","metaKey","String","fromCharCode","which","toLowerCase","preventDefault","toggleDistractionFree","launchIntoFullscreen","element","requestFullscreen","mozRequestFullScreen","webkitRequestFullscreen","msRequestFullscreen","exitFullscreen","mozCancelFullScreen","webkitExitFullscreen","fullscreenElement","mozFullScreenElement","webkitFullscreenElement","getElementById","$watch","newValue","$window","route","notesLoaded","folderSelectorOpen","filterCategory","orderRecent","orderAlpha","filterOrder","notesResource","all","getList","addAll","create","post","remove","$emit","toggleFavorite","favorite","target","blur","categories","toggleFolderSelector","setFilter","animate","scrollTop","categoryFilter","startsWith","isCategory","item","onbeforeunload","i","extensions","settings","isObject","on","msg","show","put","window","location","reload","filter","$filter","items","searchString","searchValues","filtered","str","prevCat","splice","substring","wordCount","n","directive","restrict","link","scope","urlFinder","simplemde","spellChecker","autoDownloadFontAwesome","toolbar","status","forceSync","editorElement","codemirror","getWrapperElement","url","this","isDefined","tooltip","container","factory","func","delay","timeout","context","args","arguments","cancel","apply","notesIds","prototype","type","updated","push","nthIndexOf","pattern","indexOf","maxLevel","details","cat","index","result","name","count","_queue","_flushLock","_manualSaveActive","_flush","keys","Object","self","requests","_noteUpdateRequest","_saveFailed","response","prev","next","text","jQuery","oc_requesttoken"],"mappings":"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","file":"app.min.js","sourcesContent":["/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n/* jshint unused: false */\nvar app = angular.module('Notes', ['restangular', 'ngRoute']).\nconfig(function($provide, $routeProvider, RestangularProvider, $httpProvider,\n $windowProvider) {\n 'use strict';\n\n // Always send the CSRF token by default\n $httpProvider.defaults.headers.common.requesttoken = requestToken;\n\n // you have to use $provide inside the config method to provide a globally\n // shared and injectable object\n $provide.value('Constants', {\n saveInterval: 5*1000 // miliseconds\n });\n\n // define your routes that that load templates into the ng-view\n $routeProvider.when('/notes/:noteId', {\n templateUrl: 'note.html',\n controller: 'NoteController',\n resolve: {\n // $routeParams does not work inside resolve so use $route\n // note is the name of the argument that will be injected into the\n // controller\n /* @ngInject */\n note: function ($route, $q, is, Restangular) {\n\n var deferred = $q.defer();\n var noteId = $route.current.params.noteId;\n is.loading = true;\n\n Restangular.one('notes', noteId).get().then(function (note) {\n is.loading = false;\n deferred.resolve(note);\n }, function () {\n is.loading = false;\n deferred.reject();\n });\n\n return deferred.promise;\n }\n }\n }).otherwise({\n redirectTo: '/'\n });\n\n var baseUrl = OC.generateUrl('/apps/notes');\n RestangularProvider.setBaseUrl(baseUrl);\n\n\n\n}).run(function ($rootScope, $location, NotesModel) {\n 'use strict';\n\n $('link[rel=\"shortcut icon\"]').attr(\n\t\t 'href',\n\t\t OC.filePath('notes', 'img', 'favicon.png')\n );\n\n // handle route errors\n $rootScope.$on('$routeChangeError', function () {\n var notes = NotesModel.getAll();\n\n // route change error should redirect to the latest note if possible\n if (notes.length > 0) {\n var sorted = notes.sort(function (a, b) {\n if(a.modified > b.modified) {\n return 1;\n } else if(a.modified < b.modified) {\n return -1;\n } else {\n return 0;\n }\n });\n\n var note = notes[sorted.length-1];\n $location.path('/notes/' + note.id);\n } else {\n $location.path('/');\n }\n });\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('AppController', function ($scope, $location, is) {\n 'use strict';\n\n $scope.is = is;\n\n $scope.init = function (lastViewedNote, errorMessage, useSearchAPI) {\n $scope.defaultTitle = document.title;\n\n if(lastViewedNote !== 0 && $location.path()==='') {\n $location.path('/notes/' + lastViewedNote);\n }\n if(errorMessage) {\n OC.Notification.showTemporary(errorMessage);\n }\n if(useSearchAPI) {\n $scope.initSearch();\n }\n };\n\n $scope.search = '';\n $scope.defaultTitle = null;\n\n $scope.initSearch = function() {\n new OCA.Search(\n function (query) {\n $scope.search = query;\n $scope.$apply();\n if($('#app-navigation-toggle').css('display')!=='none' &&\n !$('body').hasClass('snapjs-left')) {\n $('#app-navigation-toggle').click();\n }\n },\n function () {\n $scope.search = '';\n $scope.$apply();\n }\n );\n };\n\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('NoteController', function($routeParams, $scope, NotesModel,\n SaveQueue, note, debounce,\n $document, $timeout) {\n 'use strict';\n\n NotesModel.updateIfExists(note);\n\n $scope.note = NotesModel.get($routeParams.noteId);\n\n $scope.isSaving = function () {\n return SaveQueue.isSaving();\n };\n $scope.isManualSaving = function () {\n return SaveQueue.isManualSaving();\n };\n\n $scope.updateTitle = function () {\n var content = $scope.note.content;\n\n // prepare content: remove markdown characters and empty spaces\n content = content.replace(/^\\s*[*+-]\\s+/mg, ''); // list item\n content = content.replace(/^#+\\s+(.*?)\\s*#*$/mg, '$1'); // headline\n content = content.replace(/^(=+|-+)$/mg, ''); // separate headline\n content = content.replace(/(\\*+|_+)(.*?)\\1/mg, '$2'); // emphasis\n\n // prevent directory traversal, illegal characters\n content = content.replace(/[\\*\\|\\/\\\\\\:\\\"<>\\?]/g, '');\n // prevent unintended file names\n content = content.replace(/^[\\. ]+/mg, '');\n\n // generate title from the first line of the content\n $scope.note.title = content.trim().split(/\\r?\\n/, 2)[0] ||\n t('notes', 'New note');\n };\n\n $scope.onEdit = function() {\n var note = $scope.note;\n note.unsaved = true;\n $scope.autoSave(note);\n };\n\n $scope.autoSave = debounce(function(note) {\n SaveQueue.add(note);\n }, 1000);\n\n $scope.manualSave = function() {\n var note = $scope.note;\n note.error = false;\n SaveQueue.addManual(note);\n };\n\n $scope.editCategory = false;\n $scope.showEditCategory = function() {\n $('#category').val($scope.note.category);\n $scope.editCategory = true;\n $('#category').autocomplete({\n source: NotesModel.getCategories(NotesModel.getAll(), 0, false),\n minLength: 0,\n position: { my: 'left bottom', at: 'left top', of: '#category' },\n open: function() {\n $timeout(function() {\n var width = $('form.category').innerWidth() - 2;\n $('.ui-autocomplete.ui-menu').width(width);\n });\n },\n }).autocomplete('widget').addClass('category-autocomplete');\n // fix space between input and confirm-button\n $('form.category .icon-confirm').insertAfter('#category');\n\n $timeout(function() {\n $('#category').focus();\n $('#category').autocomplete('search', '');\n });\n };\n $scope.saveCategory = function () {\n var category = $('#category').val();\n if($scope.note.category === category) {\n $scope.editCategory = false;\n return;\n }\n $scope.isCategorySaving = true;\n $scope.note.customPUT({category: category}, 'category', {}, {})\n .then(\n function (updatedNote) {\n $scope.note.category = updatedNote.category;\n if(category !== updatedNote.category) {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.'+\n ' Is the target directory writable?')\n );\n }\n },\n function () {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.')\n );\n }\n )\n .finally(\n function () {\n $scope.isCategorySaving = false;\n $scope.editCategory = false;\n }\n );\n };\n\n\n $document.unbind('keypress.notes.save');\n $document.bind('keypress.notes.save', function(event) {\n if(event.ctrlKey || event.metaKey) {\n switch(String.fromCharCode(event.which).toLowerCase()) {\n case 's':\n event.preventDefault();\n $scope.manualSave();\n break;\n }\n }\n });\n\n $scope.toggleDistractionFree = function() {\n function launchIntoFullscreen(element) {\n if(element.requestFullscreen) {\n element.requestFullscreen();\n } else if(element.mozRequestFullScreen) {\n element.mozRequestFullScreen();\n } else if(element.webkitRequestFullscreen) {\n element.webkitRequestFullscreen();\n } else if(element.msRequestFullscreen) {\n element.msRequestFullscreen();\n }\n }\n\n function exitFullscreen() {\n if(document.exitFullscreen) {\n document.exitFullscreen();\n } else if(document.mozCancelFullScreen) {\n document.mozCancelFullScreen();\n } else if(document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n }\n }\n\n if(document.fullscreenElement ||\n document.mozFullScreenElement ||\n document.webkitFullscreenElement) {\n exitFullscreen();\n } else {\n launchIntoFullscreen(document.getElementById('app-content'));\n }\n };\n\n $scope.$watch(function() {\n return $scope.note.title;\n }, function(newValue) {\n if(newValue) {\n document.title = newValue + ' - ' + $scope.defaultTitle;\n } else {\n document.title = $scope.defaultTitle;\n }\n });\n\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// This is available by using ng-controller=\"NotesController\" in your HTML\napp.controller('NotesController', function($routeParams, $scope, $location,\n Restangular, NotesModel, $window) {\n 'use strict';\n\n $scope.route = $routeParams;\n $scope.notesLoaded = false;\n $scope.notes = NotesModel.getAll();\n\n $scope.folderSelectorOpen = false;\n $scope.filterCategory = null;\n\n $scope.orderRecent = ['-favorite','-modified'];\n $scope.orderAlpha = ['category','-favorite','title'];\n $scope.filterOrder = $scope.orderRecent;\n\n var notesResource = Restangular.all('notes');\n\n // initial request for getting all notes\n notesResource.getList().then(function (notes) {\n NotesModel.addAll(notes);\n $scope.notesLoaded = true;\n });\n\n $scope.create = function () {\n notesResource.post({category: $scope.filterCategory})\n .then(function (note) {\n NotesModel.add(note);\n $location.path('/notes/' + note.id);\n });\n };\n\n $scope.delete = function (noteId) {\n var note = NotesModel.get(noteId);\n note.remove().then(function () {\n NotesModel.remove(noteId);\n $scope.$emit('$routeChangeError');\n });\n };\n\n $scope.toggleFavorite = function (noteId, event) {\n var note = NotesModel.get(noteId);\n note.customPUT({favorite: !note.favorite},\n 'favorite', {}, {}).then(function (favorite) {\n note.favorite = favorite ? true : false;\n });\n event.target.blur();\n };\n\n $scope.categories = [];\n $scope.$watch('notes', function(notes) {\n $scope.categories = NotesModel.getCategories(notes, 1, true);\n }, true);\n\n $scope.toggleFolderSelector = function () {\n $scope.folderSelectorOpen = !$scope.folderSelectorOpen;\n };\n\n $scope.setFilter = function (category) {\n if(category===null) {\n $scope.filterOrder = $scope.orderRecent;\n } else {\n $scope.filterOrder = $scope.orderAlpha;\n }\n $scope.filterCategory = category;\n $scope.folderSelectorOpen = false;\n $('#app-navigation > ul').animate({scrollTop: 0}, 'fast');\n };\n\n $scope.categoryFilter = function (note) {\n if($scope.filterCategory!==null) {\n if(note.category===$scope.filterCategory) {\n return true;\n } else if(note.category!==null) {\n return note.category.startsWith($scope.filterCategory+'/');\n }\n }\n return true;\n };\n\n $scope.isCategory = function (item) {\n return typeof item === 'string';\n };\n\n $window.onbeforeunload = function() {\n var notes = NotesModel.getAll();\n for(var i=0; i<notes.length; i+=1) {\n if(notes[i].unsaved) {\n return t('notes', 'There are unsaved notes. Leaving ' +\n 'the page will discard all changes!');\n }\n }\n return null;\n };\n});\n","app.controller('NotesSettingsController',\n function($scope, Restangular, $document) {\n 'use strict';\n\n $scope.extensions = ['.txt', '.md'];\n\n Restangular.one('settings').get().then(function(settings) {\n if(angular.isObject(settings)) {\n $scope.settings = settings;\n } else {\n $scope.settings = Restangular.one('settings');\n }\n });\n\n $document.on('change', '#notesPath', function() {\n var msg = t('notes', 'Please wait while new settings are applied…');\n OC.Notification.show(msg);\n $scope.settings.put().then(function() {\n window.location.reload(true);\n });\n });\n\n $document.on('change', '#fileSuffix', function() {\n $scope.settings.put();\n });\n});\n","(function(angular, $, requestToken, SimpleMDE, undefined){'use strict';/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n/* jshint unused: false */\nvar app = angular.module('Notes', ['restangular', 'ngRoute']).\nconfig([\"$provide\", \"$routeProvider\", \"RestangularProvider\", \"$httpProvider\", \"$windowProvider\", function($provide, $routeProvider, RestangularProvider, $httpProvider,\n $windowProvider) {\n 'use strict';\n\n // Always send the CSRF token by default\n $httpProvider.defaults.headers.common.requesttoken = requestToken;\n\n // you have to use $provide inside the config method to provide a globally\n // shared and injectable object\n $provide.value('Constants', {\n saveInterval: 5*1000 // miliseconds\n });\n\n // define your routes that that load templates into the ng-view\n $routeProvider.when('/notes/:noteId', {\n templateUrl: 'note.html',\n controller: 'NoteController',\n resolve: {\n // $routeParams does not work inside resolve so use $route\n // note is the name of the argument that will be injected into the\n // controller\n /* @ngInject */\n note: [\"$route\", \"$q\", \"is\", \"Restangular\", function ($route, $q, is, Restangular) {\n\n var deferred = $q.defer();\n var noteId = $route.current.params.noteId;\n is.loading = true;\n\n Restangular.one('notes', noteId).get().then(function (note) {\n is.loading = false;\n deferred.resolve(note);\n }, function () {\n is.loading = false;\n deferred.reject();\n });\n\n return deferred.promise;\n }]\n }\n }).otherwise({\n redirectTo: '/'\n });\n\n var baseUrl = OC.generateUrl('/apps/notes');\n RestangularProvider.setBaseUrl(baseUrl);\n\n\n\n}]).run([\"$rootScope\", \"$location\", \"NotesModel\", function ($rootScope, $location, NotesModel) {\n 'use strict';\n\n $('link[rel=\"shortcut icon\"]').attr(\n\t\t 'href',\n\t\t OC.filePath('notes', 'img', 'favicon.png')\n );\n\n // handle route errors\n $rootScope.$on('$routeChangeError', function () {\n var notes = NotesModel.getAll();\n\n // route change error should redirect to the latest note if possible\n if (notes.length > 0) {\n var sorted = notes.sort(function (a, b) {\n if(a.modified > b.modified) {\n return 1;\n } else if(a.modified < b.modified) {\n return -1;\n } else {\n return 0;\n }\n });\n\n var note = notes[sorted.length-1];\n $location.path('/notes/' + note.id);\n } else {\n $location.path('/');\n }\n });\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('AppController', [\"$scope\", \"$location\", \"is\", function ($scope, $location, is) {\n 'use strict';\n\n $scope.is = is;\n\n $scope.init = function (lastViewedNote, errorMessage, useSearchAPI) {\n $scope.defaultTitle = document.title;\n\n if(lastViewedNote !== 0 && $location.path()==='') {\n $location.path('/notes/' + lastViewedNote);\n }\n if(errorMessage) {\n OC.Notification.showTemporary(errorMessage);\n }\n if(useSearchAPI) {\n $scope.initSearch();\n }\n };\n\n $scope.search = '';\n $scope.defaultTitle = null;\n\n $scope.initSearch = function() {\n new OCA.Search(\n function (query) {\n $scope.search = query;\n $scope.$apply();\n if($('#app-navigation-toggle').css('display')!=='none' &&\n !$('body').hasClass('snapjs-left')) {\n $('#app-navigation-toggle').click();\n }\n },\n function () {\n $scope.search = '';\n $scope.$apply();\n }\n );\n };\n\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('NoteController', [\"$routeParams\", \"$scope\", \"NotesModel\", \"SaveQueue\", \"note\", \"debounce\", \"$document\", \"$timeout\", function($routeParams, $scope, NotesModel,\n SaveQueue, note, debounce,\n $document, $timeout) {\n 'use strict';\n\n NotesModel.updateIfExists(note);\n\n $scope.note = NotesModel.get($routeParams.noteId);\n\n $scope.isSaving = function () {\n return SaveQueue.isSaving();\n };\n $scope.isManualSaving = function () {\n return SaveQueue.isManualSaving();\n };\n\n $scope.updateTitle = function () {\n var content = $scope.note.content;\n\n // prepare content: remove markdown characters and empty spaces\n content = content.replace(/^\\s*[*+-]\\s+/mg, ''); // list item\n content = content.replace(/^#+\\s+(.*?)\\s*#*$/mg, '$1'); // headline\n content = content.replace(/^(=+|-+)$/mg, ''); // separate headline\n content = content.replace(/(\\*+|_+)(.*?)\\1/mg, '$2'); // emphasis\n\n // prevent directory traversal, illegal characters\n content = content.replace(/[\\*\\|\\/\\\\\\:\\\"<>\\?]/g, '');\n // prevent unintended file names\n content = content.replace(/^[\\. ]+/mg, '');\n\n // generate title from the first line of the content\n $scope.note.title = content.trim().split(/\\r?\\n/, 2)[0] ||\n t('notes', 'New note');\n };\n\n $scope.onEdit = function() {\n var note = $scope.note;\n note.unsaved = true;\n $scope.autoSave(note);\n };\n\n $scope.autoSave = debounce(function(note) {\n SaveQueue.add(note);\n }, 1000);\n\n $scope.manualSave = function() {\n var note = $scope.note;\n note.error = false;\n SaveQueue.addManual(note);\n };\n\n $scope.editCategory = false;\n $scope.showEditCategory = function() {\n $('#category').val($scope.note.category);\n $scope.editCategory = true;\n $('#category').autocomplete({\n source: NotesModel.getCategories(NotesModel.getAll(), 0, false),\n minLength: 0,\n position: { my: 'left bottom', at: 'left top', of: '#category' },\n open: function() {\n $timeout(function() {\n var width = $('form.category').innerWidth() - 2;\n $('.ui-autocomplete.ui-menu').width(width);\n });\n },\n }).autocomplete('widget').addClass('category-autocomplete');\n // fix space between input and confirm-button\n $('form.category .icon-confirm').insertAfter('#category');\n\n $timeout(function() {\n $('#category').focus();\n $('#category').autocomplete('search', '');\n });\n };\n $scope.saveCategory = function () {\n var category = $('#category').val();\n if($scope.note.category === category) {\n $scope.editCategory = false;\n return;\n }\n $scope.isCategorySaving = true;\n $scope.note.customPUT({category: category}, 'category', {}, {})\n .then(\n function (updatedNote) {\n $scope.note.category = updatedNote.category;\n if(category !== updatedNote.category) {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.'+\n ' Is the target directory writable?')\n );\n }\n },\n function () {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.')\n );\n }\n )\n .finally(\n function () {\n $scope.isCategorySaving = false;\n $scope.editCategory = false;\n }\n );\n };\n\n\n $document.unbind('keypress.notes.save');\n $document.bind('keypress.notes.save', function(event) {\n if(event.ctrlKey || event.metaKey) {\n switch(String.fromCharCode(event.which).toLowerCase()) {\n case 's':\n event.preventDefault();\n $scope.manualSave();\n break;\n }\n }\n });\n\n $scope.toggleDistractionFree = function() {\n function launchIntoFullscreen(element) {\n if(element.requestFullscreen) {\n element.requestFullscreen();\n } else if(element.mozRequestFullScreen) {\n element.mozRequestFullScreen();\n } else if(element.webkitRequestFullscreen) {\n element.webkitRequestFullscreen();\n } else if(element.msRequestFullscreen) {\n element.msRequestFullscreen();\n }\n }\n\n function exitFullscreen() {\n if(document.exitFullscreen) {\n document.exitFullscreen();\n } else if(document.mozCancelFullScreen) {\n document.mozCancelFullScreen();\n } else if(document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n }\n }\n\n if(document.fullscreenElement ||\n document.mozFullScreenElement ||\n document.webkitFullscreenElement) {\n exitFullscreen();\n } else {\n launchIntoFullscreen(document.getElementById('app-content'));\n }\n };\n\n $scope.$watch(function() {\n return $scope.note.title;\n }, function(newValue) {\n if(newValue) {\n document.title = newValue + ' - ' + $scope.defaultTitle;\n } else {\n document.title = $scope.defaultTitle;\n }\n });\n\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// This is available by using ng-controller=\"NotesController\" in your HTML\napp.controller('NotesController', [\"$routeParams\", \"$scope\", \"$location\", \"Restangular\", \"NotesModel\", \"$window\", function($routeParams, $scope, $location,\n Restangular, NotesModel, $window) {\n 'use strict';\n\n $scope.route = $routeParams;\n $scope.notesLoaded = false;\n $scope.notes = NotesModel.getAll();\n\n $scope.folderSelectorOpen = false;\n $scope.filterCategory = null;\n\n $scope.orderRecent = ['-favorite','-modified'];\n $scope.orderAlpha = ['category','-favorite','title'];\n $scope.filterOrder = $scope.orderRecent;\n\n var notesResource = Restangular.all('notes');\n\n // initial request for getting all notes\n notesResource.getList().then(function (notes) {\n NotesModel.addAll(notes);\n $scope.notesLoaded = true;\n });\n\n $scope.create = function () {\n notesResource.post({category: $scope.filterCategory})\n .then(function (note) {\n NotesModel.add(note);\n $location.path('/notes/' + note.id);\n });\n };\n\n $scope.delete = function (noteId) {\n var note = NotesModel.get(noteId);\n note.remove().then(function () {\n NotesModel.remove(noteId);\n $scope.$emit('$routeChangeError');\n });\n };\n\n $scope.toggleFavorite = function (noteId, event) {\n var note = NotesModel.get(noteId);\n note.customPUT({favorite: !note.favorite},\n 'favorite', {}, {}).then(function (favorite) {\n note.favorite = favorite ? true : false;\n });\n event.target.blur();\n };\n\n $scope.categories = [];\n $scope.$watch('notes', function(notes) {\n $scope.categories = NotesModel.getCategories(notes, 1, true);\n }, true);\n\n $scope.toggleFolderSelector = function () {\n $scope.folderSelectorOpen = !$scope.folderSelectorOpen;\n };\n\n $scope.setFilter = function (category) {\n if(category===null) {\n $scope.filterOrder = $scope.orderRecent;\n } else {\n $scope.filterOrder = $scope.orderAlpha;\n }\n $scope.filterCategory = category;\n $scope.folderSelectorOpen = false;\n $('#app-navigation > ul').animate({scrollTop: 0}, 'fast');\n };\n\n $scope.categoryFilter = function (note) {\n if($scope.filterCategory!==null) {\n if(note.category===$scope.filterCategory) {\n return true;\n } else if(note.category!==null) {\n return note.category.startsWith($scope.filterCategory+'/');\n }\n }\n return true;\n };\n\n $scope.isCategory = function (item) {\n return typeof item === 'string';\n };\n\n $window.onbeforeunload = function() {\n var notes = NotesModel.getAll();\n for(var i=0; i<notes.length; i+=1) {\n if(notes[i].unsaved) {\n return t('notes', 'There are unsaved notes. Leaving ' +\n 'the page will discard all changes!');\n }\n }\n return null;\n };\n}]);\n\napp.controller('NotesSettingsController',\n [\"$scope\", \"Restangular\", \"$document\", function($scope, Restangular, $document) {\n 'use strict';\n\n $scope.extensions = ['.txt', '.md'];\n\n Restangular.one('settings').get().then(function(settings) {\n if(angular.isObject(settings)) {\n $scope.settings = settings;\n } else {\n $scope.settings = Restangular.one('settings');\n }\n });\n\n $document.on('change', '#notesPath', function() {\n var msg = t('notes', 'Please wait while new settings are applied…');\n OC.Notification.show(msg);\n $scope.settings.put().then(function() {\n window.location.reload(true);\n });\n });\n\n $document.on('change', '#fileSuffix', function() {\n $scope.settings.put();\n });\n}]);\n\n/**\n * filter by multiple words (AND operation)\n */\napp.filter('and', ['$filter', function ($filter) {\n\t'use strict';\n\treturn function (items, searchString) {\n\t\tvar searchValues = searchString.split(' ');\n\t\tvar filtered = items;\n\t\tfor(var i in searchValues) {\n\t\t\tfiltered = $filter('filter')(filtered, searchValues[i]);\n\t\t}\n\t\treturn filtered;\n\t};\n}]);\n\napp.filter('categoryTitle', function () {\n\t'use strict';\n\treturn function (str) {\n\t\tif (str && (typeof str === 'string')) {\n\t\t\treturn str.replace(/\\//g, ' / ');\n\t\t} else {\n\t\t\treturn '';\n\t\t}\n\t};\n});\n\n/**\n * group notes by (sub) category\n */\napp.filter('groupNotes', function () {\n\t'use strict';\n\treturn function (items, category) {\n\t\tif(category) {\n\t\t\tvar prevCat = null;\n\t\t\tfor(var i=0; i<items.length; i+=1) {\n\t\t\t\tvar note = items[i];\n\t\t\t\tif(prevCat !== null && prevCat !== note.category) {\n\t\t\t\t\titems.splice(i, 0,\n\t\t\t\t\t\tnote.category.substring(category.length+1));\n\t\t\t\t}\n\t\t\t\tprevCat = note.category;\n\t\t\t}\n\t\t\treturn items;\n\t\t} else {\n\t\t\treturn items;\n\t\t}\n\t};\n});\n\napp.filter('wordCount', function () {\n\t'use strict';\n\treturn function (value) {\n\t\tif (value && (typeof value === 'string')) {\n\t\t\tvar wordCount = value.split(/\\s+/).filter(\n\t\t\t\t// only count words containing\n\t\t\t\t// at least one alphanumeric character\n\t\t\t\tfunction(value) {\n\t\t\t\t\treturn value.search(/[A-Za-z0-9]/) !== -1;\n\t\t\t\t}\n\t\t\t).length;\n\t\t\treturn window.n('notes', '%n word', '%n words', wordCount);\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t};\n});\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesAutofocus', function () {\n 'use strict';\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.focus();\n }\n };\n});\n\n/*global SimpleMDE*/\napp.directive('editor', ['$timeout',\n 'urlFinder',\n function ($timeout, urlFinder) {\n\t'use strict';\n\treturn {\n\t\trestrict: 'A',\n\t\tlink: function(scope, element) {\n\n\t\t\tvar simplemde = new SimpleMDE({\n\t\t\t\telement: element[0],\n\t\t\t\tspellChecker: false,\n\t\t\t\tautoDownloadFontAwesome: false,\n\t\t\t\ttoolbar: false,\n\t\t\t\tstatus: false,\n\t\t\t\tforceSync: true\n\t\t\t});\n\t\t\tvar editorElement = $(simplemde.codemirror.getWrapperElement());\n\n\t\t\tsimplemde.value(scope.note.content);\n\t\t\tsimplemde.codemirror.focus();\n\n\t\t\tsimplemde.codemirror.on('change', function() {\n\t\t\t\t$timeout(function() {\n\t\t\t\t\tscope.$apply(function () {\n\t\t\t\t\t\tscope.note.content = simplemde.value();\n\t\t\t\t\t\tscope.onEdit();\n\t\t\t\t\t\tscope.updateTitle();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\n\t\t\teditorElement.on('click', '.cm-link, .cm-url', function(event) {\n\t\t\t\tif(event.ctrlKey) {\n\t\t\t\t\tvar url = urlFinder(this);\n\t\t\t\t\tif(angular.isDefined(url)) {\n\t\t\t\t\t\twindow.open(url, '_blank');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesTooltip', function () {\n 'use strict';\n\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.tooltip({'container': 'body'});\n\n element.on('$destroy', function() {\n element.tooltip('hide');\n });\n\n element.on('click', function() {\n element.tooltip('hide');\n });\n }\n };\n});\n\n/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('debounce', ['$timeout', function($timeout) {\n\t'use strict';\n\n\treturn function debounce(func, delay) {\n\t\tvar timeout;\n\n\t\treturn function() {\n\t\t\tvar context = this, args = arguments;\n\n\t\t\tif(timeout) {\n\t\t\t\t$timeout.cancel(timeout);\n\t\t\t}\n\t\t\ttimeout = $timeout(function() {\n\t\t\t\tfunc.apply(context, args);\n\t\t\t}, delay);\n\t\t};\n\t};\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('is', function () {\n 'use strict';\n\n return {\n loading: false\n };\n});\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// take care of fileconflicts by appending a number\napp.factory('NotesModel', function () {\n 'use strict';\n\n var NotesModel = function () {\n this.notes = [];\n this.notesIds = {};\n };\n\n NotesModel.prototype = {\n addAll: function (notes) {\n for(var i=0; i<notes.length; i+=1) {\n this.add(notes[i]);\n }\n },\n add: function(note) {\n this.updateIfExists(note);\n },\n getAll: function () {\n return this.notes;\n },\n get: function (id) {\n if(this.notesIds[id].error) {\n OC.Notification.show(\n this.notesIds[id].errorMessage,\n { type: 'error' }\n );\n return false;\n }\n return this.notesIds[id];\n },\n updateIfExists: function(updated) {\n var note = this.notesIds[updated.id];\n if(angular.isDefined(note)) {\n // don't update meta-data over full data\n if(updated.content !== null || note.content === null) {\n note.title = updated.title;\n note.modified = updated.modified;\n note.content = updated.content;\n note.favorite = updated.favorite;\n note.category = updated.category;\n note.error = updated.error;\n note.errorMessage = updated.errorMessage;\n }\n } else {\n this.notes.push(updated);\n this.notesIds[updated.id] = updated;\n }\n },\n remove: function (id) {\n for(var i=0; i<this.notes.length; i+=1) {\n var note = this.notes[i];\n if(note.id === id) {\n this.notes.splice(i, 1);\n delete this.notesIds[id];\n break;\n }\n }\n },\n\n nthIndexOf: function(str, pattern, n) {\n var i = -1;\n while (n-- && i++ < str.length) {\n i = str.indexOf(pattern, i);\n if (i < 0) {\n break;\n }\n }\n return i;\n },\n\n getCategories: function (notes, maxLevel, details) {\n var categories = {};\n for(var i=0; i<notes.length; i+=1) {\n var cat = notes[i].category;\n if(maxLevel>0) {\n var index = this.nthIndexOf(cat, '/', maxLevel);\n if(index>0) {\n cat = cat.substring(0, index);\n }\n }\n if(categories[cat]===undefined) {\n categories[cat] = 1;\n } else {\n categories[cat] += 1;\n }\n }\n var result = [];\n for(var category in categories) {\n if(details) {\n result.push({\n name: category,\n count: categories[category],\n });\n } else if(category) {\n result.push(category);\n }\n }\n if(!details) {\n result.sort();\n }\n return result;\n },\n\n };\n\n return new NotesModel();\n});\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('SaveQueue', [\"$q\", function($q) {\n 'use strict';\n\n var SaveQueue = function () {\n this._queue = {};\n this._flushLock = false;\n this._manualSaveActive = false;\n };\n\n SaveQueue.prototype = {\n add: function (note) {\n this._queue[note.id] = note;\n this._flush();\n },\n addManual: function (note) {\n this._manualSaveActive = true;\n this.add(note);\n },\n _flush: function () {\n // if there are no changes dont execute the requests\n var keys = Object.keys(this._queue);\n if(keys.length === 0 || this._flushLock) {\n return;\n } else {\n this._flushLock = true;\n }\n\n var self = this;\n var requests = [];\n\n // iterate over updated objects and run an update request for\n // each one of them\n for(var i=0; i<keys.length; i+=1) {\n var note = this._queue[keys[i]];\n // if the update finished, update the modified and title\n // attributes on the note\n requests.push(note.put().then(\n this._noteUpdateRequest.bind(null, note))\n .catch(this._saveFailed.bind(null, note))\n );\n }\n this._queue = {};\n\n // if all update requests are completed, run the flush\n // again to update the next batch of queued notes\n $q.all(requests).then(function () {\n self._flushLock = false;\n self._flush();\n self._manualSaveActive = false;\n });\n },\n _noteUpdateRequest: function (note, response) {\n note.error = false;\n note.title = response.title;\n note.modified = response.modified;\n note.category = response.category;\n if(response.content === note.content) {\n note.unsaved = false;\n }\n },\n _saveFailed: function (note) {\n note.error = true;\n },\n isSaving: function () {\n return this._flushLock;\n },\n isManualSaving: function () {\n return this._manualSaveActive;\n },\n };\n\n return new SaveQueue();\n}]);\n\n/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// finds the url which should be opened when a link is clicked\n// example: '[hello](http://example.com)'\napp.factory('urlFinder', [function() {\n\t'use strict';\n\n\treturn function urlFinder(element) {\n\t\telement = $(element);\n\n\t\t// special case: click on ')'\n\t\tif(element.is('.cm-url.cm-formatting')) {\n\t\t\tif(element.prev().length !== 0) {\n\t\t\t\telement = element.prev();\n\t\t\t}\n\t\t}\n\n\t\t// skip '[hello]'\n\t\twhile(element.is('.cm-link')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// skip '('\n\t\twhile(element.is('.cm-url.cm-formatting')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// check if we actually have a cm-url\n\t\tif(element.is('.cm-url:not(.cm-formatting)')) {\n\t\t\treturn element.text();\n\t\t}\n\n\t\treturn undefined;\n\t};\n}]);\n})(angular, jQuery, oc_requesttoken, SimpleMDE);","/**\n * filter by multiple words (AND operation)\n */\napp.filter('and', ['$filter', function ($filter) {\n\t'use strict';\n\treturn function (items, searchString) {\n\t\tvar searchValues = searchString.split(' ');\n\t\tvar filtered = items;\n\t\tfor(var i in searchValues) {\n\t\t\tfiltered = $filter('filter')(filtered, searchValues[i]);\n\t\t}\n\t\treturn filtered;\n\t};\n}]);\n","app.filter('categoryTitle', function () {\n\t'use strict';\n\treturn function (str) {\n\t\tif (str && (typeof str === 'string')) {\n\t\t\treturn str.replace(/\\//g, ' / ');\n\t\t} else {\n\t\t\treturn '';\n\t\t}\n\t};\n});\n","/**\n * group notes by (sub) category\n */\napp.filter('groupNotes', function () {\n\t'use strict';\n\treturn function (items, category) {\n\t\tif(category) {\n\t\t\tvar prevCat = null;\n\t\t\tfor(var i=0; i<items.length; i+=1) {\n\t\t\t\tvar note = items[i];\n\t\t\t\tif(prevCat !== null && prevCat !== note.category) {\n\t\t\t\t\titems.splice(i, 0,\n\t\t\t\t\t\tnote.category.substring(category.length+1));\n\t\t\t\t}\n\t\t\t\tprevCat = note.category;\n\t\t\t}\n\t\t\treturn items;\n\t\t} else {\n\t\t\treturn items;\n\t\t}\n\t};\n});\n","app.filter('wordCount', function () {\n\t'use strict';\n\treturn function (value) {\n\t\tif (value && (typeof value === 'string')) {\n\t\t\tvar wordCount = value.split(/\\s+/).filter(\n\t\t\t\t// only count words containing\n\t\t\t\t// at least one alphanumeric character\n\t\t\t\tfunction(value) {\n\t\t\t\t\treturn value.search(/[A-Za-z0-9]/) !== -1;\n\t\t\t\t}\n\t\t\t).length;\n\t\t\treturn window.n('notes', '%n word', '%n words', wordCount);\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t};\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesAutofocus', function () {\n 'use strict';\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.focus();\n }\n };\n});\n","/*global SimpleMDE*/\napp.directive('editor', ['$timeout',\n 'urlFinder',\n function ($timeout, urlFinder) {\n\t'use strict';\n\treturn {\n\t\trestrict: 'A',\n\t\tlink: function(scope, element) {\n\n\t\t\tvar simplemde = new SimpleMDE({\n\t\t\t\telement: element[0],\n\t\t\t\tspellChecker: false,\n\t\t\t\tautoDownloadFontAwesome: false,\n\t\t\t\ttoolbar: false,\n\t\t\t\tstatus: false,\n\t\t\t\tforceSync: true\n\t\t\t});\n\t\t\tvar editorElement = $(simplemde.codemirror.getWrapperElement());\n\n\t\t\tsimplemde.value(scope.note.content);\n\t\t\tsimplemde.codemirror.focus();\n\n\t\t\tsimplemde.codemirror.on('change', function() {\n\t\t\t\t$timeout(function() {\n\t\t\t\t\tscope.$apply(function () {\n\t\t\t\t\t\tscope.note.content = simplemde.value();\n\t\t\t\t\t\tscope.onEdit();\n\t\t\t\t\t\tscope.updateTitle();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\n\t\t\teditorElement.on('click', '.cm-link, .cm-url', function(event) {\n\t\t\t\tif(event.ctrlKey) {\n\t\t\t\t\tvar url = urlFinder(this);\n\t\t\t\t\tif(angular.isDefined(url)) {\n\t\t\t\t\t\twindow.open(url, '_blank');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n}]);\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesTooltip', function () {\n 'use strict';\n\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.tooltip({'container': 'body'});\n\n element.on('$destroy', function() {\n element.tooltip('hide');\n });\n\n element.on('click', function() {\n element.tooltip('hide');\n });\n }\n };\n});\n","/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('debounce', ['$timeout', function($timeout) {\n\t'use strict';\n\n\treturn function debounce(func, delay) {\n\t\tvar timeout;\n\n\t\treturn function() {\n\t\t\tvar context = this, args = arguments;\n\n\t\t\tif(timeout) {\n\t\t\t\t$timeout.cancel(timeout);\n\t\t\t}\n\t\t\ttimeout = $timeout(function() {\n\t\t\t\tfunc.apply(context, args);\n\t\t\t}, delay);\n\t\t};\n\t};\n}]);\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('is', function () {\n 'use strict';\n\n return {\n loading: false\n };\n});","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// take care of fileconflicts by appending a number\napp.factory('NotesModel', function () {\n 'use strict';\n\n var NotesModel = function () {\n this.notes = [];\n this.notesIds = {};\n };\n\n NotesModel.prototype = {\n addAll: function (notes) {\n for(var i=0; i<notes.length; i+=1) {\n this.add(notes[i]);\n }\n },\n add: function(note) {\n this.updateIfExists(note);\n },\n getAll: function () {\n return this.notes;\n },\n get: function (id) {\n if(this.notesIds[id].error) {\n OC.Notification.show(\n this.notesIds[id].errorMessage,\n { type: 'error' }\n );\n return false;\n }\n return this.notesIds[id];\n },\n updateIfExists: function(updated) {\n var note = this.notesIds[updated.id];\n if(angular.isDefined(note)) {\n // don't update meta-data over full data\n if(updated.content !== null || note.content === null) {\n note.title = updated.title;\n note.modified = updated.modified;\n note.content = updated.content;\n note.favorite = updated.favorite;\n note.category = updated.category;\n note.error = updated.error;\n note.errorMessage = updated.errorMessage;\n }\n } else {\n this.notes.push(updated);\n this.notesIds[updated.id] = updated;\n }\n },\n remove: function (id) {\n for(var i=0; i<this.notes.length; i+=1) {\n var note = this.notes[i];\n if(note.id === id) {\n this.notes.splice(i, 1);\n delete this.notesIds[id];\n break;\n }\n }\n },\n\n nthIndexOf: function(str, pattern, n) {\n var i = -1;\n while (n-- && i++ < str.length) {\n i = str.indexOf(pattern, i);\n if (i < 0) {\n break;\n }\n }\n return i;\n },\n\n getCategories: function (notes, maxLevel, details) {\n var categories = {};\n for(var i=0; i<notes.length; i+=1) {\n var cat = notes[i].category;\n if(maxLevel>0) {\n var index = this.nthIndexOf(cat, '/', maxLevel);\n if(index>0) {\n cat = cat.substring(0, index);\n }\n }\n if(categories[cat]===undefined) {\n categories[cat] = 1;\n } else {\n categories[cat] += 1;\n }\n }\n var result = [];\n for(var category in categories) {\n if(details) {\n result.push({\n name: category,\n count: categories[category],\n });\n } else if(category) {\n result.push(category);\n }\n }\n if(!details) {\n result.sort();\n }\n return result;\n },\n\n };\n\n return new NotesModel();\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('SaveQueue', function($q) {\n 'use strict';\n\n var SaveQueue = function () {\n this._queue = {};\n this._flushLock = false;\n this._manualSaveActive = false;\n };\n\n SaveQueue.prototype = {\n add: function (note) {\n this._queue[note.id] = note;\n this._flush();\n },\n addManual: function (note) {\n this._manualSaveActive = true;\n this.add(note);\n },\n _flush: function () {\n // if there are no changes dont execute the requests\n var keys = Object.keys(this._queue);\n if(keys.length === 0 || this._flushLock) {\n return;\n } else {\n this._flushLock = true;\n }\n\n var self = this;\n var requests = [];\n\n // iterate over updated objects and run an update request for\n // each one of them\n for(var i=0; i<keys.length; i+=1) {\n var note = this._queue[keys[i]];\n // if the update finished, update the modified and title\n // attributes on the note\n requests.push(note.put().then(\n this._noteUpdateRequest.bind(null, note))\n .catch(this._saveFailed.bind(null, note))\n );\n }\n this._queue = {};\n\n // if all update requests are completed, run the flush\n // again to update the next batch of queued notes\n $q.all(requests).then(function () {\n self._flushLock = false;\n self._flush();\n self._manualSaveActive = false;\n });\n },\n _noteUpdateRequest: function (note, response) {\n note.error = false;\n note.title = response.title;\n note.modified = response.modified;\n note.category = response.category;\n if(response.content === note.content) {\n note.unsaved = false;\n }\n },\n _saveFailed: function (note) {\n note.error = true;\n },\n isSaving: function () {\n return this._flushLock;\n },\n isManualSaving: function () {\n return this._manualSaveActive;\n },\n };\n\n return new SaveQueue();\n});\n","/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// finds the url which should be opened when a link is clicked\n// example: '[hello](http://example.com)'\napp.factory('urlFinder', [function() {\n\t'use strict';\n\n\treturn function urlFinder(element) {\n\t\telement = $(element);\n\n\t\t// special case: click on ')'\n\t\tif(element.is('.cm-url.cm-formatting')) {\n\t\t\tif(element.prev().length !== 0) {\n\t\t\t\telement = element.prev();\n\t\t\t}\n\t\t}\n\n\t\t// skip '[hello]'\n\t\twhile(element.is('.cm-link')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// skip '('\n\t\twhile(element.is('.cm-url.cm-formatting')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// check if we actually have a cm-url\n\t\tif(element.is('.cm-url:not(.cm-formatting)')) {\n\t\t\treturn element.text();\n\t\t}\n\n\t\treturn undefined;\n\t};\n}]);\n"]} \ No newline at end of file
+{"version":3,"sources":["app.js","controllers/appcontroller.js","controllers/notecontroller.js","controllers/notescontroller.js","controllers/notessettingscontroller.js","app.min.js","directives/autofocus.js","directives/editor.js","directives/tooltip.js","filters/and.js","filters/categoryTitle.js","filters/groupNotes.js","filters/wordCount.js","services/debounce.js","services/is.js","services/notesmodel.js","services/savequeue.js","services/urlFinder.js"],"names":["angular","$","requestToken","SimpleMDE","undefined","app","module","config","$provide","$routeProvider","RestangularProvider","$httpProvider","$windowProvider","defaults","headers","common","requesttoken","value","saveInterval","when","templateUrl","controller","resolve","note","$route","$q","is","Restangular","deferred","defer","noteId","current","params","loading","one","get","then","reject","promise","otherwise","redirectTo","baseUrl","OC","generateUrl","setBaseUrl","run","$rootScope","$location","NotesModel","attr","filePath","$on","notes","getAll","length","sorted","sort","a","b","modified","path","id","$scope","init","lastViewedNote","errorMessage","useSearchAPI","defaultTitle","document","title","Notification","showTemporary","initSearch","search","OCA","Search","query","$apply","css","hasClass","click","$routeParams","SaveQueue","debounce","$document","$timeout","updateIfExists","isSaving","isManualSaving","updateTitle","content","replace","trim","split","t","onEdit","unsaved","autoSave","add","manualSave","error","addManual","editCategory","showEditCategory","val","category","autocomplete","source","getCategories","minLength","position","my","at","of","open","width","innerWidth","addClass","insertAfter","focus","saveCategory","isCategorySaving","customPUT","updatedNote","unbind","bind","event","ctrlKey","metaKey","String","fromCharCode","which","toLowerCase","preventDefault","toggleDistractionFree","launchIntoFullscreen","element","requestFullscreen","mozRequestFullScreen","webkitRequestFullscreen","msRequestFullscreen","exitFullscreen","mozCancelFullScreen","webkitExitFullscreen","fullscreenElement","mozFullScreenElement","webkitFullscreenElement","getElementById","$watch","newValue","$window","route","notesLoaded","folderSelectorOpen","filterCategory","orderRecent","orderAlpha","filterOrder","notesResource","all","getList","addAll","create","post","remove","$emit","toggleFavorite","favorite","target","blur","categories","toggleFolderSelector","setFilter","animate","scrollTop","categoryFilter","startsWith","isCategory","item","onbeforeunload","i","extensions","settings","isObject","on","msg","show","put","window","location","reload","directive","restrict","link","scope","urlFinder","simplemde","spellChecker","autoDownloadFontAwesome","toolbar","status","forceSync","editorElement","codemirror","getWrapperElement","url","this","isDefined","tooltip","container","filter","$filter","items","searchString","searchValues","filtered","str","prevCat","splice","substring","wordCount","n","factory","func","delay","timeout","context","args","arguments","cancel","apply","notesIds","prototype","type","updated","push","nthIndexOf","pattern","indexOf","maxLevel","details","cat","index","result","name","count","_queue","_flushLock","_manualSaveActive","_flush","keys","Object","self","requests","_noteUpdateRequest","_saveFailed","response","prev","next","text","jQuery","oc_requesttoken"],"mappings":"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","file":"app.min.js","sourcesContent":["/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n/* jshint unused: false */\nvar app = angular.module('Notes', ['restangular', 'ngRoute']).\nconfig(function($provide, $routeProvider, RestangularProvider, $httpProvider,\n $windowProvider) {\n 'use strict';\n\n // Always send the CSRF token by default\n $httpProvider.defaults.headers.common.requesttoken = requestToken;\n\n // you have to use $provide inside the config method to provide a globally\n // shared and injectable object\n $provide.value('Constants', {\n saveInterval: 5*1000 // miliseconds\n });\n\n // define your routes that that load templates into the ng-view\n $routeProvider.when('/notes/:noteId', {\n templateUrl: 'note.html',\n controller: 'NoteController',\n resolve: {\n // $routeParams does not work inside resolve so use $route\n // note is the name of the argument that will be injected into the\n // controller\n /* @ngInject */\n note: function ($route, $q, is, Restangular) {\n\n var deferred = $q.defer();\n var noteId = $route.current.params.noteId;\n is.loading = true;\n\n Restangular.one('notes', noteId).get().then(function (note) {\n is.loading = false;\n deferred.resolve(note);\n }, function () {\n is.loading = false;\n deferred.reject();\n });\n\n return deferred.promise;\n }\n }\n }).otherwise({\n redirectTo: '/'\n });\n\n var baseUrl = OC.generateUrl('/apps/notes');\n RestangularProvider.setBaseUrl(baseUrl);\n\n\n\n}).run(function ($rootScope, $location, NotesModel) {\n 'use strict';\n\n $('link[rel=\"shortcut icon\"]').attr(\n\t\t 'href',\n\t\t OC.filePath('notes', 'img', 'favicon.png')\n );\n\n // handle route errors\n $rootScope.$on('$routeChangeError', function () {\n var notes = NotesModel.getAll();\n\n // route change error should redirect to the latest note if possible\n if (notes.length > 0) {\n var sorted = notes.sort(function (a, b) {\n if(a.modified > b.modified) {\n return 1;\n } else if(a.modified < b.modified) {\n return -1;\n } else {\n return 0;\n }\n });\n\n var note = notes[sorted.length-1];\n $location.path('/notes/' + note.id);\n } else {\n $location.path('/');\n }\n });\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('AppController', function ($scope, $location, is) {\n 'use strict';\n\n $scope.is = is;\n\n $scope.init = function (lastViewedNote, errorMessage, useSearchAPI) {\n $scope.defaultTitle = document.title;\n\n if(lastViewedNote !== 0 && $location.path()==='') {\n $location.path('/notes/' + lastViewedNote);\n }\n if(errorMessage) {\n OC.Notification.showTemporary(errorMessage);\n }\n if(useSearchAPI) {\n $scope.initSearch();\n }\n };\n\n $scope.search = '';\n $scope.defaultTitle = null;\n\n $scope.initSearch = function() {\n new OCA.Search(\n function (query) {\n $scope.search = query;\n $scope.$apply();\n if($('#app-navigation-toggle').css('display')!=='none' &&\n !$('body').hasClass('snapjs-left')) {\n $('#app-navigation-toggle').click();\n }\n },\n function () {\n $scope.search = '';\n $scope.$apply();\n }\n );\n };\n\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('NoteController', function($routeParams, $scope, NotesModel,\n SaveQueue, note, debounce,\n $document, $timeout) {\n 'use strict';\n\n NotesModel.updateIfExists(note);\n\n $scope.note = NotesModel.get($routeParams.noteId);\n\n $scope.isSaving = function () {\n return SaveQueue.isSaving();\n };\n $scope.isManualSaving = function () {\n return SaveQueue.isManualSaving();\n };\n\n $scope.updateTitle = function () {\n var content = $scope.note.content;\n\n // prepare content: remove markdown characters and empty spaces\n content = content.replace(/^\\s*[*+-]\\s+/mg, ''); // list item\n content = content.replace(/^#+\\s+(.*?)\\s*#*$/mg, '$1'); // headline\n content = content.replace(/^(=+|-+)$/mg, ''); // separate headline\n content = content.replace(/(\\*+|_+)(.*?)\\1/mg, '$2'); // emphasis\n\n // prevent directory traversal, illegal characters\n content = content.replace(/[\\*\\|\\/\\\\\\:\\\"<>\\?]/g, '');\n // prevent unintended file names\n content = content.replace(/^[\\. ]+/mg, '');\n\n // generate title from the first line of the content\n $scope.note.title = content.trim().split(/\\r?\\n/, 2)[0] ||\n t('notes', 'New note');\n };\n\n $scope.onEdit = function() {\n var note = $scope.note;\n note.unsaved = true;\n $scope.autoSave(note);\n };\n\n $scope.autoSave = debounce(function(note) {\n SaveQueue.add(note);\n }, 1000);\n\n $scope.manualSave = function() {\n var note = $scope.note;\n note.error = false;\n SaveQueue.addManual(note);\n };\n\n $scope.editCategory = false;\n $scope.showEditCategory = function() {\n $('#category').val($scope.note.category);\n $scope.editCategory = true;\n $('#category').autocomplete({\n source: NotesModel.getCategories(NotesModel.getAll(), 0, false),\n minLength: 0,\n position: { my: 'left bottom', at: 'left top', of: '#category' },\n open: function() {\n $timeout(function() {\n var width = $('form.category').innerWidth() - 2;\n $('.ui-autocomplete.ui-menu').width(width);\n });\n },\n }).autocomplete('widget').addClass('category-autocomplete');\n // fix space between input and confirm-button\n $('form.category .icon-confirm').insertAfter('#category');\n\n $timeout(function() {\n $('#category').focus();\n $('#category').autocomplete('search', '');\n });\n };\n $scope.saveCategory = function () {\n var category = $('#category').val();\n if($scope.note.category === category) {\n $scope.editCategory = false;\n return;\n }\n $scope.isCategorySaving = true;\n $scope.note.customPUT({category: category}, 'category', {}, {})\n .then(\n function (updatedNote) {\n $scope.note.category = updatedNote.category;\n if(category !== updatedNote.category) {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.'+\n ' Is the target directory writable?')\n );\n }\n },\n function () {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.')\n );\n }\n )\n .finally(\n function () {\n $scope.isCategorySaving = false;\n $scope.editCategory = false;\n }\n );\n };\n\n\n $document.unbind('keypress.notes.save');\n $document.bind('keypress.notes.save', function(event) {\n if(event.ctrlKey || event.metaKey) {\n switch(String.fromCharCode(event.which).toLowerCase()) {\n case 's':\n event.preventDefault();\n $scope.manualSave();\n break;\n }\n }\n });\n\n $scope.toggleDistractionFree = function() {\n function launchIntoFullscreen(element) {\n if(element.requestFullscreen) {\n element.requestFullscreen();\n } else if(element.mozRequestFullScreen) {\n element.mozRequestFullScreen();\n } else if(element.webkitRequestFullscreen) {\n element.webkitRequestFullscreen();\n } else if(element.msRequestFullscreen) {\n element.msRequestFullscreen();\n }\n }\n\n function exitFullscreen() {\n if(document.exitFullscreen) {\n document.exitFullscreen();\n } else if(document.mozCancelFullScreen) {\n document.mozCancelFullScreen();\n } else if(document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n }\n }\n\n if(document.fullscreenElement ||\n document.mozFullScreenElement ||\n document.webkitFullscreenElement) {\n exitFullscreen();\n } else {\n launchIntoFullscreen(document.getElementById('app-content'));\n }\n };\n\n $scope.$watch(function() {\n return $scope.note.title;\n }, function(newValue) {\n if(newValue) {\n document.title = newValue + ' - ' + $scope.defaultTitle;\n } else {\n document.title = $scope.defaultTitle;\n }\n });\n\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// This is available by using ng-controller=\"NotesController\" in your HTML\napp.controller('NotesController', function($routeParams, $scope, $location,\n Restangular, NotesModel, $window) {\n 'use strict';\n\n $scope.route = $routeParams;\n $scope.notesLoaded = false;\n $scope.notes = NotesModel.getAll();\n\n $scope.folderSelectorOpen = false;\n $scope.filterCategory = null;\n\n $scope.orderRecent = ['-favorite','-modified'];\n $scope.orderAlpha = ['category','-favorite','title'];\n $scope.filterOrder = $scope.orderRecent;\n\n var notesResource = Restangular.all('notes');\n\n // initial request for getting all notes\n notesResource.getList().then(function (notes) {\n NotesModel.addAll(notes);\n $scope.notesLoaded = true;\n });\n\n $scope.create = function () {\n notesResource.post({category: $scope.filterCategory})\n .then(function (note) {\n NotesModel.add(note);\n $location.path('/notes/' + note.id);\n });\n };\n\n $scope.delete = function (noteId) {\n var note = NotesModel.get(noteId);\n note.remove().then(function () {\n NotesModel.remove(noteId);\n $scope.$emit('$routeChangeError');\n });\n };\n\n $scope.toggleFavorite = function (noteId, event) {\n var note = NotesModel.get(noteId);\n note.customPUT({favorite: !note.favorite},\n 'favorite', {}, {}).then(function (favorite) {\n note.favorite = favorite ? true : false;\n });\n event.target.blur();\n };\n\n $scope.categories = [];\n $scope.$watch('notes', function(notes) {\n $scope.categories = NotesModel.getCategories(notes, 1, true);\n }, true);\n\n $scope.toggleFolderSelector = function () {\n $scope.folderSelectorOpen = !$scope.folderSelectorOpen;\n };\n\n $scope.setFilter = function (category) {\n if(category===null) {\n $scope.filterOrder = $scope.orderRecent;\n } else {\n $scope.filterOrder = $scope.orderAlpha;\n }\n $scope.filterCategory = category;\n $scope.folderSelectorOpen = false;\n $('#app-navigation > ul').animate({scrollTop: 0}, 'fast');\n };\n\n $scope.categoryFilter = function (note) {\n if($scope.filterCategory!==null) {\n if(note.category===$scope.filterCategory) {\n return true;\n } else if(note.category!==null) {\n return note.category.startsWith($scope.filterCategory+'/');\n }\n }\n return true;\n };\n\n $scope.isCategory = function (item) {\n return typeof item === 'string';\n };\n\n $window.onbeforeunload = function() {\n var notes = NotesModel.getAll();\n for(var i=0; i<notes.length; i+=1) {\n if(notes[i].unsaved) {\n return t('notes', 'There are unsaved notes. Leaving ' +\n 'the page will discard all changes!');\n }\n }\n return null;\n };\n});\n","app.controller('NotesSettingsController',\n function($scope, Restangular, $document) {\n 'use strict';\n\n $scope.extensions = ['.txt', '.md'];\n\n Restangular.one('settings').get().then(function(settings) {\n if(angular.isObject(settings)) {\n $scope.settings = settings;\n } else {\n $scope.settings = Restangular.one('settings');\n }\n });\n\n $document.on('change', '#notesPath', function() {\n var msg = t('notes', 'Please wait while new settings are applied…');\n OC.Notification.show(msg);\n $scope.settings.put().then(function() {\n window.location.reload(true);\n });\n });\n\n $document.on('change', '#fileSuffix', function() {\n $scope.settings.put();\n });\n});\n","(function(angular, $, requestToken, SimpleMDE, undefined){'use strict';/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n/* jshint unused: false */\nvar app = angular.module('Notes', ['restangular', 'ngRoute']).\nconfig([\"$provide\", \"$routeProvider\", \"RestangularProvider\", \"$httpProvider\", \"$windowProvider\", function($provide, $routeProvider, RestangularProvider, $httpProvider,\n $windowProvider) {\n 'use strict';\n\n // Always send the CSRF token by default\n $httpProvider.defaults.headers.common.requesttoken = requestToken;\n\n // you have to use $provide inside the config method to provide a globally\n // shared and injectable object\n $provide.value('Constants', {\n saveInterval: 5*1000 // miliseconds\n });\n\n // define your routes that that load templates into the ng-view\n $routeProvider.when('/notes/:noteId', {\n templateUrl: 'note.html',\n controller: 'NoteController',\n resolve: {\n // $routeParams does not work inside resolve so use $route\n // note is the name of the argument that will be injected into the\n // controller\n /* @ngInject */\n note: [\"$route\", \"$q\", \"is\", \"Restangular\", function ($route, $q, is, Restangular) {\n\n var deferred = $q.defer();\n var noteId = $route.current.params.noteId;\n is.loading = true;\n\n Restangular.one('notes', noteId).get().then(function (note) {\n is.loading = false;\n deferred.resolve(note);\n }, function () {\n is.loading = false;\n deferred.reject();\n });\n\n return deferred.promise;\n }]\n }\n }).otherwise({\n redirectTo: '/'\n });\n\n var baseUrl = OC.generateUrl('/apps/notes');\n RestangularProvider.setBaseUrl(baseUrl);\n\n\n\n}]).run([\"$rootScope\", \"$location\", \"NotesModel\", function ($rootScope, $location, NotesModel) {\n 'use strict';\n\n $('link[rel=\"shortcut icon\"]').attr(\n\t\t 'href',\n\t\t OC.filePath('notes', 'img', 'favicon.png')\n );\n\n // handle route errors\n $rootScope.$on('$routeChangeError', function () {\n var notes = NotesModel.getAll();\n\n // route change error should redirect to the latest note if possible\n if (notes.length > 0) {\n var sorted = notes.sort(function (a, b) {\n if(a.modified > b.modified) {\n return 1;\n } else if(a.modified < b.modified) {\n return -1;\n } else {\n return 0;\n }\n });\n\n var note = notes[sorted.length-1];\n $location.path('/notes/' + note.id);\n } else {\n $location.path('/');\n }\n });\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('AppController', [\"$scope\", \"$location\", \"is\", function ($scope, $location, is) {\n 'use strict';\n\n $scope.is = is;\n\n $scope.init = function (lastViewedNote, errorMessage, useSearchAPI) {\n $scope.defaultTitle = document.title;\n\n if(lastViewedNote !== 0 && $location.path()==='') {\n $location.path('/notes/' + lastViewedNote);\n }\n if(errorMessage) {\n OC.Notification.showTemporary(errorMessage);\n }\n if(useSearchAPI) {\n $scope.initSearch();\n }\n };\n\n $scope.search = '';\n $scope.defaultTitle = null;\n\n $scope.initSearch = function() {\n new OCA.Search(\n function (query) {\n $scope.search = query;\n $scope.$apply();\n if($('#app-navigation-toggle').css('display')!=='none' &&\n !$('body').hasClass('snapjs-left')) {\n $('#app-navigation-toggle').click();\n }\n },\n function () {\n $scope.search = '';\n $scope.$apply();\n }\n );\n };\n\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.controller('NoteController', [\"$routeParams\", \"$scope\", \"NotesModel\", \"SaveQueue\", \"note\", \"debounce\", \"$document\", \"$timeout\", function($routeParams, $scope, NotesModel,\n SaveQueue, note, debounce,\n $document, $timeout) {\n 'use strict';\n\n NotesModel.updateIfExists(note);\n\n $scope.note = NotesModel.get($routeParams.noteId);\n\n $scope.isSaving = function () {\n return SaveQueue.isSaving();\n };\n $scope.isManualSaving = function () {\n return SaveQueue.isManualSaving();\n };\n\n $scope.updateTitle = function () {\n var content = $scope.note.content;\n\n // prepare content: remove markdown characters and empty spaces\n content = content.replace(/^\\s*[*+-]\\s+/mg, ''); // list item\n content = content.replace(/^#+\\s+(.*?)\\s*#*$/mg, '$1'); // headline\n content = content.replace(/^(=+|-+)$/mg, ''); // separate headline\n content = content.replace(/(\\*+|_+)(.*?)\\1/mg, '$2'); // emphasis\n\n // prevent directory traversal, illegal characters\n content = content.replace(/[\\*\\|\\/\\\\\\:\\\"<>\\?]/g, '');\n // prevent unintended file names\n content = content.replace(/^[\\. ]+/mg, '');\n\n // generate title from the first line of the content\n $scope.note.title = content.trim().split(/\\r?\\n/, 2)[0] ||\n t('notes', 'New note');\n };\n\n $scope.onEdit = function() {\n var note = $scope.note;\n note.unsaved = true;\n $scope.autoSave(note);\n };\n\n $scope.autoSave = debounce(function(note) {\n SaveQueue.add(note);\n }, 1000);\n\n $scope.manualSave = function() {\n var note = $scope.note;\n note.error = false;\n SaveQueue.addManual(note);\n };\n\n $scope.editCategory = false;\n $scope.showEditCategory = function() {\n $('#category').val($scope.note.category);\n $scope.editCategory = true;\n $('#category').autocomplete({\n source: NotesModel.getCategories(NotesModel.getAll(), 0, false),\n minLength: 0,\n position: { my: 'left bottom', at: 'left top', of: '#category' },\n open: function() {\n $timeout(function() {\n var width = $('form.category').innerWidth() - 2;\n $('.ui-autocomplete.ui-menu').width(width);\n });\n },\n }).autocomplete('widget').addClass('category-autocomplete');\n // fix space between input and confirm-button\n $('form.category .icon-confirm').insertAfter('#category');\n\n $timeout(function() {\n $('#category').focus();\n $('#category').autocomplete('search', '');\n });\n };\n $scope.saveCategory = function () {\n var category = $('#category').val();\n if($scope.note.category === category) {\n $scope.editCategory = false;\n return;\n }\n $scope.isCategorySaving = true;\n $scope.note.customPUT({category: category}, 'category', {}, {})\n .then(\n function (updatedNote) {\n $scope.note.category = updatedNote.category;\n if(category !== updatedNote.category) {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.'+\n ' Is the target directory writable?')\n );\n }\n },\n function () {\n OC.Notification.showTemporary(\n t('notes', 'Updating the note\\'s category has failed.')\n );\n }\n )\n .finally(\n function () {\n $scope.isCategorySaving = false;\n $scope.editCategory = false;\n }\n );\n };\n\n\n $document.unbind('keypress.notes.save');\n $document.bind('keypress.notes.save', function(event) {\n if(event.ctrlKey || event.metaKey) {\n switch(String.fromCharCode(event.which).toLowerCase()) {\n case 's':\n event.preventDefault();\n $scope.manualSave();\n break;\n }\n }\n });\n\n $scope.toggleDistractionFree = function() {\n function launchIntoFullscreen(element) {\n if(element.requestFullscreen) {\n element.requestFullscreen();\n } else if(element.mozRequestFullScreen) {\n element.mozRequestFullScreen();\n } else if(element.webkitRequestFullscreen) {\n element.webkitRequestFullscreen();\n } else if(element.msRequestFullscreen) {\n element.msRequestFullscreen();\n }\n }\n\n function exitFullscreen() {\n if(document.exitFullscreen) {\n document.exitFullscreen();\n } else if(document.mozCancelFullScreen) {\n document.mozCancelFullScreen();\n } else if(document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n }\n }\n\n if(document.fullscreenElement ||\n document.mozFullScreenElement ||\n document.webkitFullscreenElement) {\n exitFullscreen();\n } else {\n launchIntoFullscreen(document.getElementById('app-content'));\n }\n };\n\n $scope.$watch(function() {\n return $scope.note.title;\n }, function(newValue) {\n if(newValue) {\n document.title = newValue + ' - ' + $scope.defaultTitle;\n } else {\n document.title = $scope.defaultTitle;\n }\n });\n\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// This is available by using ng-controller=\"NotesController\" in your HTML\napp.controller('NotesController', [\"$routeParams\", \"$scope\", \"$location\", \"Restangular\", \"NotesModel\", \"$window\", function($routeParams, $scope, $location,\n Restangular, NotesModel, $window) {\n 'use strict';\n\n $scope.route = $routeParams;\n $scope.notesLoaded = false;\n $scope.notes = NotesModel.getAll();\n\n $scope.folderSelectorOpen = false;\n $scope.filterCategory = null;\n\n $scope.orderRecent = ['-favorite','-modified'];\n $scope.orderAlpha = ['category','-favorite','title'];\n $scope.filterOrder = $scope.orderRecent;\n\n var notesResource = Restangular.all('notes');\n\n // initial request for getting all notes\n notesResource.getList().then(function (notes) {\n NotesModel.addAll(notes);\n $scope.notesLoaded = true;\n });\n\n $scope.create = function () {\n notesResource.post({category: $scope.filterCategory})\n .then(function (note) {\n NotesModel.add(note);\n $location.path('/notes/' + note.id);\n });\n };\n\n $scope.delete = function (noteId) {\n var note = NotesModel.get(noteId);\n note.remove().then(function () {\n NotesModel.remove(noteId);\n $scope.$emit('$routeChangeError');\n });\n };\n\n $scope.toggleFavorite = function (noteId, event) {\n var note = NotesModel.get(noteId);\n note.customPUT({favorite: !note.favorite},\n 'favorite', {}, {}).then(function (favorite) {\n note.favorite = favorite ? true : false;\n });\n event.target.blur();\n };\n\n $scope.categories = [];\n $scope.$watch('notes', function(notes) {\n $scope.categories = NotesModel.getCategories(notes, 1, true);\n }, true);\n\n $scope.toggleFolderSelector = function () {\n $scope.folderSelectorOpen = !$scope.folderSelectorOpen;\n };\n\n $scope.setFilter = function (category) {\n if(category===null) {\n $scope.filterOrder = $scope.orderRecent;\n } else {\n $scope.filterOrder = $scope.orderAlpha;\n }\n $scope.filterCategory = category;\n $scope.folderSelectorOpen = false;\n $('#app-navigation > ul').animate({scrollTop: 0}, 'fast');\n };\n\n $scope.categoryFilter = function (note) {\n if($scope.filterCategory!==null) {\n if(note.category===$scope.filterCategory) {\n return true;\n } else if(note.category!==null) {\n return note.category.startsWith($scope.filterCategory+'/');\n }\n }\n return true;\n };\n\n $scope.isCategory = function (item) {\n return typeof item === 'string';\n };\n\n $window.onbeforeunload = function() {\n var notes = NotesModel.getAll();\n for(var i=0; i<notes.length; i+=1) {\n if(notes[i].unsaved) {\n return t('notes', 'There are unsaved notes. Leaving ' +\n 'the page will discard all changes!');\n }\n }\n return null;\n };\n}]);\n\napp.controller('NotesSettingsController',\n [\"$scope\", \"Restangular\", \"$document\", function($scope, Restangular, $document) {\n 'use strict';\n\n $scope.extensions = ['.txt', '.md'];\n\n Restangular.one('settings').get().then(function(settings) {\n if(angular.isObject(settings)) {\n $scope.settings = settings;\n } else {\n $scope.settings = Restangular.one('settings');\n }\n });\n\n $document.on('change', '#notesPath', function() {\n var msg = t('notes', 'Please wait while new settings are applied…');\n OC.Notification.show(msg);\n $scope.settings.put().then(function() {\n window.location.reload(true);\n });\n });\n\n $document.on('change', '#fileSuffix', function() {\n $scope.settings.put();\n });\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesAutofocus', function () {\n 'use strict';\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.focus();\n }\n };\n});\n\n/*global SimpleMDE*/\napp.directive('editor', ['$timeout',\n 'urlFinder',\n function ($timeout, urlFinder) {\n\t'use strict';\n\treturn {\n\t\trestrict: 'A',\n\t\tlink: function(scope, element) {\n\n\t\t\tvar simplemde = new SimpleMDE({\n\t\t\t\telement: element[0],\n\t\t\t\tspellChecker: false,\n\t\t\t\tautoDownloadFontAwesome: false,\n\t\t\t\ttoolbar: false,\n\t\t\t\tstatus: false,\n\t\t\t\tforceSync: true\n\t\t\t});\n\t\t\tvar editorElement = $(simplemde.codemirror.getWrapperElement());\n\n\t\t\tsimplemde.value(scope.note.content);\n\t\t\tsimplemde.codemirror.focus();\n\n\t\t\tsimplemde.codemirror.on('change', function() {\n\t\t\t\t$timeout(function() {\n\t\t\t\t\tscope.$apply(function () {\n\t\t\t\t\t\tscope.note.content = simplemde.value();\n\t\t\t\t\t\tscope.onEdit();\n\t\t\t\t\t\tscope.updateTitle();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\n\t\t\teditorElement.on('click', '.cm-link, .cm-url', function(event) {\n\t\t\t\tif(event.ctrlKey) {\n\t\t\t\t\tvar url = urlFinder(this);\n\t\t\t\t\tif(angular.isDefined(url)) {\n\t\t\t\t\t\twindow.open(url, '_blank');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesTooltip', function () {\n 'use strict';\n\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.tooltip({'container': 'body'});\n\n element.on('$destroy', function() {\n element.tooltip('hide');\n });\n\n element.on('click', function() {\n element.tooltip('hide');\n });\n }\n };\n});\n\n/**\n * filter by multiple words (AND operation)\n */\napp.filter('and', ['$filter', function ($filter) {\n\t'use strict';\n\treturn function (items, searchString) {\n\t\tvar searchValues = searchString.split(' ');\n\t\tvar filtered = items;\n\t\tfor(var i in searchValues) {\n\t\t\tfiltered = $filter('filter')(filtered, searchValues[i]);\n\t\t}\n\t\treturn filtered;\n\t};\n}]);\n\napp.filter('categoryTitle', function () {\n\t'use strict';\n\treturn function (str) {\n\t\tif (str && (typeof str === 'string')) {\n\t\t\treturn str.replace(/\\//g, ' / ');\n\t\t} else {\n\t\t\treturn '';\n\t\t}\n\t};\n});\n\n/**\n * group notes by (sub) category\n */\napp.filter('groupNotes', function () {\n\t'use strict';\n\treturn function (items, category) {\n\t\tif(category) {\n\t\t\tvar prevCat = null;\n\t\t\tfor(var i=0; i<items.length; i+=1) {\n\t\t\t\tvar note = items[i];\n\t\t\t\tif(prevCat !== null && prevCat !== note.category) {\n\t\t\t\t\titems.splice(i, 0,\n\t\t\t\t\t\tnote.category.substring(category.length+1));\n\t\t\t\t}\n\t\t\t\tprevCat = note.category;\n\t\t\t}\n\t\t\treturn items;\n\t\t} else {\n\t\t\treturn items;\n\t\t}\n\t};\n});\n\napp.filter('wordCount', function () {\n\t'use strict';\n\treturn function (value) {\n\t\tif (value && (typeof value === 'string')) {\n\t\t\tvar wordCount = value.split(/\\s+/).filter(\n\t\t\t\t// only count words containing\n\t\t\t\t// at least one alphanumeric character\n\t\t\t\tfunction(value) {\n\t\t\t\t\treturn value.search(/[A-Za-z0-9]/) !== -1;\n\t\t\t\t}\n\t\t\t).length;\n\t\t\treturn window.n('notes', '%n word', '%n words', wordCount);\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t};\n});\n\n/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('debounce', ['$timeout', function($timeout) {\n\t'use strict';\n\n\treturn function debounce(func, delay) {\n\t\tvar timeout;\n\n\t\treturn function() {\n\t\t\tvar context = this, args = arguments;\n\n\t\t\tif(timeout) {\n\t\t\t\t$timeout.cancel(timeout);\n\t\t\t}\n\t\t\ttimeout = $timeout(function() {\n\t\t\t\tfunc.apply(context, args);\n\t\t\t}, delay);\n\t\t};\n\t};\n}]);\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('is', function () {\n 'use strict';\n\n return {\n loading: false\n };\n});\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// take care of fileconflicts by appending a number\napp.factory('NotesModel', function () {\n 'use strict';\n\n var NotesModel = function () {\n this.notes = [];\n this.notesIds = {};\n };\n\n NotesModel.prototype = {\n addAll: function (notes) {\n for(var i=0; i<notes.length; i+=1) {\n this.add(notes[i]);\n }\n },\n add: function(note) {\n this.updateIfExists(note);\n },\n getAll: function () {\n return this.notes;\n },\n get: function (id) {\n if(this.notesIds[id].error) {\n OC.Notification.show(\n this.notesIds[id].errorMessage,\n { type: 'error' }\n );\n return false;\n }\n return this.notesIds[id];\n },\n updateIfExists: function(updated) {\n var note = this.notesIds[updated.id];\n if(angular.isDefined(note)) {\n // don't update meta-data over full data\n if(updated.content !== null || note.content === null) {\n note.title = updated.title;\n note.modified = updated.modified;\n note.content = updated.content;\n note.favorite = updated.favorite;\n note.category = updated.category;\n note.error = updated.error;\n note.errorMessage = updated.errorMessage;\n }\n } else {\n this.notes.push(updated);\n this.notesIds[updated.id] = updated;\n }\n },\n remove: function (id) {\n for(var i=0; i<this.notes.length; i+=1) {\n var note = this.notes[i];\n if(note.id === id) {\n this.notes.splice(i, 1);\n delete this.notesIds[id];\n break;\n }\n }\n },\n\n nthIndexOf: function(str, pattern, n) {\n var i = -1;\n while (n-- && i++ < str.length) {\n i = str.indexOf(pattern, i);\n if (i < 0) {\n break;\n }\n }\n return i;\n },\n\n getCategories: function (notes, maxLevel, details) {\n var categories = {};\n for(var i=0; i<notes.length; i+=1) {\n var cat = notes[i].category;\n if(maxLevel>0) {\n var index = this.nthIndexOf(cat, '/', maxLevel);\n if(index>0) {\n cat = cat.substring(0, index);\n }\n }\n if(categories[cat]===undefined) {\n categories[cat] = 1;\n } else {\n categories[cat] += 1;\n }\n }\n var result = [];\n for(var category in categories) {\n if(details) {\n result.push({\n name: category,\n count: categories[category],\n });\n } else if(category) {\n result.push(category);\n }\n }\n if(!details) {\n result.sort();\n }\n return result;\n },\n\n };\n\n return new NotesModel();\n});\n\n/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('SaveQueue', [\"$q\", function($q) {\n 'use strict';\n\n var SaveQueue = function () {\n this._queue = {};\n this._flushLock = false;\n this._manualSaveActive = false;\n };\n\n SaveQueue.prototype = {\n add: function (note) {\n this._queue[note.id] = note;\n this._flush();\n },\n addManual: function (note) {\n this._manualSaveActive = true;\n this.add(note);\n },\n _flush: function () {\n // if there are no changes dont execute the requests\n var keys = Object.keys(this._queue);\n if(keys.length === 0 || this._flushLock) {\n return;\n } else {\n this._flushLock = true;\n }\n\n var self = this;\n var requests = [];\n\n // iterate over updated objects and run an update request for\n // each one of them\n for(var i=0; i<keys.length; i+=1) {\n var note = this._queue[keys[i]];\n // if the update finished, update the modified and title\n // attributes on the note\n requests.push(note.put().then(\n this._noteUpdateRequest.bind(null, note))\n .catch(this._saveFailed.bind(null, note))\n );\n }\n this._queue = {};\n\n // if all update requests are completed, run the flush\n // again to update the next batch of queued notes\n $q.all(requests).then(function () {\n self._flushLock = false;\n self._flush();\n self._manualSaveActive = false;\n });\n },\n _noteUpdateRequest: function (note, response) {\n note.error = false;\n note.title = response.title;\n note.modified = response.modified;\n note.category = response.category;\n if(response.content === note.content) {\n note.unsaved = false;\n }\n },\n _saveFailed: function (note) {\n note.error = true;\n },\n isSaving: function () {\n return this._flushLock;\n },\n isManualSaving: function () {\n return this._manualSaveActive;\n },\n };\n\n return new SaveQueue();\n}]);\n\n/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// finds the url which should be opened when a link is clicked\n// example: '[hello](http://example.com)'\napp.factory('urlFinder', [function() {\n\t'use strict';\n\n\treturn function urlFinder(element) {\n\t\telement = $(element);\n\n\t\t// special case: click on ')'\n\t\tif(element.is('.cm-url.cm-formatting')) {\n\t\t\tif(element.prev().length !== 0) {\n\t\t\t\telement = element.prev();\n\t\t\t}\n\t\t}\n\n\t\t// skip '[hello]'\n\t\twhile(element.is('.cm-link')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// skip '('\n\t\twhile(element.is('.cm-url.cm-formatting')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// check if we actually have a cm-url\n\t\tif(element.is('.cm-url:not(.cm-formatting)')) {\n\t\t\treturn element.text();\n\t\t}\n\n\t\treturn undefined;\n\t};\n}]);\n})(angular, jQuery, oc_requesttoken, SimpleMDE);","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesAutofocus', function () {\n 'use strict';\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.focus();\n }\n };\n});\n","/*global SimpleMDE*/\napp.directive('editor', ['$timeout',\n 'urlFinder',\n function ($timeout, urlFinder) {\n\t'use strict';\n\treturn {\n\t\trestrict: 'A',\n\t\tlink: function(scope, element) {\n\n\t\t\tvar simplemde = new SimpleMDE({\n\t\t\t\telement: element[0],\n\t\t\t\tspellChecker: false,\n\t\t\t\tautoDownloadFontAwesome: false,\n\t\t\t\ttoolbar: false,\n\t\t\t\tstatus: false,\n\t\t\t\tforceSync: true\n\t\t\t});\n\t\t\tvar editorElement = $(simplemde.codemirror.getWrapperElement());\n\n\t\t\tsimplemde.value(scope.note.content);\n\t\t\tsimplemde.codemirror.focus();\n\n\t\t\tsimplemde.codemirror.on('change', function() {\n\t\t\t\t$timeout(function() {\n\t\t\t\t\tscope.$apply(function () {\n\t\t\t\t\t\tscope.note.content = simplemde.value();\n\t\t\t\t\t\tscope.onEdit();\n\t\t\t\t\t\tscope.updateTitle();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\n\t\t\teditorElement.on('click', '.cm-link, .cm-url', function(event) {\n\t\t\t\tif(event.ctrlKey) {\n\t\t\t\t\tvar url = urlFinder(this);\n\t\t\t\t\tif(angular.isDefined(url)) {\n\t\t\t\t\t\twindow.open(url, '_blank');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n}]);\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.directive('notesTooltip', function () {\n 'use strict';\n\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.tooltip({'container': 'body'});\n\n element.on('$destroy', function() {\n element.tooltip('hide');\n });\n\n element.on('click', function() {\n element.tooltip('hide');\n });\n }\n };\n});\n","/**\n * filter by multiple words (AND operation)\n */\napp.filter('and', ['$filter', function ($filter) {\n\t'use strict';\n\treturn function (items, searchString) {\n\t\tvar searchValues = searchString.split(' ');\n\t\tvar filtered = items;\n\t\tfor(var i in searchValues) {\n\t\t\tfiltered = $filter('filter')(filtered, searchValues[i]);\n\t\t}\n\t\treturn filtered;\n\t};\n}]);\n","app.filter('categoryTitle', function () {\n\t'use strict';\n\treturn function (str) {\n\t\tif (str && (typeof str === 'string')) {\n\t\t\treturn str.replace(/\\//g, ' / ');\n\t\t} else {\n\t\t\treturn '';\n\t\t}\n\t};\n});\n","/**\n * group notes by (sub) category\n */\napp.filter('groupNotes', function () {\n\t'use strict';\n\treturn function (items, category) {\n\t\tif(category) {\n\t\t\tvar prevCat = null;\n\t\t\tfor(var i=0; i<items.length; i+=1) {\n\t\t\t\tvar note = items[i];\n\t\t\t\tif(prevCat !== null && prevCat !== note.category) {\n\t\t\t\t\titems.splice(i, 0,\n\t\t\t\t\t\tnote.category.substring(category.length+1));\n\t\t\t\t}\n\t\t\t\tprevCat = note.category;\n\t\t\t}\n\t\t\treturn items;\n\t\t} else {\n\t\t\treturn items;\n\t\t}\n\t};\n});\n","app.filter('wordCount', function () {\n\t'use strict';\n\treturn function (value) {\n\t\tif (value && (typeof value === 'string')) {\n\t\t\tvar wordCount = value.split(/\\s+/).filter(\n\t\t\t\t// only count words containing\n\t\t\t\t// at least one alphanumeric character\n\t\t\t\tfunction(value) {\n\t\t\t\t\treturn value.search(/[A-Za-z0-9]/) !== -1;\n\t\t\t\t}\n\t\t\t).length;\n\t\t\treturn window.n('notes', '%n word', '%n words', wordCount);\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t};\n});\n","/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('debounce', ['$timeout', function($timeout) {\n\t'use strict';\n\n\treturn function debounce(func, delay) {\n\t\tvar timeout;\n\n\t\treturn function() {\n\t\t\tvar context = this, args = arguments;\n\n\t\t\tif(timeout) {\n\t\t\t\t$timeout.cancel(timeout);\n\t\t\t}\n\t\t\ttimeout = $timeout(function() {\n\t\t\t\tfunc.apply(context, args);\n\t\t\t}, delay);\n\t\t};\n\t};\n}]);\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('is', function () {\n 'use strict';\n\n return {\n loading: false\n };\n});","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// take care of fileconflicts by appending a number\napp.factory('NotesModel', function () {\n 'use strict';\n\n var NotesModel = function () {\n this.notes = [];\n this.notesIds = {};\n };\n\n NotesModel.prototype = {\n addAll: function (notes) {\n for(var i=0; i<notes.length; i+=1) {\n this.add(notes[i]);\n }\n },\n add: function(note) {\n this.updateIfExists(note);\n },\n getAll: function () {\n return this.notes;\n },\n get: function (id) {\n if(this.notesIds[id].error) {\n OC.Notification.show(\n this.notesIds[id].errorMessage,\n { type: 'error' }\n );\n return false;\n }\n return this.notesIds[id];\n },\n updateIfExists: function(updated) {\n var note = this.notesIds[updated.id];\n if(angular.isDefined(note)) {\n // don't update meta-data over full data\n if(updated.content !== null || note.content === null) {\n note.title = updated.title;\n note.modified = updated.modified;\n note.content = updated.content;\n note.favorite = updated.favorite;\n note.category = updated.category;\n note.error = updated.error;\n note.errorMessage = updated.errorMessage;\n }\n } else {\n this.notes.push(updated);\n this.notesIds[updated.id] = updated;\n }\n },\n remove: function (id) {\n for(var i=0; i<this.notes.length; i+=1) {\n var note = this.notes[i];\n if(note.id === id) {\n this.notes.splice(i, 1);\n delete this.notesIds[id];\n break;\n }\n }\n },\n\n nthIndexOf: function(str, pattern, n) {\n var i = -1;\n while (n-- && i++ < str.length) {\n i = str.indexOf(pattern, i);\n if (i < 0) {\n break;\n }\n }\n return i;\n },\n\n getCategories: function (notes, maxLevel, details) {\n var categories = {};\n for(var i=0; i<notes.length; i+=1) {\n var cat = notes[i].category;\n if(maxLevel>0) {\n var index = this.nthIndexOf(cat, '/', maxLevel);\n if(index>0) {\n cat = cat.substring(0, index);\n }\n }\n if(categories[cat]===undefined) {\n categories[cat] = 1;\n } else {\n categories[cat] += 1;\n }\n }\n var result = [];\n for(var category in categories) {\n if(details) {\n result.push({\n name: category,\n count: categories[category],\n });\n } else if(category) {\n result.push(category);\n }\n }\n if(!details) {\n result.sort();\n }\n return result;\n },\n\n };\n\n return new NotesModel();\n});\n","/**\n * Copyright (c) 2013, Bernhard Posselt <dev@bernhard-posselt.com>\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\napp.factory('SaveQueue', function($q) {\n 'use strict';\n\n var SaveQueue = function () {\n this._queue = {};\n this._flushLock = false;\n this._manualSaveActive = false;\n };\n\n SaveQueue.prototype = {\n add: function (note) {\n this._queue[note.id] = note;\n this._flush();\n },\n addManual: function (note) {\n this._manualSaveActive = true;\n this.add(note);\n },\n _flush: function () {\n // if there are no changes dont execute the requests\n var keys = Object.keys(this._queue);\n if(keys.length === 0 || this._flushLock) {\n return;\n } else {\n this._flushLock = true;\n }\n\n var self = this;\n var requests = [];\n\n // iterate over updated objects and run an update request for\n // each one of them\n for(var i=0; i<keys.length; i+=1) {\n var note = this._queue[keys[i]];\n // if the update finished, update the modified and title\n // attributes on the note\n requests.push(note.put().then(\n this._noteUpdateRequest.bind(null, note))\n .catch(this._saveFailed.bind(null, note))\n );\n }\n this._queue = {};\n\n // if all update requests are completed, run the flush\n // again to update the next batch of queued notes\n $q.all(requests).then(function () {\n self._flushLock = false;\n self._flush();\n self._manualSaveActive = false;\n });\n },\n _noteUpdateRequest: function (note, response) {\n note.error = false;\n note.title = response.title;\n note.modified = response.modified;\n note.category = response.category;\n if(response.content === note.content) {\n note.unsaved = false;\n }\n },\n _saveFailed: function (note) {\n note.error = true;\n },\n isSaving: function () {\n return this._flushLock;\n },\n isManualSaving: function () {\n return this._manualSaveActive;\n },\n };\n\n return new SaveQueue();\n});\n","/**\n * Copyright (c) 2016, Hendrik Leppelsack\n * This file is licensed under the Affero General Public License version 3 or\n * later.\n * See the COPYING file.\n */\n\n// finds the url which should be opened when a link is clicked\n// example: '[hello](http://example.com)'\napp.factory('urlFinder', [function() {\n\t'use strict';\n\n\treturn function urlFinder(element) {\n\t\telement = $(element);\n\n\t\t// special case: click on ')'\n\t\tif(element.is('.cm-url.cm-formatting')) {\n\t\t\tif(element.prev().length !== 0) {\n\t\t\t\telement = element.prev();\n\t\t\t}\n\t\t}\n\n\t\t// skip '[hello]'\n\t\twhile(element.is('.cm-link')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// skip '('\n\t\twhile(element.is('.cm-url.cm-formatting')) {\n\t\t\telement = element.next();\n\t\t}\n\n\t\t// check if we actually have a cm-url\n\t\tif(element.is('.cm-url:not(.cm-formatting)')) {\n\t\t\treturn element.text();\n\t\t}\n\n\t\treturn undefined;\n\t};\n}]);\n"]} \ No newline at end of file