diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..b421021
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/fonts/glyphicons-halflings-regular.eot b/public/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 0000000..b93a495
Binary files /dev/null and b/public/fonts/glyphicons-halflings-regular.eot differ
diff --git a/public/fonts/glyphicons-halflings-regular.svg b/public/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 0000000..94fb549
--- /dev/null
+++ b/public/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,288 @@
+
+
+
\ No newline at end of file
diff --git a/public/fonts/glyphicons-halflings-regular.ttf b/public/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 0000000..1413fc6
Binary files /dev/null and b/public/fonts/glyphicons-halflings-regular.ttf differ
diff --git a/public/fonts/glyphicons-halflings-regular.woff b/public/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 0000000..9e61285
Binary files /dev/null and b/public/fonts/glyphicons-halflings-regular.woff differ
diff --git a/public/fonts/glyphicons-halflings-regular.woff2 b/public/fonts/glyphicons-halflings-regular.woff2
new file mode 100644
index 0000000..64539b5
Binary files /dev/null and b/public/fonts/glyphicons-halflings-regular.woff2 differ
diff --git a/public/js/main.js b/public/js/main.js
index f166a23..27110e7 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -16,12 +16,7 @@ var objectStore;
var myIp;
-$.getJSON('https://api.ipify.org?format=json', function (data) {
- myIp = data.ip;
-});
-// $.getJSON("http://jsonip.com?callback=?", function (data) {
-// myIp = data.host;
-// });
+
@@ -68,38 +63,25 @@ function getUrl(){
return _.template(services[options.service])(options);
}
-
-function ebayParser(){}
- // s = req.lstrip('/**/nil/(').rstrip(')')
- // sugg_texts = json.loads(s)['res']['sug']
- // print('j', sugg_texts)
- // return {'sugg_texts': sugg_texts}
-
-
-function twitterParser(){}
- // j = json.loads(req)
- // return {
- // 'sugg_texts': [t['topic'] for t in j['topics']],
- // 'meta': j,
- // 'relevances': [t['rounded_score'] for t in j['topics']],
- // }
-
-/** Parse response per service **/
-function parseServiceResponse(res){
- var service = $('#service').val();
- var parser = RESPONSE_TEMPLATES[service] || RESPONSE_TEMPLATES["default"];
- return parser(res);
-}
var RESPONSE_TEMPLATES = {
"default": function(res){return res[1];},
"google": function(res){return res[1];},
"youtube": function(res){return res[1];},
"yahoo": function(res){return _.map(res.gossip.results,'key');},
"bing": function(res){return res[1];},
- "ebay": function(res){return res.res.sug;},
+ "ebay": function(res){
+ return res.res? res.res.sug: undefined;
+ },
"amazon": function(res){return res[1];},
- "twitter": function(res){return Array.concat(res.users,_.map(res.topics,'topic'),res.hashtags,res.oneclick);}
+ "twitter": function(res){return _.concat(res.users,_.map(res.topics,'topic'),res.hashtags,res.oneclick);}
};
+/** Parse response per service **/
+function parseServiceResponse(res){
+ var service = $('#service').val();
+ var parser = RESPONSE_TEMPLATES[service] || RESPONSE_TEMPLATES["default"];
+ return parser(res);
+}
+
// setup a db. Ref: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
@@ -109,18 +91,16 @@ function errorHandler(){
return this; // for chaining
}
var db;
-var dbReq = window.indexedDB.open("KeywordShitter2", 2);
+var dbReq = window.indexedDB.open("KeywordShitter2", 3);
+/** Error handler for all child transactions as events bubbe up **/
dbReq.onerror = function (event) {
console.error('dbReq', event);
};
dbReq.onsuccess = function (event) {
- // Do something with request.result!
- console.log('dbReq', event);
db = event.target.result;
db.onerror = function (event) {
- // Generic error handler for all errors targeted at this database's
- // requests!
- console.error("Database error: " + event.target.errorCode);
+ // Generic error handler requests
+ console.error("Database error: " + event.currentTarget.error.errorCode, event.currentTarget.error.message, event);
};
};
dbReq.onupgradeneeded = function (event) {
@@ -128,22 +108,18 @@ dbReq.onupgradeneeded = function (event) {
db = event.target.result;
if (!db.objectStoreNames.contains("suggestions")) {
- objectStore = db.createObjectStore("suggestions", {
- autoIncrement: true
+ var objectStore = db.createObjectStore("suggestions", {
+ autoIncrement: true, keyPath: 'id'
});
-
// Create an index to search suggestions by
// he query that prompted the suggestion
- objectStore.createIndex("search", "search", {
- unique: false
- });
- // and by suggestion
- objectStore.createIndex("keyword", "keyword", {
- unique: false
- });
+ if (!objectStore.indexNames.contains('search'))
+ objectStore.createIndex("search", "search", {unique: false});
+
+ // and by suggestion/keyword
+ if (!objectStore.indexNames.contains('keyword'))
+ objectStore.createIndex("keyword", "keyword", {unique: false});
- } else {
- // objectStore = db.objectStore("customers");
}
};
@@ -157,7 +133,7 @@ function StartJob() {
hashMapResults[""] = 1;
// hashMapResults[" "] = 1;
- // hashMapResults[" "] = 1;
+ hashMapResults[" "] = 1;
// update config
prefixes = $('#prefixes').val().split(',');
@@ -229,7 +205,7 @@ function permuteResultsToQueue(retList, search){
hashMapResults[cleanKw] = 1;
// add base suggestion to queue
- if (cleanKw!==search)
+ if (cleanKw && cleanKw.trim().length && cleanKw!==search)
keywordsToQuery[keywordsToQuery.length] = cleanKw;
// add prefix permutations
@@ -257,80 +233,120 @@ function loadFromDB(){
.getAll()
.onsuccess = function(e) {
if (e.target.result.length){
- table.data(e.target.result);
+ /// grab the fields we want
var data =[];
for (var i = 0; i < e.target.result.length; i++) {
var d = e.target.result[i];
- data.push([i,d.keyword,d.Length,null,null,d.search]);
+ var da = [
+ d.id,
+ d.keyword,
+ d.length,
+ d.volume,
+ d.cpc,
+ d.search,
+ d.domain
+ ];
+ // also remove undefined so datatables doesn't bring up alerts
+ da = da.map(function(v){return v===undefined ? null: v;});
+ // parse nums
+ // da = da.map(v => /^[\d+\.]+$/.test(v) ? Number(v): v);
+ data.push(da);
}
table.rows.add(data);
}
- table.draw(false);
+ return table.draw(false);
};
reqObj.onerror=errorHandler;
+ return;
}
/** Display results **/
-function displayResults(retList, search, dontDisplay){
-
-
-
-
-
+function displayResults(retList, search, dontDisplay, url,data){
+ var rows=[];
for (var i = 0; i < retList.length; i++) {
var cleanKw = CleanVal(retList[i]);
- // we get an annoying popup alert if we add undefined values, catch them
- if (cleanKw===undefined||table.rows()[0].length===undefined||cleanKw.length===undefined,search===undefined){
- console.error('Undefined values',{
- id: table.rows()[0].length,
- keyword: cleanKw,
- length: cleanKw? cleanKw.length: undefined,
- search:search
- });
- continue;
+ // url might be in retlist
+ if (url===undefined) url=data[i].url;
- } else if (cleanKw!==undefined && cleanKw.length){
- // Check if suggestion is already displayed before adding
+ var da = [
+ table.rows()[0].length+i,
+ cleanKw,
+ cleanKw.length,
+ null,
+ null,
+ search,
+ extractDomain(url)
+ ];
+
+ // remove undefined values to avoid datatable alerts
+ da = da.map(function(v){return v===undefined ? null: v;});
+
+ // TODO Check if suggestion is already displayed before adding
// var matches = table.data().filter(function(v){return v[1]===cleanKw && v[5]==search;}).count();
// if (!matches)
- table.row.add([
- table.rows()[0].length,
- cleanKw,
- cleanKw.length,
- null,
- null,
- search]);
- }
+ rows.push(da);
}
+ table.rows.add(rows);
if (!dontDisplay) table.draw(false);
}
+function extractDomain(url) {
+ if (url===undefined) return null;
+ var domain;
+ //find & remove protocol (http, ftp, etc.) and get domain
+ if (url.indexOf("://") > -1) {
+ domain = url.split('/')[2];
+ }
+ else {
+ domain = url.split('/')[0];
+ }
+
+ //find & remove port number
+ domain = domain.split(':')[0];
+
+ return domain;
+}
+
/** Store new results in db and hashmap **/
function storeResults(retList, search, url){
- for (var i = 0; i < retList.length; i++) {
- var cleanKw = CleanVal(retList[i]);
- if (cleanKw.length){
- // TODO check if I should add in bulk?
+ // We will add the items async in order
+ // Ref: http://stackoverflow.com/a/13666741/221742
+ var transaction = db.transaction(["suggestions"], "readwrite");
+ var store = transaction.objectStore("suggestions");
+ var i=0;
+ addNext();
- // add to db
- var transaction = db.transaction(["suggestions"], "readwrite");
- transaction.onerror = errorHandler;
- var objectStore = transaction.objectStore("suggestions");
- addReq = objectStore.add({
- keyword: cleanKw,
- Length: cleanKw.length,
- search: search,
- ip: myIp,
- url: this.url,
- time: (new Date()).toUTCString()
- });
- addReq.onerror=errorHandler;
+ /** Like an async for loop to add each to db **/
+ function addNext() {
+ if (i<'col-sm-7'<'pull-right'p>>>" +
"<'row'<'col-sm-8'i><'col-sm-4'<'pull-right'f>>>" +
"<'row'<'col-sm-12'tr>>",
- buttons: ['copyHtml5', 'csvHtml5','colvis','pageLength'],
+ buttons: [
+ 'copyHtml5',
+ 'csvHtml5',
+ 'colvis',
+ 'pageLength',
+ {
+ extend: 'csvHtml5',
+ fieldBoundary: "",
+ text: 'Copy keywords',
+ // 'customize': function(data,options){return data.split('\n').join(',');},
+ header: false,
+ exportOptions: {
+ stripNewlines: true,
+ stripHtml: true,
+ decodeEntities: true,
+ columns: 1,
+ // format:{
+ // body: function(html,i){console.log(html);return html}
+ // }
+ }
+ },
+ ],
"columnDefs": [
{
"name": "id",
@@ -574,9 +615,17 @@ $(document).ready(function () {
"name": "search",
"targets": 5,
"visible": false,
+ }, {
+ "name": "domain",
+ "targets": 6,
+ "visible": false,
}],
order: [[ 0, 'desc' ]],
colReorder: {},
stateSave: true
});
});
+
+$.getJSON('https://api.ipify.org?format=json', function (data) {
+ myIp = data.ip;
+});