diff options
Diffstat (limited to 'js/controllers')
-rw-r--r-- | js/controllers/deleteredirect.js | 25 | ||||
-rw-r--r-- | js/controllers/editredirect.js | 82 | ||||
-rw-r--r-- | js/controllers/importexport.js | 110 | ||||
-rw-r--r-- | js/controllers/listredirects.js | 44 | ||||
-rw-r--r-- | js/controllers/redirectorpage.js | 50 |
5 files changed, 311 insertions, 0 deletions
diff --git a/js/controllers/deleteredirect.js b/js/controllers/deleteredirect.js new file mode 100644 index 0000000..f480339 --- /dev/null +++ b/js/controllers/deleteredirect.js @@ -0,0 +1,25 @@ +redirectorApp.controller('DeleteRedirectCtrl', ['$scope', function($s) { + + // Ok, this is pretty ugly. But I want to make this controller to control + // everything about the deleting process, so I make this available on + // the parent scope, so the RedirectListCtrl can access it. + $s.$parent.confirmDeleteRedirect = function(index) { + $s.redirect = $s.redirects[index]; + $s.deleteIndex = index; + $s.$parent.showDeleteForm = true; + }; + + $s.cancelDelete = function(index) { + delete $s.redirect; + delete $s.deletingIndex; + $s.$parent.showDeleteForm = false; + } + + $s.deleteRedirect = function() { + $s.redirects.splice($s.deletingIndex, 1); + delete $s.redirect; + delete $s.deletingIndex; + $s.$parent.showDeleteForm = false; + $s.saveChanges(); + }; +}]);
\ No newline at end of file diff --git a/js/controllers/editredirect.js b/js/controllers/editredirect.js new file mode 100644 index 0000000..f24f3e6 --- /dev/null +++ b/js/controllers/editredirect.js @@ -0,0 +1,82 @@ +redirectorApp.controller('EditRedirectCtrl', ['$scope', function($s) { + + + $s.requestTypes = Redirect.requestTypes; + + // Ok, this is pretty ugly. But I want to make this controller to control + // everything about the editing process, so I make this available on + // the parent scope, so the RedirectListCtrl can access it. + $s.$parent.editRedirect = function(index) { + $s.redirect = new Redirect($s.redirects[index]); + $s.editIndex = index; + $s.redirect.updateExampleResult(); + if ($s.redirect.escapeMatches || $s.redirect.unescapeMatches || $s.redirect.excludePattern + || !($s.redirect.appliesTo.length == 1 && $s.redirect.appliesTo[0] == "main_frame")) { + $s.showAdvanced = true; //Auto show advanced if redirect uses advanced options + } + $s.$parent.showEditForm = true; + }; + + // Same, this is for the Create New button, which is starting + // the edit form, so I want to control it from here. + $s.$parent.createNewRedirect = function() { + $s.redirect = new Redirect({}); + $s.$parent.showEditForm = true; + }; + + $s.saveRedirect = function() { + if ($s.redirect.error) { + return; //Button is already disabled, but we still get the click + } + + if ($s.editIndex >= 0) { + $s.redirects[$s.editIndex] = $s.redirect; + } else { + $s.redirects.push($s.redirect); + } + closeEditForm(); + $s.saveChanges(); + }; + + $s.cancelEdit = function() { + closeEditForm(); + } + + // To bind a list of strings to a list of checkboxes + $s.appliesTo = function(key) { + if (!$s.redirect) { + return; + } + return $s.redirect.appliesTo.indexOf(key) != -1; + }; + + // Add or remove string from array based on whether checkbox is checked + $s.toggleApplies = function(key) { + if (!$s.redirect) { + return; + } + var arr = $s.redirect.appliesTo; + + var index = arr.indexOf(key); + if (index == -1) { + arr.push(key); + } else { + arr.splice(index, 1); + } + + var order = 'main_frame,sub_frame,stylesheet,script,image,object,xmlhttprequest,other'; + + arr.sort(function(a,b) { + return order.indexOf(a) - order.indexOf(b); + }); + + $s.redirect.updateExampleResult(); + }; + + function closeEditForm() { + $s.editIndex = -1; + $s.redirect = null; + $s.showAdvanced = false; + $s.$parent.showEditForm = false; + } +}]); diff --git a/js/controllers/importexport.js b/js/controllers/importexport.js new file mode 100644 index 0000000..191990c --- /dev/null +++ b/js/controllers/importexport.js @@ -0,0 +1,110 @@ + +//This controller, and associated directives and config, are responsible for import and exporting redirects +//from .json files. + +redirectorApp.config([ + '$compileProvider', + function($compileProvider) { + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|data):/); + }] +).directive('fileselected', function() { //Directive for file upload: + return { + restrict: 'A', + link: function(scope, element, attr, ctrl) { + element.bind('change', function(e) { + var f = element[0].files[0]; + element[0].value = ''; + scope.$eval(attr.fileselected, {'$file':f}); + }); + } + } +}).controller('ImportExportCtrl', ['$scope', function($s) { + + // Shows a message explaining how many redirects were imported. + function showImportedMessage(imported, existing) { + if (imported == 0 && existing == 0) { + $s.showMessage('No redirects existed in the file.'); + } + if (imported > 0 && existing == 0) { + $s.showMessage('Successfully imported ' + imported + ' redirect' + (imported > 1 ? 's.' : '.'), true); + } + if (imported == 0 && existing > 0) { + $s.showMessage('All redirects in the file already existed and were ignored.'); + } + if (imported > 0 && existing > 0) { + var m = 'Successfully imported ' + imported + ' redirect' + (imported > 1 ? 's' : '') + '. '; + if (existing == 1) { + m += '1 redirect already existed and was ignored.'; + } else { + m += existing + ' redirects already existed and were ignored.'; + } + $s.showMessage(m, true); + } + } + + $s.importRedirects = function(file) { + if (!file) { + return; + } + var reader = new FileReader(); + + reader.onload = function(e) { + var data; + try { + var data = JSON.parse(reader.result); + } catch(e) { + $s.showMessage('Failed to parse JSON data, invalid JSON: ' + (e.message||'').substr(0,100)); + return $s.$parent.$apply(); + } + + if (!data.redirects) { + $s.showMessage('Invalid JSON, missing "redirects" property'); + return $s.$parent.$apply(); + } + + var imported = 0, existing = 0; + for (var i = 0; i < data.redirects.length; i++) { + var r = new Redirect(data.redirects[i]); + + if ($s.redirects.some(function(i) { return new Redirect(i).equals(r);})) { + existing++; + } else { + $s.redirects.push(r.toObject()); + imported++; + } + } + + showImportedMessage(imported, existing); + + $s.saveChanges(); + $s.$parent.$apply(); + }; + try { + reader.readAsText(file, 'utf-8'); + } catch(e) { + $s.showMessage('Failed to read import file'); + } + } + + // Updates the export link with a data url containing all the redirects. + // We want to have the href updated instead of just generated on click to + // allow people to right click and choose Save As... + $s.updateExportLink = function() { + var redirects = $s.redirects.map(function(r) { + return new Redirect(r).toObject(); + }); + + var exportObj = { + createdBy : 'Redirector v' + chrome.app.getDetails().version, + createdAt : new Date(), + redirects : redirects + }; + + var json = JSON.stringify(exportObj, null, 4); + + //Using encodeURIComponent here instead of base64 because base64 always messed up our encoding for some reason... + $s.redirectDownload = 'data:text/plain;charset=utf-8,' + encodeURIComponent(json); + } + + $s.updateExportLink(); //Run once so the a will have a href to begin with +}]);
\ No newline at end of file diff --git a/js/controllers/listredirects.js b/js/controllers/listredirects.js new file mode 100644 index 0000000..008a527 --- /dev/null +++ b/js/controllers/listredirects.js @@ -0,0 +1,44 @@ +// This controller is responsible for the list of redirects and the actions +// that can be taken from there. +redirectorApp.filter('requestTypeDisplay', function() { //Filter for displaying nice names for request types + return function(input) { + return input.map(function(key) { return Redirect.requestTypes[key]; }).join(', '); + } +}).controller('ListRedirectsCtrl', ['$scope', function($s) { + + function swap(arr, i, n) { + var item = arr[i]; + arr[i] = arr[n]; + arr[n] = item; + } + + // Move the redirect at index up in the list, giving it higher priority + $s.moveUp = function(index) { + if (index == 0) { + return; + } + swap($s.redirects, index, index-1); + $s.saveChanges(); + }; + + // Move the redirect at index down in the list, giving it lower priority + $s.moveDown = function(index) { + if (index == $s.redirects.length-1) { + return; + } + swap($s.redirects, index, index+1); + $s.saveChanges(); + }; + + $s.toggleDisabled = function(redirect) { + redirect.disabled = !redirect.disabled; + $s.saveChanges(); + }; + + $s.example = function(redirect) { + return new Redirect(redirect).getMatch(redirect.exampleUrl).redirectTo; + }; + + //Edit button is defined in EditRedirectCtrl + //Delete button is defined in DeleteRedirectCtrl +}]);
\ No newline at end of file diff --git a/js/controllers/redirectorpage.js b/js/controllers/redirectorpage.js new file mode 100644 index 0000000..05fbe9f --- /dev/null +++ b/js/controllers/redirectorpage.js @@ -0,0 +1,50 @@ +// This is the main controller of the page. It is responsible for showing messages, +// modal windows and loading and saving the list of redirects, that all of the +// controllers work with. +redirectorApp.controller('RedirectorPageCtrl', ['$scope', '$timeout', function($s, $timeout) { + + $s.deleting = null; //Variable for redirect being edited, of the form { index:<nr>, redirect:<redirect>}; + $s.showEditForm = $s.showDeleteForm = false; // Variables, child controllers can set them to show their forms + + var storage = chrome.storage.local; //TODO: Change to sync when Firefox supports it... + + function normalize(r) { + return new Redirect(r).toObject(); //Cleans out any extra props, and adds default values for missing ones. + } + + // Saves the entire list of redirects to storage. + $s.saveChanges = function() { + + // Clean them up so angular $$hash things and stuff don't get serialized. + var arr = $s.redirects.map(normalize); + + storage.set({redirects:arr}, function() { + console.log('Saved redirects at ' + new Date()); + }); + } + + $s.redirects = []; + storage.get('redirects', function(results) { + if (!results || !results.redirects) { + return; + } + + for (var i=0; i < results.redirects.length; i++) { + $s.redirects.push(normalize(results.redirects[i])); + } + $s.$apply(); + }); + + // Shows a message bar above the list of redirects. + $s.showMessage = function(message, success) { + $s.message = message; + $s.messageType = success ? 'success' : 'error'; + + //Remove the message in 20 seconds if it hasn't been changed... + $timeout(function() { + if ($s.message == message) { + $s.message = null; + } + }, 20 * 1000); + } +}]); |