aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--css/redirector.css63
-rw-r--r--js/advancedmode.js20
-rw-r--r--js/redirect.js48
-rw-r--r--js/redirectorpage.js164
-rw-r--r--redirector.html6
5 files changed, 272 insertions, 29 deletions
diff --git a/css/redirector.css b/css/redirector.css
index 29cec4f..e12a934 100644
--- a/css/redirector.css
+++ b/css/redirector.css
@@ -261,6 +261,65 @@ a.disabled:hover, button[disabled]:hover {
background:white !important;
}
+/* Toggle Grouping Checkbox */
+.toggle-container {
+ display: block;
+ position: absolute;
+ top: 8%;
+ right: 5%;
+ cursor: pointer;
+ font-size: 22px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.toggle-container input {
+ position: absolute;
+ opacity: 0;
+ cursor: pointer;
+ height: 0;
+ width: 0;
+}
+
+.checkmark {
+ position: absolute;
+ height: 15px;
+ width: 15px;
+ background-color: #eee;
+}
+
+.toggle-container:hover input ~ .checkmark {
+ background-color: #ccc;
+}
+
+.toggle-container input:checked ~ .checkMarked {
+ background-color: #2196F3;
+}
+
+.checkmark:after {
+ content: "";
+ position: absolute;
+ display: none;
+}
+
+.toggle-container input:checked ~ .checkMarked:after {
+ display: block;
+}
+
+.toggle-container .checkMarked:after {
+ left: 4px;
+ top: -1px;
+ width: 4px;
+ height: 9px;
+ border: solid white;
+ border-width: 0 3px 3px 0;
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+
/* Popup form for deleting redirects */
#delete-redirect-form {
@@ -530,6 +589,10 @@ footer small a:hover {
color: rgb(53,180,75);
}
+ .toggle {
+ background-color: #ccc;
+ }
+
#message-box.success {
background-color: rgb(53,203,75);;
}
diff --git a/js/advancedmode.js b/js/advancedmode.js
new file mode 100644
index 0000000..1567223
--- /dev/null
+++ b/js/advancedmode.js
@@ -0,0 +1,20 @@
+
+function advancedModeToggle(ev) {
+ ev.preventDefault();
+ let advancedModes = ['.groupings', '.arrows']
+ for (let mode of advancedModes) {
+ let advancedModeElement = el(mode);
+ let isElementHidden = advancedModeElement.classList.contains('hidden');
+ isElementHidden ? advancedModeElement.classList.remove('hidden') : advancedModeElement.classList.add('hidden');
+ }
+
+ let buttonText = el('#advanced-mode').textContent;
+ buttonText.contains('Show') ? el('#advanced-mode').textContent = 'Hide Advanced Mode' : el('#advanced-mode').textContent = 'Show Advanced Mode';
+}
+
+
+function setupAdvancedModeEventListener() {
+ el('#advanced-mode').addEventListener('click', advancedModeToggle);
+}
+
+setupAdvancedModeEventListener(); \ No newline at end of file
diff --git a/js/redirect.js b/js/redirect.js
index 4ad57d5..b902da2 100644
--- a/js/redirect.js
+++ b/js/redirect.js
@@ -27,7 +27,7 @@ Redirect.requestTypes = {
Redirect.prototype = {
-
+
//attributes
description : '',
exampleUrl : '',
@@ -40,7 +40,8 @@ Redirect.prototype = {
patternType : '',
processMatches : 'noProcessing',
disabled : false,
-
+ grouped: false,
+
compile : function() {
var incPattern = this._preparePattern(this.includePattern);
@@ -65,7 +66,7 @@ Redirect.prototype = {
&& this.processMatches == redirect.processMatches
&& this.appliesTo.toString() == redirect.appliesTo.toString();
},
-
+
toObject : function() {
return {
description : this.description,
@@ -79,6 +80,7 @@ Redirect.prototype = {
patternType : this.patternType,
processMatches : this.processMatches,
disabled : this.disabled,
+ grouped: this.grouped,
appliesTo : this.appliesTo.slice(0)
};
},
@@ -87,10 +89,10 @@ Redirect.prototype = {
if (!this._rxInclude) {
this.compile();
}
- var result = {
- isMatch : false,
- isExcludeMatch : false,
- isDisabledMatch : false,
+ var result = {
+ isMatch : false,
+ isExcludeMatch : false,
+ isDisabledMatch : false,
redirectTo : '',
toString : function() { return JSON.stringify(this); }
};
@@ -106,11 +108,11 @@ Redirect.prototype = {
result.redirectTo = redirectTo;
}
}
- return result;
+ return result;
},
-
+
//Updates the .exampleResult field or the .error
- //field depending on if the example url and patterns match
+ //field depending on if the example url and patterns match
//and make a good redirect
updateExampleResult : function() {
@@ -171,25 +173,25 @@ Redirect.prototype = {
isRegex: function() {
return this.patternType == Redirect.REGEX;
},
-
+
isWildcard : function() {
- return this.patternType == Redirect.WILDCARD;
+ return this.patternType == Redirect.WILDCARD;
},
test : function() {
- return this.getMatch(this.exampleUrl);
+ return this.getMatch(this.exampleUrl);
},
- //Private functions below
+ //Private functions below
_rxInclude : null,
_rxExclude : null,
-
+
_preparePattern : function(pattern) {
if (!pattern) {
return null;
}
if (this.patternType == Redirect.REGEX) {
- return pattern;
+ return pattern;
} else { //Convert wildcard to regex pattern
var converted = '^';
for (var i = 0; i < pattern.length; i++) {
@@ -206,7 +208,7 @@ Redirect.prototype = {
return converted;
}
},
-
+
_init : function(o) {
o = o || {};
this.description = o.description || '';
@@ -240,7 +242,7 @@ Redirect.prototype = {
get appliesToText() {
return this.appliesTo.map(type => Redirect.requestTypes[type]).join(', ');
},
-
+
get processMatchesExampleText() {
let examples = {
noProcessing : 'Use matches as they are',
@@ -256,11 +258,11 @@ Redirect.prototype = {
toString : function() {
return JSON.stringify(this.toObject(), null, 2);
},
-
+
_includeMatch : function(url) {
if (!this._rxInclude) {
return null;
- }
+ }
var matches = this._rxInclude.exec(url);
if (!matches) {
return null;
@@ -285,12 +287,12 @@ Redirect.prototype = {
this._rxInclude.lastIndex = 0;
return resultUrl;
},
-
+
_excludeMatch : function(url) {
if (!this._rxExclude) {
- return false;
+ return false;
}
- var shouldExclude = this._rxExclude.test(url);
+ var shouldExclude = this._rxExclude.test(url);
this._rxExclude.lastIndex = 0;
return shouldExclude;
}
diff --git a/js/redirectorpage.js b/js/redirectorpage.js
index 1cad8a8..6d0db2e 100644
--- a/js/redirectorpage.js
+++ b/js/redirectorpage.js
@@ -77,6 +77,12 @@ function renderSingleRedirect(node, redirect, index) {
btn.setAttribute('data-index', index);
}
+ let checkmark = node.querySelectorAll('.checkmark');
+
+ if(checkmark.length == 1) {
+ checkmark[0].setAttribute('data-index', index);
+ }
+
//Remove extra props...
delete redirect.$first;
delete redirect.$last;
@@ -117,19 +123,156 @@ function toggleDisabled(index) {
saveChanges();
}
+// function handleGroupedMove(index) {
+// console.log(`NSC`, arguments);
+// let grouping = REDIRECTS.filter(row => row.grouped);
+// let size = grouping.length;
+// console.log(grouping)
+// }
+
+// function wrap(node, elm) {
+// node.parentNode.insertBefore(elm, node);
+// // node.previousElementSibling.appendChild(node);
+// }
+
+function swap(node1, node2) {
+ const afterNode2 = node2.nextElementSibling;
+ const parent = node2.parentNode;
+ node1.replaceWith(node2);
+ parent.insertBefore(node1, afterNode2);
+}
+
+function groupedMoveDown(group) {
+ // let grouping = REDIRECTS.map((row, i) => { return { row, index: i}})
+ // .filter(result => result.row.grouped)
+ // .sort((a, b) => b.index - a.index);
+ for(let rule of group) {
+ // swap positions in dom
+ let elm = document.querySelector("[data-index='" + (rule.index).toString() + "']");
+ let prev = document.querySelector("[data-index='" + (rule.index + group.length).toString() + "']");
+ swap(elm,prev);
+ }
+
+ for(let rule of group) {
+ // swap positions in array
+ rule.row.grouping = false;
+ let prevRedir = REDIRECTS[rule.index + group.length];
+ REDIRECTS[rule.index + group.length] = REDIRECTS[rule.index];
+ REDIRECTS[rule.index] = prevRedir;
+ // REDIRECTS[rule.index].grouped = false;
+ }
+}
+
+function isGroupAdjacent(grouping) {
+ let distances = [];
+ for(let i = grouping.length - 1; i >= 0; i--) {
+
+ if(i != 0) {
+ distances.push(grouping[i].index - grouping[i - 1].index);
+
+ }
+
+ }
+ return distances.every(distance => distance === 1);
+}
+
+function groupedMoveUp(group) {
+
+
+ console.log(group);
+
+ // working config - sort of
+ // for(let rule of group) {
+ // // swap positions in dom
+ // let elm = document.querySelector("[data-index='" + (rule.index).toString() + "']");
+ // let prev = document.querySelector("[data-index='" + (rule.index - group.length).toString() + "']");
+ // elm.childNodes[7].childNodes[3].classList.remove("checkMarked");
+ // console.log(`NSC: groupedMoveUp -> elm`, elm);
+ // prev.childNodes[7].childNodes[3].classList.remove("checkMarked");
+ // console.log(`NSC: groupedMoveUp -> prev`, prev);
+ // swap(elm,prev);
+ // }
+
+ // for(let rule of group) {
+ // // swap positions in array
+ // rule.row.grouping = false;
+ // let prevRedir = REDIRECTS[rule.index - group.length];
+ // REDIRECTS[rule.index - group.length] = REDIRECTS[rule.index];
+ // REDIRECTS[rule.index] = prevRedir;
+ // // REDIRECTS[rule.index].grouped = false;
+ // }
+
+ // only set the below to 1 if groupings are not next to each other.
+ var jumpLength = 1;
+
+ if(isGroupAdjacent(group)) {
+ console.log('adjacent')
+ jumpLength = group.length;
+ }
+
+
+
+ for(let rule of group) {
+ console.log(`NSC: groupedMoveUp -> rule`, rule);
+ // swap positions in dom
+ let elm = document.querySelector("[data-index='" + (rule.index).toString() + "']");
+ console.log(`NSC: groupedMoveUp -> elm`, elm);
+ let prev = document.querySelector("[data-index='" + (rule.index - jumpLength).toString() + "']");
+ console.log(`NSC: groupedMoveUp -> prev`, prev);
+ elm.childNodes[7].childNodes[3].classList.remove("checkMarked");
+ prev.childNodes[7].childNodes[3].classList.remove("checkMarked");
+ if(jumpLength > 1) {
+ swap(elm,prev);
+ }
+
+ }
+
+ for(let rule of group) {
+ // swap positions in array
+ rule.row.grouping = false;
+ let prevRedir = REDIRECTS[rule.index - jumpLength];
+ REDIRECTS[rule.index - jumpLength] = REDIRECTS[rule.index];
+ REDIRECTS[rule.index] = prevRedir;
+ }
+}
function moveUp(index) {
- let prev = REDIRECTS[index-1];
- REDIRECTS[index-1] = REDIRECTS[index];
- REDIRECTS[index] = prev;
+ let grouping = REDIRECTS.map((row, i) => { return { row, index: i}})
+ .filter(result => result.row.grouped)
+ .sort((a, b) => a.index - b.index);
+
+ if(grouping.length > 1) {
+ // many
+ console.log('many')
+
+ groupedMoveUp(grouping);
+
+ } else {
+ // one
+ let prev = REDIRECTS[index-1];
+ REDIRECTS[index-1] = REDIRECTS[index];
+ REDIRECTS[index] = prev;
+ }
+
updateBindings();
saveChanges();
}
function moveDown(index) {
- let next = REDIRECTS[index+1];
- REDIRECTS[index+1] = REDIRECTS[index];
- REDIRECTS[index] = next;
+ let grouping = REDIRECTS.map((row, i) => { return { row, index: i}})
+ .filter(result => result.row.grouped)
+ .sort((a, b) => a.index - b.index);
+
+ if(grouping.length > 1) {
+ // many
+ groupedMoveDown(grouping);
+ } else {
+ // one
+ let next = REDIRECTS[index+1];
+ REDIRECTS[index+1] = REDIRECTS[index];
+ REDIRECTS[index] = next;
+ }
+
updateBindings();
saveChanges();
}
@@ -200,6 +343,11 @@ function pageLoad() {
el('#storage-sync-option input').addEventListener('click', toggleSyncSetting);
el('.redirect-rows').addEventListener('click', function(ev) {
+ // apply checkMarked class for Grouping
+ if(ev.target.type == 'checkbox') {
+ ev.target.nextElementSibling.classList.add("checkMarked");
+ }
+
let action = ev.target.getAttribute('data-action');
//We clone and re-use nodes all the time, so instead of attaching and removing event handlers endlessly we just put
@@ -228,4 +376,8 @@ let mql = window.matchMedia('(prefers-color-scheme:dark)');
mql.onchange = updateFavicon;
updateFavicon(mql);
+function toggleGrouping(index) {
+ REDIRECTS[index].grouped = !REDIRECTS[index].grouped;
+}
+
pageLoad(); \ No newline at end of file
diff --git a/redirector.html b/redirector.html
index 6a2e492..03c5714 100644
--- a/redirector.html
+++ b/redirector.html
@@ -136,6 +136,7 @@
<input type="file" id="import-file" accept=".rjson,.json,.txt" />
<label for="import-file" class="btn blue large">Import</label>
<a class="btn blue large" id="export-link" download="Redirector.json">Export</a>
+ <button class="btn blue large" id="advanced-mode">Show Advanced Mode</button>
</span>
<a class="btn blue large" href="help.html" target="_blank">Help</a>
@@ -183,6 +184,10 @@
<button class="btn medium grey move-downbottom-btn" data-action="moveDownBottom" data-disabled="$last">⟱</button>
<button class="btn medium grey" data-action="duplicateRedirect">Duplicate</button>
</div>
+ <label class="toggle-container">
+ <input type="checkbox">
+ <span class="checkmark" data-action="toggleGrouping"></span>
+ </label>
</div>
</div>
<label id="storage-sync-option"><input type="checkbox" /> Enable Storage Sync</label>
@@ -200,5 +205,6 @@
<script src="js/redirectorpage.js"></script>
<script src="js/editredirect.js"></script>
<script src="js/importexport.js"></script>
+ <script src="js/advancedmode.js"></script>
</body>
</html>