Skip to content

Commit d621f41

Browse files
committedDec 24, 2018
First commit
0 parents  commit d621f41

15 files changed

+442
-0
lines changed
 

‎background.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
var background = {
3+
4+
config: {},
5+
init: function() {
6+
7+
}
8+
9+
};
10+
11+
background.init();

‎config.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
var config = {
2+
"entities": {
3+
"IMDB Movie": "https://www.imdb.com/title/tt",
4+
"IMDB Name": "https://www.imdb.com/name/nm",
5+
"Example1": "https://www.example.com/example/",
6+
"Example2": "https://www.example.com/example/",
7+
"Example3": "https://www.example.com/example/"
8+
}
9+
}

‎icon100.png

2.99 KB
Loading

‎icon128.png

4.33 KB
Loading

‎icon16.png

500 Bytes
Loading

‎icon24.png

771 Bytes
Loading

‎icon32.png

986 Bytes
Loading

‎icon48.png

1.45 KB
Loading

‎icon64.png

1.87 KB
Loading

‎manifest.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"manifest_version": 2,
3+
"name": "Quick Links",
4+
"short_name": "QuickLinks",
5+
"version": "0.0.005",
6+
"version_name": "0.0.005",
7+
"description": "Provides configurable quick links.",
8+
"permissions": ["activeTab", "storage"],
9+
"icons": {
10+
"16": "icon16.png",
11+
"24": "icon24.png",
12+
"32": "icon32.png",
13+
"48": "icon48.png",
14+
"64": "icon64.png",
15+
"100": "icon100.png",
16+
"128": "icon128.png"
17+
},
18+
"browser_action": {
19+
"default_icon": {
20+
"16": "icon16.png",
21+
"24": "icon24.png",
22+
"32": "icon32.png",
23+
"48": "icon48.png",
24+
"64": "icon64.png",
25+
"100": "icon100.png",
26+
"128": "icon128.png"
27+
},
28+
"default_title": "Quick Links",
29+
"default_popup": "popup.html"
30+
},
31+
"options_page": "options.html",
32+
"background": {
33+
"scripts": ["config.js", "background.js"]
34+
}
35+
36+
}

‎options.html

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<html>
2+
<head>
3+
<title>Quick Links Options</title>
4+
<link rel="stylesheet" href="styles.css">
5+
</head>
6+
7+
<body>
8+
<h4>Quick Links Options Page</h4>
9+
<div id="tab-section">
10+
<p>Open links in:</p>
11+
<form id="form-options">
12+
<div>
13+
<input type="radio" id="new-tab" name="tab-option" value="new-tab" checked>
14+
<label for="new-tab">New Tab</label>
15+
</div>
16+
<div>
17+
<input type="radio" id="current-tab" name="tab-option" value="current-tab">
18+
<label for="current-tab">Current Tab</label>
19+
</div>
20+
<div id="entity-section">
21+
<p>Enter new entities:</p>
22+
</div>
23+
<br>
24+
<button type="submit" id="save-button">Save</button>
25+
</form>
26+
<div id="status"></div>
27+
</div>
28+
</body>
29+
<script src="options.js"></script>
30+
31+
</html>

