diff --git a/Info.plist b/Info.plist
index 0a51306..6764c01 100644
--- a/Info.plist
+++ b/Info.plist
@@ -2,50 +2,52 @@
- Author
- Mutwin Kraus, Jannik Nielsen
- CFBundleDisplayName
- vim
- CFBundleIdentifier
- com.mutwinkraus.vim
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleShortVersionString
- 0.6
- CFBundleVersion
- 2
- Chrome
-
- Database Quota
- 1048576
- Global Page
- globalpage.html
-
- Content
-
- Scripts
-
- End
-
- overlay.js
-
- Start
-
- vim-keybindings.js
-
-
-
- ExtensionInfoDictionaryVersion
- 1.0
- Permissions
-
- Website Access
-
- Include Secure Pages
-
- Level
- All
-
-
+ Author
+ Mutwin Kraus, Jannik Nielsen, Khaled Hussein
+ Builder Version
+ 7534.57.2
+ CFBundleDisplayName
+ Vim Bindings
+ CFBundleIdentifier
+ com.mutwinkraus.vim
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleShortVersionString
+ 0.6
+ CFBundleVersion
+ 2
+ Chrome
+
+ Database Quota
+ 1048576
+ Global Page
+ globalpage.html
+
+ Content
+
+ Scripts
+
+ End
+
+ overlay.js
+
+ Start
+
+ vim-keybindings.js
+
+
+
+ ExtensionInfoDictionaryVersion
+ 1.0
+ Permissions
+
+ Website Access
+
+ Include Secure Pages
+
+ Level
+ All
+
+
diff --git a/README.md b/README.md
index 399972c..8c21eba 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,16 @@
-Vim Keybindings for Safari
---------------------------
+# Vim Keybindings for Safari
-Currently supported keys:
+## Currently supported keys:
* gg, G
* h, j, k, l
* ^D, ^U, ^F, ^B
* esc, i, dd
* gt, gT, gt
+* t -- starts a new tab
+* d -- closes a tab
-Currently supported commands:
+## Currently supported commands:
* :q, :q!, :tabnew
* :tabn, :tabp, :tabfir, :tabfirst, :tablast
@@ -21,14 +22,15 @@ Currently supported commands:
In the preferences for the extension, it is possible to give a list of sites, where the extension should not be loaded. Separate sites by , (comma). Spaces are allowed.
-Known issues
-------------
+## Known issues
+
* Some pages takes over the keyboard just as this extension does. That means that on some pages the overlay wont show up and wont recieve key strokes.
* Some pages makes the gt and gT combos jump past it.
-Contributors
-============
+# AUTHORS
+
+- Mutwin Kraus
+- Jason Green
+- Jannik Nielsen
+- Khaled Hussein
-Mutwin Kraus
-Jason Green
-Jannik Nielsen
diff --git a/Settings.plist b/Settings.plist
index 2ab72d0..83d57c5 100644
--- a/Settings.plist
+++ b/Settings.plist
@@ -2,13 +2,13 @@
-
- Key
- disabledsites
- Title
- Disabled sites
- Type
- TextField
-
+
+ Key
+ disabledsites
+ Title
+ Disabled sites
+ Type
+ TextField
+
diff --git a/globalpage.html b/globalpage.html
index 15a0136..2b148e2 100644
--- a/globalpage.html
+++ b/globalpage.html
@@ -1,154 +1,153 @@
- global page
-
+safari.application.addEventListener("message",respondToMessage,false);
+
+
-
+
-
-
diff --git a/overlay.js b/overlay.js
index 1b529a0..38893cd 100644
--- a/overlay.js
+++ b/overlay.js
@@ -15,7 +15,7 @@ if (window.top === window) {
overlay.style.display = "none";
overlay.setAttribute('id', 'vimOverlay');
overlay.style.opacity = ".9";
- overlay.style.zIndex = "2147483648";
+ overlay.style.zIndex = "2147483648";
var overlayTextinput = document.createElement("input");
overlayTextinput.style.border = "0";
@@ -25,11 +25,9 @@ if (window.top === window) {
overlayTextinput.style.color = "black";
overlayTextinput.style.margin = "0";
overlayTextinput.style.opacity = ".9";
- overlayTextinput.style.clear = "none";
+ overlayTextinput.style.clear = "none";
overlayTextinput.setAttribute('id', 'vimOverlayTextinput');
document.body.insertBefore(overlay, document.body.firstChild);
overlay.appendChild(overlayTextinput);
-
-
}
diff --git a/vim-keybindings.js b/vim-keybindings.js
index 2b8c070..178ca8f 100644
--- a/vim-keybindings.js
+++ b/vim-keybindings.js
@@ -5,325 +5,331 @@ var timer;
var loaded = false;
var handler = function(e) {
- var c = String.fromCharCode(e.keyCode).toLowerCase();
- if(e.shiftKey) c = c.toUpperCase();
- if (e.keyCode > 32 && e.keyCode < 91) {
- if (parseInt(c, 10) == c) {
- multiplier = (multiplier * 10) + c;
+ var c = String.fromCharCode(e.keyCode).toLowerCase();
+ if(e.shiftKey) c = c.toUpperCase();
+ if (e.keyCode > 32 && e.keyCode < 91) {
+ if (parseInt(c, 10) == c) {
+ multiplier = (multiplier * 10) + c;
+ } else {
+ combokey += c;
+ }
+ clearTimeout(timer);
+ timer = window.setTimeout(function() { combokey = ''; multiplier = 0; }, 5000);
+ }
+
+ if(window.document.activeElement !== window.document.body) {
+ switch (e.keyCode) {
+ case 27:
+ if (document.getElementById('vimOverlay').style.display == "block") {
+ document.getElementById('vimOverlay').style.display = 'none';
+ document.getElementById('vimOverlayTextinput').value = '';
+ } else {
+ t.lastActiveElement = window.document.activeElement;
+ }
+ combokey = '';
+ multiplier = 0;
+ window.document.activeElement.blur();
+ break;
+ case 8:
+ if (window.document.activeElement.id == "vimOverlayTextinput" && window.document.activeElement.value === '') {
+ window.document.activeElement.blur();
+ document.getElementById('vimOverlay').style.display = "none";
+ e.preventDefault();
+ }
+ break;
+ case 13:
+ if (window.document.activeElement.id == "vimOverlayTextinput") {
+ t.inputCommand(window.document.activeElement.value);
+ window.document.activeElement.value = '';
+ window.document.activeElement.blur();
+ document.getElementById('vimOverlay').style.display = "none";
+ }
+ break;
+ }
+ return;
} else {
- combokey += c;
+
+ switch (e.keyCode) {
+ case 27:
+ t.resetCombo();
+ break;
+ }
}
- clearTimeout(timer);
- timer = window.setTimeout(function() { combokey = ''; multiplier = 0; }, 5000);
- }
-
- if(window.document.activeElement !== window.document.body) {
- switch (e.keyCode) {
- case 27:
- if (document.getElementById('vimOverlay').style.display == "block") {
- document.getElementById('vimOverlay').style.display = 'none';
- document.getElementById('vimOverlayTextinput').value = '';
- } else {
- t.lastActiveElement = window.document.activeElement;
- }
- combokey = '';
- multiplier = 0;
- window.document.activeElement.blur();
- break;
- case 8:
- if (window.document.activeElement.id == "vimOverlayTextinput" && window.document.activeElement.value == '') {
- window.document.activeElement.blur();
- document.getElementById('vimOverlay').style.display = "none";
- e.preventDefault();
- }
- break;
- case 13:
- if (window.document.activeElement.id == "vimOverlayTextinput") {
- t.inputCommand(window.document.activeElement.value);
- window.document.activeElement.value = '';
- window.document.activeElement.blur();
- document.getElementById('vimOverlay').style.display = "none";
- }
- break;
+
+ t.scroll = function(x, y) {
+ window.scrollBy(x, y);
+ };
+ t.scrollTo = function(x, y) {
+ window.scrollTo(x, y);
+ };
+
+ t.halfWindowHeight = function() {
+ return window.innerHeight / 2;
+ };
+
+ t.fullWindowHeight = function() {
+ return window.innerHeight;
+ };
+
+ t.screenHeight = function() {
+ return document.body.offsetHeight;
+ };
+
+ t.functionkeys = function(keys) {
+ if (keys.none == '1' && (e.altKey || e.metaKey || e.ctrlKey || e.altGraphKey || e.shiftKey)) {
+ return false;
+ }
+ if ((keys.alt != '1' && e.altKey) || (keys.alt == '1' && !e.altKey)) {
+ return false;
+ }
+ if ((keys.meta != '1' && e.metaKey) || (keys.meta == '1' && !e.metaKey)) {
+ return false;
+ }
+ if ((keys.ctrl != '1' && e.ctrlKey) || (keys.ctrl == '1' && !e.ctrlKey)) {
+ return false;
+ }
+ if ((keys.altgr != '1' && e.altGraphKey) || (keys.altgr == '1' && !e.altGraphKey)) {
+ return false;
+ }
+ if ((keys.shift != '1' && e.shiftKey) || (keys.shift == '1' && !e.shiftKey)) {
+ return false;
+ }
+ return true;
+ };
+
+ switch (e.keyIdentifier) {
+ case "U+003A":
+ document.getElementById('vimOverlay').style.display = "block";
+ document.getElementById('vimOverlayTextinput').focus();
+ e.preventDefault();
+ break;
+ case "U+0008":
+ if (document.getElementById('vimOverlay').style.display == "block" && document.getElementById('vimOverlayTextinput').value == '') {
+ document.getElementById('vimOverlayTextinput').blur();
+ document.getElementById('vimOverlay').style.display = "none";
+ }
+ break;
+ case "U+0027":
+ combokey += "'";
+ break;
}
- return;
- } else {
- switch (e.keyCode) {
- case 27:
- t.resetCombo();
- break;
+ t.keyCommand(combokey, e);
+};
+
+t.keyCommand = function(c, e) {
+
+ var reset_combo = true;
+ var SCROLL_STEP = 35;
+
+ switch(c) {
+ case 'gg':
+ if (t.functionkeys({'none': '1'})) {
+ t.scrollTo(0,0);
+ }
+ break;
+ case 'h':
+ if (t.functionkeys({'none': '1'})) {
+ t.scroll(-SCROLL_STEP, 0);
+ }
+ break;
+ case 'j':
+ if (t.functionkeys({'none': '1'})) {
+ t.scroll(0, SCROLL_STEP);
+ }
+ break;
+ case 'k':
+ if (t.functionkeys({'none': '1'})) {
+ t.scroll(0, -SCROLL_STEP);
+ }
+ break;
+ case 'l':
+ if (t.functionkeys({'none': '1'})) {
+ t.scroll(SCROLL_STEP, 0);
+ }
+ break;
+ //case 'd':
+ // if (t.functionkeys({'ctrl': '1'})) {
+ // t.scroll(0, t.halfWindowHeight());
+ // } else {
+ // reset_combo = false;
+ // }
+ //break;
+ case 'dd':
+ if (t.functionkeys({'none': '1'}) && t.lastActiveElement != undefined) {
+ t.lastActiveElement.value = '';
+ }
+ break;
+ case 'f':
+ if(t.functionkeys({'ctrl': '1'})) {
+ t.scroll(0, t.fullWindowHeight());
+ }
+ break;
+ case 'u':
+ if(t.functionkeys({'ctrl': '1'})) {
+ t.scroll(0, -t.halfWindowHeight());
+ }
+ break;
+ case 'b':
+ if(t.functionkeys({'ctrl': '1'})) {
+ t.scroll(0, -t.fullWindowHeight());
+ }
+ break;
+ case 'G':
+ if (t.functionkeys({'shift': '1'})) {
+ t.scrollTo(0, t.screenHeight());
+ }
+ break;
+ case 'i':
+ if (t.lastActiveElement != undefined) {
+ t.lastActiveElement.focus();
+ e.preventDefault();
+ }
+ break;
+ case 'd':
+ safari.self.tab.dispatchMessage("closeTab");
+ break;
+ case 't':
+ safari.self.tab.dispatchMessage("openTab", "https://");
+ break;
+ case 'gT':
+ if (t.functionkeys({'shift': '1'})) {
+ safari.self.tab.dispatchMessage("prevTab","");
+ }
+ break;
+ case 'gt':
+ if (t.functionkeys({'none': '1'})) {
+ safari.self.tab.dispatchMessage("nextTab",multiplier);
+ }
+ break;
+ /*case '\'\'':
+ if (t.functionkeys({'none': '1'})) {
+ safari.self.tab.dispatchMessage("backTab", "");
+ }
+ break;*/
+
+ default:
+ reset_combo = false;
+ break;
}
- }
-
- t.scroll = function(x, y) {
- window.scrollBy(x, y);
- };
- t.scrollTo = function(x, y) {
- window.scrollTo(x, y);
- };
-
- t.halfWindowHeight = function() {
- return window.innerHeight / 2;
- };
-
- t.fullWindowHeight = function() {
- return window.innerHeight;
- };
-
- t.screenHeight = function() {
- return document.body.offsetHeight;
- };
-
- t.functionkeys = function(keys) {
- if (keys.none == '1' && (e.altKey || e.metaKey || e.ctrlKey || e.altGraphKey || e.shiftKey)) {
- return false;
+
+ if (reset_combo || c.length > 4) {
+ t.resetCombo();
}
- if ((keys.alt != '1' && e.altKey) || (keys.alt == '1' && !e.altKey)) {
- return false;
- }
- if ((keys.meta != '1' && e.metaKey) || (keys.meta == '1' && !e.metaKey)) {
- return false;
- }
- if ((keys.ctrl != '1' && e.ctrlKey) || (keys.ctrl == '1' && !e.ctrlKey)) {
- return false;
- }
- if ((keys.altgr != '1' && e.altGraphKey) || (keys.altgr == '1' && !e.altGraphKey)) {
- return false;
- }
- if ((keys.shift != '1' && e.shiftKey) || (keys.shift == '1' && !e.shiftKey)) {
- return false;
- }
- return true;
- }
-
- switch (e.keyIdentifier) {
- case "U+003A":
- document.getElementById('vimOverlay').style.display = "block";
- document.getElementById('vimOverlayTextinput').focus();
- e.preventDefault();
- break;
- case "U+0008":
- if (document.getElementById('vimOverlay').style.display == "block" && document.getElementById('vimOverlayTextinput').value == '') {
- document.getElementById('vimOverlayTextinput').blur();
- document.getElementById('vimOverlay').style.display = "none";
- }
- break;
- case "U+0027":
- combokey += "'";
- break;
- }
-
- t.keyCommand(combokey, e);
-}
-t.keyCommand = function(c, e) {
-
- var reset_combo = true;
- var SCROLL_STEP = 35;
-
- switch(c) {
- case 'gg':
- if (t.functionkeys({'none': '1'})) {
- t.scrollTo(0,0);
- }
- break;
- case 'h':
- if (t.functionkeys({'none': '1'})) {
- t.scroll(-SCROLL_STEP, 0);
- }
- break;
- case 'j':
- if (t.functionkeys({'none': '1'})) {
- t.scroll(0, SCROLL_STEP);
- }
- break;
- case 'k':
- if (t.functionkeys({'none': '1'})) {
- t.scroll(0, -SCROLL_STEP);
- }
- break;
- case 'l':
- if (t.functionkeys({'none': '1'})) {
- t.scroll(SCROLL_STEP, 0);
- }
- break;
- case 'd':
- if (t.functionkeys({'ctrl': '1'})) {
- t.scroll(0, t.halfWindowHeight());
- } else {
- reset_combo = false;
- }
- break;
- case 'dd':
- if (t.functionkeys({'none': '1'}) && t.lastActiveElement != undefined) {
- t.lastActiveElement.value = '';
- }
- break;
- case 'f':
- if(t.functionkeys({'ctrl': '1'})) {
- t.scroll(0, t.fullWindowHeight());
- }
- break;
- case 'u':
- if(t.functionkeys({'ctrl': '1'})) {
- t.scroll(0, -t.halfWindowHeight());
- }
- break;
- case 'b':
- if(t.functionkeys({'ctrl': '1'})) {
- t.scroll(0, -t.fullWindowHeight());
- }
- break;
- case 'G':
- if (t.functionkeys({'shift': '1'})) {
- t.scrollTo(0, t.screenHeight());
- }
- break;
- case 'i':
- if (t.lastActiveElement != undefined) {
- t.lastActiveElement.focus();
- e.preventDefault();
- }
- break;
- case 'gT':
- if (t.functionkeys({'shift': '1'})) {
- safari.self.tab.dispatchMessage("prevTab","");
- }
- break;
- case 'gt':
- if (t.functionkeys({'none': '1'})) {
- safari.self.tab.dispatchMessage("nextTab",multiplier);
- }
- break;
- /*case '\'\'':
- if (t.functionkeys({'none': '1'})) {
- safari.self.tab.dispatchMessage("backTab", "");
- }
- break;*/
-
- default:
- reset_combo = false;
- break;
- }
-
- if (reset_combo || c.length > 4) {
- t.resetCombo();
- }
-
-}
+};
t.inputCommand = function(command) {
- if (command == '') return;
-
- if (command.charAt(0) == "%") {
- t.percentCommand(command);
- return;
- }
-
- param = command.split(" ");
-
- switch (param[0]) {
- case 'tabe':
- case 'tabedit':
- case 'e':
- case 'edit':
- if (param[1] == "" || param[1] == undefined) {
- if (param[0] == 'e' || param[0] == 'edit') {
- alert('Usage: command "edit" or "e" for short, opens the url specified as first parameter in the current tab');
- } else {
- alert('Usage: command "tabedit" or "tabe" for short, opens a url specified as first parameter in a new tab');
- }
-
- } else {
- var url = param[1]
- if (url.substr(0,5) != "http:" && url.substr(0,6) != "https:") {
- url = "http://" + url;
- }
- if (param[0] == 'tabe' || param[0] == 'tabedit') {
- safari.self.tab.dispatchMessage("openTab",url);
- } else {
- location.href = url;
- }
- }
- break;
-
- case 'q':
- safari.self.tab.dispatchMessage("closeTab");
- break;
-
- case 'qa':
- safari.self.tab.dispatchMessage("closeWindow");
- break;
-
- case 'tabn':
- safari.self.tab.dispatchMessage("nextTab",0);
- break;
-
- case 'tabp':
- safari.self.tab.dispatchMessage("prevTab","");
- break;
-
- case 'tabfirst':
- case 'tabfir':
- safari.self.tab.dispatchMessage("nextTab",1);
- break;
-
- case 'tablast':
- safari.self.tab.dispatchMessage("nextTab","last");
- break;
-
- case 'tabnew':
- safari.self.tab.dispatchMessage("newTab","");
- break;
-
- }
-}
+ if (command === '') return;
+
+ if (command.charAt(0) == "%") {
+ t.percentCommand(command);
+ return;
+ }
+
+ param = command.split(" ");
+
+ switch (param[0]) {
+ case 'tabe':
+ case 'tabedit':
+ case 'e':
+ case 't':
+ case 'edit':
+ if (param[1] == "" || param[1] == undefined) {
+ if (param[0] == 'e' || param[0] == 'edit') {
+ alert('Usage: command "edit" or "e" for short, opens the url specified as first parameter in the current tab');
+ } else {
+ alert('Usage: command "tabedit" or "tabe" for short, opens a url specified as first parameter in a new tab');
+ }
+
+ } else {
+ var url = param[1];
+ if (url.substr(0,5) != "http:" && url.substr(0,6) != "https:") {
+ url = "http://" + url;
+ }
+ if (param[0] == 'tabe' || param[0] == 'tabedit') {
+ safari.self.tab.dispatchMessage("openTab",url);
+ } else {
+ location.href = url;
+ }
+ }
+ break;
+
+ case 'q':
+ safari.self.tab.dispatchMessage("closeTab");
+ break;
+
+ case 'qa':
+ safari.self.tab.dispatchMessage("closeWindow");
+ break;
+
+ case 'tabn':
+ safari.self.tab.dispatchMessage("nextTab",0);
+ break;
+
+ case 'tabp':
+ safari.self.tab.dispatchMessage("prevTab","");
+ break;
+
+ case 'tabfirst':
+ case 'tabfir':
+ safari.self.tab.dispatchMessage("nextTab",1);
+ break;
+
+ case 'tablast':
+ safari.self.tab.dispatchMessage("nextTab","last");
+ break;
+
+ case 'tabnew':
+ safari.self.tab.dispatchMessage("newTab","");
+ break;
+
+ }
+};
t.percentCommand = function(command) {
- param = command.split("/");
-
- switch (param[0]) {
- case "%s":
- if (t.lastActiveElement == undefined) break;
- if (param.length == 3 || param.length == 4) {
- var mod = "";
- if (param.length == 4) mod = param[3];
- var regex = new RegExp(param[1], mod);
- t.lastActiveElement.value = t.lastActiveElement.value.replace(regex, param[2]);
- }
- break;
- }
-}
+ param = command.split("/");
+ switch (param[0]) {
+ case "%s":
+ if (t.lastActiveElement == undefined) break;
+ if (param.length == 3 || param.length == 4) {
+ var mod = "";
+ if (param.length == 4) mod = param[3];
+ var regex = new RegExp(param[1], mod);
+ t.lastActiveElement.value = t.lastActiveElement.value.replace(regex, param[2]);
+ }
+ break;
+ }
+};
t.resetCombo = function() {
- combokey = '';
- multiplier = 0;
-}
+ combokey = '';
+ multiplier = 0;
+};
t.disable = function() {
- window.document.removeEventListener("keydown", handler, false);
-}
+ window.document.removeEventListener("keydown", handler, false);
+};
function getAnswer(theMessageEvent) {
- switch (theMessageEvent.name) {
- case "resetcombo":
- t.resetCombo();
- break;
-
- case "disable":
- if (loaded) {
- t.disable();
- }
- break;
-
- case "load":
- if (!loaded) {
- loaded = true;
- window.document.addEventListener("keydown", handler);
- }
- break;
- }
+ switch (theMessageEvent.name) {
+ case "resetcombo":
+ t.resetCombo();
+ break;
+
+ case "disable":
+ if (loaded) {
+ t.disable();
+ }
+ break;
+
+ case "load":
+ if (!loaded) {
+ loaded = true;
+ window.document.addEventListener("keydown", handler);
+ }
+ break;
+ }
}
safari.self.addEventListener("message", getAnswer, false);