1
0
Fork 0
This repository has been archived on 2024-06-28. You can view files and clone it, but cannot push or open issues or pull requests.
matomo-injector/lib/popup.js

460 lines
15 KiB
JavaScript
Raw Normal View History

2014-05-11 19:19:09 +02:00
(function($) {
var popup = {
2014-05-12 13:20:19 +02:00
key: 'popup',
2014-05-11 19:19:09 +02:00
el: {
popupForm: $('#popup-form'),
hostSelect: $('#host'),
hostGoToLink: $('#goto-host'),
enableCheck: $('#enable'),
shareBtn: $('#share'),
includeOpenPopboxLink: $('#open-popbox'),
includePopbox: $('#include-popbox'),
includeSelect: $('#include'),
includeTextarea: $('#extra-scripts'),
includeMask: $('#screen-mask'),
sourceEditor: $('#ace-editor'),
saveBtn: $('#save'),
draftRemoveLink: $('#draft-remove')
2014-05-11 19:19:09 +02:00
},
title: {
host: {
select: "List of websites modified by Your custom js",
goTo: "Jump to the selected host"
},
share: "Share Your script with other people",
2014-05-12 11:22:21 +02:00
save: "Save and apply this script",
2014-05-11 19:19:09 +02:00
include: {
textarea: 'Uncomment address of script below or type your own (one per line)',
mask: 'Click to close textarea popup'
},
draft: "This is a draft, click to remove it"
2014-05-11 19:19:09 +02:00
},
2014-05-12 11:22:21 +02:00
applyTitles: function() {
this.el.hostSelect.attr('title', this.title.host.select);
this.el.hostGoToLink.attr('title', this.title.host.goTo);
this.el.includeTextarea.attr('title', this.title.include.textarea);
this.el.includeMask.attr('title', this.title.include.mask);
this.el.shareBtn.attr('title', this.title.share);
this.el.saveBtn.attr('title', this.title.save);
this.el.shareBtn.attr('title', this.title.share);
this.el.draftRemoveLink.attr('title', this.title.draft);
},
2014-05-11 19:19:09 +02:00
include: {
predefined: [
{
name: 'jQuery 1.11.0',
path: '/jquery/1.11.0/jquery.min.js'
},
{
name: 'jQuery 2.1.0',
path: '/jquery/2.1.0/jquery.min.js'
}
],
extra: [
'//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js'
]
},
editor: {
instance: null,
defaultValue: "// Here You can type your custom JavaScript...",
value: '',
init: function() {
var editor = this.instance = ace.edit(popup.el.sourceEditor[0]);
editor.setTheme("ace/theme/tomorrow");
editor.getSession().setMode("ace/mode/javascript");
editor.setHighlightActiveLine(false);
editor.getSession().on('change', this.onChange);
},
apply: function(source) {
var editor = this.instance;
editor.setValue(source);
editor.gotoLine(1);
2014-05-11 19:19:09 +02:00
}
},
storage: {
2014-05-12 15:20:54 +02:00
data: {
private: {},
global: {}
},
2014-05-12 13:20:19 +02:00
MODE: {
private: 1,
global: 2,
},
setMode: function(mode) {
if( mode === this.MODE.private ) {
2014-05-12 15:20:54 +02:00
this.key = popup.key + "-" + popup.protocol + "//" + popup.host;
2014-05-12 13:20:19 +02:00
this.mode = this.MODE.private;
}
if( mode === this.MODE.global ) {
this.key = popup.key;
this.mode = this.MODE.global;
}
},
2014-05-12 15:20:54 +02:00
load: function() {
this.setMode(this.MODE.private);
this._setData(JSON.parse(localStorage.getItem(this.key) || "{}"));
2014-05-12 15:20:54 +02:00
this.setMode(this.MODE.global);
this._setData(JSON.parse(localStorage.getItem(this.key) || "{}"));
2014-05-12 15:20:54 +02:00
},
2014-05-12 13:20:19 +02:00
_getData: function(key) {
2014-05-12 15:20:54 +02:00
var storage = popup.storage;
if( storage.mode == storage.MODE.private ) {
2014-05-12 13:20:19 +02:00
if( key ) {
2014-05-12 15:20:54 +02:00
return storage.data.private[key];
2014-05-12 13:20:19 +02:00
}
else {
2014-05-12 15:20:54 +02:00
return storage.data.private;
2014-05-12 13:20:19 +02:00
}
}
2014-05-12 15:20:54 +02:00
if( storage.mode == storage.MODE.global ) {
2014-05-12 13:20:19 +02:00
if( key ) {
2014-05-12 15:20:54 +02:00
return storage.data.global[key];
2014-05-12 13:20:19 +02:00
}
else {
2014-05-12 15:20:54 +02:00
return storage.data.global;
2014-05-12 13:20:19 +02:00
}
}
},
_setData: function(data, key) {
2014-05-12 15:20:54 +02:00
var storage = popup.storage;
if( storage.mode == storage.MODE.private ) {
2014-05-12 13:20:19 +02:00
if( key ) {
2014-05-12 15:20:54 +02:00
storage.data.private[key] = data;
2014-05-12 13:20:19 +02:00
}
else {
2014-05-12 15:20:54 +02:00
storage.data.private = data;
2014-05-12 13:20:19 +02:00
}
}
2014-05-12 15:20:54 +02:00
if( storage.mode == storage.MODE.global ) {
2014-05-12 13:20:19 +02:00
if( key ) {
2014-05-12 15:20:54 +02:00
storage.data.global[key] = data;
2014-05-12 13:20:19 +02:00
}
else {
2014-05-12 15:20:54 +02:00
storage.data.global = data;
2014-05-12 13:20:19 +02:00
}
}
2014-05-11 19:19:09 +02:00
},
2014-05-12 13:20:19 +02:00
get: function(key) {
return this._getData(key);
2014-05-11 19:19:09 +02:00
},
set: function(arg1, arg2) {
// arg1 is a key
if( typeof arg1 === 'string' ) {
2014-05-12 13:20:19 +02:00
this._setData(arg2, arg1);
2014-05-11 19:19:09 +02:00
}
// arg1 is data
else {
2014-05-12 13:20:19 +02:00
this._setData(arg1);
2014-05-11 19:19:09 +02:00
}
2014-05-12 13:20:19 +02:00
var str = JSON.stringify(this._getData() || {});
2014-05-11 19:19:09 +02:00
localStorage.setItem(this.key, str);
2014-05-12 11:35:25 +02:00
},
remove: function(key) {
if( key ) {
2014-05-12 13:20:19 +02:00
var data = this._getData();
delete data[key];
2014-05-12 15:20:54 +02:00
2014-05-12 13:20:19 +02:00
if( $.isEmptyObject(data) ) {
2014-05-12 11:35:25 +02:00
this.remove();
}
else {
2014-05-12 13:20:19 +02:00
var str = JSON.stringify(this._getData());
2014-05-12 11:35:25 +02:00
localStorage.setItem(this.key, str);
}
}
else {
localStorage.removeItem(this.key);
}
2014-05-11 19:19:09 +02:00
}
},
apiclb: {
onSelectedTab: function(tab) {
2014-05-12 11:22:21 +02:00
popup.tabId = tab.id;
2014-05-12 15:20:54 +02:00
chrome.tabs.sendRequest(popup.tabId, {method: "getData", reload: false}, popup.apiclb.onGetData);
2014-05-11 19:19:09 +02:00
},
2014-05-12 15:20:54 +02:00
onGetData: function(response) {
if( !response || typeof response.host !== 'string' ) {
2014-05-11 19:19:09 +02:00
popup.error();
return;
}
2014-05-12 15:20:54 +02:00
/**
* Create 'hosts select'
*/
2014-05-12 13:20:19 +02:00
popup.host = response.host;
2014-05-12 15:20:54 +02:00
popup.protocol = response.protocol;
// Set storage to store data accessible from all hosts
popup.storage.setMode(popup.storage.MODE.global);
2014-05-11 19:19:09 +02:00
2014-05-12 15:20:54 +02:00
var hosts = popup.storage.get('hosts') || [],
url = popup.protocol + "//" + response.host;
2014-05-12 13:20:19 +02:00
2014-05-12 15:20:54 +02:00
// Add current host to list
if( hosts.indexOf(url) === -1 ) {
hosts.push(url);
2014-05-12 13:20:19 +02:00
}
2014-05-12 15:20:54 +02:00
// Fill 'hosts select'
2014-05-11 19:19:09 +02:00
hosts.forEach(function(host) {
2014-05-12 13:20:19 +02:00
var option = $('<option>' + host + '</option>');
2014-05-12 15:20:54 +02:00
if( host === url ) {
2014-05-12 13:20:19 +02:00
option.attr('selected', 'selected');
}
2014-05-11 19:19:09 +02:00
popup.el.hostSelect.append(option);
2014-05-12 13:20:19 +02:00
});
2014-05-12 15:20:54 +02:00
// Store host (current included in array) if is customjs defined
if( response.customjs ) {
popup.storage.set('hosts', hosts);
2014-05-11 19:19:09 +02:00
}
2014-05-12 15:20:54 +02:00
/**
* Set-up data (script, enable, include, extra)
*/
2014-05-12 15:20:54 +02:00
// Backward compatibility (version <1 and 1)
if( response.customjs && response.customjs.src ) {
response.customjs.source = decodeURI(response.customjs.src); // Old format ...
delete response.customjs.src;
2014-05-11 19:19:09 +02:00
}
2014-05-07 13:56:35 +02:00
2014-05-12 15:20:54 +02:00
// Merge host's data to defaults
popup.data = $.extend(popup.data, response.customjs);
// ... source is now encoded as base64
if( popup.data.source.indexOf('data:text/javascript;base64,') === 0 ) {
popup.data.source = popup.data.source.replace('data:text/javascript;base64,', '');
popup.data.source = atob(popup.data.source);
2014-05-11 19:19:09 +02:00
}
2014-05-12 15:20:54 +02:00
// Set storage to store data accessible ONLY from current host
2014-05-12 13:20:19 +02:00
popup.storage.setMode(popup.storage.MODE.private);
2014-05-12 15:20:54 +02:00
// Save local copy of live data
if( response.customjs ) {
popup.storage.set('data', popup.data);
}
// Apply data (draft if exist)
2014-05-12 11:22:21 +02:00
popup.applyData(popup.storage.get('draft'));
}
},
2014-05-12 13:20:19 +02:00
host: undefined,
data: {
config: {
enable: false,
include: '',
extra: ''
2014-05-11 19:19:09 +02:00
},
source: ''
},
2014-05-12 15:20:54 +02:00
applyData: function(data, notDraft) {
if( data && !notDraft ) {
this.el.draftRemoveLink.removeClass('is-hidden');
}
2014-05-11 19:19:09 +02:00
data = data || this.data;
2014-05-12 15:20:54 +02:00
// Default value for 'extra include'
if( !data.config.extra ) {
data.config.extra = '# ' + popup.title.include.textarea + "\n";
popup.include.extra.forEach(function(url) {
data.config.extra += '# ' + url + "\n";
});
}
2014-05-12 15:20:54 +02:00
// Readable format for 'extra include'
else {
data.config.extra = data.config.extra.replace(';', "\n");
}
// Default value for source
if( !data.source ) {
data.source = popup.editor.defaultValue;
2014-05-12 15:20:54 +02:00
}
// Set 'predefined include' value
2014-05-12 15:20:54 +02:00
popup.el.includeSelect.val(data.config.include);
// Set enable checkbox
popup.el.enableCheck.prop('checked', data.config.enable);
// Fill 'extra include' textarea
2014-05-12 11:22:21 +02:00
popup.el.includeTextarea.val(data.config.extra);
// Apply source into editor
popup.editor.apply(data.source);
},
getCurrentData: function() {
return {
config: {
enable: popup.el.enableCheck.prop('checked'),
include: popup.el.includeSelect.val(),
extra: popup.el.includeTextarea.val()
},
source: popup.editor.instance.getValue()
};
},
removeDraft: function() {
2014-05-12 13:20:19 +02:00
popup.storage.setMode(popup.storage.MODE.private);
2014-05-12 15:20:54 +02:00
popup.storage.remove('draft');
2014-05-12 13:20:19 +02:00
popup.applyData();
popup.el.draftRemoveLink.addClass('is-hidden');
2014-05-11 19:19:09 +02:00
},
2014-05-12 15:20:54 +02:00
save: function(e) {
2014-05-12 11:22:21 +02:00
e.preventDefault();
2014-05-12 15:20:54 +02:00
// Is allowed to save?
if( popup.el.saveBtn.hasClass('pure-button-disabled') ) {
return false;
}
var data = popup.getCurrentData();
// Transform source for correct apply
2014-05-12 11:22:21 +02:00
data.config.extra = data.config.extra.replace("\n", ';');
data.source = 'data:text/javascript;base64,' + btoa(data.source);
2014-05-12 15:20:54 +02:00
// Send new data to apply
chrome.tabs.sendRequest(popup.tabId, {method: "setData", customjs: data, reload: true});
2014-05-12 11:22:21 +02:00
2014-05-12 15:20:54 +02:00
// Save local copy of data
popup.storage.setMode(popup.storage.MODE.private);
popup.storage.set('data', popup.data);
// Clear draft
2014-05-12 11:22:21 +02:00
popup.removeDraft();
2014-05-12 15:20:54 +02:00
// Close popup
2014-05-12 11:22:21 +02:00
window.close();
return false;
},
2014-05-11 19:19:09 +02:00
error: function() {
alert('err');
}
2014-05-07 13:56:35 +02:00
};
2014-05-11 19:19:09 +02:00
window.popup = popup;
2014-05-07 13:56:35 +02:00
2014-05-12 15:20:54 +02:00
/**
* Load storage (global, local) IMPORTANT: Must be called first of all
*/
popup.storage.load();
2014-05-12 11:22:21 +02:00
/**
* Add titles to elements
*/
2014-05-12 13:20:19 +02:00
2014-05-12 11:22:21 +02:00
popup.applyTitles();
2014-05-12 15:20:54 +02:00
/**
* Change host by select
*/
popup.el.hostSelect.on('change', function(e) {
var host = $(this).val();
if( host !== popup.protocol + '//' + popup.host ) {
popup.el.hostGoToLink.removeClass('is-hidden');
popup.el.saveBtn.addClass('pure-button-disabled');
}
else {
popup.el.hostGoToLink.addClass('is-hidden');
popup.el.saveBtn.removeClass('pure-button-disabled');
}
var hostData = JSON.parse(localStorage.getItem(popup.key + '-' + host), true);
popup.applyData(hostData.data, true);
});
/**
* Click to goTo host link
*/
popup.el.hostGoToLink.on('click', function() {
var link = popup.el.hostSelect.val();
chrome.tabs.sendRequest(popup.tabId, {method: "goTo", link: link, reload: false});
window.close();
2014-05-12 15:20:54 +02:00
});
2014-05-07 13:56:35 +02:00
/**
2014-05-11 19:19:09 +02:00
* Fill predefined libs to include
2014-05-07 13:56:35 +02:00
*/
2014-05-11 19:19:09 +02:00
popup.include.predefined.forEach(function(lib) {
var option = '<option value="' + lib.path + '">' + lib.name + '</option>';
popup.el.includeSelect.append(option);
2014-05-07 13:56:35 +02:00
});
2014-05-11 19:19:09 +02:00
/**
* Inicialize Ace Editor
*/
popup.editor.init();
2014-05-07 13:56:35 +02:00
/**
2014-05-11 19:19:09 +02:00
* Connect front end (load info about current site)
*/
chrome.tabs.getSelected(null, popup.apiclb.onSelectedTab);
2014-05-07 20:31:25 +02:00
2014-05-07 13:56:35 +02:00
/**
2014-05-11 19:19:09 +02:00
* 'Include extra scripts' control
2014-05-07 20:31:25 +02:00
*/
2014-05-11 19:19:09 +02:00
popup.el.includeOpenPopboxLink.on('click', function() {
popup.el.includePopbox.removeClass('is-hidden');
});
popup.el.includeMask.on('click', function() {
popup.el.includePopbox.addClass('is-hidden');
});
/**
* Auto save draft
*/
setInterval(function() {
var draft = popup.getCurrentData(),
2014-05-12 13:20:19 +02:00
source = draft.source;
if( (source || !popup.data.source) && source !== popup.data.source ) {
2014-05-12 15:20:54 +02:00
2014-05-12 13:20:19 +02:00
popup.storage.setMode(popup.storage.MODE.private);
popup.storage.set('draft', draft);
2014-05-12 15:20:54 +02:00
2014-05-12 11:22:21 +02:00
// Auto switch 'enable checkbox' on source edit
popup.el.enableCheck.prop('checked', true);
}
2014-05-12 13:20:19 +02:00
}, 2000);
2014-05-11 19:19:09 +02:00
2014-05-12 11:22:21 +02:00
/**
* Save script
*/
2014-05-12 15:20:54 +02:00
2014-05-12 11:22:21 +02:00
popup.el.popupForm.on('submit', popup.save);
2014-05-11 19:19:09 +02:00
/**
* Remove draft
2014-05-11 19:19:09 +02:00
*/
popup.el.draftRemoveLink.on('click', popup.removeDraft);
2014-05-11 19:19:09 +02:00
})(jQuery);