‎options.js

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
2+
/*!s
3+
* Saves options to chrome.storage
4+
* @param {Array} Serialized form data
5+
* @return {}
6+
*/
7+
function saveOptions(data) {
8+
console.log("options: ", JSON.stringify(data));
9+
var tabPref = data.find(function (element) {
10+
return element.name === "tab-option";
11+
});
12+
13+
14+
chrome.storage.sync.set({
15+
16+
tabOption: tabPref.value
17+
// entities:
18+
19+
}, function() {
20+
21+
// Update status to let user know options were saved.
22+
var status = document.getElementById("status");
23+
status.textContent = "Options saved.";
24+
setTimeout(function() {
25+
status.textContent = "";
26+
}, 750);
27+
28+
});
29+
30+
}
31+
32+
/*!
33+
* Restores select box and checkbox state using the preferences
34+
* stored in chrome.storage.
35+
* Might need to add checks for existense of objects
36+
*/
37+
function restoreOptions() {
38+
chrome.storage.sync.get({
39+
40+
tabOption: "new-tab" // this is a default in case there is no value in storage.
41+
42+
}, function(items) {
43+
44+
document.getElementById(items["tabOption"]).checked = true;
45+
46+
});
47+
48+
};
49+
50+
51+
/*!
52+
* Serialize all form data into an array
53+
* (c) 2018 Chris Ferdinandi, MIT License, https://gomakethings.com
54+
* @param {Node} form The form to serialize
55+
* @return {String} The serialized form data
56+
*/
57+
var serializeArray = function (form) {
58+
var serialized = [];
59+
60+
for (var i = 0; i < form.elements.length; i++) {
61+
var field = form.elements[i];
62+
63+
if (!field.name || field.disabled || field.type === "file" ||
64+
field.type === "reset" || field.type === "submit" ||
65+
field.type === "button") continue;
66+
67+
if (field.type === "select-multiple") {
68+
for (var n = 0; n < field.options.length; n++) {
69+
if (!field.options[n].selected) continue;
70+
serialized.push({
71+
name: field.name,
72+
value: field.options[n].value
73+
});
74+
}
75+
}
76+
else if (field.id.includes("-label-input")) {
77+
// create key named with label field.value;
78+
serialized.push({
79+
name: {}
80+
})
81+
}
82+
else if (field.id.includes("-url-input")) {
83+
// add value to previously added label value key
84+
serialized[field.name] = field.value;
85+
}
86+
else if ((field.type !== "checkbox" && field.type !== "radio") ||
87+
field.checked) {
88+
serialized.push({
89+
name: field.name,
90+
value: field.value
91+
});
92+
}
93+
}
94+
95+
return serialized;
96+
97+
};
98+
99+
// Debugging:
100+
// chrome.storage.onChanged.addListener(function(changes, namespace) {
101+
// for (key in changes) {
102+
// var storageChange = changes[key];
103+
// console.log('Storage key "%s" in namespace "%s" changed. ' +
104+
// 'Old value was "%s", new value is "%s".',
105+
// key,
106+
// namespace,
107+
// storageChange.oldValue,
108+
// storageChange.newValue);
109+
// }
110+
// });
111+
112+
var urlComponent = function(name) {
113+
return '<div id="'+ name +'-section" >' +
114+
'<label for="'+ name +'-label-input" class="display-block" >Label for '+ name +':</label>' +
115+
'<input id="'+ name +'-label-input" name="'+ name + '"' +
116+
'class="border border-radius width-small height-small" type="text">' +
117+
'<label for="'+ name +'-url-input" class="display-block" >URL for '+ name +':</label>' +
118+
'<input id="'+ name +'-url-input" name="'+ name + '"' +
119+
'class="border border-radius width-small height-small" type="text">' +
120+
'</div>';
121+
}
122+
123+
document.addEventListener("DOMContentLoaded", function() {
124+
restoreOptions();
125+
126+
127+
128+
entitySection = document.querySelector('#entity-section');
129+
entitySection.innerHTML += urlComponent('Example');
130+
131+
132+
133+
document.addEventListener("click", function (event) {
134+
135+
if (!event.target.matches("#save-button")) return;
136+
137+
event.preventDefault();
138+
139+
data = serializeArray(document.querySelector("#form-options"));
140+
saveOptions(data);
141+
142+
});
143+
144+
145+
});
146+
147+
148+

‎popup.html

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Quick Links</title>
5+
<link rel="stylesheet" href="styles.css">
6+
</head>
7+
<body>
8+
<div id="main" class="width-medium">
9+
<h4 class="font-size-1rem margin-bottom-8px margin-top-12px" >Quick Links</h4>
10+
</div>
11+
<script src="popup.js"></script>
12+
</body>
13+
</html>

