1
0
mirror of https://github.com/MatMoul/quickdial-webext.git synced 2025-12-16 08:53:13 +00:00

35 Commits

Author SHA1 Message Date
3c79e9e38f Version 0.1.5 2017-10-21 18:13:26 +02:00
5e61b65e82 Bug: (Properties) Image is lost when clicking OK and Unlock title don't work 2017-10-21 18:03:30 +02:00
cebdb32c35 Feature: Add a setting to lock title from update 2017-10-21 17:51:35 +02:00
1e5e450565 Improvement: Add escape support on popup 2017-10-21 17:10:51 +02:00
5a2c30e00f Feature: Root folder path customization 2017-10-21 16:53:39 +02:00
938f1a0fde Improvement: Don't send setNodeIndex if new index is the same than older index 2017-10-21 16:08:38 +02:00
4019c0cf77 Improvement: Use backgroundpage for data if possible 2017-10-21 14:43:56 +02:00
152506f463 Merge branch 'acolombo25-master' into develop 2017-10-18 20:12:17 +02:00
Andrea Colombo
cf0ed2bf69 Add Italian translation 2017-10-18 12:07:29 +02:00
121da31400 Version 0.1.4 2017-10-15 13:58:41 +02:00
7c9a1bb624 Project: Update TODO, README, Screenshots 2017-10-15 13:42:06 +02:00
550757a186 Bug: Prevent dragdrop on back node 2017-10-15 13:20:18 +02:00
dbe7751b77 Improvement: Old styles and old grid are removed after redrawing the new 2017-10-15 12:18:10 +02:00
957f468c59 Improvement: Add bookmark without sheme add http:// 2017-10-15 12:04:40 +02:00
325fdc8c83 Bug: Add to Quick Dial menu is missing 2017-10-15 11:53:33 +02:00
245d70a6eb Bug: Somme node are empty and make data unusable 2017-10-15 11:28:21 +02:00
4a3072bbdc Version 0.1.3 2017-10-15 01:14:23 +02:00
9c907f37e0 Improvement: Update thumbnails when url has changed 2017-10-15 00:51:50 +02:00
39f96b015b Feature: Add Default button on node properties 2017-10-15 00:25:12 +02:00
d3cc6cf68f Bug: Custom image are not displayed in properties window 2017-10-15 00:10:53 +02:00
b91255375f Bug: Custom image are not displayed in properties window 2017-10-15 00:02:41 +02:00
c00b227599 Version 0.1.2 2017-10-14 23:12:38 +02:00
73152dedd0 Feature: Add settings to set custom image on nodes 2017-10-14 23:11:33 +02:00
0f956667a0 Code: Rename var core to app 2017-10-14 22:43:48 +02:00
feafd8449e Feature: Add first support to editing nodes 2017-10-14 22:41:28 +02:00
20ca231945 Feature: Add Capture in a new Tab support for folder 2017-10-14 20:51:38 +02:00
30b432d1b8 Features: Add toolbar button 2017-10-14 19:33:20 +02:00
7e11b0b7da Stability: Encode url path 2017-10-14 19:00:15 +02:00
420f356136 Bug reported by Scienmind: Background color flickering on subfolder 2017-10-14 18:53:59 +02:00
d6ee45da30 Version 0.1.1 2017-10-14 17:20:59 +02:00
45a5bd5d44 Bug: Sync from bookmark is disabed 2017-10-14 17:13:57 +02:00
55521d2d53 Improvement: Speed start 2017-10-14 16:51:39 +02:00
1dd5409dd0 Version 0.1.0 2017-10-14 12:57:14 +02:00
039c3566ea Bug reported by Scienmind and Acid Crash: Private Window and Contextual Identities don't work 2017-10-14 12:44:56 +02:00
1413464149 Update screenshot 2017-10-08 19:10:46 +02:00
20 changed files with 1073 additions and 464 deletions

View File

