nextcloud-notes/js/public/app.min.js.map

1 line
46 KiB
Plaintext

{"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/noteTitle.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","Notification","showTemporary","search","$routeParams","SaveQueue","debounce","$document","updateIfExists","isSaving","isManualSaving","updateTitle","title","content","split","t","onEdit","unsaved","autoSave","add","manualSave","error","addManual","unbind","bind","event","ctrlKey","metaKey","String","fromCharCode","which","toLowerCase","preventDefault","toggleDistractionFree","launchIntoFullscreen","element","requestFullscreen","mozRequestFullScreen","webkitRequestFullscreen","msRequestFullscreen","exitFullscreen","document","mozCancelFullScreen","webkitExitFullscreen","fullscreenElement","mozFullScreenElement","webkitFullscreenElement","getElementById","$window","route","notesResource","all","getList","addAll","create","post","remove","$emit","toggleFavorite","customPUT","favorite","onbeforeunload","i","extensions","settings","isObject","on","msg","put","window","location","reload","directive","restrict","link","scope","focus","$timeout","urlFinder","simplemde","spellChecker","autoDownloadFontAwesome","toolbar","status","forceSync","editorElement","codemirror","getWrapperElement","$apply","url","this","isDefined","open","tooltip","container","filter","$filter","items","searchString","searchValues","filtered","trim","replace","wordCount","n","factory","func","delay","timeout","context","args","arguments","cancel","apply","notesIds","prototype","dialogs","alert","updated","push","splice","_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) {\n\n\n if(lastViewedNote !== 0) {\n $location.path('/notes/' + lastViewedNote);\n }\n if(errorMessage !==0){\n OC.Notification.showTemporary(errorMessage);\n }\n };\n\n $scope.search = '';\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) {\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 $scope.note.title = $scope.note.content.split('\\n')[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 $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});\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.notes = NotesModel.getAll();\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 });\n\n $scope.create = function () {\n notesResource.post().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) {\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 };\n\n\n $window.onbeforeunload = function() {\n var notes = NotesModel.getAll();\n for(var i=0; i<notes.length; i++) {\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.showTemporary(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) {\n\n\n if(lastViewedNote !== 0) {\n $location.path('/notes/' + lastViewedNote);\n }\n if(errorMessage !==0){\n OC.Notification.showTemporary(errorMessage);\n }\n };\n\n $scope.search = '';\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\", function($routeParams, $scope, NotesModel,\n SaveQueue, note, debounce,\n $document) {\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 $scope.note.title = $scope.note.content.split('\\n')[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 $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}]);\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.notes = NotesModel.getAll();\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 });\n\n $scope.create = function () {\n notesResource.post().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) {\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 };\n\n\n $window.onbeforeunload = function() {\n var notes = NotesModel.getAll();\n for(var i=0; i<notes.length; i++) {\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.showTemporary(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\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 };\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\n/**\n * removes whitespaces and leading #\n */\napp.filter('noteTitle', function () {\n\t'use strict';\n\treturn function (value) {\n \tvalue = value.split('\\n')[0] || 'newNote';\n\t\treturn value.trim().replace(/^#+/g, '');\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.dialogs.alert(\n this.notesIds[id].errorMessage,\n t('notes','An error occurred!')\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 note.title = updated.title;\n note.modified = updated.modified;\n note.content = updated.content;\n note.favorite = updated.favorite;\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\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 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\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 };\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","/**\n * removes whitespaces and leading #\n */\napp.filter('noteTitle', function () {\n\t'use strict';\n\treturn function (value) {\n \tvalue = value.split('\\n')[0] || 'newNote';\n\t\treturn value.trim().replace(/^#+/g, '');\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.dialogs.alert(\n this.notesIds[id].errorMessage,\n t('notes','An error occurred!')\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 note.title = updated.title;\n note.modified = updated.modified;\n note.content = updated.content;\n note.favorite = updated.favorite;\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\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 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"]}