‎popup.js

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"use strict";
2+
3+
var console = chrome.extension.getBackgroundPage().console;
4+
var config = chrome.extension.getBackgroundPage().config;
5+
6+
var app = {
7+
8+
entities: {},
9+
10+
init: function() {
11+
12+
this.entities = config.entities;
13+
//console.log("entities", config.entities);
14+
15+
this.entityComponent = function(name, url) {
16+
return '<div id="'+ name +'-section" >' +
17+
'<label for="'+ name +'-input " >'+ name +':</label>' +
18+
'<input id="'+ name +'-input" name="'+ name + '"' +
19+
'class="border border-radius width-small height-small" type="text">' +
20+
'<button id="'+ name +'-button" value="'+ name +'" class="float-right">Go</button>' +
21+
'</div>';
22+
}
23+
this.mainpage = document.querySelector("#main"); // innerHTML(this.entityComponent());
24+
Object.keys(this.entities).forEach(key => {
25+
var value = this.entities[key];
26+
this.mainpage.innerHTML += this.entityComponent(key, value);
27+
});
28+
},
29+
30+
openLink: function(element) {
31+
console.log("OpenLink Function : ",this.entities);
32+
33+
var inputValue = element.value.trim();
34+
35+
// check for blank input
36+
if (inputValue === "") {
37+
element.classList.add("border-red");
38+
element.classList.remove("border");
39+
return;
40+
}
41+
42+
// build url
43+
var urlKey = element.name;
44+
var pageUrl = this.entities[urlKey] + inputValue;
45+
46+
console.log("resourceType (Input Element name):", urlKey);
47+
console.log("inputValue (Input Element value):", inputValue);
48+
console.log("pageURL:", pageUrl);
49+
50+
chrome.storage.sync.get({
51+
52+
tabOption: "new-tab" // this is a default in case there is no value in storage.
53+
54+
}, function(items) {
55+
56+
if (items["tabOption"] === "current-tab") {
57+
58+
// use existing tab
59+
chrome.tabs.update({
60+
url: pageUrl
61+
});
62+
63+
} else {
64+
65+
// open new tab
66+
chrome.tabs.create({
67+
url: pageUrl
68+
});
69+
70+
}
71+
72+
window.close();
73+
74+
});
75+
return;
76+
},
77+
78+
};
79+
80+
// app start
81+
document.addEventListener("DOMContentLoaded", function() {
82+
83+
app.init();
84+
85+
document.addEventListener("keyup", function (event) {
86+
87+
//ignore enter key on non-input elements
88+
if (!event.target.matches("input")) return;
89+
90+
if (event.key === "Enter") {
91+
app.openLink(event.target);
92+
}
93+
}, false);
94+
95+
document.addEventListener("click", function (event) {
96+
97+
//ignore clicks on non-buttons
98+
if (!event.target.matches("button")) return;
99+
event.preventDefault();
100+
101+
// get input element based on button value attribute
102+
var inputElement = document.getElementById(event.target.value+"-input");
103+
104+
app.openLink(inputElement);
105+
106+
}, false);
107+
108+
});

‎styles.css

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
html {
2+
box-sizing: border-box;
3+
}
4+
5+
*, *:before, *:after {
6+
box-sizing: inherit;
7+
}
8+
9+
.display-block {
10+
display: block;
11+
}
12+
13+
.font-size-1rem {
14+
font-size: 1rem;
15+
}
16+
17+
.margin-bottom-8px {
18+
margin-bottom: 8px;
19+
}
20+
21+
.margin-top-12px {
22+
margin-top: 12px;
23+
}
24+
25+
.width-small {
26+
width: 126px;
27+
}
28+
29+
.height-small {
30+
height: 21px;
31+
}
32+
33+
.width-medium {
34+
width: 160px;
35+
}
36+
37+
.float-right{
38+
float: right;
39+
}
40+
41+
.border-red {
42+
border: 1px solid red;
43+
}
44+
45+
.border {
46+
border: 1px solid rgb(182, 180, 180);
47+
}
48+
49+
.border-radius {
50+
border-radius: 3px;
51+
}
52+
53+
input {
54+
border: none;
55+
}
56+
57+
input:focus,
58+
select:focus,
59+
textarea:focus
60+
{
61+
outline: none;
62+
}
63+
64+
button {
65+
display: inline-block;
66+
vertical-align: middle;
67+
border: none;
68+
border-radius: 4px;
69+
height: 21px;
70+
color: #fff;
71+
background-color: #004ea1;
72+
border-color: #0062cc;
73+
-webkit-transform: perspective(1px) translateZ(0);
74+
transform: perspective(1px) translateZ(0);
75+
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
76+
overflow: hidden;
77+
-webkit-transition-duration: 0.3s;
78+
transition-duration: 0.3s;
79+
-webkit-transition-property: color, background-color;
80+
transition-property: color, background-color;
81+
}
82+
button:hover {
83+
color: #fff;
84+
background-color: #007bff;
85+
border-color: #007bff;
86+
}

0 commit comments

Comments
 (0)
Please sign in to comment.