@@ -1,2 +1,9 @@
# quickdial-webext # quickdial-webext
QuickDial is a WebExt Dial page for Firefox QuickDial is a WebExt Dial page for Firefox
[QuickDial on addons.mozilla.org](https://addons.mozilla.org/fr/firefox/addon/quick-dial/?src=search)
## Contribute and evolution :</br>
* [CONTRIBUTING.md](https://github.com/MatMoul/quickdial-webext/blob/develop/CONTRIBUTING.md)

3
TODO
View File

@@ -1,6 +1,5 @@
Add node settings popup
Add custom image (thumbnails)
Create style for popup Create style for popup
Add a visual hint for multipage
Need a best solution to update folder and bookmark when it are updated from Firefox Need a best solution to update folder and bookmark when it are updated from Firefox
Improve screenshot result Improve screenshot result
Add favicon support Add favicon support

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 535 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 KiB

After

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 430 KiB

View File

@@ -34,6 +34,11 @@
"description": "Text of the add folder prompt." "description": "Text of the add folder prompt."
}, },
"menuProperties": {
"message": "Properties",
"description": "Text of properties menu item."
},
"menuRefreshItem": { "menuRefreshItem": {
"message": "Refresh", "message": "Refresh",
"description": "Text of refresh menu item." "description": "Text of refresh menu item."

View File

@@ -34,6 +34,11 @@
"description": "Text of the add folder prompt." "description": "Text of the add folder prompt."
}, },
"menuProperties": {
"message": "Propriétés",
"description": "Text of properties menu item."
},
"menuRefreshItem": { "menuRefreshItem": {
"message": "Actualiser", "message": "Actualiser",
"description": "Text of refresh menu item." "description": "Text of refresh menu item."

View File

@@ -0,0 +1,67 @@
{
"extensionDescription": {
"message": "Quick Dial, una dial page inspirata a fast dial.",
"description": "Description of the extension."
},
"menuAddToQuickDial": {
"message": "Aggiungi a Quick Dial",
"description": "Text of add bookmark menu item."
},
"menuNew": {
"message": "Nuovo",
"description": "Text of new menu item."
},
"menuNewBookmark": {
"message": "Segnalibro",
"description": "Text of add bookmark menu item."
},
"AddBookmarkPrompt": {
"message": "Scrivi l'url del nuovo segnalibro:",
"description": "Text of the add bookmark prompt."
},
"menuNewFolder": {
"message": "Cartella",
"description": "Text of add folder menu item."
},
"AddFolderPrompt": {
"message": "Scrivi il nome della nuova cartella:",
"description": "Text of the add folder prompt."
},
"menuProperties": {
"message": "Proprietà",
"description": "Text of properties menu item."
},
"menuRefreshItem": {
"message": "Aggiorna",
"description": "Text of refresh menu item."
},
"menuCapturePage": {
"message": "Cattura in una nuova scheda",
"description": "Text of capture menu item."
},
"menuDeleteItem": {
"message": "Elimina",
"description": "Text of delete menu item."
},
"deleteItemConfimation": {
"message": "Eliminare $1?",
"description": "Text of delete confirmation."
},
"menuSettings": {
"message": "Impostazioni Quick Dial",
"description": "Text of settings menu item."
}
}

View File

@@ -1 +1 @@
<!DOCTYPE html><html><head id="head"><meta charset="utf-8" /><link rel="shortcut icon" type="image/png" href="img/24.png" /><title id="title"></title><script type="text/javascript" src="js/dial.js"></script></head><body id="body"></body></html> <!DOCTYPE html><html><head><meta charset="utf-8" /><link rel="shortcut icon" type="image/png" href="img/24.png" /><script type="text/javascript" src="js/dial.js"></script></head><body></body></html>

73
src/html/properties.html Normal file
View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" type="image/png" href="img/24.png" />
<title id="title">Quick Dial Node Propoerties</title>
<script type="text/javascript" src="/js/properties.js"></script>
<style>
body { margin: 0px; padding: 4px; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
h1 { font-size: 11pt; text-decoration: underline; }
input[type=number] { width: 56px; }
input[type=color] { width: 60px; }
.hidden { display: none; }
.Tab>table { width: 100%; border-collapse: collapse; }
.Tab .TabSpace { width: 100%; border-bottom: solid 1px #505050; }
.Tab .TabButton { border: solid 1px #505050; padding: 2px 6px 2px 6px; cursor: default; }
.Tab .TabButtonActive { border: solid 1px #505050; border-bottom: none; padding: 2px 6px 2px 6px; cursor: default; }
.Tab>div { padding: 8px; height: 330px; border-left: solid 1px #505050; border-bottom: solid 1px #505050; border-right: solid 1px #505050; }
</style>
</head>
<body>
<div id="Tabs" class="Tab">
<table>
<tr>
<td class="TabButtonActive">Main</td>
<td class="TabButton" style="display:none">Temp</td>
<td class="TabSpace"></td>
</tr>
</table>
<div>
<div>
<table style="width:100%">
<tr>
<td><span>Title :</span></td>
<td><input id="Title" type="text" style="width:100%"></td>
<td style="width:20px"><input id="TitleLocked" type="checkbox" title="Lock title"></td>
</tr>
<tr>
<td><span>Url :</span></td>
<td colspan="2"><input id="Url" type="text" style="width:100%"></td>
</tr>
<tr>
<td><span>Image :</span></td>
<td colspan="2">
<button id="ImageReset">Reset</button>
<button id="ImageDefault">Default</button>
<button class="hidden" id="ImageRefresh">Refresh</button>
<button class="hidden" id="ImageCapture">Capture</button>
<input id="ImageFile" type="file" style="width:180px;">
</td>
</tr>
<tr>
<td></td>
<td colspan="2"><div id="ImagePreview" style="width: 300px; height: 180px;"></div></td>
</tr>
</table>
</div>
<div class="hidden">
</div>
</div>
</div>
<div style="text-align: right; margin-top: 14px;">
<button id="BtnOk">OK</button>
<button id="BtnApply">Apply</button>
<button id="BtnCancel">Cancel</button>
</div>
</body>
</html>

View File

@@ -15,7 +15,7 @@
.Tab .TabSpace { width: 100%; border-bottom: solid 1px #505050; } .Tab .TabSpace { width: 100%; border-bottom: solid 1px #505050; }
.Tab .TabButton { border: solid 1px #505050; padding: 2px 6px 2px 6px; cursor: default; } .Tab .TabButton { border: solid 1px #505050; padding: 2px 6px 2px 6px; cursor: default; }
.Tab .TabButtonActive { border: solid 1px #505050; border-bottom: none; padding: 2px 6px 2px 6px; cursor: default; } .Tab .TabButtonActive { border: solid 1px #505050; border-bottom: none; padding: 2px 6px 2px 6px; cursor: default; }
.Tab>div { padding: 8px; height: 330px; border-left: solid 1px #505050; border-bottom: solid 1px #505050; border-right: solid 1px #505050; } .Tab>div { padding: 8px; height: 350px; border-left: solid 1px #505050; border-bottom: solid 1px #505050; border-right: solid 1px #505050; }
</style> </style>
</head> </head>
<body id="body"> <body id="body">
@@ -82,6 +82,12 @@
</td> </td>
</tr> </tr>
</table> </table>
<table style="width:100%;">
<tr>
<td><span>Root Folder :</span></td>
<td><input id="GridRoot" type="text" style="width:100%;"></td>
</tr>
</table>
</div> </div>
<div class="hidden"> <div class="hidden">
<table> <table>

View File

@@ -1,107 +1,226 @@
var core = {}; // Main app object in background.js var app = {}; // App object
var app = {}; // Shared app object with pages
core.init = function(){ // Init module app.init = function(){ // Init module
core.Settings.load(function(){ app.Settings.init(function(){
core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root, function(){ // Sync bookmarks with stored data app.Messages.init();
core.ContextMenus.initMenu(); browser.runtime.sendMessage({ cmd: app.Messages.Commands.settingsChanged });
core.Bookmarks.initListener(); browser.browserAction.onClicked.addListener(function(){
browser.tabs.create({});
});
app.GridNodes.sync(app.node, app.settings.grid.root, function(){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded });
app.Bookmarks.initListener();
app.ContextMenus.initMenu();
}); });
}); });
} };
core.Settings = {}; // Settings helper object app.Messages = {}; // Messages helper object
core.Settings.load = function(callback){ // Load settings app.Messages.Commands = {
browser.storage.local.get({ getSettings: 0,
version: 2, setSettings: 1,
backgroundColor: '#3c4048', getNode: 2,
backgroundImage: null, getNodeByID: 3,
grid: { updateNode: 4,
margin: 10, setNodeIndex: 5,
rows: 4, createBookmark: 6,
columns: 5, createFolder: 7,
backNode: true, deleteNode: 8,
backIcon: 'url(/img/back.png)', refreshNode: 9,
folderIcon: 'url(/img/folder.png)', capturePage: 10,
loadingIcon: 'url(/img/throbber.gif)', settingsChanged: 100,
cells: { gridNodesLoaded: 101
margin: 4, };
marginHover: 4, app.Messages.init = function(){ // Init Messages Listeners
ratioX: 4, browser.runtime.onMessage.addListener(function(request, sender, sendResponse){
ratioY: 3, switch(request.cmd){
backgroundColor: null, case app.Messages.Commands.getSettings:
backgroundColorHover: null, sendResponse(app.settings);
borderColor: '#333333', break;
borderColorHover: '#a9a9a9', case app.Messages.Commands.setSettings:
borderRadius: 4, let rootChanged = (app.settings.grid.root!=request.settings.grid.root);
borderRadiusHover: 4, app.settings = request.settings;
title: true, app.Settings.save();
titleHeight: 16, sendResponse(app.settings);
titleFontSize: 10, browser.runtime.sendMessage( { cmd: app.Messages.Commands.settingsChanged } );
titleFont: 'Arial, Verdana, Sans-serif', if(rootChanged){
titleColor: '#ffffff', app.node = { children: [] };
titleColorHover: '#33ccff', app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); });
titleBackgroundColor: null, } else {
titleBackgroundColorHover: null browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
}, }
root: 'Quick Dial', break;
node: { children: [] } case app.Messages.Commands.getNodeByID:
var nodes = app.GridNodes.getNodeWithParents(request.id);
if(nodes) sendResponse(nodes[nodes.length-1]);
else sendResponse(null);
break;
case app.Messages.Commands.updateNode:
app.GridNodes.updateNode(app.GridNodes.getNodeById(request.id), request.value, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.getNode:
sendResponse(app.GridNodes.getNode(app.node, request.path.substr(1)));
break;
case app.Messages.Commands.setNodeIndex:
app.GridNodes.setNodeIndex(app.GridNodes.getNode(app.node, request.path.substr(1)), request.index, request.newIndex, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.createBookmark:
app.GridNodes.createBookmark(app.GridNodes.getNode(app.node, request.path.substr(1)), request.url, request.title, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.createFolder:
app.GridNodes.createFolder(app.GridNodes.getNode(app.node, request.path.substr(1)), request.name, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.deleteNode:
app.GridNodes.deleteNode(app.GridNodes.getNode(app.node, request.path.substr(1)), request.id, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.refreshNode:
app.GridNodes.refreshNode(app.GridNodes.getChildNode(app.GridNodes.getNode(app.node, request.path.substr(1)), request.id), function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.capturePage:
app.GridNodes.capturePage(app.GridNodes.getChildNode(app.GridNodes.getNode(app.node, request.path.substr(1)), request.id), function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
} }
}).then(function(obj){
if(obj.grid.cells.backIcon){ // Upgrade Data Version
obj.version = 2;
obj.grid.backNode = true;
obj.grid.backIcon = 'url(/img/back.png)';
obj.grid.folderIcon = 'url(/img/folder.png)';
obj.grid.loadingIcon = 'url(/img/throbber.gif)';
obj.grid.cells.backgroundColor = null;
obj.grid.cells.backgroundColorHover = null;
obj.grid.cells.titleBackgroundColor = null;
obj.grid.cells.titleBackgroundColorHover = null;
delete obj.grid.cells.backIcon;
delete obj.grid.cells.folderIcon;
delete obj.grid.cells.loadingIcon;
delete obj.grid.cells.backPanel;
}
app.settings = obj;
if(callback) callback();
}); });
} };
core.Settings.save = function(){ // Save settings
browser.storage.local.set(app.settings); app.Settings = {}; // Settings helper object
browser.runtime.sendMessage({ command: 'SettingsChanged' }); app.Settings.init = function(callback){ // Load settings and nodes
browser.storage.local.get().then(function(data){
if(Object.keys(data).length == 0) {
data = {
version: 3,
settings: {
backgroundColor: '#3c4048',
backgroundImage: null,
grid: {
margin: 10,
rows: 4,
columns: 5,
backNode: true,
backIcon: 'url(/img/back.png)',
folderIcon: 'url(/img/folder.png)',
loadingIcon: 'url(/img/throbber.gif)',
cells: {
margin: 4,
marginHover: 4,
backgroundColor: null,
backgroundColorHover: null,
borderColor: '#333333',
borderColorHover: '#a9a9a9',
borderRadius: 4,
borderRadiusHover: 4,
title: true,
titleHeight: 16,
titleFontSize: 10,
titleFont: 'Arial, Verdana, Sans-serif',
titleColor: '#ffffff',
titleColorHover: '#33ccff',
titleBackgroundColor: null,
titleBackgroundColorHover: null,
previewWidth: 1200,
previewHeight: 710
},
root: 'Quick Dial',
}
},
node: { children: [] }
}
}
if(!data.version){ // Upgrade Data Version
data.version = 2;
data.grid.backNode = true;
data.grid.backIcon = 'url(/img/back.png)';
data.grid.folderIcon = 'url(/img/folder.png)';
data.grid.loadingIcon = 'url(/img/throbber.gif)';
data.grid.cells.backgroundColor = null;
data.grid.cells.backgroundColorHover = null;
data.grid.cells.titleBackgroundColor = null;
data.grid.cells.titleBackgroundColorHover = null;
delete data.grid.cells.backIcon;
delete data.grid.cells.folderIcon;
delete data.grid.cells.loadingIcon;
delete data.grid.cells.backPanel;
}
if(data.version == 2){ // Upgrade Data Version
var oldData = data;
data = {};
data.version = 3;
data.settings = oldData;
data.node = oldData.grid.node;
delete data.settings.version;
delete data.settings.grid.node;
app.settings = data.settings;
app.node = data.node;
browser.storage.local.clear().then(function(){
app.Settings.save();
});
}
app.settings = data.settings;
app.node = data.node;
if(callback) callback();
}, function(){ console.log('Error loading data'); });
};
app.Settings.update = function(settings, callback){ // Save new settings
app.settings = settings;
app.Settings.save(callback);
};
app.Settings.save = function(callback){ // Save settings
var data = { version: 3 };
data.settings = app.settings;
data.node = app.node;
browser.storage.local.set(data).then(function(){
if(callback) callback();
}, function(){ console.log('Error saving settings'); });
} }
core.init(); app.init();
core.ContextMenus = {} // ContextMenu helper Object app.ContextMenus = {} // ContextMenu helper Object
core.ContextMenus.initMenu = function(){ // (Called from core.init) Init context menu in all pages app.ContextMenus.initMenu = function(){ // (Called from app.init) Init context menu in all pages
browser.contextMenus.create({ // Create Context menu browser.contextMenus.create({ // Create Context menu
id: 'AddToQuickDial', id: 'AddToQuickDial',
title: browser.i18n.getMessage("menuAddToQuickDial"), title: browser.i18n.getMessage("menuAddToQuickDial"),
contexts: ["all"], contexts: ["all"],
documentUrlPatterns: [ 'http://*/*', 'https://*/*', 'file://*/*' ] documentUrlPatterns: [ 'http://*/*', 'https://*/*', 'file://*/*', 'ftp://*/*' ]
}, function(){}); }, function(){});
browser.contextMenus.onClicked.addListener(function(info, tab) { // Context menu click event browser.contextMenus.onClicked.addListener(function(info, tab) { // Context menu click event
if (info.menuItemId == "AddToQuickDial") if (info.menuItemId == "AddToQuickDial")
core.GridNodes.createBookmark(app.settings.grid.node, info.pageUrl, tab.title, function(){}); app.GridNodes.createBookmark(app.node, info.pageUrl, tab.title, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
}); });
} }
core.Bookmarks = {} // Bookmarks helper object app.Bookmarks = {} // Bookmarks helper object
core.Bookmarks._onCreated = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onCreated = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks._onChanged = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onChanged = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks._onMoved = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onMoved = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks._onRemoved = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onRemoved = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks.initListener = function(){ // (Called from core.init) (/!\ Need filter to root tree only) Init listener of bookmarks app.Bookmarks.initListener = function(){ // (Called from app.init) (/!\ Need filter to root tree only) Init listener of bookmarks
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
//browser.bookmarks.onChanged.addListener(core.Bookmarks._onChanged); //browser.bookmarks.onChanged.addListener(app.Bookmarks._onChanged);
browser.bookmarks.onMoved.addListener(core.Bookmarks._onMoved); browser.bookmarks.onMoved.addListener(app.Bookmarks._onMoved);
browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.addListener(app.Bookmarks._onRemoved);
} }
core.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and create it if not exist app.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and create it if not exist
if(!callback) return; if(!callback) return;
browser.bookmarks.getSubTree('menu________').then(function(bookmarkItems){ var root = 'menu________';
if(rootPath.substr(0,1)=='/') root = 'root________';
browser.bookmarks.getSubTree(root).then(function(bookmarkItems){
function getChildItem(bookmarkItem, path, callback){ function getChildItem(bookmarkItem, path, callback){
if(path.length == 0){ if(path.length == 0){
callback(bookmarkItem); callback(bookmarkItem);
@@ -117,35 +236,13 @@ core.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and cr
return getChildItem(bookmarkItem, path.substr(bookmarkItem.title.length + 1), callback); return getChildItem(bookmarkItem, path.substr(bookmarkItem.title.length + 1), callback);
}, function(){ callback(); }); }, function(){ callback(); });
} }
getChildItem(bookmarkItems[0], rootPath, callback); if(rootPath.substr(0,1)=='/') getChildItem(bookmarkItems[0], rootPath.substr(1), callback);
else getChildItem(bookmarkItems[0], rootPath, callback);
}, function(){ callback(); }); }, function(){ callback(); });
} }
core.SiteInfos = {} // Siteinfos helper object app.SiteInfos = {} // Siteinfos helper object
core.SiteInfos.fromTab = function(callback){ // Retrieve infos from current tab. callback( { url, title, icon, screenshot } || error: callback() ) app.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a new tab. callback( { url, title, icon, screenshot } || error: callback() )
browser.tabs.getCurrent().then(function(tab){
function whaitLoaded(){
browser.tabs.get(tab.id).then(function(tab){
if(tab.status == 'loading') setTimeout(whaitLoaded, 300);
else {
browser.tabs.update(tab.id, {active: true}).then(function(){
setTimeout(function(){
browser.tabs.captureVisibleTab().then(function(img){
browser.tabs.remove(tab.id);
if(callback) callback( { url: tab.url, title: tab.title, icon: tab.favIconUrl, screenshot: img } );
}, function(){
browser.tabs.remove(tab.id);
if(callback) callback();
});
}, 300);
}, function(){ if(callback) callback(); });
}
}, function(){ if(callback) callback(); });
}
setTimeout(whaitLoaded, 300);
}, function(){ if(callback) callback(); });
}
core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a new tab. callback( { url, title, icon, screenshot } || error: callback() )
browser.tabs.create({url: url, active: false}).then(function(tab){ browser.tabs.create({url: url, active: false}).then(function(tab){
browser.tabs.update(tab.id, {muted: true}).then(); browser.tabs.update(tab.id, {muted: true}).then();
function whaitLoaded(){ function whaitLoaded(){
@@ -185,12 +282,12 @@ core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a n
ctx.restore(); ctx.restore();
img = canvas.toDataURL(); img = canvas.toDataURL();
if(callback) callback( { url: tab.url, title: tab.title, icon: tab.favIconUrl, screenshot: img } ); if(callback) callback( { url: tab.url, title: tab.title, icon: tab.favIconUrl, screenshot: img } );
}, 1); }, 100);
}, function(){ }, function(){
browser.tabs.remove(tab.id); browser.tabs.remove(tab.id);
if(callback) callback(); if(callback) callback();
}); });
}, 300); }, 500);
}, function(){ if(callback) callback(); }); }, function(){ if(callback) callback(); });
} }
}, function(){ if(callback) callback(); }); }, function(){ if(callback) callback(); });
@@ -198,7 +295,7 @@ core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a n
setTimeout(whaitLoaded, 300); setTimeout(whaitLoaded, 300);
}, function(){ if(callback) callback(); }); }, function(){ if(callback) callback(); });
} }
core.SiteInfos.fromFrame = function(url, callback){ // Retrieve infos from an iframe. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() ) app.SiteInfos.fromFrame = function(url, callback){ // Retrieve infos from an iframe. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() )
function pageLoaded(){ function pageLoaded(){
if(!iframe) return; if(!iframe) return;
var docTitle = iframe.contentWindow.document.title; var docTitle = iframe.contentWindow.document.title;
@@ -248,47 +345,35 @@ core.SiteInfos.fromFrame = function(url, callback){ // Retrieve infos from an if
xmlHttp.onerror = function(){ if(callback) callback(); } xmlHttp.onerror = function(){ if(callback) callback(); }
xmlHttp.ontimeout = function(){ if(callback) callback(); } xmlHttp.ontimeout = function(){ if(callback) callback(); }
xmlHttp.send(); xmlHttp.send();
} }
core.SiteInfos.fromWS = function(url, callback){ // Retrieve infos from a Web Service. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() ) app.SiteInfos.fromWS = function(url, callback){ // Retrieve infos from a Web Service. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() )
console.log('Not implemented'); console.log('Not implemented');
return core.SiteInfos.fromFrame(url, callback); return app.SiteInfos.fromFrame(url, callback);
} }
/* app.GridNodes = {}; // GridNodes helper object
core.GridNodes.GridNode = function(){ app.GridNodes.GridNodeType = { // GridNodeType
this.id = null; // 0
//this.lastUpdate = new Date(0);
this.type = core.GridNodes.GridNodeType.empty;
//this.path = '';
this.title = null; // ''
this.icon = null; // ''
this.image = null; // ''
this.url = null; // ''
this.children = null; // []
}
*/
core.GridNodes = {}; // GridNodes helper object
core.GridNodes.GridNodeType = { // GridNodeType
back: -1, back: -1,
empty: 0, empty: 0,
folder: 1, folder: 1,
bookmark: 2 bookmark: 2
} }
core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes with Bookmarks app.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes with Bookmarks
core.Bookmarks.load(rootPath, function(bookmarkItem){ app.Bookmarks.load(rootPath, function(bookmarkItem){
function syncNode(gridNode, bookmarkItem){ function syncNode(gridNode, bookmarkItem){
gridNode.id = bookmarkItem.id; gridNode.id = bookmarkItem.id;
if(!gridNode.title) gridNode.title = bookmarkItem.title; if(!gridNode.title) gridNode.title = bookmarkItem.title;
if(bookmarkItem.url){ if(bookmarkItem.url){
gridNode.type = core.GridNodes.GridNodeType.bookmark; gridNode.type = app.GridNodes.GridNodeType.bookmark;
if(!gridNode.url) gridNode.url = bookmarkItem.url; if(!gridNode.url) gridNode.url = bookmarkItem.url;
} else if(bookmarkItem.children){ } else if(bookmarkItem.children){
gridNode.type = core.GridNodes.GridNodeType.folder; gridNode.type = app.GridNodes.GridNodeType.folder;
var EmptyNodes = []; var EmptyNodes = [];
if(! gridNode.children) gridNode.children = []; if(! gridNode.children) gridNode.children = [];
else { else {
for(var i=gridNode.children.length-1; i>=0; i--){ for(var i=gridNode.children.length-1; i>=0; i--){
if(gridNode.children[i].type==core.GridNodes.GridNodeType.empty){ if(!gridNode.children[i]) gridNode.children[i] = { type: app.GridNodes.GridNodeType.empty };
if(gridNode.children[i].type==app.GridNodes.GridNodeType.empty){
EmptyNodes.unshift(gridNode.children[i]); EmptyNodes.unshift(gridNode.children[i]);
} else { } else {
var found = false; var found = false;
@@ -300,7 +385,7 @@ core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes
} }
if(! found){ if(! found){
if(i<gridNode.children.length - 1){ if(i<gridNode.children.length - 1){
gridNode.children[i] = { type: core.GridNodes.GridNodeType.empty }; gridNode.children[i] = { type: app.GridNodes.GridNodeType.empty };
EmptyNodes.unshift(gridNode.children[i]); EmptyNodes.unshift(gridNode.children[i]);
} else { } else {
gridNode.children.pop(); gridNode.children.pop();
@@ -310,7 +395,7 @@ core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes
} }
} }
for(var child of bookmarkItem.children){ for(var child of bookmarkItem.children){
var childGridNode = core.GridNodes.getChildNode(gridNode, child.id); var childGridNode = app.GridNodes.getChildNode(gridNode, child.id);
if(!childGridNode){ if(!childGridNode){
if(EmptyNodes.length>0){ if(EmptyNodes.length>0){
childGridNode = EmptyNodes[0]; childGridNode = EmptyNodes[0];
@@ -324,152 +409,222 @@ core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes
} }
EmptyNodes.length = 0; EmptyNodes.length = 0;
} else { } else {
gridNode.type = core.GridNodes.GridNodeType.empty; gridNode.type = app.GridNodes.GridNodeType.empty;
} }
} }
syncNode(gridNode, bookmarkItem); syncNode(gridNode, bookmarkItem);
core.GridNodes.save(); app.GridNodes.save();
if(callback) callback(); if(callback) callback();
}); });
} }
core.GridNodes.save = function(){ // Save GridNode app.GridNodes.save = function(callback){ // Save GridNodes
browser.storage.local.set(app.settings); app.Settings.save(callback);
browser.runtime.sendMessage({ command: 'GridNodesSaved'});
} }
core.GridNodes.getNode = function(gridNode, path){ // Return GridNode from RootGridNode path app.GridNodes.getNode = function(gridNode, path){ // Return GridNode from RootGridNode path
if(path.length == 0 || path == '/') return gridNode; if(path.length == 0 || path == '/') return gridNode;
for(var child of gridNode.children) for(var child of gridNode.children)
if(path.startsWith(child.title + '/')) if(path.startsWith(child.title + '/'))
return core.GridNodes.getNode(child, path.substr(child.title.length + 1)); return app.GridNodes.getNode(child, path.substr(child.title.length + 1));
return null; return null;
} }
core.GridNodes.getChildNode = function(gridNode, id){ // Return child node by ID app.GridNodes.getNodeById = function(id){
var nodes = app.GridNodes.getNodeWithParents(id);
if(nodes) return nodes[nodes.length-1];
return null;
}
app.GridNodes.getNodeWithParents = function(id){
var parents = [];
function findNode(gridNode){
if(gridNode.id == id){
parents.unshift(gridNode);
return gridNode;
}
if(gridNode.children){
for(var i=0; i<gridNode.children.length; i++){
var result = findNode(gridNode.children[i]);
if(result){
parents.unshift(gridNode);
return result;
}
}
}
return null;
}
findNode(app.node, id);
if(parents.length>0) return parents;
return null;
}
app.GridNodes.updateNode = function(gridNode, value, callback){
if(value){
if(value.title) gridNode.title = value.title;
if(value.titleLocked!=null) gridNode.titleLocked = value.titleLocked;
if(value.image) gridNode.image = value.image;
else delete gridNode.image;
if(gridNode.type == app.GridNodes.GridNodeType.bookmark && value.url && gridNode.url != value.url){
gridNode.url = value.url;
app.GridNodes.refreshNode(gridNode, function(){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded });
});
}
app.GridNodes.saveNode(gridNode);
}
if(callback) callback(gridNode);
}
app.GridNodes.getChildNode = function(gridNode, id){ // Return child node by ID
for(var child of gridNode.children) if(child.id == id) return child; for(var child of gridNode.children) if(child.id == id) return child;
return null; return null;
} }
core.GridNodes.saveNode = function(gridNode){ // Save GridNode app.GridNodes.saveNode = function(gridNode, callback){ // Save GridNode
browser.storage.local.set(app.settings); app.Settings.save(callback);
browser.runtime.sendMessage({ command: 'GridNodeSaved', gridNode: gridNode });
} }
core.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // Set Child GridNodeIndex. callback(gridNode, node1, node2) app.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // Set Child GridNodeIndex. callback(gridNode, node1, node2)
while(newIndex>=gridNode.children.length) while(newIndex>=gridNode.children.length)
gridNode.children.push({ type: core.GridNodes.GridNodeType.empty }); gridNode.children.push({ type: app.GridNodes.GridNodeType.empty });
var node1 = gridNode.children[index]; var node1 = gridNode.children[index];
var node2 = gridNode.children[newIndex]; var node2 = gridNode.children[newIndex];
gridNode.children[index] = node2; gridNode.children[index] = node2;
gridNode.children[newIndex] = node1; gridNode.children[newIndex] = node1;
for(var i=gridNode.children.length-1; i>=0; i--){ for(var i=gridNode.children.length-1; i>=0; i--){
if(gridNode.children[i].type != core.GridNodes.GridNodeType.empty) break; if(gridNode.children[i].type != app.GridNodes.GridNodeType.empty) break;
gridNode.children.pop(); gridNode.children.pop();
} }
core.GridNodes.saveNode(gridNode); app.GridNodes.saveNode(gridNode);
if(callback) callback(gridNode, node1, node2); if(callback) callback(gridNode, node1, node2);
} }
core.GridNodes.createFolder = function(gridNode, name, callback){ // Create a new folder in a GridNode. callback(gridNode, newGridNode) app.GridNodes.createBookmark = function(gridNode, url, title, callback){ // Create a new Bookmark in a GridNode. callback(gridNode, newGridNode)
browser.bookmarks.onCreated.removeListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.removeListener(app.Bookmarks._onCreated);
var prefix = '';
if(url.indexOf('://')<0) prefix = 'http://';
browser.bookmarks.create({
parentId: gridNode.id,
title: title || url,
url: prefix + url
}).then(function(bookmarkItem){
if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ???
browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
var newGridNode = { id: bookmarkItem.id, type: app.GridNodes.GridNodeType.bookmark, url: prefix + url, title };
var EmptyCellFound = false;
for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].type == app.GridNodes.GridNodeType.empty){
EmptyCellFound = true;
gridNode.children[i] = newGridNode;
break;
}
}
if(EmptyCellFound == false) gridNode.children.push(newGridNode);
app.GridNodes.saveNode(newGridNode);
if(callback) callback(gridNode, newGridNode);
}, function(){
browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
});
}
app.GridNodes.createFolder = function(gridNode, name, callback){ // Create a new folder in a GridNode. callback(gridNode, newGridNode)
browser.bookmarks.onCreated.removeListener(app.Bookmarks._onCreated);
browser.bookmarks.create({ browser.bookmarks.create({
parentId: gridNode.id, parentId: gridNode.id,
title: name title: name
}).then(function(bookmarkItem){ }).then(function(bookmarkItem){
if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ??? if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ???
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
var newGridNode = { id: bookmarkItem.id, type: core.GridNodes.GridNodeType.folder, title: name, children: [] }; var newGridNode = { id: bookmarkItem.id, type: app.GridNodes.GridNodeType.folder, title: name, children: [] };
var EmptyCellFound = false; var EmptyCellFound = false;
for(var i=0; i<gridNode.children.length; i++){ for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].type == core.GridNodes.GridNodeType.empty){ if(gridNode.children[i].type == app.GridNodes.GridNodeType.empty){
EmptyCellFound = true; EmptyCellFound = true;
gridNode.children[i] = newGridNode; gridNode.children[i] = newGridNode;
break; break;
} }
} }
if(EmptyCellFound == false) gridNode.children.push(newGridNode); if(EmptyCellFound == false) gridNode.children.push(newGridNode);
core.GridNodes.saveNode(newGridNode); app.GridNodes.saveNode(newGridNode);
if(callback) callback(gridNode, newGridNode); if(callback) callback(gridNode, newGridNode);
}, function(){ }, function(){
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
}); });
} }
core.GridNodes.createBookmark = function(gridNode, url, title, callback){ // Create a new Bookmark in a GridNode. callback(gridNode, newGridNode) app.GridNodes.deleteNode = function(gridNode, id, callback){ // Delete a GridNode. callback(gridNode, id)
browser.bookmarks.onCreated.removeListener(core.Bookmarks._onCreated);
browser.bookmarks.create({
parentId: gridNode.id,
title: title || url,
url: url
}).then(function(bookmarkItem){
if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ???
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated);
var newGridNode = { id: bookmarkItem.id, type: core.GridNodes.GridNodeType.bookmark, url: url, title };
var EmptyCellFound = false;
for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].type == core.GridNodes.GridNodeType.empty){
EmptyCellFound = true;
gridNode.children[i] = newGridNode;
break;
}
}
if(EmptyCellFound == false) gridNode.children.push(newGridNode);
core.GridNodes.saveNode(newGridNode);
if(callback) callback(gridNode, newGridNode);
}, function(){
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated);
});
}
core.GridNodes.deleteNode = function(gridNode, id, callback){ // Delete a GridNode. callback(gridNode, id)
for(var i=0; i<gridNode.children.length; i++){ for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].id == id){ if(gridNode.children[i].id == id){
gridNode.children[i] = { type: core.GridNodes.GridNodeType.empty }; gridNode.children[i] = { type: app.GridNodes.GridNodeType.empty };
core.GridNodes.saveNode(gridNode); app.GridNodes.saveNode(gridNode);
break; break;
} }
} }
for(var i=gridNode.children.length-1; i>=0; i--){ for(var i=gridNode.children.length-1; i>=0; i--){
if(gridNode.children[i].type != core.GridNodes.GridNodeType.empty) break; if(gridNode.children[i].type != app.GridNodes.GridNodeType.empty) break;
gridNode.children.pop(); gridNode.children.pop();
} }
browser.bookmarks.onRemoved.removeListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.removeListener(app.Bookmarks._onRemoved);
browser.bookmarks.removeTree(id).then(function(){ browser.bookmarks.removeTree(id).then(function(){
browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.addListener(app.Bookmarks._onRemoved);
}, function(){ }, function(){
browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.addListener(app.Bookmarks._onRemoved);
}); });
if(callback) callback(gridNode, id); if(callback) callback(gridNode, id);
} }
core.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of a GridNode app.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of a GridNode
if(gridNode.__isLoading == true) return; if(gridNode.__isLoading == true) return;
gridNode.__isLoading = true; gridNode.__isLoading = true;
core.SiteInfos.fromFrame(gridNode.url, function(infos){ switch(gridNode.type){
if(infos){ case app.GridNodes.GridNodeType.folder:
gridNode.title = infos.title; delete gridNode.image;
gridNode.image = infos.screenshot;
delete gridNode.__isLoading; delete gridNode.__isLoading;
core.GridNodes.saveNode(gridNode); app.GridNodes.saveNode(gridNode);
} else delete gridNode.__isLoading; if(callback) callback({ title: gridNode.title, screenshot: gridNode.image });
if(callback) callback(infos); break;
}); case app.GridNodes.GridNodeType.bookmark:
app.SiteInfos.fromFrame(gridNode.url, function(infos){
if(infos){
if(gridNode.titleLocked!=true) gridNode.title = infos.title;
gridNode.image = infos.screenshot;
} else {
gridNode.image = '0';
}
delete gridNode.__isLoading;
app.GridNodes.saveNode(gridNode);
if(callback) callback(infos);
});
break;
}
} }
core.GridNodes.capturePage = function(gridNode, callback){ app.GridNodes.capturePage = function(gridNode, callback){
if(gridNode.__isLoading == true) return; if(gridNode.__isLoading == true) return;
gridNode.__isLoading = true; gridNode.__isLoading = true;
core.SiteInfos.fromNewTab(gridNode.url, function(infos){ switch(gridNode.type){
if(infos){ case app.GridNodes.GridNodeType.folder:
gridNode.title = infos.title; var nodes = app.GridNodes.getNodeWithParents(gridNode.id);
gridNode.image = infos.screenshot; if(nodes){
delete gridNode.__isLoading; var path = '';
core.GridNodes.saveNode(gridNode); for(var i=1; i<nodes.length; i++) path = path + '/' + nodes[i].title;
} else delete gridNode.__isLoading; app.SiteInfos.fromNewTab('/dial?path=' + path, function(infos){
if(callback) callback(infos); if(infos){
}); gridNode.image = infos.screenshot;
} else {
delete gridNode.image;
}
delete gridNode.__isLoading;
app.GridNodes.saveNode(gridNode);
if(callback) callback({ title: gridNode.title, screenshot: gridNode.image });
});
}
break;
case app.GridNodes.GridNodeType.bookmark:
app.SiteInfos.fromNewTab(gridNode.url, function(infos){
if(infos){
if(gridNode.titleLocked!=true) gridNode.title = infos.title;
gridNode.image = infos.screenshot;
} else {
gridNode.image = '0';
}
delete gridNode.__isLoading;
app.GridNodes.saveNode(gridNode);
if(callback) callback(infos);
});
break;
}
} }
// Public members
app.GridNodeType = core.GridNodes.GridNodeType;
app.refreshNode = core.GridNodes.refreshNode;
app.getNode = core.GridNodes.getNode;
app.createFolder = core.GridNodes.createFolder;
app.createBookmark = core.GridNodes.createBookmark;
app.deleteNode = core.GridNodes.deleteNode;
app.setNodeIndex = core.GridNodes.setNodeIndex;
app.capturePage = core.GridNodes.capturePage;
app.saveSettings = core.Settings.save;

View File

@@ -1,94 +1,230 @@
var app = {} var utils = {};
var dial = { var app = {};
styles: {}, var dial = {
page: 1, page: 1,
maxpage: 1 maxpage: 1
}; };
window.onload = function(){ document.addEventListener("DOMContentLoaded", function(event) {
function initPage(){ document.body.style.backgroundColor = utils.getBackgroundColor();
browser.runtime.getBackgroundPage().then(function(page){ app.init();
if(page.app.settings){ dial.init();
app = page.app; });
dial.initUI();
browser.runtime.onMessage.addListener(function(request, sender, sendResponse){
switch(request.command){
case 'SettingsChanged':
if(app.settings){
dial.Head.removeChild(dial.Style);
dial.Body.removeChild(dial.Grid);
dial.initStyles();
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, '/');
}
dial.Title.innerText = dial.Node.title;
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node);
}
break;
case 'GridNodesSaved':
if(app.settings) dial.populateGrid(dial.Grid, app.settings.grid, dial.Node);
break;
case 'GridNodeSaved':
// request.gridNode
if(app.settings) dial.populateGrid(dial.Grid, app.settings.grid, dial.Node);
break;
}
});
} else{
setTimeout(initPage, 100);
}
}, function(){});
}
initPage();
}
window.onresize = function(){ window.onresize = function(){
if(app && app.settings) dial.updateGridLayout(dial.Grid, app.settings.grid, dial.styles.grid); if(app && app.settings) dial.updateGridLayout();
} }
window.onwheel = function(ev){ window.onwheel = function(ev){
if(app && app.settings){ if(app && app.settings){
if(ev.deltaY > 0){ if(ev.deltaY > 0){
if(dial.page < dial.maxpage){ if(dial.page < dial.maxpage){
dial.page += 1; dial.page += 1;
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); dial.populateGrid();
} }
} else if(ev.deltaY < 0){ } else if(ev.deltaY < 0){
if(dial.page > 1){ if(dial.page > 1){
dial.page -= 1; dial.page -= 1;
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); dial.populateGrid();
} }
} }
} }
} }
dial.initUI = function(){
dial.Head = document.getElementById('head'); utils.getBackgroundColor = function(){
dial.Title = document.getElementById('title'); return new URL(window.location).searchParams.get('bg');
dial.Body = document.getElementById('body'); };
dial.Body.setAttribute('contextmenu', 'page'); utils.getPath = function(){
dial.Body.setAttribute('contextmenu', 'page'); var path = new URL(window.location).searchParams.get('path');
dial.initStyles(); if(path) return path + '/';
dial.initMenus(); else return '/';
dial.Grid = dial.initGrid('Grid', app.settings.grid, dial.Body); };
var url = new URL(window.location);
dial.path = url.searchParams.get('path'); app.init = function(){
if(url.searchParams.get('path')) { app.Messages.getSettings(function(settings){
dial.Node = app.getNode(app.settings.grid.node, dial.path + '/'); if(settings && settings.grid) app.Settings._changed(settings);
} else { dial.path = utils.getPath();
dial.Node = app.getNode(app.settings.grid.node, '/'); app.Messages.getNode(dial.path, app.GridNodes._changed);
} app.Messages.init();
dial.Title.innerText = dial.Node.title; });
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); };
app.Messages = {};
app.Messages.Commands = {
getSettings: 0,
setSettings: 1,
getNode: 2,
getNodeByID: 3,
updateNode: 4,
setNodeIndex: 5,
createBookmark: 6,
createFolder: 7,
deleteNode: 8,
refreshNode: 9,
capturePage: 10,
settingsChanged: 100,
gridNodesLoaded: 101
};
app.Messages.init = function(){
browser.runtime.onMessage.addListener(function(request, sender, sendResponse){
switch(request.cmd){
case app.Messages.Commands.settingsChanged:
app.Messages.getSettings(app.Settings._changed);
break;
case app.Messages.Commands.gridNodesLoaded:
app.Messages.getNode(dial.path, app.GridNodes._changed);
break;
}
});
};
app.Messages.getSettings = function(callback){
browser.runtime.getBackgroundPage().then(function(page){
if(page){
if(callback) callback(page.app.settings);
} else {
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getSettings }).then(callback, callback);
}
});
};
app.Messages.getNode = function(path, callback){
browser.runtime.getBackgroundPage().then(function(page){
if(page){
if(callback) callback(page.app.GridNodes.getNode(page.app.node, dial.path.substr(1)));
} else {
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getNode, path: path }).then(callback);
}
});
};
app.Messages.setNodeIndex = function(index, newIndex, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.setNodeIndex, path: dial.path, index: index, newIndex: newIndex }).then(callback);
};
app.Messages.createBookmark = function(url, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.createBookmark, path: dial.path, url: url, title: url }).then(callback);
};
app.Messages.createFolder = function(name, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.createFolder, path: dial.path, name: name }).then(callback);
};
app.Messages.deleteNode = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.deleteNode, path: dial.path, id: id }).then(callback);
};
app.Messages.refreshNode = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.refreshNode, path: dial.path, id: id }).then(callback);
}
app.Messages.capturePage = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.capturePage, path: dial.path, id: id }).then(callback);
} }
app.Settings = {};
app.Settings._changed = function(settings){
app.settings = settings;
dial.initStyles();
dial.initGrid();
};
app.GridNodes = {};
app.GridNodes.GridNodeType = { // GridNodeType
back: -1,
empty: 0,
folder: 1,
bookmark: 2
}
app.GridNodes._changed = function(node){
app.node = node;
dial.Title.innerText = app.node.title;
dial.populateGrid();
};
dial.init = function(){
dial.initMenus();
dial.Title = document.createElement('title');
document.head.appendChild(dial.Title);
};
dial.initMenus = function(){
document.body.setAttribute('contextmenu', 'page');
dial.PageMenu = document.createElement('menu');
dial.PageMenu.type = 'context';
dial.PageMenu.id = 'page'
dial.PageMenuNew = document.createElement('menu');
dial.PageMenuNew.label = browser.i18n.getMessage("menuNew");
dial.PageMenuCreateBookmark = document.createElement('menuitem');
dial.PageMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.PageMenuCreateBookmark.onclick = dial.createBookmark;
dial.PageMenuCreateFolder = document.createElement('menuitem');
dial.PageMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
dial.PageMenuCreateFolder.onclick = dial.createFolder;
dial.PageMenuSettings = document.createElement('menuitem');
dial.PageMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.PageMenuSettings.onclick = dial.editSettings;
dial.PageMenu.appendChild(dial.PageMenuNew);
dial.PageMenuNew.appendChild(dial.PageMenuCreateBookmark);
dial.PageMenuNew.appendChild(dial.PageMenuCreateFolder);
dial.PageMenu.appendChild(document.createElement('hr'));
dial.PageMenu.appendChild(dial.PageMenuSettings);
document.body.appendChild(dial.PageMenu);
dial.ItemMenu = document.createElement('menu');
dial.ItemMenu.type = 'context';
dial.ItemMenu.id = 'item'
dial.ItemMenuNew = document.createElement('menu');
dial.ItemMenuNew.label = browser.i18n.getMessage("menuNew");
dial.ItemMenuCreateBookmark = document.createElement('menuitem');
dial.ItemMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.ItemMenuCreateBookmark.onclick = dial.createBookmark;
dial.ItemMenuCreateFolder = document.createElement('menuitem');
dial.ItemMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
dial.ItemMenuCreateFolder.onclick = dial.createFolder;
dial.ItemMenuProperties = document.createElement('menuitem');
dial.ItemMenuProperties.label = browser.i18n.getMessage("menuProperties");
dial.ItemMenuProperties.onclick = function(){
dial.editProperties(dial._selectedItem);
};
dial.ItemMenuRefresh = document.createElement('menuitem');
dial.ItemMenuRefresh.label = browser.i18n.getMessage("menuRefreshItem");
dial.ItemMenuRefresh.onclick = function(){
dial.refreshNode(dial._selectedItem);
};
dial.ItemMenuCapture = document.createElement('menuitem');
dial.ItemMenuCapture.label = browser.i18n.getMessage("menuCapturePage");
dial.ItemMenuCapture.onclick = function(){
dial.capturePage(dial._selectedItem);
};
dial.ItemMenuDelete = document.createElement('menuitem');
dial.ItemMenuDelete.label = browser.i18n.getMessage("menuDeleteItem");
dial.ItemMenuDelete.onclick = dial.deleteNode;
dial.ItemMenuSettings = document.createElement('menuitem');
dial.ItemMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.ItemMenuSettings.onclick = dial.editSettings;
dial.ItemMenu.appendChild(dial.ItemMenuNew);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateBookmark);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateFolder);
dial.ItemMenu.appendChild(document.createElement('hr'));
dial.ItemMenu.appendChild(dial.ItemMenuProperties);
dial.ItemMenu.appendChild(dial.ItemMenuRefresh);
dial.ItemMenu.appendChild(dial.ItemMenuCapture);
dial.ItemMenu.appendChild(dial.ItemMenuDelete);
dial.ItemMenu.appendChild(document.createElement('hr'));
dial.ItemMenu.appendChild(dial.ItemMenuSettings);
document.body.appendChild(dial.ItemMenu);
}
dial.initStyles = function(){ dial.initStyles = function(){
var oldStyle = dial.Style;
dial.Style = document.createElement('style'), StyleSheet; dial.Style = document.createElement('style'), StyleSheet;
document.head.appendChild(dial.Style); document.head.appendChild(dial.Style);
dial.styles = {};
dial.styles.html = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('html { height: 100%; }')].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-color: ' + app.settings.backgroundColor + '; background-image: ' + app.settings.backgroundImage + '; background-repeat: no-repeat; background-size: 100% 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-color: ' + app.settings.backgroundColor + '; background-image: ' + app.settings.backgroundImage + '; background-repeat: no-repeat; background-size: 100% 100%; }')].style;
dial.styles.grid = {}; dial.styles.grid = {};
@@ -110,105 +246,49 @@ dial.initStyles = function(){
dial.styles.grid.linkFolder = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Folder :first-child { background-image: ' + app.settings.grid.folderIcon + '; background-repeat: no-repeat; background-size: 100% 100%; }')].style; dial.styles.grid.linkFolder = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Folder :first-child { background-image: ' + app.settings.grid.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.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.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;
} if(oldStyle) document.head.removeChild(oldStyle);
};
dial.initMenus = function(){ dial.initGrid = function(){
dial.PageMenu = document.createElement('menu'); var oldGrid = dial.Grid;
dial.PageMenu.type = 'context'; dial.Grid = document.createElement('table');
dial.PageMenu.id = 'page'
dial.PageMenuNew = document.createElement('menu');
dial.PageMenuNew.label = browser.i18n.getMessage("menuNew");
dial.PageMenuCreateBookmark = document.createElement('menuitem');
dial.PageMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.PageMenuCreateBookmark.onclick = dial.createBookmark;
dial.PageMenuCreateFolder = document.createElement('menuitem');
dial.PageMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
dial.PageMenuCreateFolder.onclick = dial.createFolder;
dial.PageMenuSettings = document.createElement('menuitem');
dial.PageMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.PageMenuSettings.onclick = dial.editSettings;
dial.PageMenu.appendChild(dial.PageMenuNew);
dial.PageMenuNew.appendChild(dial.PageMenuCreateBookmark);
dial.PageMenuNew.appendChild(dial.PageMenuCreateFolder);
dial.PageMenu.appendChild(document.createElement('hr'));
dial.PageMenu.appendChild(dial.PageMenuSettings);
dial.Body.appendChild(dial.PageMenu);
dial.ItemMenu = document.createElement('menu');
dial.ItemMenu.type = 'context';
dial.ItemMenu.id = 'item'
dial.ItemMenuNew = document.createElement('menu');
dial.ItemMenuNew.label = browser.i18n.getMessage("menuNew");
dial.ItemMenuCreateBookmark = document.createElement('menuitem');
dial.ItemMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.ItemMenuCreateBookmark.onclick = dial.createBookmark;
dial.ItemMenuCreateFolder = document.createElement('menuitem');
dial.ItemMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
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 = browser.i18n.getMessage("menuRefreshItem");
dial.ItemMenuRefresh.onclick = dial.refreshNode;
dial.ItemMenuCapture = document.createElement('menuitem');
dial.ItemMenuCapture.label = browser.i18n.getMessage("menuCapturePage");
dial.ItemMenuCapture.onclick = dial.capturePage;
dial.ItemMenuDelete = document.createElement('menuitem');
dial.ItemMenuDelete.label = browser.i18n.getMessage("menuDeleteItem");
dial.ItemMenuDelete.onclick = dial.deleteNode;
dial.ItemMenuSettings = document.createElement('menuitem');
dial.ItemMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.ItemMenuSettings.onclick = dial.editSettings;
dial.ItemMenu.appendChild(dial.ItemMenuNew);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateBookmark);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateFolder);
dial.ItemMenu.appendChild(document.createElement('hr'));
//dial.ItemMenu.appendChild(dial.ItemMenuEdit);
dial.ItemMenu.appendChild(dial.ItemMenuRefresh);
dial.ItemMenu.appendChild(dial.ItemMenuCapture);
dial.ItemMenu.appendChild(dial.ItemMenuDelete);
dial.ItemMenu.appendChild(document.createElement('hr'));
dial.ItemMenu.appendChild(dial.ItemMenuSettings);
dial.Body.appendChild(dial.ItemMenu);
}
dial.initGrid = function(name, settings, container){
var grid = document.createElement('table'); var grid = document.createElement('table');
grid.className = name; dial.Grid.className = 'Grid';
grid.getLink = function(index){ dial.Grid.getLink = function(index){
var num_columns = grid.rows[0].cells.length; var num_columns = dial.Grid.rows[0].cells.length;
return grid.rows[Math.floor(index/num_columns)].cells[index % num_columns].childNodes[0]; return dial.Grid.rows[Math.floor(index/num_columns)].cells[index % num_columns].childNodes[0];
} }
for(var i=0; i<settings.rows; i++){ for(var i=0; i<app.settings.grid.rows; i++){
var row = grid.insertRow(); var row = dial.Grid.insertRow();
for(var j=0; j<settings.columns; j++){ for(var j=0; j<app.settings.grid.columns; j++){
var cell = row.insertCell(); var cell = row.insertCell();
var link = document.createElement('a'); var link = document.createElement('a');
cell.setAttribute('gridindex', (i * settings.columns + j)); cell.setAttribute('gridindex', (i * app.settings.grid.columns + j));
cell.appendChild(link); cell.appendChild(link);
link.className = 'Empty';
link.appendChild(document.createElement('div')); link.appendChild(document.createElement('div'));
link.appendChild(document.createElement('div')); link.appendChild(document.createElement('div'));
link.onmousedown = function(){ dial._selectedItem = this; }; link.onmousedown = function(){ dial._selectedItem = this; };
function dragstart_handler(ev) { function dragstart_handler(ev) {
if(!ev.target.Node){
ev.preventDefault();
return;
}
var index = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.parentElement.getAttribute('gridindex')); var index = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.parentElement.getAttribute('gridindex'));
if(settings.backNode && dial.path) index -= dial.page; if(app.settings.grid.backNode && dial.path != '/') index -= dial.page;
console.log(index);
ev.dataTransfer.setData("text/plain", index); ev.dataTransfer.setData("text/plain", index);
} }
function dragover_handler(ev) { function dragover_handler(ev) {
ev.preventDefault(); ev.preventDefault();
ev.dataTransfer.dropEffect = "move" if(app.settings.grid.backNode && dial.path != '/'){
var gridIndex = 0;
if(ev.target.tagName == 'DIV') gridIndex = +(ev.target.parentElement.parentElement.getAttribute('gridindex'));
else gridIndex = +(ev.target.getAttribute('gridindex'));
if(gridIndex==0) ev.dataTransfer.dropEffect = "none";
else ev.dataTransfer.dropEffect = "move";
} else {
ev.dataTransfer.dropEffect = "move";
}
} }
function drop_handler(ev) { function drop_handler(ev) {
ev.preventDefault(); ev.preventDefault();
@@ -218,44 +298,42 @@ dial.initGrid = function(name, settings, container){
if(ev.target.tagName == 'DIV'){ if(ev.target.tagName == 'DIV'){
EndIndex = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.parentElement.parentElement.getAttribute('gridindex')); EndIndex = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.parentElement.parentElement.getAttribute('gridindex'));
} else{ } else{
EndIndex =(dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.getAttribute('gridindex')); EndIndex = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.getAttribute('gridindex'));
} }
if(settings.backNode && dial.path) EndIndex -= dial.page; if(app.settings.grid.backNode && dial.path != '/') EndIndex -= dial.page;
app.setNodeIndex(dial.Node, StartIndex, EndIndex); if(StartIndex != EndIndex) app.Messages.setNodeIndex(StartIndex, EndIndex);
} }
link.draggable = true; link.draggable = true;
link.ondragstart = dragstart_handler; link.ondragstart = dragstart_handler;
cell.ondragover = dragover_handler; cell.ondragover = dragover_handler;
cell.ondrop = drop_handler; cell.ondrop = drop_handler;
} }
} }
container.appendChild(grid); document.body.appendChild(dial.Grid);
dial.updateGridLayout(grid, settings, dial.styles.grid); dial.updateGridLayout();
return grid; if(oldGrid) document.body.removeChild(oldGrid);
} return dial.Grid;
};
dial.updateGridLayout = function(grid, settings, styles){ dial.updateGridLayout = function(){
var fullWidth = grid.parentElement.offsetWidth - 2 * settings.margin; var fullWidth = dial.Grid.parentElement.offsetWidth - 2 * app.settings.grid.margin;
var fullHeight = grid.parentElement.offsetHeight - 2 * settings.margin; var fullHeight = dial.Grid.parentElement.offsetHeight - 2 * app.settings.grid.margin;
var linkWidth = fullWidth / settings.columns; var linkWidth = fullWidth / app.settings.grid.columns;
var linkHeight = fullHeight / settings.rows; var linkHeight = fullHeight / app.settings.grid.rows;
if(linkWidth <= linkHeight * settings.cells.ratioX / settings.cells.ratioY) linkHeight = linkWidth / settings.cells.ratioX * settings.cells.ratioY; if(linkWidth <= linkHeight * 4 / 3) linkHeight = linkWidth / 4 * 3;
else linkWidth = linkHeight / settings.cells.ratioY * settings.cells.ratioX; else linkWidth = linkHeight / 3 * 4;
styles.cell.width = linkWidth.toString() + 'px'; dial.styles.grid.cell.width = linkWidth.toString() + 'px';
styles.cell.height = linkHeight.toString() + 'px'; dial.styles.grid.cell.height = linkHeight.toString() + 'px';
linkWidth = linkWidth - 2 * (settings.cells.margin + 1); linkWidth = linkWidth - 2 * (app.settings.grid.cells.margin + 1);
linkHeight = linkHeight - 2 * (settings.cells.margin + 1); linkHeight = linkHeight - 2 * (app.settings.grid.cells.margin + 1);
styles.link.width = linkWidth.toString() + 'px'; dial.styles.grid.link.width = linkWidth.toString() + 'px';
styles.link.height = linkHeight.toString() + 'px'; dial.styles.grid.link.height = linkHeight.toString() + 'px';
if(settings.cells.title) styles.linkPanel.height = (linkHeight - settings.cells.titleHeight - 1).toString() + 'px'; if(app.settings.grid.cells.title) dial.styles.grid.linkPanel.height = (linkHeight - app.settings.grid.cells.titleHeight - 1).toString() + 'px';
else styles.linkPanel.height = linkHeight.toString() + 'px'; else dial.styles.grid.linkPanel.height = linkHeight.toString() + 'px';
} };
dial.populateGrid = function(){
dial.populateGrid = function(grid, settings, node){
populateEmpty = function(link){ populateEmpty = function(link){
link.Node = null; link.Node = null;
link.className = 'Empty'; link.className = 'Empty';
@@ -276,10 +354,13 @@ dial.populateGrid = function(grid, settings, node){
populateFolder = function(link, node){ populateFolder = function(link, node){
link.Node = node; link.Node = node;
link.className = 'Folder'; link.className = 'Folder';
link.childNodes[0].style.backgroundImage = ''; if(node.image){
if(node.image.indexOf('url(')>=0) link.childNodes[0].style.backgroundImage = node.image;
else link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')';
} else link.childNodes[0].style.backgroundImage = '';
link.childNodes[1].innerText = node.title; link.childNodes[1].innerText = node.title;
if(dial.path) link.href = '?path=' + dial.path + '/' + node.title; if(dial.path) link.href = '?' + 'bg=' + encodeURIComponent(app.settings.backgroundColor) + '&path=' + encodeURIComponent(dial.path + node.title);
else link.href = '?path=' + node.title; else link.href = '?' + 'bg=' + encodeURIComponent(app.settings.backgroundColor) + '&path=' + encodeURIComponent(node.title);
link.onclick = null; link.onclick = null;
link.setAttribute('contextmenu', 'item'); link.setAttribute('contextmenu', 'item');
} }
@@ -287,15 +368,12 @@ dial.populateGrid = function(grid, settings, node){
link.Node = node; link.Node = node;
if(node.image){ if(node.image){
link.className = 'Bookmark'; link.className = 'Bookmark';
link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')'; if(node.image.indexOf('url(')>=0) link.childNodes[0].style.backgroundImage = node.image;
else link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')';
} else { } else {
link.className = 'BookmarkLoading'; link.className = 'BookmarkLoading';
link.childNodes[0].style.backgroundImage = ''; link.childNodes[0].style.backgroundImage = '';
app.refreshNode(node, function(){ dial.refreshNode(link);
link.className = 'Bookmark';
link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')';
link.childNodes[1].innerText = node.title;
});
} }
link.childNodes[1].innerText = node.title; link.childNodes[1].innerText = node.title;
link.href = node.url; link.href = node.url;
@@ -305,69 +383,59 @@ dial.populateGrid = function(grid, settings, node){
var iBase = 0; var iBase = 0;
var linkItem = 0; var linkItem = 0;
var allCells = settings.rows * settings.columns; var allCells = app.settings.grid.rows * app.settings.grid.columns;
var maxCells = allCells; var maxCells = allCells;
if(settings.backNode && dial.path){ if(app.settings.grid.backNode && dial.path != '/'){
populateBack(grid.getLink(linkItem)); populateBack(dial.Grid.getLink(linkItem));
linkItem++; linkItem++;
maxCells -= 1; maxCells -= 1;
} }
dial.maxpage = Math.floor(node.children.length / maxCells); dial.maxpage = Math.floor(app.node.children.length / maxCells);
if(dial.maxpage != node.children.length / maxCells) dial.maxpage += 1; if(dial.maxpage != app.node.children.length / maxCells) dial.maxpage += 1;
if(dial.page > dial.maxpage) dial.page = dial.maxpage; if(dial.page > dial.maxpage) dial.page = dial.maxpage;
if(dial.page > 1) iBase = (dial.page -1) * maxCells; if(dial.page > 1) iBase = (dial.page -1) * maxCells;
for(var i = iBase; i<node.children.length && i<maxCells + iBase; i++) { for(var i = iBase; i<app.node.children.length && i<maxCells + iBase; i++) {
switch(node.children[i].type){ switch(app.node.children[i].type){
case app.GridNodeType.empty: case app.GridNodes.GridNodeType.empty:
populateEmpty(grid.getLink(linkItem)); populateEmpty(dial.Grid.getLink(linkItem));
break; break;
case app.GridNodeType.folder: case app.GridNodes.GridNodeType.folder:
populateFolder(grid.getLink(linkItem), node.children[i]); populateFolder(dial.Grid.getLink(linkItem), app.node.children[i]);
break; break;
case app.GridNodeType.bookmark: case app.GridNodes.GridNodeType.bookmark:
populateBookmark(grid.getLink(linkItem), node.children[i]); populateBookmark(dial.Grid.getLink(linkItem), app.node.children[i]);
break; break;
} }
linkItem++; linkItem++;
} }
while(linkItem<allCells){ while(linkItem<allCells){
populateEmpty(grid.getLink(linkItem)); populateEmpty(dial.Grid.getLink(linkItem));
linkItem++; linkItem++;
} }
} };
dial.createBookmark = function(){ dial.createBookmark = function(){
var url = prompt(browser.i18n.getMessage("AddBookmarkPrompt"), 'https://'); var url = prompt(browser.i18n.getMessage("AddBookmarkPrompt"), 'https://');
if(url) app.createBookmark(dial.Node, url); if(url) app.Messages.createBookmark(url);
}; };
dial.createFolder = function(){ dial.createFolder = function(){
var name = prompt(browser.i18n.getMessage("AddFolderPrompt"), 'New Folder'); var name = prompt(browser.i18n.getMessage("AddFolderPrompt"), 'New Folder');
if(name) app.createFolder(dial.Node, name); if(name) app.Messages.createFolder(name);
}; };
dial.refreshNode = function(){
if(dial._selectedItem.Node.type == app.GridNodeType.bookmark){
var link = dial._selectedItem;
link.className = 'BookmarkLoading';
link.childNodes[0].style.backgroundImage = '';
app.refreshNode(link.Node, function(){
link.className = 'Bookmark';
link.childNodes[0].style.backgroundImage = 'url(' + link.Node.image + ')';
link.childNodes[1].innerText = link.Node.title;
});
}
}
dial.deleteNode = function(){ dial.deleteNode = function(){
if(confirm(browser.i18n.getMessage("deleteItemConfimation", dial._selectedItem.Node.title))) if(confirm(browser.i18n.getMessage("deleteItemConfimation", dial._selectedItem.Node.title)))
app.deleteNode(dial.Node, dial._selectedItem.Node.id); app.Messages.deleteNode(dial._selectedItem.Node.id);
}
dial.refreshNode = function(selectedItem){
selectedItem.className = 'BookmarkLoading';
selectedItem.childNodes[0].style.backgroundImage = app.settings.grid.loadingIcon;
app.Messages.refreshNode(selectedItem.Node.id);
}
dial.capturePage = function(selectedItem){
selectedItem.className = 'BookmarkLoading';
selectedItem.childNodes[0].style.backgroundImage = app.settings.grid.loadingIcon;
app.Messages.capturePage(selectedItem.Node.id);
} }
dial.capturePage = function(){
if(dial._selectedItem.Node.type == app.GridNodeType.bookmark)
app.capturePage(dial._selectedItem.Node);
}
@@ -399,26 +467,26 @@ dial.PopupPanel = function(width, height, modal){ // PopupPanel Object
this._contextMenuHandler = function(e){ e.preventDefault(); } this._contextMenuHandler = function(e){ e.preventDefault(); }
this.popup = function(){ this.popup = function(){
window.addEventListener('contextmenu', this._contextMenuHandler, false); window.addEventListener('contextmenu', this._contextMenuHandler, false);
dial.Body.appendChild(this.modal); document.body.appendChild(this.modal);
dial.Body.appendChild(this.panelContainer); document.body.appendChild(this.panelContainer);
} }
this.close = function(){ this.close = function(){
dial.Body.removeChild(this.modal); document.body.removeChild(this.modal);
dial.Body.removeChild(this.panelContainer); document.body.removeChild(this.panelContainer);
window.removeEventListener('contextmenu', this._contextMenuHandler, false); window.removeEventListener('contextmenu', this._contextMenuHandler, false);
} }
} else { } else {
this.popup = function(){ this.popup = function(){
dial.Body.appendChild(this.panelContainer); document.body.appendChild(this.panelContainer);
} }
this.close = function(){ this.close = function(){
dialBody.removeChild(this.panelContainer); document.body.removeChild(this.panelContainer);
} }
} }
} }
dial.editSettings = function(){ dial.editSettings = function(){
var popup = new dial.PopupPanel(500, 420, true); var popup = new dial.PopupPanel(500, 440, true);
var iframe = document.createElement('iframe'); var iframe = document.createElement('iframe');
iframe.style.width = '100%'; iframe.style.width = '100%';
iframe.style.height = '100%'; iframe.style.height = '100%';
@@ -430,4 +498,21 @@ dial.editSettings = function(){
iframe.src = '/html/settings.html'; iframe.src = '/html/settings.html';
iframe.popup = popup; iframe.popup = popup;
popup.popup(); popup.popup();
iframe.focus();
}
dial.editProperties = function(selectedItem){
var popup = new dial.PopupPanel(500, 420, true);
var iframe = document.createElement('iframe');
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.backgroundColor = 'transparent';
iframe.style.border = '0px none transparent';
iframe.style.padding = '0px';
iframe.style.overflow = 'hidden';
popup.frame.appendChild(iframe);
iframe.src = '/html/properties.html?id=' + selectedItem.Node.id;
iframe.popup = popup;
popup.popup();
iframe.focus();
} }

161
src/js/properties.js Normal file
View File

@@ -0,0 +1,161 @@
var app = {};
var Image = null;
document.addEventListener("DOMContentLoaded", function(event) {
app.init();
});
app.init = function(){
document.addEventListener('keyup', function(e){
switch(e.key){
case 'Escape':
window.frameElement.popup.close();
break;
}
});
app.Messages.getSettings(function(settings){
app.settings = settings;
app.Messages.getNodeByID(new URL(window.location).searchParams.get('id'), function(node){
app.node = node;
Title.value = node.title;
ImagePreview.style.backgroundRepeat = 'no-repeat';
ImagePreview.style.backgroundSize = '100% 100%';
switch(node.type){
case app.GridNodes.GridNodeType.folder:
TitleLocked.parentNode.style.display = 'none';
Url.parentNode.parentNode.style.display = 'none';
if(node.image){
if(node.image.indexOf('url(')>=0) Image = node.image;
else Image = 'url(' + node.image + ')';
} else Image = null;
if(Image==null) ImagePreview.style.backgroundImage = app.settings.grid.folderIcon;
else ImagePreview.style.backgroundImage = Image;
break;
case app.GridNodes.GridNodeType.bookmark:
TitleLocked.checked = (node.titleLocked==true);
ImageDefault.style.display = 'none';
Url.value = node.url;
if(node.image.indexOf('url(')>=0) Image = node.image;
else Image = 'url(' + node.image + ')';
ImagePreview.style.backgroundImage = Image;
break;
}
ImageReset.onclick = function(){
switch(node.type){
case app.GridNodes.GridNodeType.folder:
if(node.image){
Image = node.image;
ImagePreview.style.backgroundImage = 'url(' + Image + ')';
} else {
Image = null;
ImagePreview.style.backgroundImage = app.settings.grid.folderIcon;
}
break;
case app.GridNodes.GridNodeType.bookmark:
Image = node.image;
ImagePreview.style.backgroundImage = 'url(' + Image + ')';
break;
}
};
ImageDefault.onclick = function(){
switch(node.type){
case app.GridNodes.GridNodeType.folder:
Image = null;
ImagePreview.style.backgroundImage = app.settings.grid.folderIcon;
break;
case app.GridNodes.GridNodeType.bookmark:
break;
}
};
ImageFile.onclick = function(){
this.value = null;
}
ImageFile.onchange = function(){
var fileReader = new FileReader();
fileReader.onload = function(e){
Image = e.target.result;
ImageFile.value = null;
ImagePreview.style.backgroundImage = 'url(' + Image + ')';
}
fileReader.readAsDataURL(ImageFile.files[0]);
}
});
});
BtnOk.onclick = function(){
BtnApply.onclick();
window.frameElement.popup.close();
}
BtnApply.onclick = function(){
switch(app.node.type){
case app.GridNodes.GridNodeType.folder:
app.Messages.updateNode(app.node.id, { title: Title.value, image: Image })
break;
case app.GridNodes.GridNodeType.bookmark:
app.Messages.updateNode(app.node.id, { title: Title.value, titleLocked: TitleLocked.checked, url: Url.value, image: Image })
break;
}
}
BtnCancel.onclick = function(){
window.frameElement.popup.close();
}
var tabButtons = Tabs.children[0].children[0].children[0];
for(var i=0; i<tabButtons.children.length-1; i++){
tabButtons.children[i].index = i;
tabButtons.children[i].onclick = function(){
for(var j=0; j<tabButtons.children.length-1; j++){
if(j==this.index){
tabButtons.children[j].className = 'TabButtonActive';
Tabs.children[1].children[j].className = '';
} else {
tabButtons.children[j].className = 'TabButton';
Tabs.children[1].children[j].className = 'hidden';
}
}
}
}
};
app.Messages = {};
app.Messages.Commands = {
getSettings: 0,
setSettings: 1,
getNode: 2,
getNodeByID: 3,
updateNode: 4,
setNodeIndex: 5,
createBookmark: 6,
createFolder: 7,
deleteNode: 8,
refreshNode: 9,
capturePage: 10,
settingsChanged: 100,
gridNodesLoaded: 101
};
app.Messages.getSettings = function(callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getSettings }).then(callback);
};
app.Messages.getNodeByID = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getNodeByID, id: id }).then(callback);
};
app.Messages.updateNode = function(id, value, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.updateNode, id: id, value: value }).then(callback);
};
app.GridNodes = {};
app.GridNodes.GridNodeType = { // GridNodeType
back: -1,
empty: 0,
folder: 1,
bookmark: 2
}

