From 4b6977d14b848a34ae83bf930e4e4fe72fdb95b3 Mon Sep 17 00:00:00 2001 From: MatMoul Date: Wed, 27 Sep 2017 22:16:38 +0200 Subject: [PATCH] First commit --- TODO | 3 + src/_locales/en/messages.json | 52 ++++++ src/_locales/fr/messages.json | 52 ++++++ src/dial | 1 + src/html/options.html | 1 + src/html/test.html | 9 + src/img/24.png | Bin 0 -> 297 bytes src/img/32.png | Bin 0 -> 462 bytes src/img/README.md | 3 + src/img/back.png | Bin 0 -> 424 bytes src/img/folder.png | Bin 0 -> 8856 bytes src/img/throbber.gif | Bin 0 -> 1079 bytes src/js/background.js | 280 +++++++++++++++++++++++++++++++ src/js/dial.js | 305 ++++++++++++++++++++++++++++++++++ src/js/test.js | 11 ++ src/manifest.json | 42 +++++ 16 files changed, 759 insertions(+) create mode 100644 TODO create mode 100644 src/_locales/en/messages.json create mode 100644 src/_locales/fr/messages.json create mode 100644 src/dial create mode 100644 src/html/options.html create mode 100644 src/html/test.html create mode 100644 src/img/24.png create mode 100644 src/img/32.png create mode 100644 src/img/README.md create mode 100644 src/img/back.png create mode 100644 src/img/folder.png create mode 100644 src/img/throbber.gif create mode 100644 src/js/background.js create mode 100644 src/js/dial.js create mode 100644 src/js/test.js create mode 100644 src/manifest.json diff --git a/TODO b/TODO new file mode 100644 index 0000000..740ca9f --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +Config Page +Improve screenshot result +Add favicon support diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json new file mode 100644 index 0000000..12a7167 --- /dev/null +++ b/src/_locales/en/messages.json @@ -0,0 +1,52 @@ +{ + "extensionName": { + "message": "Quick Dial", + "description": "Name of the extension." + }, + + "extensionDescription": { + "message": "Quick Dial, new tab page.", + "description": "Description of the extension." + }, + + "menuAddToQuickDial": { + "message": "Add to Quick Dial", + "description": "Text of add bookmark menu item." + }, + + "menuAddBookmark": { + "message": "Add Bookmark", + "description": "Text of add bookmark menu item." + }, + + "AddBookmarkPrompt": { + "message": "Enter the new bookmark url :", + "description": "Text of the add bookmark prompt." + }, + + "menuAddFolder": { + "message": "Add Folder", + "description": "Text of add folder menu item." + }, + + "AddFolderPrompt": { + "message": "Enter the new folder name :", + "description": "Text of the add folder prompt." + }, + + "menuRefreshItem": { + "message": "Refresh", + "description": "Text of refresh menu item." + }, + + "menuDeleteItem": { + "message": "Delete", + "description": "Text of delete menu item." + }, + + "deleteItemConfimation": { + "message": "Delete $1 ?", + "description": "Text of delete confirmation." + } + +} diff --git a/src/_locales/fr/messages.json b/src/_locales/fr/messages.json new file mode 100644 index 0000000..4e7e134 --- /dev/null +++ b/src/_locales/fr/messages.json @@ -0,0 +1,52 @@ +{ + "extensionName": { + "message": "Quick Dial", + "description": "Name of the extension." + }, + + "extensionDescription": { + "message": "Quick Dial, page nouvel onglet.", + "description": "Description of the extension." + }, + + "menuAddToQuickDial": { + "message": "Ajouter à Quick Dial", + "description": "Text of add bookmark menu item." + }, + + "menuAddBookmark": { + "message": "Ajouter un marque-page", + "description": "Text of add bookmark menu item." + }, + + "AddBookmarkPrompt": { + "message": "Entrez l'url du nouveau marque-page :", + "description": "Text of the add bookmark prompt." + }, + + "menuAddFolder": { + "message": "Ajouter un dossier", + "description": "Text of add folder menu item." + }, + + "AddFolderPrompt": { + "message": "Entrez le nom du nouveau dossier :", + "description": "Text of the add folder prompt." + }, + + "menuRefreshItem": { + "message": "Actualiser", + "description": "Text of refresh menu item." + }, + + "menuDeleteItem": { + "message": "Supprimer", + "description": "Text of delete menu item." + }, + + "deleteItemConfimation": { + "message": "Supprimer $1 ?", + "description": "Text of delete confirmation." + } + +} diff --git a/src/dial b/src/dial new file mode 100644 index 0000000..92123f6 --- /dev/null +++ b/src/dial @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/html/options.html b/src/html/options.html new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/src/html/options.html @@ -0,0 +1 @@ + diff --git a/src/html/test.html b/src/html/test.html new file mode 100644 index 0000000..6906290 --- /dev/null +++ b/src/html/test.html @@ -0,0 +1,9 @@ + + + test + + + + + + \ No newline at end of file diff --git a/src/img/24.png b/src/img/24.png new file mode 100644 index 0000000000000000000000000000000000000000..6f9210f0341b338fdfd51ef33a3f9434d01cc26a GIT binary patch literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjA3R+gLn>}1rz|i`kcku1@ZBBD zzoe$|hJ^3kNQHYf`rcawkNm6;6IgHM_V|164jqfhi#r!`@+^xyFiWxlE(7>3%sC=dAzXP{KLBs)uEe(ZNm^SGys8qRZHuDnGh3if4 zkMcz9J*Sa-4+ocL43);?}FpWfJPZV zn2Q0D}Z;CzWNm;;} t-Y7Q1L07?g(nmG>uF0CZ2QF-9U|_j-PSPM&Z6?s~44$rjF6*2UngGI=c?JLg literal 0 HcmV?d00001 diff --git a/src/img/32.png b/src/img/32.png new file mode 100644 index 0000000000000000000000000000000000000000..c4975670b9160a844ecb21a7261fbd3e412a3a7a GIT binary patch literal 462 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 S#8q1Mq~sxIGZttzvjzaQ-lD4j literal 0 HcmV?d00001 diff --git a/src/js/background.js b/src/js/background.js new file mode 100644 index 0000000..333de77 --- /dev/null +++ b/src/js/background.js @@ -0,0 +1,280 @@ +var core = {}; // Main app object in background.js +var app = {}; // Shared app object with pages + +core._init = function(){ // Called from core.Settings.load() + core.Bookmarks.initRoot(function(){ + core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); // Sync bookmarks with stored data + core.ContextMenus.initMenu(); + core.Bookmarks.initListener(); + }) +} + +core.Settings = {}; // Settings helper object +core.Settings.load = function(){ // Load settings and call core.init + browser.storage.local.get({ + background: '#3c4048', + grid: { + margin: 10, + rows: 4, + columns: 5, + cells: { + margin: 4, + ratioX: 4, + ratioY: 3, + borderColor: '#333333', + borderColorHover: '#a9a9a9', + borderRadius: 4, + title: true, + titleHeight: 18, + titleFontSize: 11, + titleFont: 'Arial, Verdana, Sans-serif', + titleColor: '#ffffff', + titleColorHover: '#33ccff', + backPanel: true, + backIcon: 'img/back.png', + folderIcon: 'img/folder.png', + loadingIcon: 'img/throbber.gif' + }, + root: 'Quick Dial', + node: {} + } + }).then(function(obj){ + app.settings = obj; + core._init(); + browser.runtime.sendMessage({ command: 'appReady'}).then(function(){}, function(){}); + },function(){}); +} +core.Settings.save = function(){ // Save settings + browser.storage.local.set(app.settings); +} +core.Settings.load(); // Need to be loaded first and call core.init when ready + +core.ContextMenus = {} // ContextMenu helper Object +core.ContextMenus.initMenu = function(){ // (Called from core._init) Init context menu in all pages + browser.contextMenus.create({ // Create Context menu + id: 'AddToQuickDial', + title: browser.i18n.getMessage("menuAddToQuickDial"), + contexts: ["all"], + documentUrlPatterns: [ 'http://*/*', 'https://*/*', 'file://*/*' ] + }, function(){}); + browser.contextMenus.onClicked.addListener(function(info, tab) { // Context menu click event + if (info.menuItemId == "AddToQuickDial") + core.GridNodes.createBookmark(app.settings.grid.node, info.pageUrl, tab.title, function(){}); + }); +} + +core.Bookmarks = {} // Bookmarks helper object +core.Bookmarks.initListener = function(){ // (Called from core._init) (/!\ Need filter to root tree only) Init listener of bookmarks + function notifyBookmarksChanged(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } + browser.bookmarks.onCreated.addListener(notifyBookmarksChanged); + browser.bookmarks.onChanged.addListener(notifyBookmarksChanged); + browser.bookmarks.onMoved.addListener(notifyBookmarksChanged); + browser.bookmarks.onRemoved.addListener(notifyBookmarksChanged); +} +core.Bookmarks.initRoot = function(callback){ // (Called from core._init) Create the root folder if not exist + browser.bookmarks.getSubTree('menu________').then(function(bookmarkItems){ + getChildItem = function(bookmarkItem, path, callback){ + if(path.length == 0){ + if(callback) callback(bookmarkItem); + return; + } + for(var child of bookmarkItem.children){ + if((path + '/').startsWith(child.title + '/')){ + getChildItem(child, path.substr(child.title.length + 1), callback); + return; + } + } + browser.bookmarks.create({ + parentId: bookmarkItem.id, + title: path.substr(0, (path + '/').indexOf('/')) + }).then(callback); + } + getChildItem(bookmarkItems[0], app.settings.grid.root, callback); + }, function(){ + console.log('Can not load bookmarks'); + if(callback) callback(null); + }); +} +core.Bookmarks.load = function(rootPath, callback){ // callback(bookmarkItem) Return BookmarkItem from rootPath + browser.bookmarks.getSubTree('menu________').then(function(bookmarkItems){ + if(callback) callback(core.Bookmarks.getItem(bookmarkItems[0], rootPath + '/')) + }, function(){ + console.log('Can not load bookmarks'); + if(callback) callback(null); + }); +} +core.Bookmarks.getItem = function(bookmarkItem, path){ // Return BookmarkItem from path from bookmarkItem as root + if(path.length == 0) return bookmarkItem; + for(var child of bookmarkItem.children) + if(path.startsWith(child.title + '/')) + return core.Bookmarks.getItem(child, path.substr(child.title.length + 1)); + return null; +} + +core.SiteInfos = {} // Siteinfos helper object +core.SiteInfos.loadInfos = function(url, args, callback){ // args: { icon: false; screenshot: false }, callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: {} ) + function pageLoaded(){ + var docTitle = iframe.contentWindow.document.title; + var docIcon = null; + var docScreenshot = null; + if(args && args.icon){ + // + } + if(args && args.screenshot){ + var canvas = document.createElement('canvas'); + canvas.style.width = previewWidth.toString() + 'px'; + canvas.style.height = previewHeight.toString() + 'px'; + canvas.width = previewWidth / 2; + canvas.height = previewHeight / 2; + var ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, previewWidth, previewHeight); + ctx.save(); + ctx.scale(0.5, 0.5); + ctx.drawWindow(iframe.contentWindow, 0, 0, previewWidth, previewHeight, 'rgb(255, 255, 255)'); + ctx.restore(); + docScreenshot = canvas.toDataURL(); + } + + document.body.removeChild(iframe); + if(callback) callback({ url: url, title: docTitle, icon: docIcon, screenshot:docScreenshot }); + } + + var previewWidth = 1200; // Need to be linked to settings + var previewHeight = 710; // Need to be linked to settings + var iframe = document.createElement('iframe'); + iframe.width = previewWidth + iframe.height = previewHeight + iframe.style.position = 'absolute'; + iframe.style.visibility = 'hidden'; + var xmlHttp = new XMLHttpRequest(); + xmlHttp.timeout = 2000 + xmlHttp.open('GET', url, true); + xmlHttp.onload = function(){ + document.body.appendChild(iframe); + iframe.contentWindow.document.write(xmlHttp.responseText.replace('', '')); + //iframe.contentWindow.document.write(xmlHttp.responseText.replace('', '')); + setTimeout(function(){ pageLoaded(); }, 2000); // /!\ Caution function can be shortcuted and sendtimeout is not the best way + } + xmlHttp.onabort = function(){ if(callback) callback(); } + xmlHttp.onerror = function(){ if(callback) callback(); } + xmlHttp.ontimeout = function(){ if(callback) callback(); } + xmlHttp.send(null); +} + +core.GridNodes = {}; // GridNodes helper object +core.GridNodes.sync = function(gridNode, rootPath){ // Sync GridNodes with Bookmarks + core.Bookmarks.load(rootPath, function(bookmarkItem){ + core.GridNodes.syncItem(gridNode, bookmarkItem); + browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); + core.Settings.save(); + }); +} +core.GridNodes.syncItem = function(gridNode, bookmarkItem){ // Sync GridNode with BookmarkItem + gridNode.id = bookmarkItem.id; + gridNode.title = bookmarkItem.title; // /!\ Need check last update + if(bookmarkItem.url){ + gridNode.type = 'bookmark'; + gridNode.url = bookmarkItem.url; // /!\ Need check last update + } else if(bookmarkItem.children){ + gridNode.type = 'folder'; + var EmptyItems = []; + if(! gridNode.children) gridNode.children = []; + else { + for(var i=gridNode.children.length-1; i>=0; i--){ + if(gridNode.children[i].type!='empty'){ + var found = false; + for(var child of bookmarkItem.children){ + if(child.id==gridNode.children[i].id){ + found = true; + break; + } + } + if(! found){ + if(i0){ + childGridNode = EmptyItems[0]; + EmptyItems.shift(); + }else { + childGridNode = {}; + gridNode.children.push(childGridNode) + } + } + core.GridNodes.syncItem(childGridNode, child); + } + EmptyItems.length = 0; + } else node.type = 'empty'; +} +core.GridNodes.getChild = function(gridNode, id){ // Return child node by ID + for(var child of gridNode.children) if(child.id == id) return child; + return null; +} +core.GridNodes.getNode = function(gridNode, path){ // Return GridNode from RootGridNode path + if(path.length == 0 || path == '/') return gridNode; + for(var child of gridNode.children) + if(path.startsWith(child.title + '/')) + return core.GridNodes.getNode(child, path.substr(child.title.length + 1)); + return null; +} +core.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of a GridNode + core.SiteInfos.loadInfos(gridNode.url, { screenshot: true }, function(infos){ + if(infos){ + gridNode.title = infos.title; + gridNode.image = infos.screenshot; + browser.bookmarks.update(gridNode.id, { + title: infos.title + }).then(function(bookmarkItem){}, function(){}); + core.Settings.save(); + } + if(callback) callback(infos); + }); +} +core.GridNodes.createFolder = function(gridNode, name, callback){ // Create a new folder in a GridNode + browser.bookmarks.create({ + parentId: gridNode.id, + title: name + }).then(callback); +} +core.GridNodes.createBookmark = function(gridNode, url, title, callback){ // Create a new Bookmark in a GridNode + browser.bookmarks.create({ + parentId: gridNode.id, + title: title || url, + url: url + }).then(callback); +} +core.GridNodes.delete = function(id, callback){ // Delete a GridNode + browser.bookmarks.removeTree(id).then(callback); +} +core.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // Set Child GridNodeIndex + while(newIndex>=gridNode.children.length){ + gridNode.children.push({ type: 'empty' }); + } + var node1 = gridNode.children[index]; + var node2 = gridNode.children[newIndex]; + gridNode.children[index] = node2; + gridNode.children[newIndex] = node1; + core.Settings.save(); + if(callback) callback(); + browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); +} + +// Public functions +app.refreshNode = core.GridNodes.refreshNode; +app.getNode = core.GridNodes.getNode; +app.createFolder = core.GridNodes.createFolder; +app.createBookmark = core.GridNodes.createBookmark; +app.deleteNode = core.GridNodes.delete; +app.setNodeIndex = core.GridNodes.setNodeIndex; diff --git a/src/js/dial.js b/src/js/dial.js new file mode 100644 index 0000000..a2a026d --- /dev/null +++ b/src/js/dial.js @@ -0,0 +1,305 @@ +var app = {} +var dial = { + styles: {}, + page: 1, + maxpage: 1 +}; + +browser.runtime.getBackgroundPage().then(function(page){ app = page.app; }, function(){}); +window.onload = function(){ if(app.settings) dial.initUI(); } +window.onresize = function(){ + if(app.settings) dial.updateGridLayout(dial.Grid, app.settings.grid, dial.styles.grid); +} +window.onwheel = function(ev){ + if(app.settings){ + if(ev.deltaY > 0){ + if(dial.page < dial.maxpage){ + dial.page += 1; + dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); + } + } else if(ev.deltaY < 0){ + if(dial.page > 1){ + dial.page -= 1; + dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); + } + } + } +} +browser.runtime.onMessage.addListener(function(request, sender, sendResponse){ + switch(request.command){ + case 'gridNodesSynced': + if(app.settings) dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); + break; + case 'appReady': + browser.runtime.getBackgroundPage().then(function(page){ app = page.app; }, function(){}); + dial.initUI(); + break; + } +}); + + +dial.initUI = function(){ + dial.Head = document.getElementById('head'); + dial.Body = document.getElementById('body'); + dial.Body.setAttribute('contextmenu', 'page'); + dial.Body.setAttribute('contextmenu', 'page'); + dial.initStyles(); + dial.initMenus(); + dial.Grid = dial.initGrid('Grid', app.settings.grid, dial.Body); + var url = new URL(window.location); + dial.path = url.searchParams.get('path'); + /* + if(url.searchParams.get('path')) dial.Node = app.getNode(app.settings.grid.node, dial.path + '/'); + else dial.Node = app.getNode(app.settings.grid.node, '/'); + */ + if(url.searchParams.get('path')) { + dial.Node = app.getNode(app.settings.grid.node, dial.path + '/'); + } else { + dial.Node = app.getNode(app.settings.grid.node, '/'); + } + dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); +} + +dial.initStyles = function(){ + dial.Style = document.createElement('style'), StyleSheet; + document.head.appendChild(dial.Style); + dial.styles.html = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('html { height: 100%; }')].style; + dial.styles.body = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('body { user-select: none; -moz-user-select: none; display: flex; width: 100%; height: 100%; margin: 0px; padding: 0px; background: ' + app.settings.background + '; }')].style; + dial.styles.grid = {}; + dial.styles.grid.grid = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid { border-collapse: collapse; margin: auto auto; }')].style; + dial.styles.grid.cell = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td { margin: 0px; padding: 0px; }')].style; + dial.styles.grid.link = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a { display: block; outline: none; text-decoration: none; margin: ' + app.settings.grid.cells.margin + 'px; border: 1px solid ' + app.settings.grid.cells.borderColor + '; border-radius: ' + app.settings.grid.cells.borderRadius + 'px; }')].style; + dial.styles.grid.linkHover = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a:hover { border-color: ' + app.settings.grid.cells.borderColorHover + '; }')].style; + dial.styles.grid.linkPanel = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a>div:first-child { background-repeat: no-repeat; }')].style; + dial.styles.grid.linkTitle = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a>div:last-child { height: ' + app.settings.grid.cells.titleHeight + 'px; font-size: ' + app.settings.grid.cells.titleFontSize + 'pt; font-family: ' + app.settings.grid.cells.titleFont + 'pt; text-align: center; overflow: hidden; color: ' + app.settings.grid.cells.titleColor + '; border-top: 1px solid ' + app.settings.grid.cells.borderColor + '; }')].style; + dial.styles.grid.linkTitleHover = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a:hover>div:last-child { color: ' + app.settings.grid.cells.titleColorHover + '; border-top-color: ' + app.settings.grid.cells.borderColorHover + ' }')].style; + dial.styles.grid.linkEmpty = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Empty { display: none; }')].style; + dial.styles.grid.linkBack = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Back :first-child { background-image: url("' + app.settings.grid.cells.backIcon + '"); background-repeat: no-repeat; background-position: center center; }')].style; + dial.styles.grid.linkFolder = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Folder :first-child { background-image: url("' + app.settings.grid.cells.folderIcon + '"); background-repeat: no-repeat; background-size: 100% 100%; }')].style; + dial.styles.grid.linkBookmark = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Bookmark :first-child { background-repeat: no-repeat; background-size: 100% 100%; }')].style; + dial.styles.grid.linkBookmarkLoading = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.BookmarkLoading :first-child { background-image: url("' + app.settings.grid.cells.loadingIcon + '"); background-repeat: no-repeat; background-position: center center; }')].style; +} + +dial.initMenus = function(){ + dial.PageMenu = document.createElement('menu'); + dial.PageMenu.type = 'context'; + dial.PageMenu.id = 'page' + dial.PageMenuCreateBookmark = document.createElement('menuitem'); + dial.PageMenuCreateBookmark.label = 'Add bookmark'; + dial.PageMenuCreateBookmark.onclick = dial.createBookmark; + dial.PageMenuCreateFolder = document.createElement('menuitem'); + dial.PageMenuCreateFolder.label = 'Add folder'; + dial.PageMenuCreateFolder.onclick = dial.createFolder; + dial.PageMenu.appendChild(dial.PageMenuCreateBookmark); + dial.PageMenu.appendChild(dial.PageMenuCreateFolder); + dial.Body.appendChild(dial.PageMenu); + + dial.ItemMenu = document.createElement('menu'); + dial.ItemMenu.type = 'context'; + dial.ItemMenu.id = 'item' + dial.ItemMenuCreateBookmark = document.createElement('menuitem'); + dial.ItemMenuCreateBookmark.label = browser.i18n.getMessage("menuAddBookmark"); + dial.ItemMenuCreateBookmark.onclick = dial.createBookmark; + dial.ItemMenuCreateFolder = document.createElement('menuitem'); + dial.ItemMenuCreateFolder.label = browser.i18n.getMessage("menuAddFolder"); + dial.ItemMenuCreateFolder.onclick = dial.createFolder; + dial.ItemMenuEdit = document.createElement('menuitem'); + dial.ItemMenuEdit.label = 'Edit'; + //dial.ItemMenuEdit.onclick = dial.test; + dial.ItemMenuRefresh = document.createElement('menuitem'); + dial.ItemMenuRefresh.label = 'Refresh'; + dial.ItemMenuRefresh.label = browser.i18n.getMessage("menuRefreshItem"); + dial.ItemMenuRefresh.onclick = dial.refreshNode; + dial.ItemMenuDelete = document.createElement('menuitem'); + dial.ItemMenuDelete.label = browser.i18n.getMessage("menuDeleteItem"); + dial.ItemMenuDelete.onclick = dial.deleteNode; + dial.ItemMenu.appendChild(dial.ItemMenuCreateBookmark); + dial.ItemMenu.appendChild(dial.ItemMenuCreateFolder); + dial.ItemMenu.appendChild(document.createElement('hr')); + //dial.ItemMenu.appendChild(dial.ItemMenuEdit); + dial.ItemMenu.appendChild(dial.ItemMenuRefresh); + dial.ItemMenu.appendChild(dial.ItemMenuDelete); + dial.Body.appendChild(dial.ItemMenu); +} + +dial.initGrid = function(name, settings, container){ + var grid = document.createElement('table'); + grid.className = name; + grid.getLink = function(index){ + var num_columns = grid.rows[0].cells.length; + return grid.rows[Math.floor(index/num_columns)].cells[index % num_columns].childNodes[0]; + } + for(var i=0; i dial.maxpage) dial.page = dial.maxpage; + if(dial.page > 1) iBase = (dial.page -1) * maxCells; + for(var i = iBase; i', '')); + } + xmlHttp.send(null); +} diff --git a/src/manifest.json b/src/manifest.json new file mode 100644 index 0000000..fbdec02 --- /dev/null +++ b/src/manifest.json @@ -0,0 +1,42 @@ +{ + + "manifest_version": 2, + "name": "__MSG_extensionName__", + "version": "0.0.2", + + "description": "__MSG_extensionDescription__", + + "icons": { + "24": "img/24.png", + "32": "img/32.png" + }, + + "permissions": [ + "storage", + "bookmarks", + "contextMenus", + "tabs", + "" + ], + + "background": { + "scripts": ["js/background.js"] + }, + + "chrome_url_overrides" : { + "newtab": "dial" + }, + + "options_ui": { + "page": "options.html" + }, + + "applications": { + "gecko": { + "id": "mat@matmoul.com_quickdial_test_3", + "strict_min_version": "52.0" + } + }, + + "default_locale": "en" +}