Skip to content

Instantly share code, notes, and snippets.

@asacarter
Last active December 9, 2015 17:01
Show Gist options
  • Save asacarter/d995834c27bf354738af to your computer and use it in GitHub Desktop.
Save asacarter/d995834c27bf354738af to your computer and use it in GitHub Desktop.
Recently jQuery Plugin
// timer function that loops through an array within a given interval
$.timer = function (list, callback, time/*, onFinish, index*/) {
var onFinish = arguments.length > 3 ? arguments[3] : void 0,
index = arguments.length > 4 ? arguments[4] : 0;
if (index < list.length) {
callback.call(this, index, list[index]);
list.__timed = setTimeout(function() {
$.timer(list, callback, time, onFinish, ++index);
}, time);
}
else if (onFinish) {
onFinish.call(this);
}
return {
cancel: function() {
if (list.__timed !== void 0) {
clearTimeout(list.__timed);
delete list.__timed;
}
},
pause: function() {
clearTimeout(list.__timed);
},
resume: function() {
list.__timed = setTimeout(function() {
$.timer(list, callback, time, onFinish, ++index);
}, time);
}
};
};
// template function that replaces strings from map
$.tmpl = function(str, obj) {
do {
var beforeReplace = str;
str = str.replace(/{{([^}]+)}}/g, function(wholeMatch, key) {
var substitution = obj[$.trim(key)];
return (substitution === undefined ? wholeMatch : substitution);
});
var afterReplace = str !== beforeReplace;
} while (afterReplace);
return str;
};
/**
* jQuery.browser.mobile (http://detectmobilebrowser.com/)
*
* jQuery.browser.mobile will be true if the browser is a mobile device
*
**/
(function(a){(jQuery.browser=jQuery.browser||{}).mobile=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera);
/*
* recentlyApp
*
* TODO:
* disable specific pages
* log requests
* CSS animations where available
*
*/
;(function($, window, document, undefined) {
var recently = function(options) {
var recentlyApp = this,
version = 1.00,
defaults = {
shop: 'order-test-store.myshopify.com', // Shopify.shop,
element: '#recently-notification',
active: true,
mobileActive: true,
loop: false,
pause: true,
close: true,
orderLimit: 0,
orderTimeLimit: 0,
interval: 3000,
delay: 4000,
placement: 'bottom-left',
direction: 'veritical',
image: 'left',
size: 'large',
animationDuration: 1200,
message: '{{first_name}} in {{city}}, {{country}} purchased a <a href="{{product_url}}">{{{product}}}</a>{{purchased}}'
},
settings = $.extend(defaults, options || {});
this.init = function() {
recentlyApp.isMobile = $.browser.mobile;
// check if active
if (settings.active == false) return;
// check if mobile and mobile active
if (recentlyApp.isMobile == true && settings.mobileActive == false) return;
var shopHash = recentlyApp.sha1(settings.shop),
v = Math.floor(Math.random() * (10000 - 1)) + 1;
// add the style sheet to header
$('<link type="text/css" rel="stylesheet" href="//recently.appifiny.co.uk/store/' + shopHash + '.css?v=' + v + '">').appendTo('head');
// add the notification container to body
$('<div id="' + settings.element.replace('#', '') + '"/>')
.addClass(settings.placement)
.addClass(settings.direction)
.addClass(settings.image)
.addClass(settings.size)
.appendTo('body');
if (recentlyApp.isMobile == true) {
$(settings.element).addClass('mobile');
}
// get the recent orders
var recentOrders = $.getJSON('//recently.appifiny.co.uk/store/' + shopHash + '.json');
recentOrders.done(function(orders) {
if (settings.orderLimit > 0) {
var orders = orders.filter(function (el) {
now = new Date();
ts = new Date(el.created * 1000);
var delta = now.getTime() - ts.getTime();
delta = Math.floor(delta / 1000);
return delta <= settings.orderLimit;
});
}
recentlyApp.orders = orders;
// get start index
var index = localStorage.getItem('recently-index');
if (index === null) {
recentlyApp.startIndex = 0;
} else {
nextIndex = parseInt(index) + 1;
if (nextIndex >= recentlyApp.orders.length) {
recentlyApp.startIndex = 0;
} else {
recentlyApp.startIndex = nextIndex;
}
}
// check style is loaded
setTimeout(function() {
if ($(settings.element).css('position') == 'fixed') {
recentlyApp.start();
}
}, 100);
});
};
this.start = function() {
if (recentlyApp.orders.length) {
recentlyApp.timer = $.timer(recentlyApp.orders, function(index, order) {
localStorage.setItem('recently-index', index);
console.log(index);
recentlyApp.displayNotification(order);
},
settings.interval + settings.delay + (settings.animationDuration * 2),
settings.loop ? recentlyApp.start : void 0,
recentlyApp.startIndex);
}
};
this.stop = function() {
recentlyApp.timer.cancel();
};
this.pause = function() {
clearTimeout(recentlyApp.currentNotification);
recentlyApp.timer.pause();
};
this.resume = function() {
recentlyApp.currentNotification = setTimeout(function() {
settings.direction == 'horizontal' ? recentlyApp.hideHorizontal() : recentlyApp.hideVertical();
}, settings.delay);
recentlyApp.timer.resume();
};
this.displayNotification = function(order) {
var messageData = {
first_name: order.customer_first_name,
city: order.city,
state: order.province,
country: order.country,
product: order.product_title,
url: '//' + settings.shop + '/products/' + order.url,
purchased: recentlyApp.timeSince(order.created)
};
var message = $.tmpl(settings.message, messageData);
// add the data to the element
var tpl = '<div class="ra-img"><a href="//' + settings.shop + '/products/' + order.url + '"';
if (order.image) {
tpl += ' style="background-image: url(' + order.image + ');"';
}
tpl += '></a></div>';
tpl += '<div class="ra-content"><div class="ra-message">' + message + '</div>';
now = new Date();
ts = new Date(order.created * 1000);
var delta = now.getTime() - ts.getTime();
delta = Math.floor(delta / 1000);
if (settings.orderTimeLimit == 0 || delta <= settings.orderTimeLimit) {
tpl += '<div class="ra-time">About ' + messageData.purchased + ' ago</div>';
}
if (settings.close == true) {
tpl += '<div class="ra-close"></div>';
}
tpl += '</div>';
$(settings.element).html(tpl);
this.show();
settings.direction == 'horizontal' ? recentlyApp.hideHorizontal() : recentlyApp.hideVertical();
};
this.show = function() {
if (recentlyApp.isMobile == true) {
placement = { bottom: '0px' }
} else {
switch (settings.placement) {
case 'top-right':
placement = { right: '20px', top: '20px' }
break;
case 'top-left':
placement = { left: '20px', top: '20px' }
break;
case 'bottom-right':
placement = { right: '20px', bottom: '20px' }
break;
case 'bottom-left':
default:
placement = { left: '20px', bottom: '20px' }
break;
}
}
$(settings.element).animate(placement, settings.animationDuration, 'linear').delay(settings.delay);
};
this.hideVertical = function() {
if (recentlyApp.isMobile == true) {
placement = { bottom: '-100%' }
} else {
switch (settings.placement) {
case 'top-right':
placement = { right: '20px', top: '-100%' }
break;
case 'top-left':
placement = { left: '20px', top: '-100%' }
break;
case 'bottom-right':
placement = { right: '20px', bottom: '-100%' }
break;
case 'bottom-left':
default:
placement = { left: '20px', bottom: '-100%' }
break;
}
}
$(settings.element).animate(placement, settings.animationDuration, 'linear').delay(settings.interval);
};
this.hideHorizontal = function() {
if (recentlyApp.isMobile == true) {
placement = { bottom: '-100%' }
} else {
switch (settings.placement) {
case 'top-right':
placement = { right: '-100%', top: '20px' }
break;
case 'top-left':
placement = { left: '-100%', top: '20px' }
break;
case 'bottom-right':
placement = { right: '-100%', bottom: '20px' }
break;
case 'bottom-left':
default:
placement = { left: '-100%', bottom: '20px' }
break;
}
}
$(settings.element).animate(placement, settings.animationDuration, 'linear').delay(settings.interval);
};
this.timeSince = function(ts) {
now = new Date();
ts = new Date(ts * 1000);
var ps, pm, ph, pd, min, hou, sec, days,
delta = now.getTime() - ts.getTime();
delta = Math.floor(delta / 1000);
if (delta <= 59) {
ps = (delta > 1) ? 's': '';
return 'a minute';
}
if (delta >= 60 && delta <= 3599) {
min = Math.floor(delta / 60);
pm = (min > 1) ? 's': '';
return min + ' minute' + pm;
}
if (delta >= 3600 && delta <= 86399) {
hours = Math.floor(delta / 3600);
min = Math.floor((delta - (hours * 3600)) / 60);
ph = (hours > 1) ? 's' : '';
pm = (min > 1) ? 's' : '';
time = hours + ' hour' + ph;
if (min > 0) {
time += ' ' + min + ' minute' + pm;
}
return time;
}
if (delta >= 86400 && delta <= 604799) {
days = Math.floor(delta / 86400);
hours = Math.floor((delta - (days * 86400)) / 60 / 60);
pd = (days > 1) ? 's' : '';
ph = (hours > 1) ? 's' : '';
time = days + ' day' + pd;
if (hours > 0) {
time += ' ' + hours + ' hour' + ph;
}
return time;
}
if (delta >= 604800) {
weeks = Math.floor(delta / 604800);
days = Math.floor((delta - (weeks * 604800)) / 60 / 60 / 60);
pw = (weeks > 1) ? 's' : '';
pd = (days > 1) ? 's' : '';
time = weeks + ' week' + pw;
if (days > 0) {
time += ' ' + days + ' day' + pd;
}
return time;
}
};
this.sha1 = function(str) {
var rotate_left = function(n, s) {
var t4 = (n << s) | (n >>> (32 - s));
return t4;
};
var cvt_hex = function(val) {
var str = '';
var i;
var v;
for (i = 7; i >= 0; i--) {
v = (val >>> (i * 4)) & 0x0f;
str += v.toString(16);
}
return str;
};
var blockstart;
var i, j;
var W = new Array(80);
var H0 = 0x67452301;
var H1 = 0xEFCDAB89;
var H2 = 0x98BADCFE;
var H3 = 0x10325476;
var H4 = 0xC3D2E1F0;
var A, B, C, D, E;
var temp;
str = unescape(encodeURIComponent(str));
var str_len = str.length;
var word_array = [];
for (i = 0; i < str_len - 3; i += 4) {
j = str.charCodeAt(i) << 24 | str.charCodeAt(i + 1) << 16 | str.charCodeAt(i + 2) << 8 | str.charCodeAt(i + 3);
word_array.push(j);
}
switch (str_len % 4) {
case 0:
i = 0x080000000;
break;
case 1:
i = str.charCodeAt(str_len - 1) << 24 | 0x0800000;
break;
case 2:
i = str.charCodeAt(str_len - 2) << 24 | str.charCodeAt(str_len - 1) << 16 | 0x08000;
break;
case 3:
i = str.charCodeAt(str_len - 3) << 24 | str.charCodeAt(str_len - 2) << 16 | str.charCodeAt(str_len - 1) <<
8 | 0x80;
break;
}
word_array.push(i);
while ((word_array.length % 16) != 14) {
word_array.push(0);
}
word_array.push(str_len >>> 29);
word_array.push((str_len << 3) & 0x0ffffffff);
for (blockstart = 0; blockstart < word_array.length; blockstart += 16) {
for (i = 0; i < 16; i++) {
W[i] = word_array[blockstart + i];
}
for (i = 16; i <= 79; i++) {
W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
}
A = H0;
B = H1;
C = H2;
D = H3;
E = H4;
for (i = 0; i <= 19; i++) {
temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
for (i = 20; i <= 39; i++) {
temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
for (i = 40; i <= 59; i++) {
temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
for (i = 60; i <= 79; i++) {
temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
H0 = (H0 + A) & 0x0ffffffff;
H1 = (H1 + B) & 0x0ffffffff;
H2 = (H2 + C) & 0x0ffffffff;
H3 = (H3 + D) & 0x0ffffffff;
H4 = (H4 + E) & 0x0ffffffff;
}
temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
return temp.toLowerCase();
};
$('body').on('click', settings.element + ' .ra-close', function() {
$(settings.element).remove();
recentlyApp.stop();
});
$('body').on('mouseover', settings.element, function() {
if (settings.pause == true) {
recentlyApp.pause();
}
});
$('body').on('mouseout', settings.element, function() {
recentlyApp.resume();
});
this.init();
};
$.recentlyApp = function( options ) {
return recently(options);
};
})(jQuery, window, document);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment