diff --git a/bin/amo/tab_search-1.1.5-an+fx.xpi b/bin/amo/tab_search-1.1.5-an+fx.xpi new file mode 100644 index 0000000..50f5cc6 Binary files /dev/null and b/bin/amo/tab_search-1.1.5-an+fx.xpi differ diff --git a/src/backgrounds/bg1.jpg b/src/backgrounds/bg1.jpg new file mode 100644 index 0000000..1c5e9fe Binary files /dev/null and b/src/backgrounds/bg1.jpg differ diff --git a/src/css/dragula.min.css b/src/css/dragula.min.css new file mode 100644 index 0000000..cdcb2bc --- /dev/null +++ b/src/css/dragula.min.css @@ -0,0 +1 @@ +.gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.gu-hide{display:none!important}.gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.gu-transit{opacity:.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20)} \ No newline at end of file diff --git a/src/css/tabsSearch.css b/src/css/tabsSearch.css index 6ff47a9..60eee58 100644 --- a/src/css/tabsSearch.css +++ b/src/css/tabsSearch.css @@ -1,51 +1,87 @@ -body { - background: rgb(255,255,255); - width: 18em; +html, body { overflow-x: hidden; - min-height: 2.5em; } -#listZone { padding-top: 2.5em; } +#masterContainer, div[id*="listZone"], .block { + display: block; + padding: 1em; +} -#toFind { +#masterContainer { + background-image: url("../backgrounds/bg1.jpg"); + background-repeat: repeat; + width: 710px; + height: auto; +} + +#controls { position: fixed; - top: 0.5em; - z-index: 100; - width: 90%; - background: rgb(255,255,255); - color: rgb(0,0,0); - border-style: solid; - border-color: rgb(0, 0, 0); - text-align: center; - padding: 0.5em; + top: 0; + background: rgba(255,255,255, 1); + margin-left: 1.5em; } -.box:hover { background-color: #3EA724; } -.box { - display: block; - cursor: pointer; - background-color: #444444; - border-radius: 5px; - padding: 20px; - width: 120px; - height: 120px; - overflow: hidden; - margin: 0 auto; +#searchBar, #errorZone { + width: 630px; + background: rgb(255,255,255); + color: rgba(9,107,120, 0.85); + border-color: rgba(9,107,120, 0.85); text-align: center; } +#searchBar { + border-style: solid; + padding: 0.5em; + font-size: 2em; +} + +#errorZone { + color: red; + border-style: dotted; + margin-top: 2em; + padding-top: 0.5em; + padding-bottom: 0.5em; +} + +#listZone { + background-color: rgba(9,107,120, 0.85); + float: left; + width: 630px; + height: auto; + margin: 1.5em; +} + +.block { + display: block; + background-color: rgba(158, 181, 219, 0.53); + color: rgba(255,255,255,1); + float: left; + width: 125px; + height: 125px; + clear: right; + overflow: hidden; + margin: 1.5em; +} +.block:hover { + cursor: pointer; + background-color: rgba(255, 255, 255, 0.8); + color: rgba(64,64,64, 0.84); +} + .thumbImg { + clear: left; width: 64px; height: 64px; - margin-left: auto; - margin-right: auto; } -.title { - float: left; - clear: left; - height: 55px; - max-width: 120px; - overflow: hidden; - color: #ffffff; +.closeImg { + background-color: rgba(79, 186, 70, 1); + width: 16px; + height: 16px; + float: right; + padding: .5em; +} + +.closeImg:hover { + background-color: rgba(255, 0, 0, 1); } diff --git a/src/icons/tab.png b/src/icons/tab.png new file mode 100644 index 0000000..353a4ed Binary files /dev/null and b/src/icons/tab.png differ diff --git a/src/icons/x.png b/src/icons/x.png new file mode 100644 index 0000000..557b3e2 Binary files /dev/null and b/src/icons/x.png differ diff --git a/src/manifest.json b/src/manifest.json index 45d231a..cb9873d 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,12 +1,13 @@ { - "manifest_version": 2, - "name": "Tab Search", - "version": "1.1.0", - "description": "Search Tabs and switch to them quickly.", + "manifest_version": 2, + "name": "Tab Search", + "version": "1.1.5", + "description": "Search Tabs and switch to them quickly.", "applications": { "gecko": { - "id": "tabsSearch@itdominator.com" + "id": "tabsSearch@itdominator.com", + "strict_min_version": "55.0" } }, @@ -15,15 +16,18 @@ "96": "icons/tabsSearch_96.png" }, + "web_accessible_resources": [ + "icons/*.png", + "backgrounds/*.jpg" + ], + "permissions": [ - "activeTab", "tabs" ], "browser_action": { - "default_icon": "icons/tabsSearch_48.png", - "default_title": "Tab Search", - "default_popup": "pages/tabsSearch.html" + "default_icon": "icons/tabsSearch_48.png", + "default_title": "Tab Search", + "default_popup": "pages/tabsSearch.html" } - } diff --git a/src/pages/tabsSearch.html b/src/pages/tabsSearch.html index 26c0d57..21e2185 100755 --- a/src/pages/tabsSearch.html +++ b/src/pages/tabsSearch.html @@ -2,14 +2,24 @@ + - + - -
- +
+ +
- +
+
+ + + + + + + + diff --git a/src/scripts/dragContainersSetup.js b/src/scripts/dragContainersSetup.js new file mode 100644 index 0000000..513a435 --- /dev/null +++ b/src/scripts/dragContainersSetup.js @@ -0,0 +1,27 @@ +var count = 2; toMoveID = 0, newIndex = 0;; +var insert = ""; + +var drake = dragula() + .on('drag', function (el) { + toMoveID = parseInt(el.getAttribute("tabID")); + el.className = el.className.replace('ex-moved', ''); + }).on('drop', function (el, container) { + var subCont = document.getElementById("listZone"); + var size = subCont.children.length; + + for (var i = 0; i < size; i++) { + if (subCont.children[i].getAttribute("tabID") == toMoveID) { + newIndex = i; + } + } + + browser.tabs.move(toMoveID, {index: newIndex}).then(); + el.className += ' ex-moved'; + }).on('over', function (el, container) { + container.className += ' ex-over'; + }).on('out', function (el, container) { + container.className = container.className.replace('ex-over', ''); +}); + +// Connect to pre created containers +drake.containers.push(document.querySelector('#listZone')); diff --git a/src/scripts/eventListeners.js b/src/scripts/eventListeners.js new file mode 100644 index 0000000..0d27020 --- /dev/null +++ b/src/scripts/eventListeners.js @@ -0,0 +1,30 @@ +// Set click events +document.addEventListener("click", (e) => { + var target = e.target; + var targetID = target.id; + var parentElm = target.parentElement; + + if (targetID == "closeBttn") { + var id = parseInt(parentElm.getAttribute("tabID")); + + browser.tabs.remove(id).then(function () { + console.log("Removed tab..." + id) + }, onError); + + parentElm.parentElement.removeChild(parentElm); + } else if (targetID == "iconElm" || targetID == "faveIcon") { + if (targetID == "faveIcon") { + var id = parseInt(parentElm.parentElement.getAttribute("tabID")); + } else { + var id = parseInt(target.getAttribute("tabID")); + } + + browser.tabs.update(id, { active: true }).then(function () { + console.log("Selected tab..." + id) + }, onError); + } +}); + +document.getElementById("searchBar").onkeypress = function(e){ + searchTabs(); +} diff --git a/src/scripts/generateView.js b/src/scripts/generateView.js new file mode 100644 index 0000000..f3f965b --- /dev/null +++ b/src/scripts/generateView.js @@ -0,0 +1,53 @@ +const tabQuery = browser.tabs.query({currentWindow: true}); +const searchBar = document.getElementById("searchBar"); +const errHandler = document.getElementById("errorZone"); +const listZone = document.getElementById("listZone"); +const notFoundText = document.createTextNode("Search not found..."); + + +function logTabs(tabs) { + // tab.url requires the `tabs` permission + for (let tab of tabs) { + createContainer(tab); + } + // Set window position to bottom of list + window.scrollTo(0,document.body.scrollHeight); +} + +function createContainer(tab) { + var id = tab.id; + var spanTag = document.createElement("SPAN"); + var iconText = document.createTextNode(tab.title); + var centerTag = document.createElement("CENTER"); + var closeImgTag = document.createElement("IMG"); + var icoImgTag = document.createElement("IMG"); + + spanTag.title = tab.title; + spanTag.id = "iconElm"; + spanTag.className = "block"; + spanTag.setAttribute("tabID",tab.id); + + closeImgTag.id = "closeBttn"; + closeImgTag.className = "closeImg"; + closeImgTag.src = "../icons/x.png"; + + icoImgTag.id = "faveIcon"; + icoImgTag.className = "thumbImg"; + if (tab.favIconUrl == null || tab.favIconUrl == "") { + icoImgTag.src = "../icons/tab.png"; + } else { + icoImgTag.src = tab.favIconUrl; + } + + centerTag.appendChild(icoImgTag); + spanTag.appendChild(closeImgTag); + spanTag.appendChild(centerTag); + spanTag.appendChild(iconText); + listZone.appendChild(spanTag); +} + + +function onError(error) { console.log(`Error: ${error}`); } +function getAllTabs() { tabQuery.then(logTabs, onError); } + +getAllTabs(); diff --git a/src/scripts/libs/dragula.min.js b/src/scripts/libs/dragula.min.js new file mode 100644 index 0000000..41e2c18 --- /dev/null +++ b/src/scripts/libs/dragula.min.js @@ -0,0 +1 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;n="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,n.dragula=e()}}(function(){return function e(n,t,r){function o(u,c){if(!t[u]){if(!n[u]){var a="function"==typeof require&&require;if(!c&&a)return a(u,!0);if(i)return i(u,!0);var f=new Error("Cannot find module '"+u+"'");throw f.code="MODULE_NOT_FOUND",f}var l=t[u]={exports:{}};n[u][0].call(l.exports,function(e){var t=n[u][1][e];return o(t?t:e)},l,l.exports,e,n,t,r)}return t[u].exports}for(var i="function"==typeof require&&require,u=0;u0?e:fe.revertOnSpill,t=ie||W,r=v(t),o=k(r);o===!1&&n&&(ie?r&&r.removeChild(ie):Q.insertBefore(t,re)),o||n?le.emit("cancel",t,Q,Q):le.emit("drop",t,r,Q,oe),j()}}function j(){var e=ie||W;I(),z(),e&&E.rm(e,"gu-transit"),ue&&clearTimeout(ue),le.dragging=!1,ae&&le.emit("out",e,ae,Q),le.emit("dragend",e),Q=W=ie=re=oe=ue=ae=null}function k(e,n){var t;return t=void 0!==n?n:J?oe:g(ie||W),e===Q&&t===re}function q(e,n,r){function o(){var o=t(i);if(o===!1)return!1;var u=H(i,e),c=V(i,u,n,r),a=k(i,c);return a?!0:fe.accepts(W,i,Q,c)}for(var i=e;i&&!o();)i=v(i);return i}function U(e){function n(e){le.emit(e,f,ae,Q)}function t(){s&&n("over")}function r(){ae&&n("out")}if(J){e.preventDefault();var o=y("clientX",e),i=y("clientY",e),u=o-Z,c=i-ee;J.style.left=u+"px",J.style.top=c+"px";var f=ie||W,l=a(J,o,i),d=q(l,o,i),s=null!==d&&d!==ae;(s||null===d)&&(r(),ae=d,t());var p=v(f);if(d===Q&&ie&&!fe.copySortSource)return void(p&&p.removeChild(f));var m,h=H(d,l);if(null!==h)m=V(d,h,o,i);else{if(fe.revertOnSpill!==!0||ie)return void(ie&&p&&p.removeChild(f));m=re,d=Q}(null===m&&s||m!==f&&m!==g(f))&&(oe=m,d.insertBefore(f,m),le.emit("shadow",f,d,Q))}}function _(e){E.rm(e,"gu-hide")}function F(e){le.dragging&&E.add(e,"gu-hide")}function K(){if(!J){var e=W.getBoundingClientRect();J=W.cloneNode(!0),J.style.width=d(e)+"px",J.style.height=s(e)+"px",E.rm(J,"gu-transit"),E.add(J,"gu-mirror"),fe.mirrorContainer.appendChild(J),o(S,"add","mousemove",U),E.add(fe.mirrorContainer,"gu-unselectable"),le.emit("cloned",J,W,"mirror")}}function z(){J&&(E.rm(fe.mirrorContainer,"gu-unselectable"),o(S,"remove","mousemove",U),v(J).removeChild(J),J=null)}function H(e,n){for(var t=n;t!==e&&v(t)!==e;)t=v(t);return t===S?null:t}function V(e,n,t,r){function o(){var n,o,i,u=e.children.length;for(n=0;u>n;n++){if(o=e.children[n],i=o.getBoundingClientRect(),c&&i.left+i.width/2>t)return o;if(!c&&i.top+i.height/2>r)return o}return null}function i(){var e=n.getBoundingClientRect();return u(c?t>e.left+d(e)/2:r>e.top+s(e)/2)}function u(e){return e?g(n):n}var c="horizontal"===fe.direction,a=n!==e?i():o();return a}function $(e,n){return"boolean"==typeof fe.copy?fe.copy:fe.copy(e,n)}var G=arguments.length;1===G&&Array.isArray(e)===!1&&(n=e,e=[]);var J,Q,W,Z,ee,ne,te,re,oe,ie,ue,ce,ae=null,fe=n||{};void 0===fe.moves&&(fe.moves=l),void 0===fe.accepts&&(fe.accepts=l),void 0===fe.invalid&&(fe.invalid=P),void 0===fe.containers&&(fe.containers=e||[]),void 0===fe.isContainer&&(fe.isContainer=f),void 0===fe.copy&&(fe.copy=!1),void 0===fe.copySortSource&&(fe.copySortSource=!1),void 0===fe.revertOnSpill&&(fe.revertOnSpill=!1),void 0===fe.removeOnSpill&&(fe.removeOnSpill=!1),void 0===fe.direction&&(fe.direction="vertical"),void 0===fe.ignoreInputTextSelection&&(fe.ignoreInputTextSelection=!0),void 0===fe.mirrorContainer&&(fe.mirrorContainer=x.body);var le=b({containers:fe.containers,start:Y,end:D,cancel:A,remove:R,destroy:h,canMove:X,dragging:!1});return fe.removeOnSpill===!0&&le.on("over",_).on("out",F),r(),le}function o(e,n,r,o){var i={mouseup:"touchend",mousedown:"touchstart",mousemove:"touchmove"},u={mouseup:"pointerup",mousedown:"pointerdown",mousemove:"pointermove"},c={mouseup:"MSPointerUp",mousedown:"MSPointerDown",mousemove:"MSPointerMove"};t.navigator.pointerEnabled?w[n](e,u[r],o):t.navigator.msPointerEnabled?w[n](e,c[r],o):(w[n](e,i[r],o),w[n](e,r,o))}function i(e){if(void 0!==e.touches)return e.touches.length;if(void 0!==e.which&&0!==e.which)return e.which;if(void 0!==e.buttons)return e.buttons;var n=e.button;return void 0!==n?1&n?1:2&n?3:4&n?2:0:void 0}function u(e){var n=e.getBoundingClientRect();return{left:n.left+c("scrollLeft","pageXOffset"),top:n.top+c("scrollTop","pageYOffset")}}function c(e,n){return"undefined"!=typeof t[n]?t[n]:S.clientHeight?S[e]:x.body[e]}function a(e,n,t){var r,o=e||{},i=o.className;return o.className+=" gu-hide",r=x.elementFromPoint(n,t),o.className=i,r}function f(){return!1}function l(){return!0}function d(e){return e.width||e.right-e.left}function s(e){return e.height||e.bottom-e.top}function v(e){return e.parentNode===x?null:e.parentNode}function p(e){return"INPUT"===e.tagName||"TEXTAREA"===e.tagName||"SELECT"===e.tagName||m(e)}function m(e){return e?"false"===e.contentEditable?!1:"true"===e.contentEditable?!0:m(v(e)):!1}function g(e){function n(){var n=e;do n=n.nextSibling;while(n&&1!==n.nodeType);return n}return e.nextElementSibling||n()}function h(e){return e.targetTouches&&e.targetTouches.length?e.targetTouches[0]:e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e}function y(e,n){var t=h(n),r={pageX:"clientX",pageY:"clientY"};return e in r&&!(e in t)&&r[e]in t&&(e=r[e]),t[e]}var b=e("contra/emitter"),w=e("crossvent"),E=e("./classes"),x=document,S=x.documentElement;n.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./classes":1,"contra/emitter":5,crossvent:6}],3:[function(e,n,t){n.exports=function(e,n){return Array.prototype.slice.call(e,n)}},{}],4:[function(e,n,t){"use strict";var r=e("ticky");n.exports=function(e,n,t){e&&r(function(){e.apply(t||null,n||[])})}},{ticky:9}],5:[function(e,n,t){"use strict";var r=e("atoa"),o=e("./debounce");n.exports=function(e,n){var t=n||{},i={};return void 0===e&&(e={}),e.on=function(n,t){return i[n]?i[n].push(t):i[n]=[t],e},e.once=function(n,t){return t._once=!0,e.on(n,t),e},e.off=function(n,t){var r=arguments.length;if(1===r)delete i[n];else if(0===r)i={};else{var o=i[n];if(!o)return e;o.splice(o.indexOf(t),1)}return e},e.emit=function(){var n=r(arguments);return e.emitterSnapshot(n.shift()).apply(this,n)},e.emitterSnapshot=function(n){var u=(i[n]||[]).slice(0);return function(){var i=r(arguments),c=this||e;if("error"===n&&t["throws"]!==!1&&!u.length)throw 1===i.length?i[0]:i;return u.forEach(function(r){t.async?o(r,i,c):r.apply(c,i),r._once&&e.off(n,r)}),e}},e}},{"./debounce":4,atoa:3}],6:[function(e,n,t){(function(t){"use strict";function r(e,n,t,r){return e.addEventListener(n,t,r)}function o(e,n,t){return e.attachEvent("on"+n,f(e,n,t))}function i(e,n,t,r){return e.removeEventListener(n,t,r)}function u(e,n,t){var r=l(e,n,t);return r?e.detachEvent("on"+n,r):void 0}function c(e,n,t){function r(){var e;return p.createEvent?(e=p.createEvent("Event"),e.initEvent(n,!0,!0)):p.createEventObject&&(e=p.createEventObject()),e}function o(){return new s(n,{detail:t})}var i=-1===v.indexOf(n)?o():r();e.dispatchEvent?e.dispatchEvent(i):e.fireEvent("on"+n,i)}function a(e,n,r){return function(n){var o=n||t.event;o.target=o.target||o.srcElement,o.preventDefault=o.preventDefault||function(){o.returnValue=!1},o.stopPropagation=o.stopPropagation||function(){o.cancelBubble=!0},o.which=o.which||o.keyCode,r.call(e,o)}}function f(e,n,t){var r=l(e,n,t)||a(e,n,t);return h.push({wrapper:r,element:e,type:n,fn:t}),r}function l(e,n,t){var r=d(e,n,t);if(r){var o=h[r].wrapper;return h.splice(r,1),o}}function d(e,n,t){var r,o;for(r=0;r 1) { + for (let sel of selection) { + createContainer(sel) + } + errHandler.style.display = "none"; + clearNodes(errHandler); + } else { + if (selection[0] != undefined) { + errHandler.style.display = "none"; + clearNodes(errHandler); + loadSelTab(selection[0].id); + } else { + errHandler.style.display = "block"; + errHandler.appendChild(notFoundText); + } + } + } else { logTabs(tabs); } +} + +function clearNodes(targetNode) { + while (targetNode.firstChild) { + targetNode.removeChild(targetNode.firstChild); + } +} + +function loadSelTab(id) { browser.tabs.update(id, { active: true }); } +function searchTabs() { tabQuery.then(findTabs, onError); } diff --git a/src/scripts/tabsSearch.js b/src/scripts/tabsSearch.js deleted file mode 100644 index 91f11b2..0000000 --- a/src/scripts/tabsSearch.js +++ /dev/null @@ -1,81 +0,0 @@ -const toFind = document.getElementById("toFind"); -const tabQuery = browser.tabs.query({currentWindow: true}); -const errHandler = document.getElementById("errorZone"); -const listZone = document.getElementById("listZone"); -const notFoundText = document.createTextNode("Search not found..."); - -document.getElementById("toFind").onkeypress = function(e){ - searchTabs(); -} - -document.addEventListener("click", (e) => { - if (e.target.id != "toFind" && e.target.id != "listZone" ) { - if (e.target.tagName == "IMG") { - var parent = e.target.parentNode; - loadSelTab(parseInt(parent.id)); - } else { - loadSelTab(parseInt(e.target.id)); - } - } -}); - -function logTabs(tabs) { - var selection = []; - - clearNodes(listZone); - if (toFind.value != "") { - for (let tab of tabs) { - var title = tab.title; - if (title.toLowerCase().includes(toFind.value.toLowerCase())) { - selection.push(tab); - } - } - if (selection.length > 1) { - for (let sel of selection) { - icon = document.createElement("DIV"); - thumbnail = document.createElement("IMG"); - title = document.createElement("P"); - lineBreak = document.createElement("BR"); - titleText = document.createTextNode(sel.title); - - icon.id = sel.id; - icon.className = "box"; - thumbnail.className = "thumbImg"; - thumbnail.src = sel.favIconUrl; - title.className = "title"; - - icon.appendChild(thumbnail); - icon.appendChild(title); - title.appendChild(titleText); - listZone.appendChild(icon); - listZone.appendChild(lineBreak); - } - errHandler.style.display = "none"; - clearNodes(errHandler); - } else { - if (selection[0] != undefined) { - errHandler.style.display = "none"; - clearNodes(errHandler); - loadSelTab(selection[0].id); - } else { - errHandler.style.display = "block"; - errHandler.appendChild(notFoundText); - } - } - } -} - -function loadSelTab(id) { - browser.tabs.update(id, { - active: true - }); -} - -function clearNodes(targetNode) { - while (targetNode.firstChild) { - targetNode.removeChild(targetNode.firstChild); - } -} - -function searchTabs() { tabQuery.then(logTabs, onError); } -function onError(error) { console.log(`Error: ${error}`); }