View File

@@ -1,16 +1,31 @@
var app = {};
var BackgroundImage = null; var BackgroundImage = null;
var GridBackImage = null; var GridBackImage = null;
var GridFolderImage = null; var GridFolderImage = null;
window.onload = function(){ document.addEventListener("DOMContentLoaded", function(event) {
browser.runtime.getBackgroundPage().then(function(page){ app.init();
app = page.app; });
app.init = function(){
document.addEventListener('keyup', function(e){
switch(e.key){
case 'Escape':
window.frameElement.popup.close();
break;
}
});
app.Messages.getSettings(function(settings){
app.settings = settings;
BackgroundColor.value = app.settings.backgroundColor; BackgroundColor.value = app.settings.backgroundColor;
BackgroundImage = app.settings.backgroundImage; BackgroundImage = app.settings.backgroundImage;
BackgroundPreview.style.backgroundColor = app.settings.backgroundColor; BackgroundPreview.style.backgroundColor = app.settings.backgroundColor;
BackgroundPreview.style.backgroundImage = app.settings.backgroundImage; BackgroundPreview.style.backgroundImage = app.settings.backgroundImage;
BackgroundPreview.style.backgroundRepeat = 'no-repeat'; BackgroundPreview.style.backgroundRepeat = 'no-repeat';
BackgroundPreview.style.backgroundSize = '100% 100%'; BackgroundPreview.style.backgroundSize = '100% 100%';
GridRoot.value = app.settings.grid.root;
GridRows.value = app.settings.grid.rows; GridRows.value = app.settings.grid.rows;
GridMargins.value = app.settings.grid.margin; GridMargins.value = app.settings.grid.margin;
GridColumns.value = app.settings.grid.columns; GridColumns.value = app.settings.grid.columns;
@@ -77,7 +92,8 @@ window.onload = function(){
else app.settings.grid.cells.titleBackgroundColor = GridCellsTitleBackgroundColor.value; else app.settings.grid.cells.titleBackgroundColor = GridCellsTitleBackgroundColor.value;
if(GridCellsTitleBackgroundTransparentHover.checked == true) app.settings.grid.cells.titleBackgroundColorHover = null; if(GridCellsTitleBackgroundTransparentHover.checked == true) app.settings.grid.cells.titleBackgroundColorHover = null;
else app.settings.grid.cells.titleBackgroundColorHover = GridCellsTitleBackgroundColorHover.value; else app.settings.grid.cells.titleBackgroundColorHover = GridCellsTitleBackgroundColorHover.value;
app.saveSettings(); app.settings.grid.root = GridRoot.value;
browser.runtime.sendMessage( { cmd: app.Messages.Commands.setSettings, settings: app.settings } );
} }
BtnCancel.onclick = function(){ BtnCancel.onclick = function(){
window.frameElement.popup.close(); window.frameElement.popup.close();
@@ -152,5 +168,28 @@ window.onload = function(){
} }
fileReader.readAsDataURL(GridFolderImageFile.files[0]); fileReader.readAsDataURL(GridFolderImageFile.files[0]);
} }
};
}
app.Messages = {};
app.Messages.Commands = {
getSettings: 0,
setSettings: 1,
getNode: 2,
getNodeByID: 3,
updateNode: 4,
setNodeIndex: 5,
createBookmark: 6,
createFolder: 7,
deleteNode: 8,
refreshNode: 9,
capturePage: 10,
settingsChanged: 100,
gridNodesLoaded: 101
};
app.Messages.getSettings = function(callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getSettings }).then(callback);
};

View File

@@ -2,7 +2,7 @@
"manifest_version": 2, "manifest_version": 2,
"name": "Quick Dial", "name": "Quick Dial",
"version": "0.0.4", "version": "0.1.5",
"author": "MatMoul", "author": "MatMoul",
"homepage_url": "https://github.com/MatMoul/quickdial-webext", "homepage_url": "https://github.com/MatMoul/quickdial-webext",
"developer": { "developer": {
@@ -28,6 +28,13 @@
"scripts": ["js/background.js"] "scripts": ["js/background.js"]
}, },
"browser_action": {
"default_icon": {
"24": "img/24.png",
"32": "img/32.png"
}
},
"chrome_url_overrides" : { "chrome_url_overrides" : {
"newtab": "dial" "newtab": "dial"
}, },