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);