sajari-website
Advanced tools
Comparing version 0.2.1 to 0.2.2
@@ -8,2 +8,3 @@ var gulp = require('gulp'); | ||
var tape = require('gulp-tape'); | ||
var prettify = require('gulp-jsbeautifier'); | ||
@@ -18,2 +19,8 @@ var tapColorize = require('tap-colorize'); | ||
gulp.task('beautify', function() { | ||
gulp.src('./src/js/*.js') | ||
.pipe(prettify({config: '.jsbeautifyrc', mode: 'VERIFY_AND_WRITE'})) | ||
.pipe(gulp.dest('./src/js/')); | ||
}); | ||
gulp.task('lint', function() { | ||
@@ -20,0 +27,0 @@ gulp.src('./src/js/*.js') |
{ | ||
"name": "sajari-website", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"description": "Website extensions for the Sajari API. Automatically index site content, add user profiles, render search and recommendations, etc.", | ||
@@ -38,2 +38,3 @@ "author": { | ||
"gulp-concat": "^2.3.4", | ||
"gulp-jsbeautifier": "^1.0.1", | ||
"gulp-jshint": "^2.0.0", | ||
@@ -40,0 +41,0 @@ "gulp-jslint": "^0.2.2", |
@@ -20,8 +20,8 @@ /* | ||
if (this.visitorId === undefined) { | ||
this.visitorId = cookie.get('sjID'); | ||
if (this.visitorId === undefined) { | ||
this.visitorId = (new Date().getTime()) + '.' + Math.floor(Math.random() * 1000000); | ||
} | ||
cookie.set('sjID', this.visitorId, 365); | ||
} | ||
this.visitorId = cookie.get('sjID'); | ||
if (this.visitorId === undefined) { | ||
this.visitorId = (new Date().getTime()) + '.' + Math.floor(Math.random() * 1000000); | ||
} | ||
cookie.set('sjID', this.visitorId, 365); | ||
} | ||
} | ||
@@ -38,8 +38,8 @@ | ||
*/ | ||
setVisitorId : function(id) { | ||
if (id !== undefined) { | ||
this.visitorId = id + ''; | ||
cookie.set('sjID', this.visitorId, 365); | ||
} | ||
return this.visitorId; | ||
setVisitorId: function(id) { | ||
if (id !== undefined) { | ||
this.visitorId = id + ''; | ||
cookie.set('sjID', this.visitorId, 365); | ||
} | ||
return this.visitorId; | ||
} | ||
@@ -52,13 +52,13 @@ }; | ||
function getGAID() { | ||
var userId = ''; | ||
var gaUserCookie = cookie.get("_ga"); | ||
if (gaUserCookie !== undefined) { | ||
var cookieValues = gaUserCookie.split('.'); | ||
if (cookieValues.length > 2 ) { | ||
userId = cookieValues[2]; | ||
} | ||
} | ||
return userId; | ||
var userId = ''; | ||
var gaUserCookie = cookie.get("_ga"); | ||
if (gaUserCookie !== undefined) { | ||
var cookieValues = gaUserCookie.split('.'); | ||
if (cookieValues.length > 2) { | ||
userId = cookieValues[2]; | ||
} | ||
} | ||
return userId; | ||
} | ||
module.exports = profile; | ||
module.exports = profile; |
@@ -13,31 +13,31 @@ require("./utils/polyfills"); | ||
var opts = { | ||
cssUrl: 'https://www.sajari.com/css/sj.css', // Default styling if desired | ||
prefix: 'data-sj-', // Elements with Sajari data parameters all use this as a prefix | ||
autoFlush: 100, // Flush the stack array queue automatically X msecs. 0 is no auto-flush | ||
debug: false, // If true, debug information will be logged to the console | ||
company: undefined, | ||
collection: undefined, | ||
cssIncluded: false, // If false, the Sajari CSS will be loaded. This can be overridden by setting to true | ||
index: true, // Whether to index the page or not | ||
indexed: false, // Whether or not the index call has already been sent | ||
scanOnLoad: true, // Scans the DOM and builds a list of nodes with dom.targets related tags | ||
autoQuery: false, // If true, "q" in the URL will automatically trigger a query | ||
autoQueryParam: "q", // If autoQuery is true, this is the search query parameter to look for in the URL | ||
currentQuery: "", // Holds the current query text | ||
searchInProgress: false, // Goes to true when a search is in process | ||
targets: [ | ||
'company', 'collection', 'profile-id', 'noindex', 'noprofile', 'profile-delay', 'conv-type', | ||
'search-query', 'search-query-word', 'search-query-go', 'search-results', 'recent', 'popular', | ||
'related', 'best', 'search-recent', 'search-noresults', 'search-error', 'personalization', 'overlay', | ||
'local' | ||
] | ||
cssUrl: 'https://www.sajari.com/css/sj.css', // Default styling if desired | ||
prefix: 'data-sj-', // Elements with Sajari data parameters all use this as a prefix | ||
autoFlush: 100, // Flush the stack array queue automatically X msecs. 0 is no auto-flush | ||
debug: false, // If true, debug information will be logged to the console | ||
company: undefined, | ||
collection: undefined, | ||
cssIncluded: false, // If false, the Sajari CSS will be loaded. This can be overridden by setting to true | ||
index: true, // Whether to index the page or not | ||
indexed: false, // Whether or not the index call has already been sent | ||
scanOnLoad: true, // Scans the DOM and builds a list of nodes with dom.targets related tags | ||
autoQuery: false, // If true, "q" in the URL will automatically trigger a query | ||
autoQueryParam: "q", // If autoQuery is true, this is the search query parameter to look for in the URL | ||
currentQuery: "", // Holds the current query text | ||
searchInProgress: false, // Goes to true when a search is in process | ||
targets: [ | ||
'company', 'collection', 'profile-id', 'noindex', 'noprofile', 'profile-delay', 'conv-type', | ||
'search-query', 'search-query-word', 'search-query-go', 'search-results', 'recent', 'popular', | ||
'related', 'best', 'search-recent', 'search-noresults', 'search-error', 'personalization', 'overlay', | ||
'local' | ||
] | ||
}; | ||
// Initialize DOM functionality | ||
var dom = new (require("./utils/dom"))(opts); | ||
var dom = new(require("./utils/dom"))(opts); | ||
// Initialize the users profile | ||
var profile = new (require("./profile"))({ | ||
send: true, // Only send profile data if this is true | ||
sent: false, // Switch when the automatic profile is sent | ||
delay: 120000 // Default profile sends if the user browses longer than this time in msecs. | ||
var profile = new(require("./profile"))({ | ||
send: true, // Only send profile data if this is true | ||
sent: false, // Switch when the automatic profile is sent | ||
delay: 120000 // Default profile sends if the user browses longer than this time in msecs. | ||
}); | ||
@@ -47,7 +47,7 @@ | ||
var page = { | ||
Id : undefined | ||
Id: undefined | ||
}; | ||
// function stack queue | ||
var stack = []; | ||
var stack = []; | ||
@@ -58,14 +58,14 @@ /** | ||
function processOptions(options) { | ||
if (isArray(options)) { | ||
for (var i = 0; i < options.length; i++) { | ||
stack.push(options[i]); | ||
} | ||
} else if (typeof options === 'object') { | ||
for (var j in options) { | ||
var opt = (isArray(options[j]) ? options[j].slice() : [options[j]]); | ||
opt.unshift(j); | ||
stack.push(opt); | ||
} | ||
} | ||
flush(); | ||
if (isArray(options)) { | ||
for (var i = 0; i < options.length; i++) { | ||
stack.push(options[i]); | ||
} | ||
} else if (typeof options === 'object') { | ||
for (var j in options) { | ||
var opt = (isArray(options[j]) ? options[j].slice() : [options[j]]); | ||
opt.unshift(j); | ||
stack.push(opt); | ||
} | ||
} | ||
flush(); | ||
} | ||
@@ -77,5 +77,5 @@ | ||
function log(text) { | ||
if (opts.debug) { | ||
console.log(text); | ||
} | ||
if (opts.debug) { | ||
console.log(text); | ||
} | ||
} | ||
@@ -94,5 +94,5 @@ | ||
} | ||
if (opts.autoFlush > 0) { | ||
setTimeout(flush, opts.autoFlush); | ||
} | ||
if (opts.autoFlush > 0) { | ||
setTimeout(flush, opts.autoFlush); | ||
} | ||
} | ||
@@ -105,65 +105,65 @@ | ||
// Clear errors | ||
if (dom.firstNode('search-error') !== undefined) { | ||
dom.firstNode('search-error').style.display = 'none'; | ||
} | ||
// Clear errors | ||
if (dom.firstNode('search-error') !== undefined) { | ||
dom.firstNode('search-error').style.display = 'none'; | ||
} | ||
var res = response.response; | ||
var res = response.response; | ||
// Setup defaults | ||
res.showThumb = false; | ||
res.showDesc = true; | ||
res.showUrl = false; | ||
res.renderSearch = true; | ||
res.formattedMsecs = 0.000; | ||
res.showMeta = []; | ||
// Setup defaults | ||
res.showThumb = false; | ||
res.showDesc = true; | ||
res.showUrl = false; | ||
res.renderSearch = true; | ||
res.formattedMsecs = 0.000; | ||
res.showMeta = []; | ||
// Handle formatting options | ||
var dynAttributes = dom.dynamicAttrs(renderNode); | ||
for (var key in dynAttributes) { | ||
if (dynAttributes.hasOwnProperty(key)) { | ||
if (key == "thumbnail") { | ||
res.showThumb = true; | ||
} | ||
if (key == "hidedesc") { | ||
res.hideDesc = true; | ||
} | ||
if (key == "showmeta") { | ||
res.showMeta = dynAttributes[key].split(/\s*,\s*/); | ||
} | ||
} | ||
} | ||
// Handle formatting options | ||
var dynAttributes = dom.dynamicAttrs(renderNode); | ||
for (var key in dynAttributes) { | ||
if (dynAttributes.hasOwnProperty(key)) { | ||
if (key == "thumbnail") { | ||
res.showThumb = true; | ||
} | ||
if (key == "hidedesc") { | ||
res.hideDesc = true; | ||
} | ||
if (key == "showmeta") { | ||
res.showMeta = dynAttributes[key].split(/\s*,\s*/); | ||
} | ||
} | ||
} | ||
// Timing formatting | ||
if (response.msecs) { | ||
res.formattedMsecs = parseFloat(response.msecs/1000).toFixed(3); | ||
} | ||
// Timing formatting | ||
if (response.msecs) { | ||
res.formattedMsecs = parseFloat(response.msecs / 1000).toFixed(3); | ||
} | ||
// Was the query a fuzzy match or autocomplete? | ||
if (res.fuzzy) { | ||
for(var i in res.fuzzy){ | ||
res.fuzzyStr = res.fuzzy[i]; | ||
break; | ||
} | ||
} | ||
// Was the query a fuzzy match or autocomplete? | ||
if (res.fuzzy) { | ||
for (var i in res.fuzzy) { | ||
res.fuzzyStr = res.fuzzy[i]; | ||
break; | ||
} | ||
} | ||
// Add the renderType so we can differentiate search and recommendations | ||
res.renderType = renderType; | ||
// Add the renderType so we can differentiate search and recommendations | ||
res.renderType = renderType; | ||
// Add tracking information to each result so clicks are handled: | ||
// TODO | ||
// .onmousedown | ||
// this.href='https://www.sajari.com/????/redir?p=???? web token | ||
// Add tracking information to each result so clicks are handled: | ||
// TODO | ||
// .onmousedown | ||
// this.href='https://www.sajari.com/????/redir?p=???? web token | ||
// Render it | ||
renderNode.innerHTML = renderResults(res); | ||
// Render it | ||
renderNode.innerHTML = renderResults(res); | ||
} | ||
function showError(renderNode) { | ||
if (!dom.hasNode('search-results') || !dom.hasNode('search-error')) { | ||
// Put the error message in the results area if it used the overlay or they don't have an error node | ||
renderNode.innerHTML = '<p class="sj-error">Oops! An error occured while searching. Please try again.</p>'; | ||
} else if (dom.firstNode('search-error') !== undefined) { | ||
dom.firstNode('search-error').style.display = 'block'; | ||
} | ||
if (!dom.hasNode('search-results') || !dom.hasNode('search-error')) { | ||
// Put the error message in the results area if it used the overlay or they don't have an error node | ||
renderNode.innerHTML = '<p class="sj-error">Oops! An error occured while searching. Please try again.</p>'; | ||
} else if (dom.firstNode('search-error') !== undefined) { | ||
dom.firstNode('search-error').style.display = 'block'; | ||
} | ||
} | ||
@@ -175,45 +175,45 @@ | ||
function overlay(attrs) { | ||
log(attrs); | ||
log(attrs); | ||
vars = { | ||
themeColor: "blue", | ||
resultsExtra: "" | ||
}; | ||
if (typeof attrs === 'object') { | ||
for (var key in attrs) { | ||
if (attrs.hasOwnProperty(key)) { | ||
// Pass any relevant parameters to the modal results | ||
vars.resultsExtra += " " + opts.prefix + key + "=" + attrs[key]; | ||
vars = { | ||
themeColor: "blue", | ||
resultsExtra: "" | ||
}; | ||
if (typeof attrs === 'object') { | ||
for (var key in attrs) { | ||
if (attrs.hasOwnProperty(key)) { | ||
// Pass any relevant parameters to the modal results | ||
vars.resultsExtra += " " + opts.prefix + key + "=" + attrs[key]; | ||
// If the theme color is different, change it | ||
if (key == "theme") { | ||
vars.themeColor = attrs[key]; | ||
} | ||
} | ||
} | ||
} | ||
// If the theme color is different, change it | ||
if (key == "theme") { | ||
vars.themeColor = attrs[key]; | ||
} | ||
} | ||
} | ||
} | ||
// Render and inject at the end of the DOM | ||
var overlayHTML = renderOverlay(vars); | ||
var div = document.createElement('div'); | ||
div.style.display = 'none'; | ||
div.setAttribute(opts.prefix+'overlay', ''); | ||
div.innerHTML = overlayHTML; | ||
document.body.appendChild(div); | ||
// Render and inject at the end of the DOM | ||
var overlayHTML = renderOverlay(vars); | ||
var div = document.createElement('div'); | ||
div.style.display = 'none'; | ||
div.setAttribute(opts.prefix + 'overlay', ''); | ||
div.innerHTML = overlayHTML; | ||
document.body.appendChild(div); | ||
// Bind close event to the close cross | ||
dom.bind(document.getElementById("sj-o-close"), 'click', function() { | ||
div.style.display = 'none'; | ||
}); | ||
// Bind close event to the close cross | ||
dom.bind(document.getElementById("sj-o-close"), 'click', function() { | ||
div.style.display = 'none'; | ||
}); | ||
// Bind close event to the shaded background | ||
dom.bind(document.getElementById("sj-o-shade"), 'click', function() { | ||
div.style.display = 'none'; | ||
}); | ||
// Bind close event to the shaded background | ||
dom.bind(document.getElementById("sj-o-shade"), 'click', function() { | ||
div.style.display = 'none'; | ||
}); | ||
// Transfer dynamic props | ||
dom.copyDynamicProperties(dom.firstNode('search-query'), dom.lastNode('search-query')); | ||
dom.copyDynamicProperties(dom.firstNode('search-query'), dom.lastNode('search-results')); | ||
// Transfer dynamic props | ||
dom.copyDynamicProperties(dom.firstNode('search-query'), dom.lastNode('search-query')); | ||
dom.copyDynamicProperties(dom.firstNode('search-query'), dom.lastNode('search-results')); | ||
return div; | ||
return div; | ||
} | ||
@@ -226,11 +226,11 @@ | ||
function builtInSearch() { | ||
var node = this, | ||
last = this.value; | ||
var node = this, | ||
last = this.value; | ||
// Propagate dynamic attributes from one set of elements to another | ||
// In this case people tend to configure the search query element, but | ||
// some properties need to enact on the results element. | ||
dom.copyDynamicProperties(dom.firstNode('search-query'), dom.firstNode('search-results')); | ||
// Propagate dynamic attributes from one set of elements to another | ||
// In this case people tend to configure the search query element, but | ||
// some properties need to enact on the results element. | ||
dom.copyDynamicProperties(dom.firstNode('search-query'), dom.firstNode('search-results')); | ||
// If we're already waiting on a search, exit here, no point starting another | ||
// If we're already waiting on a search, exit here, no point starting another | ||
if (opts.searchInProgress) { | ||
@@ -240,35 +240,35 @@ return; | ||
// Show the overlay if there is one | ||
if (dom.hasNode('overlay')) { | ||
log("Launching overlay..."); | ||
dom.firstNode('overlay').style.display = 'block'; | ||
} | ||
// Show the overlay if there is one | ||
if (dom.hasNode('overlay')) { | ||
log("Launching overlay..."); | ||
dom.firstNode('overlay').style.display = 'block'; | ||
} | ||
// Start the search process | ||
// Start the search process | ||
opts.searchInProgress = true; | ||
SJ.Search( | ||
this.value.replace(/(^ *| *$)/, ''), | ||
function (response) { | ||
SJ.Search( | ||
this.value.replace(/(^ *| *$)/, ''), | ||
function(response) { | ||
opts.searchInProgress = false; | ||
showResults(response, dom.resultsNode, "search"); | ||
if (node.value !== last && hasInstantSearch(node)) { | ||
builtInSearch.apply(node); | ||
} | ||
}, | ||
function () { | ||
showResults(response, dom.resultsNode, "search"); | ||
if (node.value !== last && hasInstantSearch(node)) { | ||
builtInSearch.apply(node); | ||
} | ||
}, | ||
function() { | ||
opts.searchInProgress = false; | ||
showError(dom.resultsNode); | ||
}, | ||
dom.dynamicAttrsUri(this) | ||
); | ||
showError(dom.resultsNode); | ||
}, | ||
dom.dynamicAttrsUri(this) | ||
); | ||
// Keep the query global so we don't need to keep searching for it | ||
opts.currentQuery = node.value; | ||
// Keep the query global so we don't need to keep searching for it | ||
opts.currentQuery = node.value; | ||
// Propagate the query to other query elements | ||
dom.eachNode('search-query', function (otherNode) { | ||
if (node !== otherNode) { | ||
otherNode.value = node.value; | ||
} | ||
}); | ||
// Propagate the query to other query elements | ||
dom.eachNode('search-query', function(otherNode) { | ||
if (node !== otherNode) { | ||
otherNode.value = node.value; | ||
} | ||
}); | ||
} | ||
@@ -281,29 +281,29 @@ | ||
// Run the search if they press enter on the input field | ||
dom.bind(node, 'keydown', function(e) { | ||
if (e.keyCode === 13) { | ||
builtInSearch.apply(this); | ||
if (e.preventDefault !== undefined) { | ||
e.preventDefault(); | ||
} | ||
} | ||
}); | ||
// Run the search if they press enter on the input field | ||
dom.bind(node, 'keydown', function(e) { | ||
if (e.keyCode === 13) { | ||
builtInSearch.apply(this); | ||
if (e.preventDefault !== undefined) { | ||
e.preventDefault(); | ||
} | ||
} | ||
}); | ||
// Keep search queries in sync | ||
dom.bind(node, 'change', function () { | ||
dom.eachNode('search-query', function (otherNode) { | ||
if (node !== otherNode) { | ||
otherNode.value = node.value; | ||
} | ||
}); | ||
}); | ||
// Keep search queries in sync | ||
dom.bind(node, 'change', function() { | ||
dom.eachNode('search-query', function(otherNode) { | ||
if (node !== otherNode) { | ||
otherNode.value = node.value; | ||
} | ||
}); | ||
}); | ||
// Auto query if "q" parameter exists in URL | ||
if (opts.autoQuery) { | ||
var auto = url.getURLParameter(opts.autoQueryParam); | ||
if (auto) { | ||
node.value = auto; | ||
builtInSearch.apply(node); | ||
} | ||
} | ||
// Auto query if "q" parameter exists in URL | ||
if (opts.autoQuery) { | ||
var auto = url.getURLParameter(opts.autoQueryParam); | ||
if (auto) { | ||
node.value = auto; | ||
builtInSearch.apply(node); | ||
} | ||
} | ||
@@ -319,3 +319,3 @@ // Install instant search if applicable | ||
return node; | ||
return node; | ||
} | ||
@@ -342,7 +342,7 @@ | ||
function installSearchGo(node, queryInput) { | ||
dom.bind(node, 'click', function(e) { | ||
e.preventDefault ? e.preventDefault() : e.returnValue = false; | ||
builtInSearch.apply(queryInput ? queryInput : dom.firstNode('search-query')); | ||
}); | ||
return node; | ||
dom.bind(node, 'click', function(e) { | ||
e.preventDefault ? e.preventDefault() : e.returnValue = false; | ||
builtInSearch.apply(queryInput ? queryInput : dom.firstNode('search-query')); | ||
}); | ||
return node; | ||
} | ||
@@ -354,26 +354,26 @@ | ||
query.prototype.run = function(success, failure) { | ||
if (this.options.func !== undefined) { | ||
if (this.options.func !== undefined) { | ||
if (this.options.q === undefined) { | ||
this.options.q = ""; | ||
} | ||
if (this.options.q === undefined) { | ||
this.options.q = ""; | ||
} | ||
switch(this.options.func) { | ||
case "search": | ||
SJ.Search(this.options.q, success, failure, this.encode()); | ||
break; | ||
case "best": | ||
SJ.Best(success, failure, this.encode()); | ||
break; | ||
case "popular": | ||
SJ.Popular(success, failure, this.encode()); | ||
break; | ||
case "recent": | ||
SJ.Recent(success, failure, this.encode()); | ||
break; | ||
case "related": | ||
SJ.Related(success, failure, this.encode()); | ||
break; | ||
} | ||
} | ||
switch (this.options.func) { | ||
case "search": | ||
SJ.Search(this.options.q, success, failure, this.encode()); | ||
break; | ||
case "best": | ||
SJ.Best(success, failure, this.encode()); | ||
break; | ||
case "popular": | ||
SJ.Popular(success, failure, this.encode()); | ||
break; | ||
case "recent": | ||
SJ.Recent(success, failure, this.encode()); | ||
break; | ||
case "related": | ||
SJ.Related(success, failure, this.encode()); | ||
break; | ||
} | ||
} | ||
}; | ||
@@ -385,126 +385,126 @@ | ||
var methods = { | ||
/** | ||
* Send free "text" and meta information into the current person's profile | ||
*/ | ||
profile: function(text, meta) { | ||
// Add new meta to the user profile | ||
for (var key in meta) { | ||
profile.meta[key] = meta[key]; | ||
} | ||
log(profile); | ||
/** | ||
* Send free "text" and meta information into the current person's profile | ||
*/ | ||
profile: function(text, meta) { | ||
// Add new meta to the user profile | ||
for (var key in meta) { | ||
profile.meta[key] = meta[key]; | ||
} | ||
log(profile); | ||
var metaToSend = {}; | ||
var metaToSend = {}; | ||
// Merge in profile meta | ||
for (key in profile.meta) { | ||
metaToSend["meta["+key+"]"] = profile.meta[key]; | ||
} | ||
metaToSend['profile.text'] = text + ''; | ||
metaToSend['p.ga'] = profile.gaId; | ||
metaToSend['p.id'] = profile.visitorId; | ||
// Merge in profile meta | ||
for (key in profile.meta) { | ||
metaToSend["meta[" + key + "]"] = profile.meta[key]; | ||
} | ||
metaToSend['profile.text'] = text + ''; | ||
metaToSend['p.ga'] = profile.gaId; | ||
metaToSend['p.id'] = profile.visitorId; | ||
api.pixel(metaToSend, '/stats/profile'); | ||
}, | ||
api.pixel(metaToSend, '/stats/profile'); | ||
}, | ||
// Set a new visitor ID | ||
profileid: function(id) { | ||
profile.setVisitorId(id); | ||
}, | ||
// Set a new visitor ID | ||
profileid: function(id) { | ||
profile.setVisitorId(id); | ||
}, | ||
// Send a conversion with the given type and value | ||
conversion: function(type, value) { | ||
if (value === null || value === undefined) { | ||
value = 0; | ||
} | ||
api.pixel({ | ||
'cv.t': type + '', | ||
'cv.v': value + '', | ||
'p.ga': profile.gaId, | ||
'p.id': profile.visitorId | ||
}, '/stats/conversion'); | ||
}, | ||
// Send a conversion with the given type and value | ||
conversion: function(type, value) { | ||
if (value === null || value === undefined) { | ||
value = 0; | ||
} | ||
api.pixel({ | ||
'cv.t': type + '', | ||
'cv.v': value + '', | ||
'p.ga': profile.gaId, | ||
'p.id': profile.visitorId | ||
}, '/stats/conversion'); | ||
}, | ||
// Track a click through for a given "qid" | ||
click: function(qid, slot, injected) { | ||
if (injected === undefined) { | ||
injected = ''; | ||
} | ||
SJ.SendClick(qid, slot, injected, undefined); | ||
// Track a click through for a given "qid" | ||
click: function(qid, slot, injected) { | ||
if (injected === undefined) { | ||
injected = ''; | ||
} | ||
SJ.SendClick(qid, slot, injected, undefined); | ||
// Reset the query sequence | ||
api.resetSequence(); | ||
log("reset query sequence..."); | ||
}, | ||
// Reset the query sequence | ||
api.resetSequence(); | ||
log("reset query sequence..."); | ||
}, | ||
// Index the page | ||
index: function() { | ||
if (!opts.index) { | ||
log('Noindex flag is set'); | ||
return; | ||
} | ||
if (opts.indexed) { | ||
log('Already indexed'); | ||
return; | ||
} | ||
opts.indexed = true; | ||
data = { | ||
'ec.ti': document.title, | ||
'ec.de': dom.getMeta("description"), | ||
'ec.ke': dom.getMeta("keywords"), | ||
'e.id': document.URL, | ||
'cc.co': opts.company, | ||
'cc.pr': opts.collection, | ||
'p.ga': profile.gaId, | ||
'p.id': profile.visitorId | ||
}; | ||
api.pixel(data, ''); | ||
log(data); | ||
}, | ||
// Index the page | ||
index: function() { | ||
if (!opts.index) { | ||
log('Noindex flag is set'); | ||
return; | ||
} | ||
if (opts.indexed) { | ||
log('Already indexed'); | ||
return; | ||
} | ||
opts.indexed = true; | ||
data = { | ||
'ec.ti': document.title, | ||
'ec.de': dom.getMeta("description"), | ||
'ec.ke': dom.getMeta("keywords"), | ||
'e.id': document.URL, | ||
'cc.co': opts.company, | ||
'cc.pr': opts.collection, | ||
'p.ga': profile.gaId, | ||
'p.id': profile.visitorId | ||
}; | ||
api.pixel(data, ''); | ||
log(data); | ||
}, | ||
// Prevent page indexing | ||
noindex: function() { | ||
opts.index = false; | ||
}, | ||
// Prevent page indexing | ||
noindex: function() { | ||
opts.index = false; | ||
}, | ||
// Automatic query from url support | ||
urlquery: function() { | ||
opts.autoQuery = true; | ||
}, | ||
// Automatic query from url support | ||
urlquery: function() { | ||
opts.autoQuery = true; | ||
}, | ||
// Prevent CSS from loading | ||
nocss: function() { | ||
opts.cssIncluded = true; | ||
}, | ||
// Prevent CSS from loading | ||
nocss: function() { | ||
opts.cssIncluded = true; | ||
}, | ||
// Prevent profiling | ||
noprofile: function() { | ||
profile.send = false; | ||
}, | ||
// Prevent profiling | ||
noprofile: function() { | ||
profile.send = false; | ||
}, | ||
// Set the collection | ||
collection: function(newCollection) { | ||
opts.collection = newCollection + ''; | ||
}, | ||
// Set the collection | ||
collection: function(newCollection) { | ||
opts.collection = newCollection + ''; | ||
}, | ||
// Set the company | ||
company: function(newCompany) { | ||
opts.company = newCompany + ''; | ||
}, | ||
// Set the company | ||
company: function(newCompany) { | ||
opts.company = newCompany + ''; | ||
}, | ||
// Don't scan the page when the script loads | ||
// Use if performance is a problem or you want to call SJ.Scan() later | ||
'no-scan': function() { | ||
opts.scanOnLoad = false; | ||
}, | ||
// Don't scan the page when the script loads | ||
// Use if performance is a problem or you want to call SJ.Scan() later | ||
'no-scan': function() { | ||
opts.scanOnLoad = false; | ||
}, | ||
// Turn debugging on and off | ||
debug: function(enabled) { | ||
opts.debug = (enabled ? true : false); | ||
}, | ||
// Turn debugging on and off | ||
debug: function(enabled) { | ||
opts.debug = (enabled ? true : false); | ||
}, | ||
// Open an empty overlay. For use with applications that do not have a search box, but trigger | ||
// a search with a button click or similar | ||
overlay: function(attrs) { | ||
overlay(attrs); | ||
} | ||
// Open an empty overlay. For use with applications that do not have a search box, but trigger | ||
// a search with a button click or similar | ||
overlay: function(attrs) { | ||
overlay(attrs); | ||
} | ||
@@ -515,3 +515,3 @@ }; | ||
// The SJ object is exported | ||
var sj = function (options) { | ||
var sj = function(options) { | ||
processOptions(options); | ||
@@ -526,3 +526,3 @@ return this; | ||
sj.prototype = { | ||
Search : function(keywords, success, failure, dynamicArgs) { | ||
Search: function(keywords, success, failure, dynamicArgs) { | ||
@@ -541,30 +541,30 @@ var data = { | ||
} | ||
if (dom.hasNode('local')) { | ||
data.local = 'true'; | ||
} | ||
if (dom.hasNode('local')) { | ||
data.local = 'true'; | ||
} | ||
api.search(api.mergeArgs(data, dynamicArgs), success, failure); | ||
api.search(api.mergeArgs(data, dynamicArgs), success, failure); | ||
}, | ||
Popular : function(success, failure, dynamicArgs) { | ||
Popular: function(success, failure, dynamicArgs) { | ||
var uri = 'popular'; | ||
if (dynamicArgs !== undefined) { | ||
uri += '?'+dynamicArgs; | ||
uri += '?' + dynamicArgs; | ||
} | ||
api.popular(api.mergeArgs({}, dynamicArgs), success, failure); | ||
api.popular(api.mergeArgs({}, dynamicArgs), success, failure); | ||
}, | ||
Recent : function(success, failure, dynamicArgs) { | ||
Recent: function(success, failure, dynamicArgs) { | ||
var uri = 'recent'; | ||
if (dynamicArgs !== undefined) { | ||
uri += '?'+dynamicArgs; | ||
uri += '?' + dynamicArgs; | ||
} | ||
api.recent(api.mergeArgs({}, dynamicArgs), success, failure); | ||
api.recent(api.mergeArgs({}, dynamicArgs), success, failure); | ||
}, | ||
Related : function(success, failure, dynamicArgs) { | ||
Related: function(success, failure, dynamicArgs) { | ||
var data = { | ||
@@ -575,70 +575,72 @@ 'url': location.href, | ||
}; | ||
api.related(api.mergeArgs(data, dynamicArgs), success, failure); | ||
api.related(api.mergeArgs(data, dynamicArgs), success, failure); | ||
}, | ||
Autocomplete : function(keywords, success, failure) { | ||
var data = { | ||
'q': keywords | ||
}; | ||
api.autocomplete(data, success, failure); | ||
Autocomplete: function(keywords, success, failure) { | ||
var data = { | ||
'q': keywords | ||
}; | ||
api.autocomplete(data, success, failure); | ||
}, | ||
Best : function(success, failure, dynamicArgs) { | ||
Best: function(success, failure, dynamicArgs) { | ||
var data = { | ||
'p.id': profile.visitorId | ||
}; | ||
api.best(api.mergeArgs(data, dynamicArgs), success, failure); | ||
}, | ||
/* USED FOR A JQIERY PLUGIN, MIGHT WANT TO DITCH??? | ||
__installInput : function (node) { | ||
installSearchQuery(node); | ||
if (domNodes['search-query'] === undefined) { | ||
domNodes['search-query'] = []; | ||
} | ||
domNodes['search-query'].push(node); | ||
api.best(api.mergeArgs(data, dynamicArgs), success, failure); | ||
}, | ||
__installGo : function (node) { | ||
installSearchGo(node) | ||
}, | ||
*/ | ||
/* USED FOR A JQIERY PLUGIN, MIGHT WANT TO DITCH??? | ||
__installInput : function (node) { | ||
installSearchQuery(node); | ||
if (domNodes['search-query'] === undefined) { | ||
domNodes['search-query'] = []; | ||
} | ||
domNodes['search-query'].push(node); | ||
}, | ||
Install : function (options) { | ||
var options = options || {}; | ||
__installGo : function (node) { | ||
installSearchGo(node) | ||
}, | ||
*/ | ||
// Reset and re-scan our components in the DOM | ||
// Because we are scanning, we need to reset our current shadow DOM | ||
dom.nodes = {}; // We reset externally as the scanShim function is recursive | ||
dom.scanShim(document.body); | ||
Install: function(options) { | ||
var options = options || {}; | ||
// Reset and re-scan our components in the DOM | ||
// Because we are scanning, we need to reset our current shadow DOM | ||
dom.nodes = {}; // We reset externally as the scanShim function is recursive | ||
dom.scanShim(document.body); | ||
processOptions(options); | ||
// DOM elements can be used to specify a company and collection | ||
// DOM elements can be used to specify a company and collection | ||
opts.company = dom.firstNodeVal('company', opts.company); | ||
opts.collection = dom.firstNodeVal('collection', opts.collection); | ||
if (opts.company === undefined || opts.collection === undefined) { | ||
log("company and collection cannot be undefined..."); | ||
log("company and collection cannot be undefined..."); | ||
return; | ||
} | ||
// We have a company and a domain so we can install the API | ||
api = new API(opts.company, opts.collection, { jsonp : true}); | ||
// We have a company and a domain so we can install the API | ||
api = new API(opts.company, opts.collection, { | ||
jsonp: true | ||
}); | ||
// Find and Install the Search Results DIV. If it does not exist, create an overlay block to handle results instead | ||
if (!dom.hasNode('search-results')) { | ||
// No results node. Need an overlay installed | ||
dom.scanShim(overlay(dom.dynamicAttrs(this))); | ||
} | ||
// Find and Install the Search Results DIV. If it does not exist, create an overlay block to handle results instead | ||
if (!dom.hasNode('search-results')) { | ||
// No results node. Need an overlay installed | ||
dom.scanShim(overlay(dom.dynamicAttrs(this))); | ||
} | ||
dom.resultsNode = dom.firstNode('search-results'); | ||
dom.resultsNode = dom.firstNode('search-results'); | ||
// Grab page meta and add it to the page object | ||
// TODO | ||
// log(dom.dynamicAttrs("meta")); | ||
// Grab page meta and add it to the page object | ||
// TODO | ||
// log(dom.dynamicAttrs("meta")); | ||
@@ -648,22 +650,22 @@ | ||
if (dom.hasNode('noprofile')) { | ||
profile.send = false; | ||
} | ||
profile.send = false; | ||
} | ||
// Set up the profiling functions if allowed | ||
if (!profile.send) { | ||
log(profile); | ||
// Send the document title as profile text | ||
if (!profile.sent) { | ||
setTimeout(function() { | ||
stack.push(['profile', document.title]); | ||
flush(); | ||
profile.sent = true; | ||
}, dom.firstNodeVal('profile-delay', profile.delay)); | ||
} | ||
// Set up the profiling functions if allowed | ||
if (!profile.send) { | ||
log(profile); | ||
// Send the document title as profile text | ||
if (!profile.sent) { | ||
setTimeout(function() { | ||
stack.push(['profile', document.title]); | ||
flush(); | ||
profile.sent = true; | ||
}, dom.firstNodeVal('profile-delay', profile.delay)); | ||
} | ||
// Add click handlers to anchor tags to profile. This means | ||
// link anchor text is used to help profile what users are | ||
// interested in. | ||
// link anchor text is used to help profile what users are | ||
// interested in. | ||
var a = document.getElementsByTagName('a'); | ||
@@ -692,24 +694,24 @@ for (var i = 0; i < a.length; i++) { | ||
// Send click throughs. We push onto the stack as the API is still initializing | ||
// TODO - Remove once click through URL tracking is added. | ||
// TODO - Remove once click through URL tracking is added. | ||
var qid = url.getURLParameter("q.id"); | ||
if (qid) { | ||
stack.push(['click', qid, url.getURLParameter("q.sl"), url.getURLParameter("q.in")]); | ||
} | ||
} | ||
// Flush our stack in case settings impact the install of components | ||
// Flush our stack in case settings impact the install of components | ||
flush(); | ||
// If required, we need to include Sajari CSS into the DOM | ||
if (!opts.cssIncluded) { | ||
dom.importCss(opts.cssUrl); | ||
} | ||
// If required, we need to include Sajari CSS into the DOM | ||
if (!opts.cssIncluded) { | ||
dom.importCss(opts.cssUrl); | ||
} | ||
// SETUP RECOMMENDATIONS | ||
// SETUP RECOMMENDATIONS | ||
// Popular | ||
if (dom.hasNode('popular')) { | ||
SJ.Popular( | ||
function (response) { | ||
function(response) { | ||
showResults(response, dom.firstNode('popular'), "popular"); | ||
}, | ||
function () {}, | ||
function() {}, | ||
dom.dynamicAttrsUri(dom.firstNode('popular')) | ||
@@ -722,6 +724,6 @@ ); | ||
SJ.Recent( | ||
function (response) { | ||
function(response) { | ||
showResults(response, dom.firstNode('recent'), "recent"); | ||
}, | ||
function () {}, | ||
function() {}, | ||
dom.dynamicAttrsUri(dom.firstNode('recent')) | ||
@@ -734,6 +736,6 @@ ); | ||
SJ.Related( | ||
function (response) { | ||
function(response) { | ||
showResults(response, dom.firstNode('related'), "related"); | ||
}, | ||
function () {}, | ||
function() {}, | ||
dom.dynamicAttrsUri(dom.firstNode('related')) | ||
@@ -746,6 +748,6 @@ ); | ||
SJ.Best( | ||
function (response) { | ||
function(response) { | ||
showResults(response, dom.firstNode('best'), "best"); | ||
}, | ||
function () {}, | ||
function() {}, | ||
dom.dynamicAttrsUri(dom.firstNode('best')) | ||
@@ -755,26 +757,26 @@ ); | ||
// SETUP SEARCH | ||
// SETUP SEARCH | ||
// Setup the search query process based on the options available. | ||
if (!dom.hasNode('search-query')) { | ||
return; | ||
} | ||
return; | ||
} | ||
// We have search query nodes, so install event handlers accordingly | ||
dom.eachNode('search-query', function (node) { | ||
// We have search query nodes, so install event handlers accordingly | ||
dom.eachNode('search-query', function(node) { | ||
installSearchQuery(node); | ||
}); | ||
// Check for a search button, if exists, bind our search func to it | ||
// Check for a search button, if exists, bind our search func to it | ||
if (dom.hasNode('search-query-go')) { | ||
dom.eachNode('search-query-go', function (node) { | ||
dom.eachNode('search-query-go', function(node) { | ||
installSearchGo(node); | ||
}); | ||
} | ||
} | ||
// There is not a search button, so we need other events to | ||
// to trigger searches accordingly | ||
if (dom.hasNode('search-results')) { | ||
// There is not a search button, so we need other events to | ||
// to trigger searches accordingly | ||
if (dom.hasNode('search-results')) { | ||
// If there isn't a go button and they have defined a place for results | ||
dom.eachNode('search-query', function (node) { | ||
dom.eachNode('search-query', function(node) { | ||
@@ -799,21 +801,21 @@ // Run the search if they put in a space character | ||
*/ | ||
push : function (value) { | ||
push: function(value) { | ||
stack.push(value); | ||
}, | ||
SendClick : function(qid, slot, injected, node) { | ||
var u = ""; | ||
if (node !== undefined) { | ||
u = node.getAttribute('href'); // This is a mousedown event | ||
} else { | ||
u = window.location.href; // No node, this must be the destination page | ||
} | ||
api.pixel({ | ||
'p.ga':profile.gaId, | ||
'p.id':profile.visitorId, | ||
'q.id':qid, | ||
'q.sl':slot, | ||
'q.in':injected, | ||
'q.de':u | ||
}, '/stats/click'); | ||
SendClick: function(qid, slot, injected, node) { | ||
var u = ""; | ||
if (node !== undefined) { | ||
u = node.getAttribute('href'); // This is a mousedown event | ||
} else { | ||
u = window.location.href; // No node, this must be the destination page | ||
} | ||
api.pixel({ | ||
'p.ga': profile.gaId, | ||
'p.id': profile.visitorId, | ||
'q.id': qid, | ||
'q.sl': slot, | ||
'q.in': injected, | ||
'q.de': u | ||
}, '/stats/click'); | ||
}, | ||
@@ -824,9 +826,11 @@ | ||
*/ | ||
Query : function (options) { | ||
Query: function(options) { | ||
if (typeof options === 'string') { | ||
options = { q : options }; | ||
options = { | ||
q: options | ||
}; | ||
} else if (typeof options !== 'object') { | ||
options = {}; | ||
} | ||
options.func = "search"; | ||
options.func = "search"; | ||
return (new query(options)); | ||
@@ -838,9 +842,11 @@ }, | ||
*/ | ||
Recommend : function (options) { | ||
if (typeof options === 'string') { | ||
options = { func : options }; | ||
} else if (typeof options !== 'object') { | ||
options = {}; | ||
} | ||
return (new query(options)); | ||
Recommend: function(options) { | ||
if (typeof options === 'string') { | ||
options = { | ||
func: options | ||
}; | ||
} else if (typeof options !== 'object') { | ||
options = {}; | ||
} | ||
return (new query(options)); | ||
} | ||
@@ -852,4 +858,4 @@ }; | ||
(function() { | ||
loaded(window, function(){ | ||
/** | ||
loaded(window, function() { | ||
/** | ||
* Import existing _sj global variable if it exists | ||
@@ -862,10 +868,9 @@ */ | ||
if (opts.scanOnLoad) { | ||
SJ.Install(); | ||
} | ||
flush(); | ||
}); | ||
if (opts.scanOnLoad) { | ||
SJ.Install(); | ||
} | ||
flush(); | ||
}); | ||
})(); | ||
module.exports = SJ; | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
16
1247
46465
17