aboutsummaryrefslogtreecommitdiff
path: root/js/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'js/controllers')
-rw-r--r--js/controllers/deleteredirect.js25
-rw-r--r--js/controllers/editredirect.js82
-rw-r--r--js/controllers/importexport.js110
-rw-r--r--js/controllers/listredirects.js44
-rw-r--r--js/controllers/redirectorpage.js50
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);
+ }
+}]);