diff --git a/samples/chat/css/style.css b/samples/chat/css/style.css
index 77d0b5b93..e8e0c9e83 100644
--- a/samples/chat/css/style.css
+++ b/samples/chat/css/style.css
@@ -120,11 +120,12 @@ input[type=file]#load-img {
position: absolute;
left: 16px;
bottom: 0px;
- width: 10%;
height: 34px;
opacity: 0;
cursor: pointer;
overflow: hidden;
+ display: none;
+
}
#progress {
@@ -178,15 +179,47 @@ input[type=file]:focus {
border-radius: 0px;
}
-#attach_btn.btn {
- border-radius: 0px;
- width: 10%;
+.icon-photo {
+ background-image: url('./../images/photo-btn.png');
+ background-repeat: no-repeat;
+ background-size: 24px 24px;
+ background-position: 0 0;
+ display: block;
+ opacity: 0.7;
+ height: 24px;
+ width: 24px;
+}
+
+.icon-sticker {
+ background-image: url('./../images/sticker-btn.png');
+ background-repeat: no-repeat;
+ background-size: 48px 24px;
+ background-position: 0 0;
+ display: block;
+ opacity: 0.7;
+ height: 24px;
+ width: 24px;
+}
+
+.icon-sticker.active {
+ background-position: -24px 0;
+ height: 24px;
+ width: 24px;
+}
+
+#attach_btn.btn,
+#stickers_btn.btn {
+ background: transparent !important;
+ border-radius: 0;
+ margin-right: 10px;
+ padding: 4px;
+ outline: none !important;
}
#message_text {
display: inline-block;
border-radius: 0px;
- width: 78.7%;
+ width: 100%;
box-shadow: none;
}
@@ -197,7 +230,7 @@ input[type=file]:focus {
#send_btn.btn {
border-radius: 0px;
- width: 10%
+ margin-left: 10px;
}
#all_occupants{
@@ -327,3 +360,25 @@ a.pull_push.active {
top: 30px;
display: none;
}
+
+.emoji {
+ height: 1.5em;
+ margin: 0 .2em;
+ width: 1.5em;
+}
+
+.sp-modal-overlay {
+ z-index: 1000000;
+}
+
+.sp-modal {
+ z-index: 1000005;
+}
+
+.visibility_hidden{
+ visibility: hidden;
+}
+
+iframe::-webkit-scrollbar {
+ width: 0;
+}
\ No newline at end of file
diff --git a/samples/chat/images/photo-btn.png b/samples/chat/images/photo-btn.png
new file mode 100644
index 000000000..85d97f0ad
Binary files /dev/null and b/samples/chat/images/photo-btn.png differ
diff --git a/samples/chat/images/sticker-btn.png b/samples/chat/images/sticker-btn.png
new file mode 100644
index 000000000..1019bd64a
Binary files /dev/null and b/samples/chat/images/sticker-btn.png differ
diff --git a/samples/chat/index.html b/samples/chat/index.html
index a90d03aa2..08f507fbf 100755
--- a/samples/chat/index.html
+++ b/samples/chat/index.html
@@ -6,6 +6,7 @@
QuickBlox JavaScript Chat code sample
+
@@ -25,7 +26,7 @@
Create dialog
Dialog info
- View source on GitHub
@@ -56,12 +57,27 @@
@@ -148,9 +164,11 @@
+
+
diff --git a/samples/chat/js/config.js b/samples/chat/js/config.js
index 5220b2318..1d8c5148e 100644
--- a/samples/chat/js/config.js
+++ b/samples/chat/js/config.js
@@ -11,6 +11,20 @@ var config = {
debug: {
mode: 1,
file: null
+ },
+ stickerpipe: {
+ elId: 'stickers_btn',
+
+ apiKey: '847b82c49db21ecec88c510e377b452c',
+
+ enableEmojiTab: false,
+ enableHistoryTab: true,
+ enableStoreTab: true,
+
+ userId: null,
+
+ priceB: '0.99 $',
+ priceC: '1.99 $'
}
};
diff --git a/samples/chat/js/connection.js b/samples/chat/js/connection.js
index 8c6ececd9..a3566cdee 100644
--- a/samples/chat/js/connection.js
+++ b/samples/chat/js/connection.js
@@ -41,6 +41,11 @@ function connectToChat(user) {
console.log(err);
} else {
console.log(roster);
+
+ // setup scroll stickerpipe module
+ //
+ setupStickerPipe();
+
// load chat dialogs
//
retrieveChatDialogs();
diff --git a/samples/chat/js/dialogs.js b/samples/chat/js/dialogs.js
index 492a094d6..75c2e92cd 100644
--- a/samples/chat/js/dialogs.js
+++ b/samples/chat/js/dialogs.js
@@ -87,6 +87,7 @@ function retrieveChatDialogs() {
var inputFile = $("input[type=file]")[0].files[0];
if (inputFile) {
$("#progress").show(0);
+ $(".input-group-btn_change_load").addClass("visibility_hidden");
}
clickSendAttachments(inputFile);
@@ -152,7 +153,7 @@ function updateDialogsList(dialogId, text){
$('#'+dialogId+'.list-group-item.inactive .badge').text(parseInt(badgeCount)+1).fadeIn(500);
// update last message
- $('#'+dialogId+' .list-group-item-text').text(text);
+ $('#'+dialogId+' .list-group-item-text').text(stickerpipe.isSticker(text) ? 'Sticker' : text);
}
// Choose dialog
diff --git a/samples/chat/js/messages.js b/samples/chat/js/messages.js
index b8c32cb89..95f7498c8 100644
--- a/samples/chat/js/messages.js
+++ b/samples/chat/js/messages.js
@@ -165,7 +165,11 @@ function clickSendAttachments(inputFile) {
if (err) {
console.log(err);
} else {
- $("#progress").fadeOut(400);
+
+ $("#progress").fadeOut(400, function() {
+ $(".input-group-btn_change_load").removeClass("visibility_hidden");
+ });
+
var uploadedFile = response;
sendMessage("[attachment]", uploadedFile.id);
@@ -177,6 +181,9 @@ function clickSendAttachments(inputFile) {
// send text or attachment
function sendMessage(text, attachmentFileId) {
+
+ stickerpipe.onUserMessageSent(stickerpipe.isSticker(text));
+
var msg = {
type: currentDialog.type === 3 ? 'chat' : 'groupchat',
body: text,
@@ -194,7 +201,7 @@ function sendMessage(text, attachmentFileId) {
opponentId = QB.chat.helpers.getRecipientId(currentDialog.occupants_ids, currentUser.id);
QB.chat.send(opponentId, msg);
- $('.list-group-item.active .list-group-item-text').text(msg.body);
+ $('.list-group-item.active .list-group-item-text').text(stickerpipe.isSticker(msg.body) ? 'Sticker' : msg.body);
if(attachmentFileId === null){
showMessage(currentUser.id, msg);
diff --git a/samples/chat/js/stickerpipe.js b/samples/chat/js/stickerpipe.js
new file mode 100644
index 000000000..1abc98a96
--- /dev/null
+++ b/samples/chat/js/stickerpipe.js
@@ -0,0 +1,89 @@
+
+var stickerpipe = null;
+
+function setupStickerPipe() {
+
+ var stickerpipeConfig = config.stickerpipe,
+
+ $stickersBtn = $('#' + stickerpipeConfig.elId + ' i'),
+ $messageText = $('#message_text');
+
+ stickerpipeConfig.userId = currentUser.id;
+
+ stickerpipe = new Stickers(stickerpipeConfig);
+
+ stickerpipe.render(function() {
+
+ this.stickerpipe.onClickSticker((function(stickerCode) {
+ sendMessage(stickerCode, null);
+ }).bind(this));
+
+ this.stickerpipe.onClickEmoji(function(emoji) {
+ console.log('click on emoji', emoji);
+ $messageText.focus();
+ pasteHtmlAtCaret(stickerpipe.parseEmojiFromText(emoji));
+ });
+
+ });
+
+ stickerpipe.onPurchase((function(packName, packTitle, pricePoint) {
+
+ try {
+ // do purchase transaction ...
+ if (confirm('Do you want buy pack "' + packName + '"?')) {
+ stickerpipe.purchaseSuccess(packName, pricePoint);
+ } else {
+ stickerpipe.purchaseFail();
+ }
+ } catch (e) {
+ stickerpipe.purchaseFail();
+ }
+ }).bind(this));
+
+ window.addEventListener('sp:popover:shown', function() {
+ $stickersBtn.addClass('active');
+ });
+
+ window.addEventListener('sp:popover:hidden', function() {
+ $stickersBtn.removeClass('active');
+ });
+
+}
+
+function pasteHtmlAtCaret(html) {
+ var sel, range;
+ if (window.getSelection) {
+ // IE9 and non-IE
+ sel = window.getSelection();
+ if (sel.getRangeAt && sel.rangeCount) {
+ range = sel.getRangeAt(0);
+ range.deleteContents();
+
+ // Range.createContextualFragment() would be useful here but is
+ // only relatively recently standardized and is not supported in
+ // some browsers (IE9, for one)
+ var el = document.createElement("div");
+ el.innerHTML = html;
+ var frag = document.createDocumentFragment(), node, lastNode;
+ while ( (node = el.firstChild) ) {
+ lastNode = frag.appendChild(node);
+ }
+ var firstNode = frag.firstChild;
+ range.insertNode(frag);
+
+ // Preserve the selection
+ if (lastNode) {
+ range = range.cloneRange();
+ range.setStartAfter(lastNode);
+ range.collapse(true);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+ } else if ( (sel = document.selection) && sel.type != "Control") {
+ // IE < 9
+ var originalRange = sel.createRange();
+ originalRange.collapse(true);
+ sel.createRange().pasteHTML(html);
+ }
+}
\ No newline at end of file
diff --git a/samples/chat/js/ui_helpers.js b/samples/chat/js/ui_helpers.js
index 1e0a2e688..5837f0eda 100644
--- a/samples/chat/js/ui_helpers.js
+++ b/samples/chat/js/ui_helpers.js
@@ -4,12 +4,39 @@ function buildMessageHTML(messageText, messageSenderId, messageDateSent, attachm
if(attachmentFileId){
messageAttach = ' ';
}
+
+ var isMessageSticker = stickerpipe.isSticker(messageText);
+
var delivered = ' ';
var read = ' ';
- var messageHtml = ''+'
'+jQuery.timeago(messageDateSent)+' '+'
'+messageSenderId+' '+
- '
'+(messageAttach ? messageAttach : messageText)+'
'+delivered+read+'
';
+ var messageTextHtml = messageText;
+ if (messageAttach) {
+ messageTextHtml = messageAttach;
+ } else if (isMessageSticker) {
+ messageTextHtml = '
';
+
+ stickerpipe.parseStickerFromText(messageText, function(sticker, isAsync) {
+ if (isAsync) {
+ $('#' + messageId + ' .message-sticker-container').html(sticker.html);
+ } else {
+ messageTextHtml = sticker.html;
+ }
+ });
+ }
+
+ var messageHtml =
+ ''+
+ '
'
+ +jQuery.timeago(messageDateSent)+
+ ' '+
+
+ '
'+messageSenderId+' '+
+ '
'+
+ messageTextHtml +
+ '
'
+ +delivered+read+
+ '
';
return messageHtml;
}
@@ -18,17 +45,29 @@ function buildDialogHtml(dialogId, dialogUnreadMessagesCount, dialogIcon, dialog
var UnreadMessagesCountShow = ''+dialogUnreadMessagesCount+' ';
UnreadMessagesCountHide = ''+dialogUnreadMessagesCount+' ';
- var dialogHtml = ''+
- (dialogUnreadMessagesCount === 0 ? UnreadMessagesCountHide : UnreadMessagesCountShow)+''+
- dialogIcon+' '+dialogName+' '+''+
- (dialogLastMessage === null ? "" : dialogLastMessage)+'
'+' ';
+ var isMessageSticker = stickerpipe.isSticker(dialogLastMessage);
+
+ var dialogHtml =
+ ''+
+ (dialogUnreadMessagesCount === 0 ? UnreadMessagesCountHide : UnreadMessagesCountShow)+
+ ''+ dialogIcon+' ' +
+ ''+dialogName+' ' +
+ ' '+
+ ''+
+ (dialogLastMessage === null ? "" : (isMessageSticker ? 'Sticker' : dialogLastMessage))+
+ '
'+
+ ' ';
return dialogHtml;
}
// build html for typing status
function buildTypingUserHtml(userId, userLogin) {
- var typingUserHtml = ''+'
writing now '+'
'+
- userLogin+' '+'
. . .
'+'
';
+ var typingUserHtml =
+ ''+
+ '
writing now '+
+ '
'+ userLogin+' '+
+ '
. . .
'+
+ '
';
return typingUserHtml;
}
diff --git a/samples/chat/libs/stickerpipe/css/stickerpipe.css b/samples/chat/libs/stickerpipe/css/stickerpipe.css
new file mode 100755
index 000000000..acd517ea3
--- /dev/null
+++ b/samples/chat/libs/stickerpipe/css/stickerpipe.css
@@ -0,0 +1,823 @@
+/*
+SCSS variables are information about icon's compiled state, stored under its original file name
+
+.icon-home {
+ width: $icon-home-width;
+}
+
+The large array-like variables contain all information about a single icon
+$icon-home: x y offset_x offset_y width height total_width total_height image_path;
+
+At the bottom of this section, we provide information about the spritesheet itself
+$spritesheet: width height image $spritesheet-sprites;
+*/
+
+/*
+These "retina group" variables are mappings for the naming and pairing of normal and retina sprites.
+
+The list formatted variables are intended for mixins like `retina-sprite` and `retina-sprites`.
+*/
+
+/*
+The provided mixins are intended to be used with the array-like variables
+
+.icon-home {
+ @include sprite-width($icon-home);
+}
+
+.icon-email {
+ @include sprite($icon-email);
+}
+*/
+
+/*
+The `retina-sprite` mixin sets up rules and a media query for a sprite/retina sprite.
+ It should be used with a "retina group" variable.
+
+The media query is from CSS Tricks: https://css-tricks.com/snippets/css/retina-display-media-query/
+
+$icon-home-group: ('icon-home', $icon-home, $icon-home-2x, );
+
+.icon-home {
+ @include retina-sprite($icon-home-group);
+}
+*/
+
+/*
+The `sprites` mixin generates identical output to the CSS template
+ but can be overridden inside of SCSS
+
+@include sprites($spritesheet-sprites);
+*/
+
+/*
+The `retina-sprites` mixin generates a CSS rule and media query for retina groups
+ This yields the same output as CSS retina template but can be overridden in SCSS
+
+@include retina-sprites($retina-groups);
+*/
+
+.sp-modal-lock {
+ overflow: hidden;
+}
+
+.sp-modal-overlay {
+ background: rgba(0, 0, 0, 0.5);
+ bottom: 0;
+ left: 0;
+ position: fixed;
+ top: 0;
+ right: 0;
+ z-index: 1000;
+ overflow: auto;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = #7F000000, endColorstr = #7F000000);
+ zoom: 1;
+}
+
+.sp-modal-overlay > * {
+ -webkit-transform: translateZ(0px);
+}
+
+.sp-modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ z-index: 1050;
+ overflow-x: hidden;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.sp-modal-dialog {
+ background: white;
+ position: relative;
+ height: 100%;
+ overflow: hidden;
+ border-radius: 3px;
+ margin: 40px auto;
+ max-width: 700px;
+}
+
+.sp-modal-dialog:before {
+ display: table;
+ content: " ";
+}
+
+@media (max-width: 700px) {
+ .sp-modal-dialog {
+ border-radius: 0;
+ margin: 0;
+ width: 100%;
+ }
+}
+
+.sp-modal-header {
+ background: rgba(255, 255, 255, 0.8);
+ border-radius: 3px;
+ display: table;
+ height: 48px;
+ width: 100%;
+ position: absolute;
+ top: 0;
+}
+
+.sp-modal-body {
+ height: 100%;
+ width: 100%;
+ overflow-y: hidden;
+}
+
+.sp-modal-back,
+.sp-modal-close {
+ cursor: pointer;
+ opacity: 0.5;
+ padding: 12px;
+}
+
+.sp-modal-back:hover,
+.sp-modal-close:hover {
+ opacity: 0.7;
+}
+
+.sp-modal-back {
+ float: left;
+ display: none;
+}
+
+.sp-modal-close {
+ float: right;
+}
+
+.ps-container {
+ -ms-touch-action: none;
+ touch-action: none;
+ overflow: hidden !important;
+ -ms-overflow-style: none;
+}
+
+@supports (-ms-overflow-style: none) {
+ .ps-container {
+ overflow: auto !important;
+ }
+}
+
+@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
+ .ps-container {
+ overflow: auto !important;
+ }
+}
+
+.ps-container.ps-active-x > .ps-scrollbar-x-rail,
+.ps-container.ps-active-y > .ps-scrollbar-y-rail {
+ display: block;
+ background-color: transparent;
+}
+
+.ps-container.ps-in-scrolling {
+ pointer-events: none;
+}
+
+.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
+ background-color: #eee;
+ opacity: 0.9;
+}
+
+.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
+ background-color: #999;
+}
+
+.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
+ background-color: #eee;
+ opacity: 0.9;
+}
+
+.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
+ background-color: #999;
+}
+
+.ps-container > .ps-scrollbar-x-rail {
+ display: none;
+ position: absolute;
+ /* please don't change 'position' */
+ border-radius: 4px;
+ opacity: 0;
+ -webkit-transition: background-color .2s linear, opacity .2s linear;
+ transition: background-color .2s linear, opacity .2s linear;
+ bottom: 3px;
+ /* there must be 'bottom' for ps-scrollbar-x-rail */
+ height: 8px;
+}
+
+.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {
+ position: absolute;
+ /* please don't change 'position' */
+ background-color: #aaa;
+ border-radius: 4px;
+ -webkit-transition: background-color .2s linear;
+ transition: background-color .2s linear;
+ bottom: 0;
+ /* there must be 'bottom' for ps-scrollbar-x */
+ height: 8px;
+}
+
+.ps-container > .ps-scrollbar-y-rail {
+ display: none;
+ position: absolute;
+ /* please don't change 'position' */
+ border-radius: 4px;
+ opacity: 0;
+ -webkit-transition: background-color .2s linear, opacity .2s linear;
+ transition: background-color .2s linear, opacity .2s linear;
+ right: 3px;
+ width: 7px;
+ margin-right: 1px;
+}
+
+.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {
+ position: absolute;
+ /* please don't change 'position' */
+ background-color: #aaa;
+ border-radius: 4px;
+ -webkit-transition: background-color .2s linear;
+ transition: background-color .2s linear;
+ right: 0;
+ width: 7px;
+}
+
+.ps-container:hover.ps-in-scrolling {
+ pointer-events: none;
+}
+
+.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
+ background-color: #eee;
+ opacity: 0.9;
+}
+
+.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
+ background-color: #999;
+}
+
+.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
+ background-color: #eee;
+ opacity: 0.9;
+}
+
+.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
+ background-color: #999;
+}
+
+.ps-container:hover > .ps-scrollbar-x-rail,
+.ps-container:hover > .ps-scrollbar-y-rail {
+ opacity: 0.6;
+}
+
+.ps-container:hover > .ps-scrollbar-x-rail:hover {
+ background-color: #eee;
+ opacity: 0.9;
+}
+
+.ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x {
+ background-color: #999;
+}
+
+.ps-container:hover > .ps-scrollbar-y-rail:hover {
+ background-color: #eee;
+ opacity: 0.9;
+}
+
+.ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y {
+ background-color: #999;
+}
+
+.sp-preloader {
+ background: white;
+ display: table;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ width: 100%;
+ z-index: 9;
+}
+
+.sp-preloader-content {
+ display: table-cell;
+ vertical-align: middle;
+}
+
+.sp-preloader-chasing-dots {
+ margin: 40px auto;
+ width: 40px;
+ height: 40px;
+ position: relative;
+ text-align: center;
+ -webkit-animation: sp-preloader-chasingDotsRotate 2s infinite linear;
+ animation: sp-preloader-chasingDotsRotate 2s infinite linear;
+}
+
+.sp-preloader-chasing-dots .sp-preloader-child {
+ width: 60%;
+ height: 60%;
+ display: inline-block;
+ position: absolute;
+ top: 0;
+ background-color: #9e9e9e;
+ border-radius: 100%;
+ -webkit-animation: sp-preloader-chasingDotsBounce 2s infinite ease-in-out;
+ animation: sp-preloader-chasingDotsBounce 2s infinite ease-in-out;
+}
+
+.sp-preloader-chasing-dots .sp-preloader-dot2 {
+ top: auto;
+ bottom: 0;
+ -webkit-animation-delay: -1s;
+ animation-delay: -1s;
+}
+
+@-webkit-keyframes sp-preloader-chasingDotsRotate {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes sp-preloader-chasingDotsRotate {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@-webkit-keyframes sp-preloader-chasingDotsBounce {
+ 0%, 100% {
+ -webkit-transform: scale(0);
+ transform: scale(0);
+ }
+
+ 50% {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ }
+}
+
+@keyframes sp-preloader-chasingDotsBounce {
+ 0%, 100% {
+ -webkit-transform: scale(0);
+ transform: scale(0);
+ }
+
+ 50% {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ }
+}
+
+.sp-popover {
+ border: 1px solid #c8c8c8;
+ border-radius: 3px;
+ position: absolute;
+ box-shadow: 1px 1px 1px 0 rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 1px 1px 1px 0 rgba(0, 0, 0, 0.15);
+ -webkit-box-shadow: 1px 1px 1px 0 rgba(0, 0, 0, 0.15);
+}
+
+.sp-popover > .sticker-pipe {
+ border-radius: 3px;
+}
+
+.sp-popover .sp-arrow,
+.sp-popover .sp-arrow:after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+
+.sp-popover .sp-arrow {
+ bottom: -11px;
+ margin-left: 1px;
+ border-top-color: rgba(0, 0, 0, 0.25);
+ border-width: 11px;
+ border-bottom-width: 0;
+}
+
+@media (max-width: 544px) {
+ .sp-popover .sp-arrow {
+ display: none;
+ }
+}
+
+.sp-popover .sp-arrow:after {
+ bottom: 1px;
+ margin-left: -10px;
+ content: " ";
+ border-top-color: #fafafa;
+ border-width: 10px;
+ border-bottom-width: 0;
+}
+
+.sticker-pipe {
+ background: #fafafa;
+ width: 100%;
+}
+
+.sticker-pipe .sp-store {
+ background: white;
+}
+
+.sticker-pipe .sp-tabs {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+ background-color: white;
+ border-bottom: 1px solid #c8c8c8;
+ border-radius: 3px 3px 0 0;
+ width: 100%;
+ white-space: nowrap;
+}
+
+.sticker-pipe .sp-tabs .sp-tabs-scrollable-container {
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ float: left;
+ overflow: hidden;
+ position: relative;
+}
+
+.sticker-pipe .sp-tabs .sp-tabs-scrollable-container .sp-tabs-scrollable-content {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+ left: 0;
+ position: relative;
+ -webkit-transition: 300ms;
+ transition: 300ms;
+ white-space: nowrap;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item {
+ display: inline-table;
+ cursor: pointer;
+ padding: 6px;
+ position: relative;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item img {
+ border-radius: 50%;
+ height: 36px;
+ width: 36px;
+ opacity: .5;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item img:hover {
+ opacity: .7;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active {
+ background: rgba(0, 0, 0, 0.1);
+ color: orange;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active img {
+ opacity: 1;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active.sp-control-tab > span,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active.sp-control-button > span {
+ opacity: 0.9;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button {
+ margin: 0;
+ padding: 12px;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab:hover > span,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button:hover > span {
+ opacity: .7;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab > span,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button > span {
+ display: table;
+ opacity: .5;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-next-packs,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-store,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-next-packs,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-store {
+ border-left: 1px solid #c8c8c8;
+ border-radius: 0;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-prev-packs,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-history,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-prev-packs,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-history {
+ border-right: 1px solid #c8c8c8;
+}
+
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-prev-packs,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-next-packs,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-prev-packs,
+.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-next-packs {
+ padding-left: 0;
+ padding-right: 0;
+}
+
+.sticker-pipe .sp-unwatched-content::after {
+ content: "";
+ width: 10px;
+ height: 10px;
+ display: block;
+ position: absolute;
+ background-color: #f60;
+ border-radius: 50%;
+ top: 32px;
+ left: 35px;
+}
+
+.sticker-pipe .sp-scroll-content {
+ position: relative;
+ overflow: hidden;
+}
+
+.sticker-pipe .sp-emojis,
+.sticker-pipe .sp-stickers {
+ border-radius: 0 0 3px 3px;
+ display: table;
+}
+
+.sticker-pipe .sp-emojis {
+ padding: 8px 16px;
+}
+
+.sticker-pipe .sp-emojis .sp-emoji {
+ display: inline-table;
+ float: left;
+ padding: 8px;
+ cursor: pointer;
+}
+
+.sticker-pipe .sp-emojis .sp-emoji:hover {
+ background: rgba(0, 0, 0, 0.1);
+ border-radius: 5px;
+}
+
+.sticker-pipe .sp-emojis .sp-emoji img {
+ height: 24px;
+ width: 24px;
+}
+
+.sticker-pipe .sp-stickers .sp-sticker-item,
+.sticker-pipe .sp-stickers .sp-sticker-placeholder {
+ float: left;
+ display: inline-table;
+}
+
+.sticker-pipe .sp-stickers .sp-sticker-placeholder {
+ background: rgba(0, 0, 0, 0.1);
+ border-radius: 50%;
+ height: 40px;
+ width: 40px;
+ margin: 32px;
+}
+
+.sticker-pipe .sp-stickers .sp-sticker-item {
+ cursor: pointer;
+ display: inline-table;
+ float: left;
+ margin: 9px;
+ padding: 3px;
+}
+
+.sticker-pipe .sp-stickers .sp-sticker-item:not(.sp-sticker-placeholder):hover {
+ background: rgba(0, 0, 0, 0.1);
+ border-radius: 5px;
+}
+
+.sticker-pipe .sp-stickers .sp-sticker-item img {
+ height: 80px;
+ width: 80px;
+}
+
+.sticker-pipe .sp-recent-empty {
+ text-align: center;
+ margin-top: 135px;
+ font-size: 20px;
+}
+
+.stickerpipe-sticker {
+ height: 160px;
+ width: 160px;
+}
+
+.stickerpipe-content-highlight:after {
+ content: "";
+ width: 8px;
+ height: 8px;
+ display: block;
+ position: absolute;
+ background-color: red;
+ border-radius: 50%;
+ margin-left: 16px;
+ margin-top: -24px !important;
+}
+
+.sp-icon-arrow-back {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: 0px 0px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-arrow-forward {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -24px 0px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-back {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: 0px -24px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-clock {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -24px -24px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-close {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -48px 0px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-face {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -48px -24px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-mall {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: 0px -48px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-plus {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -24px -48px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-settings {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -48px -48px;
+ width: 24px;
+ height: 24px;
+}
+
+.sp-icon-arrow-back {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: 0px 0px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-arrow-back {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-arrow-forward {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -24px 0px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-arrow-forward {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-back {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: 0px -24px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-back {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-clock {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -24px -24px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-clock {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-close {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -48px 0px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-close {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-face {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -48px -24px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-face {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-mall {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: 0px -48px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-mall {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-plus {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -24px -48px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-plus {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
+
+.sp-icon-settings {
+ background-image: url("../img/icons/icons_sprite.1453724705945.png");
+ background-position: -48px -48px;
+ width: 24px;
+ height: 24px;
+}
+
+@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
+ .sp-icon-settings {
+ background-image: url("../img/icons/icons_sprite@2x.1453724705945.png");
+ background-size: 72px 72px;
+ }
+}
\ No newline at end of file
diff --git a/samples/chat/libs/stickerpipe/css/stickerpipe.min.css b/samples/chat/libs/stickerpipe/css/stickerpipe.min.css
new file mode 100755
index 000000000..c620b0a76
--- /dev/null
+++ b/samples/chat/libs/stickerpipe/css/stickerpipe.min.css
@@ -0,0 +1 @@
+.sp-modal,.sp-modal-overlay{position:fixed;bottom:0;right:0;top:0;left:0}.ps-container.ps-in-scrolling,.ps-container:hover.ps-in-scrolling{pointer-events:none}.sp-modal-lock{overflow:hidden}.sp-modal-overlay{background:rgba(0,0,0,.5);z-index:1000;overflow:auto;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#7F000000, endColorstr=#7F000000);zoom:1}.sp-modal-overlay>*{-webkit-transform:translateZ(0)}.sp-modal{z-index:1050;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch}.sp-modal-dialog{background:#fff;position:relative;height:100%;overflow:hidden;border-radius:3px;margin:40px auto;max-width:700px}.sp-modal-dialog:before{display:table;content:" "}@media (max-width:700px){.sp-modal-dialog{border-radius:0;margin:0;width:100%}}.sp-modal-header{background:rgba(255,255,255,.8);border-radius:3px;display:table;height:48px;width:100%;position:absolute;top:0}.sp-modal-body{height:100%;width:100%;overflow-y:hidden}.sp-modal-back,.sp-modal-close{cursor:pointer;opacity:.5;padding:12px}.sp-modal-back:hover,.sp-modal-close:hover{opacity:.7}.sp-modal-back{float:left;display:none}.sp-modal-close{float:right}.ps-container{-ms-touch-action:none;touch-action:none;overflow:hidden!important;-ms-overflow-style:none}@supports (-ms-overflow-style:none){.ps-container{overflow:auto!important}}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.ps-container{overflow:auto!important}}.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block;background-color:transparent}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999}.ps-container>.ps-scrollbar-x-rail{display:none;position:absolute;border-radius:4px;opacity:0;-webkit-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;bottom:3px;height:8px}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;background-color:#aaa;border-radius:4px;-webkit-transition:background-color .2s linear;transition:background-color .2s linear;bottom:0;height:8px}.ps-container>.ps-scrollbar-y-rail{display:none;position:absolute;border-radius:4px;opacity:0;-webkit-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;right:3px;width:7px;margin-right:1px}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;background-color:#aaa;border-radius:4px;-webkit-transition:background-color .2s linear;transition:background-color .2s linear;right:0;width:7px}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999}.ps-container:hover>.ps-scrollbar-x-rail,.ps-container:hover>.ps-scrollbar-y-rail{opacity:.6}.ps-container:hover>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{background-color:#999}.ps-container:hover>.ps-scrollbar-y-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999}.sp-preloader{background:#fff;display:table;height:100%;position:absolute;top:0;width:100%;z-index:9}.sp-preloader-content{display:table-cell;vertical-align:middle}.sp-preloader-chasing-dots{margin:40px auto;width:40px;height:40px;position:relative;text-align:center;-webkit-animation:sp-preloader-chasingDotsRotate 2s infinite linear;animation:sp-preloader-chasingDotsRotate 2s infinite linear}.sp-preloader-chasing-dots .sp-preloader-child{width:60%;height:60%;display:inline-block;position:absolute;top:0;background-color:#9e9e9e;border-radius:100%;-webkit-animation:sp-preloader-chasingDotsBounce 2s infinite ease-in-out;animation:sp-preloader-chasingDotsBounce 2s infinite ease-in-out}.sp-preloader-chasing-dots .sp-preloader-dot2{top:auto;bottom:0;-webkit-animation-delay:-1s;animation-delay:-1s}@-webkit-keyframes sp-preloader-chasingDotsRotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes sp-preloader-chasingDotsRotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes sp-preloader-chasingDotsBounce{0%,100%{-webkit-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes sp-preloader-chasingDotsBounce{0%,100%{-webkit-transform:scale(0);transform:scale(0)}50%{-webkit-transform:scale(1);transform:scale(1)}}.sp-popover{border:1px solid #c8c8c8;border-radius:3px;position:absolute;box-shadow:1px 1px 1px 0 rgba(0,0,0,.15);-moz-box-shadow:1px 1px 1px 0 rgba(0,0,0,.15);-webkit-box-shadow:1px 1px 1px 0 rgba(0,0,0,.15)}.sp-popover>.sticker-pipe{border-radius:3px}.sp-popover .sp-arrow,.sp-popover .sp-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.sp-popover .sp-arrow{bottom:-11px;margin-left:1px;border-top-color:rgba(0,0,0,.25);border-width:11px 11px 0}@media (max-width:544px){.sp-popover .sp-arrow{display:none}}.sp-popover .sp-arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fafafa;border-width:10px 10px 0}.sticker-pipe{background:#fafafa;width:100%}.sticker-pipe .sp-store{background:#fff}.sticker-pipe .sp-tabs{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;background-color:#fff;border-bottom:1px solid #c8c8c8;border-radius:3px 3px 0 0;width:100%;white-space:nowrap}.sticker-pipe .sp-tabs .sp-tabs-scrollable-container{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;float:left;overflow:hidden;position:relative}.sticker-pipe .sp-tabs .sp-tabs-scrollable-container .sp-tabs-scrollable-content{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;left:0;position:relative;-webkit-transition:.3s;transition:.3s;white-space:nowrap}.sticker-pipe .sp-tabs .sp-tab-item{display:inline-table;cursor:pointer;padding:6px;position:relative}.sticker-pipe .sp-tabs .sp-tab-item img{border-radius:50%;height:36px;width:36px;opacity:.5}.sticker-pipe .sp-tabs .sp-tab-item img:hover{opacity:.7}.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active{background:rgba(0,0,0,.1);color:orange}.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active img{opacity:1}.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active.sp-control-button>span,.sticker-pipe .sp-tabs .sp-tab-item.sp-tab-active.sp-control-tab>span{opacity:.9}.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab{margin:0;padding:12px}.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button:hover>span,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab:hover>span{opacity:.7}.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button>span,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab>span{display:table;opacity:.5}.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-next-packs,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-store,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-next-packs,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-store{border-left:1px solid #c8c8c8;border-radius:0}.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-history,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-prev-packs,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-history,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-prev-packs{border-right:1px solid #c8c8c8}.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-next-packs,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-button.sp-tab-prev-packs,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-next-packs,.sticker-pipe .sp-tabs .sp-tab-item.sp-control-tab.sp-tab-prev-packs{padding-left:0;padding-right:0}.sticker-pipe .sp-unwatched-content::after{content:"";width:10px;height:10px;display:block;position:absolute;background-color:#f60;border-radius:50%;top:32px;left:35px}.sticker-pipe .sp-scroll-content{position:relative;overflow:hidden}.sticker-pipe .sp-emojis,.sticker-pipe .sp-stickers{border-radius:0 0 3px 3px;display:table}.sticker-pipe .sp-emojis{padding:8px 16px}.sticker-pipe .sp-emojis .sp-emoji{display:inline-table;float:left;padding:8px;cursor:pointer}.sticker-pipe .sp-emojis .sp-emoji:hover{background:rgba(0,0,0,.1);border-radius:5px}.sticker-pipe .sp-emojis .sp-emoji img{height:24px;width:24px}.sticker-pipe .sp-stickers .sp-sticker-item,.sticker-pipe .sp-stickers .sp-sticker-placeholder{float:left;display:inline-table}.sticker-pipe .sp-stickers .sp-sticker-placeholder{background:rgba(0,0,0,.1);border-radius:50%;height:40px;width:40px;margin:32px}.sticker-pipe .sp-stickers .sp-sticker-item{cursor:pointer;display:inline-table;float:left;margin:9px;padding:3px}.sticker-pipe .sp-stickers .sp-sticker-item:not(.sp-sticker-placeholder):hover{background:rgba(0,0,0,.1);border-radius:5px}.sticker-pipe .sp-stickers .sp-sticker-item img{height:80px;width:80px}.sticker-pipe .sp-recent-empty{text-align:center;margin-top:135px;font-size:20px}.stickerpipe-sticker{height:160px;width:160px}.stickerpipe-content-highlight:after{content:"";width:8px;height:8px;display:block;position:absolute;background-color:red;border-radius:50%;margin-left:16px;margin-top:-24px!important}.sp-icon-arrow-back,.sp-icon-arrow-forward,.sp-icon-back,.sp-icon-clock,.sp-icon-close,.sp-icon-face,.sp-icon-mall,.sp-icon-plus,.sp-icon-settings{width:24px;height:24px}.sp-icon-arrow-back{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:0 0}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-arrow-back{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-arrow-forward{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:-24px 0}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-arrow-forward{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-back{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:0 -24px}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-back{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-clock{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:-24px -24px}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-clock{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-close{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:-48px 0}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-close{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-face{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:-48px -24px}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-face{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-mall{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:0 -48px}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-mall{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-plus{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:-24px -48px}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-plus{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}.sp-icon-settings{background-image:url(../img/icons/icons_sprite.1453724705945.png);background-position:-48px -48px}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.sp-icon-settings{background-image:url(../img/icons/icons_sprite@2x.1453724705945.png);background-size:72px 72px}}
\ No newline at end of file
diff --git a/samples/chat/libs/stickerpipe/img/icons/icons_sprite.1453724705945.png b/samples/chat/libs/stickerpipe/img/icons/icons_sprite.1453724705945.png
new file mode 100755
index 000000000..dcbddffc2
Binary files /dev/null and b/samples/chat/libs/stickerpipe/img/icons/icons_sprite.1453724705945.png differ
diff --git a/samples/chat/libs/stickerpipe/img/icons/icons_sprite@2x.1453724705945.png b/samples/chat/libs/stickerpipe/img/icons/icons_sprite@2x.1453724705945.png
new file mode 100755
index 000000000..7fe193e2a
Binary files /dev/null and b/samples/chat/libs/stickerpipe/img/icons/icons_sprite@2x.1453724705945.png differ
diff --git a/samples/chat/libs/stickerpipe/js/stickerpipe.js b/samples/chat/libs/stickerpipe/js/stickerpipe.js
new file mode 100755
index 000000000..83e092dc2
--- /dev/null
+++ b/samples/chat/libs/stickerpipe/js/stickerpipe.js
@@ -0,0 +1,6547 @@
+
+// todo: move StickersModule --> Stickers
+window.StickersModule = {};
+
+
+window.StickersModule.Libs = {};
+(function(Plugin) {
+
+ /**
+ *
+ * Copyright (C) 2011 by crac
+ * Thanks for Hardy Keppler for shortened version
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **/
+ var Class = (function() {
+
+ function _rewriteStatics(fnc, statics) {
+ for (var prop in statics) {
+ if (prop === 'extend' || prop === 'static' || prop === 'typeOf' || prop === 'mixin' ) {
+ continue;
+ }
+
+ if (typeof statics[prop] === 'object' || typeof statics[prop] === 'function') {
+ fnc[prop] = statics[prop];
+ return;
+ }
+
+ //check if static is a constant
+ if (prop === prop.toUpperCase()) {
+ Object.defineProperty(fnc, prop, {
+ writable: false,
+ configurable: false,
+ enumerable: true,
+ value: statics[prop]
+ });
+ Object.defineProperty(fnc.prototype, prop, {
+ writable: false,
+ configurable: false,
+ enumerable: true,
+ value: statics[prop]
+ });
+ } else {
+ Object.defineProperty(fnc, prop, {
+ get: function() {
+ return statics[prop]
+ },
+ set: function(val) {
+ statics[prop] = val;
+ }
+ });
+ Object.defineProperty(fnc.prototype, prop, {
+ get: function() {
+ return statics[prop]
+ },
+ set: function(val) {
+ statics[prop] = val;
+ }
+ });
+ }
+ }
+ }
+
+ function _extend(base, source, overrideConstructor) {
+ overrideConstructor = overrideConstructor || false;
+
+ for (var p in source) {
+ if ((p === '_constructor' && !overrideConstructor) || p === 'typeOf' || p === 'mixin' || p === 'static' || p === 'extend') {
+ continue;
+ }
+ base[p] = source[p];
+ }
+ }
+
+ return function (classBody) {
+
+ var _preventCreateCall = false;
+
+ return (function createClass(self, classBody) {
+
+ var _mixins = [];
+ var instance;
+
+ var isSingleton = classBody.hasOwnProperty('singleton') && classBody.singleton;
+
+ var classConstructor = function () {
+ //apply constructor pattern
+ if (typeof this['_constructor'] === 'function' && _preventCreateCall === false) {
+ this._constructor.apply(this, arguments);
+ }
+
+ //apply getter pattern
+ if (classBody.hasOwnProperty('get')) {
+ for (var p in classBody.get) {
+
+ var setter = 'set' in classBody ? (p in classBody.set ? classBody.set[p] : null) : null;
+ if (setter === null) {
+ Object.defineProperty(this, p, {
+ get: classBody.get[p]
+ });
+ }
+ }
+ }
+
+ //apply setter pattern
+ if (classBody.hasOwnProperty('set')) {
+ for (var p in classBody.set) {
+
+ var getter = 'get' in classBody ? (p in classBody.get ? classBody.get[p] : null) : null;
+ if (getter !== null) {
+ Object.defineProperty(this, p, {
+ set: classBody.set[p],
+ get: classBody.get[p]
+ });
+ } else {
+ Object.defineProperty(this, p, {
+ set: classBody.set[p]
+ });
+ }
+ }
+ }
+
+ if (isSingleton && typeof this !== 'undefined') {
+ throw new Error('Singleton object cannot have more than one instance, call instance method instead');
+ }
+ this.constructor = classConstructor;
+ };
+
+ //make new class instance of extended object
+ if (self !== null) {
+ _preventCreateCall = true;
+ classConstructor.prototype = new self();
+ _preventCreateCall = false;
+ }
+
+ var classPrototype = classConstructor.prototype;
+
+ classPrototype.typeOf = function(cls) {
+ if (typeof cls === 'object') {
+ return _mixins.indexOf(cls) >= 0;
+ } else if (typeof cls === 'function') {
+ if (this instanceof cls) {
+ return true;
+ } else if (_mixins.indexOf(cls) >= 0) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+ if (typeof classBody === 'function') {
+ classBody = classBody();
+ }
+
+ _extend(classPrototype, classBody, true);
+
+ /**
+ * Defines statics and constans in class' body.
+ *
+ * @param {Object} statics
+ * @returns {Function}
+ */
+ classConstructor.static = function(statics) {
+ _rewriteStatics(classConstructor, statics);
+ return classConstructor;
+ };
+
+ /**
+ * Extends class body by passed other class declaration
+ * @param {Function} *mixins
+ * @returns {Function}
+ */
+ classConstructor.mixin = function() {
+ for (var i = 0, l = arguments.length; i < l; i++) {
+ //check if class implements interfaces
+ var mixin = arguments[i];
+
+ if (typeof mixin === 'function') {
+ var methods = mixin.prototype;
+ } else if (typeof mixin === 'object') {
+ var methods = mixin;
+ } else {
+ throw new Error('js.class mixin method accepts only types: object, function - `' + (typeof mixin) + '` type given');
+ }
+ _extend(classPrototype, methods, false);
+ _mixins.push(mixin);
+ }
+ return classConstructor;
+ };
+
+ /**
+ * Creates and returns new constructor function which extends
+ * its parent
+ *
+ * @param {Object} classBody
+ * @returns {Function}
+ */
+ if (isSingleton) {
+ classConstructor.extend = function() {
+ throw new Error('Singleton class cannot be extended');
+ };
+
+ classConstructor.instance = function() {
+ if (!instance) {
+ isSingleton = false;
+ instance = new classConstructor();
+ isSingleton = true;
+ }
+ return instance;
+ }
+
+ } else {
+ classConstructor.extend = function (classBody) {
+ return createClass(this, classBody);
+ };
+ }
+
+ return classConstructor;
+ })(null, classBody);
+ }
+ })();
+
+ if (typeof module !== "undefined") {
+ module.exports = Class;
+ } else {
+ Plugin.Libs.Class = Class; // for browser
+ }
+
+})(window.StickersModule);
+
+// todo: remove
+
+/*
+ * classList.js: Cross-browser full element.classList implementation.
+ * 2014-12-13
+ *
+ * By Eli Grey, http://eligrey.com
+ * Public Domain.
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+ */
+
+/*global self, document, DOMException */
+
+/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
+
+if ("document" in self) {
+
+// Full polyfill for browsers with no classList support
+ if (!("classList" in document.createElement("_"))) {
+
+ (function (view) {
+
+ "use strict";
+
+ if (!('Element' in view)) return;
+
+ var
+ classListProp = "classList"
+ , protoProp = "prototype"
+ , elemCtrProto = view.Element[protoProp]
+ , objCtr = Object
+ , strTrim = String[protoProp].trim || function () {
+ return this.replace(/^\s+|\s+$/g, "");
+ }
+ , arrIndexOf = Array[protoProp].indexOf || function (item) {
+ var
+ i = 0
+ , len = this.length
+ ;
+ for (; i < len; i++) {
+ if (i in this && this[i] === item) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ // Vendors: please allow content code to instantiate DOMExceptions
+ , DOMEx = function (type, message) {
+ this.name = type;
+ this.code = DOMException[type];
+ this.message = message;
+ }
+ , checkTokenAndGetIndex = function (classList, token) {
+ if (token === "") {
+ throw new DOMEx(
+ "SYNTAX_ERR"
+ , "An invalid or illegal string was specified"
+ );
+ }
+ if (/\s/.test(token)) {
+ throw new DOMEx(
+ "INVALID_CHARACTER_ERR"
+ , "String contains an invalid character"
+ );
+ }
+ return arrIndexOf.call(classList, token);
+ }
+ , ClassList = function (elem) {
+ var
+ trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
+ , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
+ , i = 0
+ , len = classes.length
+ ;
+ for (; i < len; i++) {
+ this.push(classes[i]);
+ }
+ this._updateClassName = function () {
+ elem.setAttribute("class", this.toString());
+ };
+ }
+ , classListProto = ClassList[protoProp] = []
+ , classListGetter = function () {
+ return new ClassList(this);
+ }
+ ;
+// Most DOMException implementations don't allow calling DOMException's toString()
+// on non-DOMExceptions. Error's toString() is sufficient here.
+ DOMEx[protoProp] = Error[protoProp];
+ classListProto.item = function (i) {
+ return this[i] || null;
+ };
+ classListProto.contains = function (token) {
+ token += "";
+ return checkTokenAndGetIndex(this, token) !== -1;
+ };
+ classListProto.add = function () {
+ var
+ tokens = arguments
+ , i = 0
+ , l = tokens.length
+ , token
+ , updated = false
+ ;
+ do {
+ token = tokens[i] + "";
+ if (checkTokenAndGetIndex(this, token) === -1) {
+ this.push(token);
+ updated = true;
+ }
+ }
+ while (++i < l);
+
+ if (updated) {
+ this._updateClassName();
+ }
+ };
+ classListProto.remove = function () {
+ var
+ tokens = arguments
+ , i = 0
+ , l = tokens.length
+ , token
+ , updated = false
+ , index
+ ;
+ do {
+ token = tokens[i] + "";
+ index = checkTokenAndGetIndex(this, token);
+ while (index !== -1) {
+ this.splice(index, 1);
+ updated = true;
+ index = checkTokenAndGetIndex(this, token);
+ }
+ }
+ while (++i < l);
+
+ if (updated) {
+ this._updateClassName();
+ }
+ };
+ classListProto.toggle = function (token, force) {
+ token += "";
+
+ var
+ result = this.contains(token)
+ , method = result ?
+ force !== true && "remove"
+ :
+ force !== false && "add"
+ ;
+
+ if (method) {
+ this[method](token);
+ }
+
+ if (force === true || force === false) {
+ return force;
+ } else {
+ return !result;
+ }
+ };
+ classListProto.toString = function () {
+ return this.join(" ");
+ };
+
+ if (objCtr.defineProperty) {
+ var classListPropDesc = {
+ get: classListGetter
+ , enumerable: true
+ , configurable: true
+ };
+ try {
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+ } catch (ex) { // IE 8 doesn't support enumerable:true
+ if (ex.number === -0x7FF5EC54) {
+ classListPropDesc.enumerable = false;
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+ }
+ }
+ } else if (objCtr[protoProp].__defineGetter__) {
+ elemCtrProto.__defineGetter__(classListProp, classListGetter);
+ }
+
+ }(self));
+
+ } else {
+// There is full or partial native classList support, so just check if we need
+// to normalize the add/remove and toggle APIs.
+
+ (function () {
+ "use strict";
+
+ var testElement = document.createElement("_");
+
+ testElement.classList.add("c1", "c2");
+
+ // Polyfill for IE 10/11 and Firefox <26, where classList.add and
+ // classList.remove exist but support only one argument at a time.
+ if (!testElement.classList.contains("c2")) {
+ var createMethod = function(method) {
+ var original = DOMTokenList.prototype[method];
+
+ DOMTokenList.prototype[method] = function(token) {
+ var i, len = arguments.length;
+
+ for (i = 0; i < len; i++) {
+ token = arguments[i];
+ original.call(this, token);
+ }
+ };
+ };
+ createMethod('add');
+ createMethod('remove');
+ }
+
+ testElement.classList.toggle("c3", false);
+
+ // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
+ // support the second argument.
+ if (testElement.classList.contains("c3")) {
+ var _toggle = DOMTokenList.prototype.toggle;
+
+ DOMTokenList.prototype.toggle = function(token, force) {
+ if (1 in arguments && !this.contains(token) === !force) {
+ return force;
+ } else {
+ return _toggle.call(this, token);
+ }
+ };
+
+ }
+
+ testElement = null;
+ }());
+
+ }
+
+}
+document.addEventListener("DOMContentLoaded", function(event) {
+
+ if(typeof window.ga === "undefined"){
+
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ }
+
+ ga('create', 'UA-1113296-81', 'auto', {'name': 'stickerTracker'});
+ ga('stickerTracker.send', 'pageview');
+
+});
+
+(function(Plugin) {
+
+ Plugin.Libs.Lockr = {
+ prefix: '',
+
+ _getPrefixedKey: function(key, options) {
+ options = options || {};
+
+ if (options.noPrefix) {
+ return key;
+ } else {
+ return this.prefix + key;
+ }
+ },
+
+ set: function (key, value, options) {
+ var query_key = this._getPrefixedKey(key, options);
+
+ try {
+ localStorage.setItem(query_key, JSON.stringify({
+ data: value
+ }));
+ } catch (e) {
+ console && console.warn('Lockr didn\'t successfully save the "{'+ key +': '+ value +'}" pair, because the localStorage is full.');
+ }
+ },
+
+ get: function (key, missing, options) {
+ var query_key = this._getPrefixedKey(key, options),
+ value;
+
+ try {
+ value = JSON.parse(localStorage.getItem(query_key));
+ } catch (e) {
+ value = null;
+ }
+
+ return (value === null) ? missing : (value.data || missing);
+ },
+
+ sadd: function(key, value, options) {
+ var query_key = this._getPrefixedKey(key, options),
+ json;
+
+ var values = this.smembers(key);
+
+ if (values.indexOf(value) > -1) {
+ return null;
+ }
+
+ try {
+ values.push(value);
+ json = JSON.stringify({"data": values});
+ localStorage.setItem(query_key, json);
+ } catch (e) {
+ if (console) {
+ console.log(e);
+ console.warn('Lockr didn\'t successfully add the '+ value +' to '+ key +' set, because the localStorage is full.');
+ }
+ }
+ },
+
+ smembers: function(key, options) {
+ var query_key = this._getPrefixedKey(key, options),
+ value;
+
+ try {
+ value = JSON.parse(localStorage.getItem(query_key));
+ } catch (e) {
+ value = null;
+ }
+
+ return (value === null) ? [] : (value.data || []);
+ },
+
+ sismember: function(key, value, options) {
+ var query_key = this._getPrefixedKey(key, options);
+ return this.smembers(key).indexOf(value) > -1;
+ },
+
+ getAll: function () {
+ var keys = Object.keys(localStorage);
+
+ return keys.map((function (key) {
+ return this.get(key);
+ }).bind(this));
+ },
+
+ srem: function(key, value, options) {
+ var query_key = this._getPrefixedKey(key, options),
+ json,
+ index;
+
+ var values = this.smembers(key, value);
+
+ index = values.indexOf(value);
+
+ if (index > -1)
+ values.splice(index, 1);
+
+ json = JSON.stringify({
+ data: values
+ });
+
+ try {
+ localStorage.setItem(query_key, json);
+ } catch (e) {
+ console && console.warn('Lockr couldn\'t remove the ' + value + ' from the set ' + key);
+ }
+ },
+
+ rm: function (key) {
+ localStorage.removeItem(key);
+ },
+
+ flush: function () {
+ localStorage.clear();
+ }
+ };
+
+})(window.StickersModule);
+(function(Plugin) {
+
+ Plugin.Libs.MD5 = function (string) {
+
+ string = string.toString();
+
+ function RotateLeft(lValue, iShiftBits) {
+ return (lValue<>>(32-iShiftBits));
+ }
+
+ function AddUnsigned(lX,lY) {
+ var lX4,lY4,lX8,lY8,lResult;
+ lX8 = (lX & 0x80000000);
+ lY8 = (lY & 0x80000000);
+ lX4 = (lX & 0x40000000);
+ lY4 = (lY & 0x40000000);
+ lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
+ if (lX4 & lY4) {
+ return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+ }
+ if (lX4 | lY4) {
+ if (lResult & 0x40000000) {
+ return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+ } else {
+ return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+ }
+ } else {
+ return (lResult ^ lX8 ^ lY8);
+ }
+ }
+
+ function F(x,y,z) { return (x & y) | ((~x) & z); }
+ function G(x,y,z) { return (x & z) | (y & (~z)); }
+ function H(x,y,z) { return (x ^ y ^ z); }
+ function I(x,y,z) { return (y ^ (x | (~z))); }
+
+ function FF(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function GG(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function HH(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function II(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function ConvertToWordArray(string) {
+ var lWordCount;
+ var lMessageLength = string.length;
+ var lNumberOfWords_temp1=lMessageLength + 8;
+ var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
+ var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
+ var lWordArray=Array(lNumberOfWords-1);
+ var lBytePosition = 0;
+ var lByteCount = 0;
+ while ( lByteCount < lMessageLength ) {
+ lWordCount = (lByteCount-(lByteCount % 4))/4;
+ lBytePosition = (lByteCount % 4)*8;
+ lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29;
+ return lWordArray;
+ }
+
+ function WordToHex(lValue) {
+ var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
+ for (lCount = 0;lCount<=3;lCount++) {
+ lByte = (lValue>>>(lCount*8)) & 255;
+ WordToHexValue_temp = "0" + lByte.toString(16);
+ WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
+ }
+ return WordToHexValue;
+ }
+
+ function Utf8Encode(string) {
+ string = string.replace(/\r\n/g,"\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ }
+
+ var x=Array();
+ var k,AA,BB,CC,DD,a,b,c,d;
+ var S11=7, S12=12, S13=17, S14=22;
+ var S21=5, S22=9 , S23=14, S24=20;
+ var S31=4, S32=11, S33=16, S34=23;
+ var S41=6, S42=10, S43=15, S44=21;
+
+ string = Utf8Encode(string);
+
+ x = ConvertToWordArray(string);
+
+ a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
+
+ for (k=0;k= 0) {
+ classes.splice(idx, 1);
+ }
+ element.className = classes.join(' ');
+}
+
+exports.add = function (element, className) {
+ if (element.classList) {
+ element.classList.add(className);
+ } else {
+ oldAdd(element, className);
+ }
+};
+
+exports.remove = function (element, className) {
+ if (element.classList) {
+ element.classList.remove(className);
+ } else {
+ oldRemove(element, className);
+ }
+};
+
+exports.list = function (element) {
+ if (element.classList) {
+ return Array.prototype.slice.apply(element.classList);
+ } else {
+ return element.className.split(' ');
+ }
+};
+
+},{}],3:[function(require,module,exports){
+'use strict';
+
+var DOM = {};
+
+DOM.e = function (tagName, className) {
+ var element = document.createElement(tagName);
+ element.className = className;
+ return element;
+};
+
+DOM.appendTo = function (child, parent) {
+ parent.appendChild(child);
+ return child;
+};
+
+function cssGet(element, styleName) {
+ return window.getComputedStyle(element)[styleName];
+}
+
+function cssSet(element, styleName, styleValue) {
+ if (typeof styleValue === 'number') {
+ styleValue = styleValue.toString() + 'px';
+ }
+ element.style[styleName] = styleValue;
+ return element;
+}
+
+function cssMultiSet(element, obj) {
+ for (var key in obj) {
+ var val = obj[key];
+ if (typeof val === 'number') {
+ val = val.toString() + 'px';
+ }
+ element.style[key] = val;
+ }
+ return element;
+}
+
+DOM.css = function (element, styleNameOrObject, styleValue) {
+ if (typeof styleNameOrObject === 'object') {
+ // multiple set with object
+ return cssMultiSet(element, styleNameOrObject);
+ } else {
+ if (typeof styleValue === 'undefined') {
+ return cssGet(element, styleNameOrObject);
+ } else {
+ return cssSet(element, styleNameOrObject, styleValue);
+ }
+ }
+};
+
+DOM.matches = function (element, query) {
+ if (typeof element.matches !== 'undefined') {
+ return element.matches(query);
+ } else {
+ if (typeof element.matchesSelector !== 'undefined') {
+ return element.matchesSelector(query);
+ } else if (typeof element.webkitMatchesSelector !== 'undefined') {
+ return element.webkitMatchesSelector(query);
+ } else if (typeof element.mozMatchesSelector !== 'undefined') {
+ return element.mozMatchesSelector(query);
+ } else if (typeof element.msMatchesSelector !== 'undefined') {
+ return element.msMatchesSelector(query);
+ }
+ }
+};
+
+DOM.remove = function (element) {
+ if (typeof element.remove !== 'undefined') {
+ element.remove();
+ } else {
+ if (element.parentNode) {
+ element.parentNode.removeChild(element);
+ }
+ }
+};
+
+DOM.queryChildren = function (element, selector) {
+ return Array.prototype.filter.call(element.childNodes, function (child) {
+ return DOM.matches(child, selector);
+ });
+};
+
+module.exports = DOM;
+
+},{}],4:[function(require,module,exports){
+'use strict';
+
+var EventElement = function (element) {
+ this.element = element;
+ this.events = {};
+};
+
+EventElement.prototype.bind = function (eventName, handler) {
+ if (typeof this.events[eventName] === 'undefined') {
+ this.events[eventName] = [];
+ }
+ this.events[eventName].push(handler);
+ this.element.addEventListener(eventName, handler, false);
+};
+
+EventElement.prototype.unbind = function (eventName, handler) {
+ var isHandlerProvided = (typeof handler !== 'undefined');
+ this.events[eventName] = this.events[eventName].filter(function (hdlr) {
+ if (isHandlerProvided && hdlr !== handler) {
+ return true;
+ }
+ this.element.removeEventListener(eventName, hdlr, false);
+ return false;
+ }, this);
+};
+
+EventElement.prototype.unbindAll = function () {
+ for (var name in this.events) {
+ this.unbind(name);
+ }
+};
+
+var EventManager = function () {
+ this.eventElements = [];
+};
+
+EventManager.prototype.eventElement = function (element) {
+ var ee = this.eventElements.filter(function (eventElement) {
+ return eventElement.element === element;
+ })[0];
+ if (typeof ee === 'undefined') {
+ ee = new EventElement(element);
+ this.eventElements.push(ee);
+ }
+ return ee;
+};
+
+EventManager.prototype.bind = function (element, eventName, handler) {
+ this.eventElement(element).bind(eventName, handler);
+};
+
+EventManager.prototype.unbind = function (element, eventName, handler) {
+ this.eventElement(element).unbind(eventName, handler);
+};
+
+EventManager.prototype.unbindAll = function () {
+ for (var i = 0; i < this.eventElements.length; i++) {
+ this.eventElements[i].unbindAll();
+ }
+};
+
+EventManager.prototype.once = function (element, eventName, handler) {
+ var ee = this.eventElement(element);
+ var onceHandler = function (e) {
+ ee.unbind(eventName, onceHandler);
+ handler(e);
+ };
+ ee.bind(eventName, onceHandler);
+};
+
+module.exports = EventManager;
+
+},{}],5:[function(require,module,exports){
+'use strict';
+
+module.exports = (function () {
+ function s4() {
+ return Math.floor((1 + Math.random()) * 0x10000)
+ .toString(16)
+ .substring(1);
+ }
+ return function () {
+ return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
+ s4() + '-' + s4() + s4() + s4();
+ };
+})();
+
+},{}],6:[function(require,module,exports){
+'use strict';
+
+var cls = require('./class')
+ , d = require('./dom');
+
+exports.toInt = function (x) {
+ return parseInt(x, 10) || 0;
+};
+
+exports.clone = function (obj) {
+ if (obj === null) {
+ return null;
+ } else if (typeof obj === 'object') {
+ var result = {};
+ for (var key in obj) {
+ result[key] = this.clone(obj[key]);
+ }
+ return result;
+ } else {
+ return obj;
+ }
+};
+
+exports.extend = function (original, source) {
+ var result = this.clone(original);
+ for (var key in source) {
+ result[key] = this.clone(source[key]);
+ }
+ return result;
+};
+
+exports.isEditable = function (el) {
+ return d.matches(el, "input,[contenteditable]") ||
+ d.matches(el, "select,[contenteditable]") ||
+ d.matches(el, "textarea,[contenteditable]") ||
+ d.matches(el, "button,[contenteditable]");
+};
+
+exports.removePsClasses = function (element) {
+ var clsList = cls.list(element);
+ for (var i = 0; i < clsList.length; i++) {
+ var className = clsList[i];
+ if (className.indexOf('ps-') === 0) {
+ cls.remove(element, className);
+ }
+ }
+};
+
+exports.outerWidth = function (element) {
+ return this.toInt(d.css(element, 'width')) +
+ this.toInt(d.css(element, 'paddingLeft')) +
+ this.toInt(d.css(element, 'paddingRight')) +
+ this.toInt(d.css(element, 'borderLeftWidth')) +
+ this.toInt(d.css(element, 'borderRightWidth'));
+};
+
+exports.startScrolling = function (element, axis) {
+ cls.add(element, 'ps-in-scrolling');
+ if (typeof axis !== 'undefined') {
+ cls.add(element, 'ps-' + axis);
+ } else {
+ cls.add(element, 'ps-x');
+ cls.add(element, 'ps-y');
+ }
+};
+
+exports.stopScrolling = function (element, axis) {
+ cls.remove(element, 'ps-in-scrolling');
+ if (typeof axis !== 'undefined') {
+ cls.remove(element, 'ps-' + axis);
+ } else {
+ cls.remove(element, 'ps-x');
+ cls.remove(element, 'ps-y');
+ }
+};
+
+exports.env = {
+ isWebKit: 'WebkitAppearance' in document.documentElement.style,
+ supportsTouch: (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch),
+ supportsIePointer: window.navigator.msMaxTouchPoints !== null
+};
+
+},{"./class":2,"./dom":3}],7:[function(require,module,exports){
+'use strict';
+
+var destroy = require('./plugin/destroy')
+ , initialize = require('./plugin/initialize')
+ , update = require('./plugin/update');
+
+module.exports = {
+ initialize: initialize,
+ update: update,
+ destroy: destroy
+};
+
+},{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":21}],8:[function(require,module,exports){
+'use strict';
+
+module.exports = {
+ maxScrollbarLength: null,
+ minScrollbarLength: null,
+ scrollXMarginOffset: 0,
+ scrollYMarginOffset: 0,
+ stopPropagationOnClick: true,
+ suppressScrollX: false,
+ suppressScrollY: false,
+ swipePropagation: true,
+ useBothWheelAxes: false,
+ useKeyboard: true,
+ useSelectionScroll: false,
+ wheelPropagation: false,
+ wheelSpeed: 1,
+ theme: 'default'
+};
+
+},{}],9:[function(require,module,exports){
+'use strict';
+
+var d = require('../lib/dom')
+ , h = require('../lib/helper')
+ , instances = require('./instances');
+
+module.exports = function (element) {
+ var i = instances.get(element);
+
+ if (!i) {
+ return;
+ }
+
+ i.event.unbindAll();
+ d.remove(i.scrollbarX);
+ d.remove(i.scrollbarY);
+ d.remove(i.scrollbarXRail);
+ d.remove(i.scrollbarYRail);
+ h.removePsClasses(element);
+
+ instances.remove(element);
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){
+'use strict';
+
+var h = require('../../lib/helper')
+ , instances = require('../instances')
+ , updateGeometry = require('../update-geometry')
+ , updateScroll = require('../update-scroll');
+
+function bindClickRailHandler(element, i) {
+ function pageOffset(el) {
+ return el.getBoundingClientRect();
+ }
+ var stopPropagation = window.Event.prototype.stopPropagation.bind;
+
+ if (i.settings.stopPropagationOnClick) {
+ i.event.bind(i.scrollbarY, 'click', stopPropagation);
+ }
+ i.event.bind(i.scrollbarYRail, 'click', function (e) {
+ var halfOfScrollbarLength = h.toInt(i.scrollbarYHeight / 2);
+ var positionTop = i.railYRatio * (e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
+ var maxPositionTop = i.railYRatio * (i.railYHeight - i.scrollbarYHeight);
+ var positionRatio = positionTop / maxPositionTop;
+
+ if (positionRatio < 0) {
+ positionRatio = 0;
+ } else if (positionRatio > 1) {
+ positionRatio = 1;
+ }
+
+ updateScroll(element, 'top', (i.contentHeight - i.containerHeight) * positionRatio);
+ updateGeometry(element);
+
+ e.stopPropagation();
+ });
+
+ if (i.settings.stopPropagationOnClick) {
+ i.event.bind(i.scrollbarX, 'click', stopPropagation);
+ }
+ i.event.bind(i.scrollbarXRail, 'click', function (e) {
+ var halfOfScrollbarLength = h.toInt(i.scrollbarXWidth / 2);
+ var positionLeft = i.railXRatio * (e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
+ var maxPositionLeft = i.railXRatio * (i.railXWidth - i.scrollbarXWidth);
+ var positionRatio = positionLeft / maxPositionLeft;
+
+ if (positionRatio < 0) {
+ positionRatio = 0;
+ } else if (positionRatio > 1) {
+ positionRatio = 1;
+ }
+
+ updateScroll(element, 'left', ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment);
+ updateGeometry(element);
+
+ e.stopPropagation();
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindClickRailHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){
+'use strict';
+
+var d = require('../../lib/dom')
+ , h = require('../../lib/helper')
+ , instances = require('../instances')
+ , updateGeometry = require('../update-geometry')
+ , updateScroll = require('../update-scroll');
+
+function bindMouseScrollXHandler(element, i) {
+ var currentLeft = null;
+ var currentPageX = null;
+
+ function updateScrollLeft(deltaX) {
+ var newLeft = currentLeft + (deltaX * i.railXRatio);
+ var maxLeft = Math.max(0, i.scrollbarXRail.getBoundingClientRect().left) + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
+
+ if (newLeft < 0) {
+ i.scrollbarXLeft = 0;
+ } else if (newLeft > maxLeft) {
+ i.scrollbarXLeft = maxLeft;
+ } else {
+ i.scrollbarXLeft = newLeft;
+ }
+
+ var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
+ updateScroll(element, 'left', scrollLeft);
+ }
+
+ var mouseMoveHandler = function (e) {
+ updateScrollLeft(e.pageX - currentPageX);
+ updateGeometry(element);
+ e.stopPropagation();
+ e.preventDefault();
+ };
+
+ var mouseUpHandler = function () {
+ h.stopScrolling(element, 'x');
+ i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ };
+
+ i.event.bind(i.scrollbarX, 'mousedown', function (e) {
+ currentPageX = e.pageX;
+ currentLeft = h.toInt(d.css(i.scrollbarX, 'left')) * i.railXRatio;
+ h.startScrolling(element, 'x');
+
+ i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+ e.stopPropagation();
+ e.preventDefault();
+ });
+}
+
+function bindMouseScrollYHandler(element, i) {
+ var currentTop = null;
+ var currentPageY = null;
+
+ function updateScrollTop(deltaY) {
+ var newTop = currentTop + (deltaY * i.railYRatio);
+ var maxTop = Math.max(0, i.scrollbarYRail.getBoundingClientRect().top) + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
+
+ if (newTop < 0) {
+ i.scrollbarYTop = 0;
+ } else if (newTop > maxTop) {
+ i.scrollbarYTop = maxTop;
+ } else {
+ i.scrollbarYTop = newTop;
+ }
+
+ var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
+ updateScroll(element, 'top', scrollTop);
+ }
+
+ var mouseMoveHandler = function (e) {
+ updateScrollTop(e.pageY - currentPageY);
+ updateGeometry(element);
+ e.stopPropagation();
+ e.preventDefault();
+ };
+
+ var mouseUpHandler = function () {
+ h.stopScrolling(element, 'y');
+ i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ };
+
+ i.event.bind(i.scrollbarY, 'mousedown', function (e) {
+ currentPageY = e.pageY;
+ currentTop = h.toInt(d.css(i.scrollbarY, 'top')) * i.railYRatio;
+ h.startScrolling(element, 'y');
+
+ i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+ e.stopPropagation();
+ e.preventDefault();
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindMouseScrollXHandler(element, i);
+ bindMouseScrollYHandler(element, i);
+};
+
+},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){
+'use strict';
+
+var h = require('../../lib/helper')
+ , d = require('../../lib/dom')
+ , instances = require('../instances')
+ , updateGeometry = require('../update-geometry')
+ , updateScroll = require('../update-scroll');
+
+function bindKeyboardHandler(element, i) {
+ var hovered = false;
+ i.event.bind(element, 'mouseenter', function () {
+ hovered = true;
+ });
+ i.event.bind(element, 'mouseleave', function () {
+ hovered = false;
+ });
+
+ var shouldPrevent = false;
+ function shouldPreventDefault(deltaX, deltaY) {
+ var scrollTop = element.scrollTop;
+ if (deltaX === 0) {
+ if (!i.scrollbarYActive) {
+ return false;
+ }
+ if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+
+ var scrollLeft = element.scrollLeft;
+ if (deltaY === 0) {
+ if (!i.scrollbarXActive) {
+ return false;
+ }
+ if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+ return true;
+ }
+
+ i.event.bind(i.ownerDocument, 'keydown', function (e) {
+ if (e.isDefaultPrevented && e.isDefaultPrevented()) {
+ return;
+ }
+
+ var focused = d.matches(i.scrollbarX, ':focus') ||
+ d.matches(i.scrollbarY, ':focus');
+
+ if (!hovered && !focused) {
+ return;
+ }
+
+ var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement;
+ if (activeElement) {
+ // go deeper if element is a webcomponent
+ while (activeElement.shadowRoot) {
+ activeElement = activeElement.shadowRoot.activeElement;
+ }
+ if (h.isEditable(activeElement)) {
+ return;
+ }
+ }
+
+ var deltaX = 0;
+ var deltaY = 0;
+
+ switch (e.which) {
+ case 37: // left
+ deltaX = -30;
+ break;
+ case 38: // up
+ deltaY = 30;
+ break;
+ case 39: // right
+ deltaX = 30;
+ break;
+ case 40: // down
+ deltaY = -30;
+ break;
+ case 33: // page up
+ deltaY = 90;
+ break;
+ case 32: // space bar
+ if (e.shiftKey) {
+ deltaY = 90;
+ } else {
+ deltaY = -90;
+ }
+ break;
+ case 34: // page down
+ deltaY = -90;
+ break;
+ case 35: // end
+ if (e.ctrlKey) {
+ deltaY = -i.contentHeight;
+ } else {
+ deltaY = -i.containerHeight;
+ }
+ break;
+ case 36: // home
+ if (e.ctrlKey) {
+ deltaY = element.scrollTop;
+ } else {
+ deltaY = i.containerHeight;
+ }
+ break;
+ default:
+ return;
+ }
+
+ updateScroll(element, 'top', element.scrollTop - deltaY);
+ updateScroll(element, 'left', element.scrollLeft + deltaX);
+ updateGeometry(element);
+
+ shouldPrevent = shouldPreventDefault(deltaX, deltaY);
+ if (shouldPrevent) {
+ e.preventDefault();
+ }
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindKeyboardHandler(element, i);
+};
+
+},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){
+'use strict';
+
+var instances = require('../instances')
+ , updateGeometry = require('../update-geometry')
+ , updateScroll = require('../update-scroll');
+
+function bindMouseWheelHandler(element, i) {
+ var shouldPrevent = false;
+
+ function shouldPreventDefault(deltaX, deltaY) {
+ var scrollTop = element.scrollTop;
+ if (deltaX === 0) {
+ if (!i.scrollbarYActive) {
+ return false;
+ }
+ if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+
+ var scrollLeft = element.scrollLeft;
+ if (deltaY === 0) {
+ if (!i.scrollbarXActive) {
+ return false;
+ }
+ if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+ return true;
+ }
+
+ function getDeltaFromEvent(e) {
+ var deltaX = e.deltaX;
+ var deltaY = -1 * e.deltaY;
+
+ if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
+ // OS X Safari
+ deltaX = -1 * e.wheelDeltaX / 6;
+ deltaY = e.wheelDeltaY / 6;
+ }
+
+ if (e.deltaMode && e.deltaMode === 1) {
+ // Firefox in deltaMode 1: Line scrolling
+ deltaX *= 10;
+ deltaY *= 10;
+ }
+
+ if (deltaX !== deltaX && deltaY !== deltaY/* NaN checks */) {
+ // IE in some mouse drivers
+ deltaX = 0;
+ deltaY = e.wheelDelta;
+ }
+
+ return [deltaX, deltaY];
+ }
+
+ function shouldBeConsumedByTextarea(deltaX, deltaY) {
+ var hoveredTextarea = element.querySelector('textarea:hover');
+ if (hoveredTextarea) {
+ var maxScrollTop = hoveredTextarea.scrollHeight - hoveredTextarea.clientHeight;
+ if (maxScrollTop > 0) {
+ if (!(hoveredTextarea.scrollTop === 0 && deltaY > 0) &&
+ !(hoveredTextarea.scrollTop === maxScrollTop && deltaY < 0)) {
+ return true;
+ }
+ }
+ var maxScrollLeft = hoveredTextarea.scrollLeft - hoveredTextarea.clientWidth;
+ if (maxScrollLeft > 0) {
+ if (!(hoveredTextarea.scrollLeft === 0 && deltaX < 0) &&
+ !(hoveredTextarea.scrollLeft === maxScrollLeft && deltaX > 0)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function mousewheelHandler(e) {
+ var delta = getDeltaFromEvent(e);
+
+ var deltaX = delta[0];
+ var deltaY = delta[1];
+
+ if (shouldBeConsumedByTextarea(deltaX, deltaY)) {
+ return;
+ }
+
+ shouldPrevent = false;
+ if (!i.settings.useBothWheelAxes) {
+ // deltaX will only be used for horizontal scrolling and deltaY will
+ // only be used for vertical scrolling - this is the default
+ updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
+ updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
+ } else if (i.scrollbarYActive && !i.scrollbarXActive) {
+ // only vertical scrollbar is active and useBothWheelAxes option is
+ // active, so let's scroll vertical bar using both mouse wheel axes
+ if (deltaY) {
+ updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
+ } else {
+ updateScroll(element, 'top', element.scrollTop + (deltaX * i.settings.wheelSpeed));
+ }
+ shouldPrevent = true;
+ } else if (i.scrollbarXActive && !i.scrollbarYActive) {
+ // useBothWheelAxes and only horizontal bar is active, so use both
+ // wheel axes for horizontal bar
+ if (deltaX) {
+ updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
+ } else {
+ updateScroll(element, 'left', element.scrollLeft - (deltaY * i.settings.wheelSpeed));
+ }
+ shouldPrevent = true;
+ }
+
+ updateGeometry(element);
+
+ shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
+ if (shouldPrevent) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+
+ if (typeof window.onwheel !== "undefined") {
+ i.event.bind(element, 'wheel', mousewheelHandler);
+ } else if (typeof window.onmousewheel !== "undefined") {
+ i.event.bind(element, 'mousewheel', mousewheelHandler);
+ }
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindMouseWheelHandler(element, i);
+};
+
+},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){
+'use strict';
+
+var instances = require('../instances')
+ , updateGeometry = require('../update-geometry');
+
+function bindNativeScrollHandler(element, i) {
+ i.event.bind(element, 'scroll', function () {
+ updateGeometry(element);
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindNativeScrollHandler(element, i);
+};
+
+},{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){
+'use strict';
+
+var h = require('../../lib/helper')
+ , instances = require('../instances')
+ , updateGeometry = require('../update-geometry')
+ , updateScroll = require('../update-scroll');
+
+function bindSelectionHandler(element, i) {
+ function getRangeNode() {
+ var selection = window.getSelection ? window.getSelection() :
+ document.getSelection ? document.getSelection() : '';
+ if (selection.toString().length === 0) {
+ return null;
+ } else {
+ return selection.getRangeAt(0).commonAncestorContainer;
+ }
+ }
+
+ var scrollingLoop = null;
+ var scrollDiff = {top: 0, left: 0};
+ function startScrolling() {
+ if (!scrollingLoop) {
+ scrollingLoop = setInterval(function () {
+ if (!instances.get(element)) {
+ clearInterval(scrollingLoop);
+ return;
+ }
+
+ updateScroll(element, 'top', element.scrollTop + scrollDiff.top);
+ updateScroll(element, 'left', element.scrollLeft + scrollDiff.left);
+ updateGeometry(element);
+ }, 50); // every .1 sec
+ }
+ }
+ function stopScrolling() {
+ if (scrollingLoop) {
+ clearInterval(scrollingLoop);
+ scrollingLoop = null;
+ }
+ h.stopScrolling(element);
+ }
+
+ var isSelected = false;
+ i.event.bind(i.ownerDocument, 'selectionchange', function () {
+ if (element.contains(getRangeNode())) {
+ isSelected = true;
+ } else {
+ isSelected = false;
+ stopScrolling();
+ }
+ });
+ i.event.bind(window, 'mouseup', function () {
+ if (isSelected) {
+ isSelected = false;
+ stopScrolling();
+ }
+ });
+
+ i.event.bind(window, 'mousemove', function (e) {
+ if (isSelected) {
+ var mousePosition = {x: e.pageX, y: e.pageY};
+ var containerGeometry = {
+ left: element.offsetLeft,
+ right: element.offsetLeft + element.offsetWidth,
+ top: element.offsetTop,
+ bottom: element.offsetTop + element.offsetHeight
+ };
+
+ if (mousePosition.x < containerGeometry.left + 3) {
+ scrollDiff.left = -5;
+ h.startScrolling(element, 'x');
+ } else if (mousePosition.x > containerGeometry.right - 3) {
+ scrollDiff.left = 5;
+ h.startScrolling(element, 'x');
+ } else {
+ scrollDiff.left = 0;
+ }
+
+ if (mousePosition.y < containerGeometry.top + 3) {
+ if (containerGeometry.top + 3 - mousePosition.y < 5) {
+ scrollDiff.top = -5;
+ } else {
+ scrollDiff.top = -20;
+ }
+ h.startScrolling(element, 'y');
+ } else if (mousePosition.y > containerGeometry.bottom - 3) {
+ if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
+ scrollDiff.top = 5;
+ } else {
+ scrollDiff.top = 20;
+ }
+ h.startScrolling(element, 'y');
+ } else {
+ scrollDiff.top = 0;
+ }
+
+ if (scrollDiff.top === 0 && scrollDiff.left === 0) {
+ stopScrolling();
+ } else {
+ startScrolling();
+ }
+ }
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindSelectionHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){
+'use strict';
+
+var instances = require('../instances')
+ , updateGeometry = require('../update-geometry')
+ , updateScroll = require('../update-scroll');
+
+function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
+ function shouldPreventDefault(deltaX, deltaY) {
+ var scrollTop = element.scrollTop;
+ var scrollLeft = element.scrollLeft;
+ var magnitudeX = Math.abs(deltaX);
+ var magnitudeY = Math.abs(deltaY);
+
+ if (magnitudeY > magnitudeX) {
+ // user is perhaps trying to swipe up/down the page
+
+ if (((deltaY < 0) && (scrollTop === i.contentHeight - i.containerHeight)) ||
+ ((deltaY > 0) && (scrollTop === 0))) {
+ return !i.settings.swipePropagation;
+ }
+ } else if (magnitudeX > magnitudeY) {
+ // user is perhaps trying to swipe left/right across the page
+
+ if (((deltaX < 0) && (scrollLeft === i.contentWidth - i.containerWidth)) ||
+ ((deltaX > 0) && (scrollLeft === 0))) {
+ return !i.settings.swipePropagation;
+ }
+ }
+
+ return true;
+ }
+
+ function applyTouchMove(differenceX, differenceY) {
+ updateScroll(element, 'top', element.scrollTop - differenceY);
+ updateScroll(element, 'left', element.scrollLeft - differenceX);
+
+ updateGeometry(element);
+ }
+
+ var startOffset = {};
+ var startTime = 0;
+ var speed = {};
+ var easingLoop = null;
+ var inGlobalTouch = false;
+ var inLocalTouch = false;
+
+ function globalTouchStart() {
+ inGlobalTouch = true;
+ }
+ function globalTouchEnd() {
+ inGlobalTouch = false;
+ }
+
+ function getTouch(e) {
+ if (e.targetTouches) {
+ return e.targetTouches[0];
+ } else {
+ // Maybe IE pointer
+ return e;
+ }
+ }
+ function shouldHandle(e) {
+ if (e.targetTouches && e.targetTouches.length === 1) {
+ return true;
+ }
+ if (e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
+ return true;
+ }
+ return false;
+ }
+ function touchStart(e) {
+ if (shouldHandle(e)) {
+ inLocalTouch = true;
+
+ var touch = getTouch(e);
+
+ startOffset.pageX = touch.pageX;
+ startOffset.pageY = touch.pageY;
+
+ startTime = (new Date()).getTime();
+
+ if (easingLoop !== null) {
+ clearInterval(easingLoop);
+ }
+
+ e.stopPropagation();
+ }
+ }
+ function touchMove(e) {
+ if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
+ var touch = getTouch(e);
+
+ var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
+
+ var differenceX = currentOffset.pageX - startOffset.pageX;
+ var differenceY = currentOffset.pageY - startOffset.pageY;
+
+ applyTouchMove(differenceX, differenceY);
+ startOffset = currentOffset;
+
+ var currentTime = (new Date()).getTime();
+
+ var timeGap = currentTime - startTime;
+ if (timeGap > 0) {
+ speed.x = differenceX / timeGap;
+ speed.y = differenceY / timeGap;
+ startTime = currentTime;
+ }
+
+ if (shouldPreventDefault(differenceX, differenceY)) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ }
+ function touchEnd() {
+ if (!inGlobalTouch && inLocalTouch) {
+ inLocalTouch = false;
+
+ clearInterval(easingLoop);
+ easingLoop = setInterval(function () {
+ if (!instances.get(element)) {
+ clearInterval(easingLoop);
+ return;
+ }
+
+ if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
+ clearInterval(easingLoop);
+ return;
+ }
+
+ applyTouchMove(speed.x * 30, speed.y * 30);
+
+ speed.x *= 0.8;
+ speed.y *= 0.8;
+ }, 10);
+ }
+ }
+
+ if (supportsTouch) {
+ i.event.bind(window, 'touchstart', globalTouchStart);
+ i.event.bind(window, 'touchend', globalTouchEnd);
+ i.event.bind(element, 'touchstart', touchStart);
+ i.event.bind(element, 'touchmove', touchMove);
+ i.event.bind(element, 'touchend', touchEnd);
+ }
+
+ if (supportsIePointer) {
+ if (window.PointerEvent) {
+ i.event.bind(window, 'pointerdown', globalTouchStart);
+ i.event.bind(window, 'pointerup', globalTouchEnd);
+ i.event.bind(element, 'pointerdown', touchStart);
+ i.event.bind(element, 'pointermove', touchMove);
+ i.event.bind(element, 'pointerup', touchEnd);
+ } else if (window.MSPointerEvent) {
+ i.event.bind(window, 'MSPointerDown', globalTouchStart);
+ i.event.bind(window, 'MSPointerUp', globalTouchEnd);
+ i.event.bind(element, 'MSPointerDown', touchStart);
+ i.event.bind(element, 'MSPointerMove', touchMove);
+ i.event.bind(element, 'MSPointerUp', touchEnd);
+ }
+ }
+}
+
+module.exports = function (element, supportsTouch, supportsIePointer) {
+ var i = instances.get(element);
+ bindTouchHandler(element, i, supportsTouch, supportsIePointer);
+};
+
+},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){
+'use strict';
+
+var cls = require('../lib/class')
+ , h = require('../lib/helper')
+ , instances = require('./instances')
+ , updateGeometry = require('./update-geometry');
+
+// Handlers
+var clickRailHandler = require('./handler/click-rail')
+ , dragScrollbarHandler = require('./handler/drag-scrollbar')
+ , keyboardHandler = require('./handler/keyboard')
+ , mouseWheelHandler = require('./handler/mouse-wheel')
+ , nativeScrollHandler = require('./handler/native-scroll')
+ , selectionHandler = require('./handler/selection')
+ , touchHandler = require('./handler/touch');
+
+module.exports = function (element, userSettings) {
+ userSettings = typeof userSettings === 'object' ? userSettings : {};
+
+ cls.add(element, 'ps-container');
+
+ // Create a plugin instance.
+ var i = instances.add(element);
+
+ i.settings = h.extend(i.settings, userSettings);
+ cls.add(element, 'ps-theme-' + i.settings.theme);
+
+ clickRailHandler(element);
+ dragScrollbarHandler(element);
+ mouseWheelHandler(element);
+ nativeScrollHandler(element);
+
+ if (i.settings.useSelectionScroll) {
+ selectionHandler(element);
+ }
+
+ if (h.env.supportsTouch || h.env.supportsIePointer) {
+ touchHandler(element, h.env.supportsTouch, h.env.supportsIePointer);
+ }
+ if (i.settings.useKeyboard) {
+ keyboardHandler(element);
+ }
+
+ updateGeometry(element);
+};
+
+},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){
+'use strict';
+
+var cls = require('../lib/class')
+ , d = require('../lib/dom')
+ , defaultSettings = require('./default-setting')
+ , EventManager = require('../lib/event-manager')
+ , guid = require('../lib/guid')
+ , h = require('../lib/helper');
+
+var instances = {};
+
+function Instance(element) {
+ var i = this;
+
+ i.settings = h.clone(defaultSettings);
+ i.containerWidth = null;
+ i.containerHeight = null;
+ i.contentWidth = null;
+ i.contentHeight = null;
+
+ i.isRtl = d.css(element, 'direction') === "rtl";
+ i.isNegativeScroll = (function () {
+ var originalScrollLeft = element.scrollLeft;
+ var result = null;
+ element.scrollLeft = -1;
+ result = element.scrollLeft < 0;
+ element.scrollLeft = originalScrollLeft;
+ return result;
+ })();
+ i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+ i.event = new EventManager();
+ i.ownerDocument = element.ownerDocument || document;
+
+ function focus() {
+ cls.add(element, 'ps-focus');
+ }
+
+ function blur() {
+ cls.remove(element, 'ps-focus');
+ }
+
+ i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
+ i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
+ i.scrollbarX.setAttribute('tabindex', 0);
+ i.event.bind(i.scrollbarX, 'focus', focus);
+ i.event.bind(i.scrollbarX, 'blur', blur);
+ i.scrollbarXActive = null;
+ i.scrollbarXWidth = null;
+ i.scrollbarXLeft = null;
+ i.scrollbarXBottom = h.toInt(d.css(i.scrollbarXRail, 'bottom'));
+ i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
+ i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top'));
+ i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth'));
+ // Set rail to display:block to calculate margins
+ d.css(i.scrollbarXRail, 'display', 'block');
+ i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
+ d.css(i.scrollbarXRail, 'display', '');
+ i.railXWidth = null;
+ i.railXRatio = null;
+
+ i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
+ i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
+ i.scrollbarY.setAttribute('tabindex', 0);
+ i.event.bind(i.scrollbarY, 'focus', focus);
+ i.event.bind(i.scrollbarY, 'blur', blur);
+ i.scrollbarYActive = null;
+ i.scrollbarYHeight = null;
+ i.scrollbarYTop = null;
+ i.scrollbarYRight = h.toInt(d.css(i.scrollbarYRail, 'right'));
+ i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
+ i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : h.toInt(d.css(i.scrollbarYRail, 'left'));
+ i.scrollbarYOuterWidth = i.isRtl ? h.outerWidth(i.scrollbarY) : null;
+ i.railBorderYWidth = h.toInt(d.css(i.scrollbarYRail, 'borderTopWidth')) + h.toInt(d.css(i.scrollbarYRail, 'borderBottomWidth'));
+ d.css(i.scrollbarYRail, 'display', 'block');
+ i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
+ d.css(i.scrollbarYRail, 'display', '');
+ i.railYHeight = null;
+ i.railYRatio = null;
+}
+
+function getId(element) {
+ if (typeof element.dataset === 'undefined') {
+ return element.getAttribute('data-ps-id');
+ } else {
+ return element.dataset.psId;
+ }
+}
+
+function setId(element, id) {
+ if (typeof element.dataset === 'undefined') {
+ element.setAttribute('data-ps-id', id);
+ } else {
+ element.dataset.psId = id;
+ }
+}
+
+function removeId(element) {
+ if (typeof element.dataset === 'undefined') {
+ element.removeAttribute('data-ps-id');
+ } else {
+ delete element.dataset.psId;
+ }
+}
+
+exports.add = function (element) {
+ var newId = guid();
+ setId(element, newId);
+ instances[newId] = new Instance(element);
+ return instances[newId];
+};
+
+exports.remove = function (element) {
+ delete instances[getId(element)];
+ removeId(element);
+};
+
+exports.get = function (element) {
+ return instances[getId(element)];
+};
+
+},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
+'use strict';
+
+var cls = require('../lib/class')
+ , d = require('../lib/dom')
+ , h = require('../lib/helper')
+ , instances = require('./instances')
+ , updateScroll = require('./update-scroll');
+
+function getThumbSize(i, thumbSize) {
+ if (i.settings.minScrollbarLength) {
+ thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
+ }
+ if (i.settings.maxScrollbarLength) {
+ thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
+ }
+ return thumbSize;
+}
+
+function updateCss(element, i) {
+ var xRailOffset = {width: i.railXWidth};
+ if (i.isRtl) {
+ xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth;
+ } else {
+ xRailOffset.left = element.scrollLeft;
+ }
+ if (i.isScrollbarXUsingBottom) {
+ xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop;
+ } else {
+ xRailOffset.top = i.scrollbarXTop + element.scrollTop;
+ }
+ d.css(i.scrollbarXRail, xRailOffset);
+
+ var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
+ if (i.isScrollbarYUsingRight) {
+ if (i.isRtl) {
+ yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth;
+ } else {
+ yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
+ }
+ } else {
+ if (i.isRtl) {
+ yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
+ } else {
+ yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
+ }
+ }
+ d.css(i.scrollbarYRail, yRailOffset);
+
+ d.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
+ d.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+
+ i.containerWidth = element.clientWidth;
+ i.containerHeight = element.clientHeight;
+ i.contentWidth = element.scrollWidth;
+ i.contentHeight = element.scrollHeight;
+
+ var existingRails;
+ if (!element.contains(i.scrollbarXRail)) {
+ existingRails = d.queryChildren(element, '.ps-scrollbar-x-rail');
+ if (existingRails.length > 0) {
+ existingRails.forEach(function (rail) {
+ d.remove(rail);
+ });
+ }
+ d.appendTo(i.scrollbarXRail, element);
+ }
+ if (!element.contains(i.scrollbarYRail)) {
+ existingRails = d.queryChildren(element, '.ps-scrollbar-y-rail');
+ if (existingRails.length > 0) {
+ existingRails.forEach(function (rail) {
+ d.remove(rail);
+ });
+ }
+ d.appendTo(i.scrollbarYRail, element);
+ }
+
+ if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) {
+ i.scrollbarXActive = true;
+ i.railXWidth = i.containerWidth - i.railXMarginWidth;
+ i.railXRatio = i.containerWidth / i.railXWidth;
+ i.scrollbarXWidth = getThumbSize(i, h.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
+ i.scrollbarXLeft = h.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
+ } else {
+ i.scrollbarXActive = false;
+ }
+
+ if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
+ i.scrollbarYActive = true;
+ i.railYHeight = i.containerHeight - i.railYMarginHeight;
+ i.railYRatio = i.containerHeight / i.railYHeight;
+ i.scrollbarYHeight = getThumbSize(i, h.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
+ i.scrollbarYTop = h.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
+ } else {
+ i.scrollbarYActive = false;
+ }
+
+ if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
+ i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
+ }
+ if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
+ i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
+ }
+
+ updateCss(element, i);
+
+ if (i.scrollbarXActive) {
+ cls.add(element, 'ps-active-x');
+ } else {
+ cls.remove(element, 'ps-active-x');
+ i.scrollbarXWidth = 0;
+ i.scrollbarXLeft = 0;
+ updateScroll(element, 'left', 0);
+ }
+ if (i.scrollbarYActive) {
+ cls.add(element, 'ps-active-y');
+ } else {
+ cls.remove(element, 'ps-active-y');
+ i.scrollbarYHeight = 0;
+ i.scrollbarYTop = 0;
+ updateScroll(element, 'top', 0);
+ }
+};
+
+},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){
+'use strict';
+
+var instances = require('./instances');
+
+var upEvent = document.createEvent('Event')
+ , downEvent = document.createEvent('Event')
+ , leftEvent = document.createEvent('Event')
+ , rightEvent = document.createEvent('Event')
+ , yEvent = document.createEvent('Event')
+ , xEvent = document.createEvent('Event')
+ , xStartEvent = document.createEvent('Event')
+ , xEndEvent = document.createEvent('Event')
+ , yStartEvent = document.createEvent('Event')
+ , yEndEvent = document.createEvent('Event')
+ , lastTop
+ , lastLeft;
+
+upEvent.initEvent('ps-scroll-up', true, true);
+downEvent.initEvent('ps-scroll-down', true, true);
+leftEvent.initEvent('ps-scroll-left', true, true);
+rightEvent.initEvent('ps-scroll-right', true, true);
+yEvent.initEvent('ps-scroll-y', true, true);
+xEvent.initEvent('ps-scroll-x', true, true);
+xStartEvent.initEvent('ps-x-reach-start', true, true);
+xEndEvent.initEvent('ps-x-reach-end', true, true);
+yStartEvent.initEvent('ps-y-reach-start', true, true);
+yEndEvent.initEvent('ps-y-reach-end', true, true);
+
+module.exports = function (element, axis, value) {
+ if (typeof element === 'undefined') {
+ throw 'You must provide an element to the update-scroll function';
+ }
+
+ if (typeof axis === 'undefined') {
+ throw 'You must provide an axis to the update-scroll function';
+ }
+
+ if (typeof value === 'undefined') {
+ throw 'You must provide a value to the update-scroll function';
+ }
+
+ if (axis === 'top' && value <= 0) {
+ element.scrollTop = value = 0; // don't allow negative scroll
+ element.dispatchEvent(yStartEvent);
+ }
+
+ if (axis === 'left' && value <= 0) {
+ element.scrollLeft = value = 0; // don't allow negative scroll
+ element.dispatchEvent(xStartEvent);
+ }
+
+ var i = instances.get(element);
+
+ if (axis === 'top' && value >= i.contentHeight - i.containerHeight) {
+ element.scrollTop = value = i.contentHeight - i.containerHeight; // don't allow scroll past container
+ element.dispatchEvent(yEndEvent);
+ }
+
+ if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
+ element.scrollLeft = value = i.contentWidth - i.containerWidth; // don't allow scroll past container
+ element.dispatchEvent(xEndEvent);
+ }
+
+ if (!lastTop) {
+ lastTop = element.scrollTop;
+ }
+
+ if (!lastLeft) {
+ lastLeft = element.scrollLeft;
+ }
+
+ if (axis === 'top' && value < lastTop) {
+ element.dispatchEvent(upEvent);
+ }
+
+ if (axis === 'top' && value > lastTop) {
+ element.dispatchEvent(downEvent);
+ }
+
+ if (axis === 'left' && value < lastLeft) {
+ element.dispatchEvent(leftEvent);
+ }
+
+ if (axis === 'left' && value > lastLeft) {
+ element.dispatchEvent(rightEvent);
+ }
+
+ if (axis === 'top') {
+ element.scrollTop = lastTop = value;
+ element.dispatchEvent(yEvent);
+ }
+
+ if (axis === 'left') {
+ element.scrollLeft = lastLeft = value;
+ element.dispatchEvent(xEvent);
+ }
+
+};
+
+},{"./instances":18}],21:[function(require,module,exports){
+'use strict';
+
+var d = require('../lib/dom')
+ , h = require('../lib/helper')
+ , instances = require('./instances')
+ , updateGeometry = require('./update-geometry')
+ , updateScroll = require('./update-scroll');
+
+module.exports = function (element) {
+ var i = instances.get(element);
+
+ if (!i) {
+ return;
+ }
+
+ // Recalcuate negative scrollLeft adjustment
+ i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+
+ // Recalculate rail margins
+ d.css(i.scrollbarXRail, 'display', 'block');
+ d.css(i.scrollbarYRail, 'display', 'block');
+ i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
+ i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
+
+ // Hide scrollbars not to affect scrollWidth and scrollHeight
+ d.css(i.scrollbarXRail, 'display', 'none');
+ d.css(i.scrollbarYRail, 'display', 'none');
+
+ updateGeometry(element);
+
+ // Update top/left scroll to trigger events
+ updateScroll(element, 'top', element.scrollTop);
+ updateScroll(element, 'left', element.scrollLeft);
+
+ d.css(i.scrollbarXRail, 'display', '');
+ d.css(i.scrollbarYRail, 'display', '');
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]);
+
+(function(Plugin) {
+
+ /*jslint indent: 2, browser: true, bitwise: true, plusplus: true */
+ Plugin.Libs.Twemoji = (function (
+ /*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
+ https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
+ */
+
+ // WARNING: this file is generated automatically via
+ // `node twemoji-generator.js`
+ // please update its `createTwemoji` function
+ // at the bottom of the same file instead.
+
+ ) {
+ 'use strict';
+
+ /*jshint maxparams:4 */
+
+ var
+ // the exported module object
+ twemoji = {
+
+
+ /////////////////////////
+ // properties //
+ /////////////////////////
+
+ // default assets url, by default will be Twitter Inc. CDN
+ base: (location.protocol === 'https:' ? 'https:' : 'http:') +
+ '//twemoji.maxcdn.com/',
+
+ // default assets file extensions, by default '.png'
+ ext: '.png',
+
+ // default assets/folder size, by default "36x36"
+ // available via Twitter CDN: 16, 36, 72
+ size: '36x36',
+
+ // default class name, by default 'emoji'
+ className: 'emoji',
+
+ // basic utilities / helpers to convert code points
+ // to JavaScript surrogates and vice versa
+ convert: {
+
+ /**
+ * Given an HEX codepoint, returns UTF16 surrogate pairs.
+ *
+ * @param string generic codepoint, i.e. '1F4A9'
+ * @return string codepoint transformed into utf16 surrogates pair,
+ * i.e. \uD83D\uDCA9
+ *
+ * @example
+ * twemoji.convert.fromCodePoint('1f1e8');
+ * // "\ud83c\udde8"
+ *
+ * '1f1e8-1f1f3'.split('-').map(twemoji.convert.fromCodePoint).join('')
+ * // "\ud83c\udde8\ud83c\uddf3"
+ */
+ fromCodePoint: fromCodePoint,
+
+ /**
+ * Given UTF16 surrogate pairs, returns the equivalent HEX codepoint.
+ *
+ * @param string generic utf16 surrogates pair, i.e. \uD83D\uDCA9
+ * @param string optional separator for double code points, default='-'
+ * @return string utf16 transformed into codepoint, i.e. '1F4A9'
+ *
+ * @example
+ * twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3');
+ * // "1f1e8-1f1f3"
+ *
+ * twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3', '~');
+ * // "1f1e8~1f1f3"
+ */
+ toCodePoint: toCodePoint
+ },
+
+
+ /////////////////////////
+ // methods //
+ /////////////////////////
+
+ /**
+ * User first: used to remove missing images
+ * preserving the original text intent when
+ * a fallback for network problems is desired.
+ * Automatically added to Image nodes via DOM
+ * It could be recycled for string operations via:
+ * $('img.emoji').on('error', twemoji.onerror)
+ */
+ onerror: function onerror() {
+ if (this.parentNode) {
+ this.parentNode.replaceChild(createText(this.alt), this);
+ }
+ },
+
+ /**
+ * Main method/logic to generate either tags or HTMLImage nodes.
+ * "emojify" a generic text or DOM Element.
+ *
+ * @overloads
+ *
+ * String replacement for `innerHTML` or server side operations
+ * twemoji.parse(string);
+ * twemoji.parse(string, Function);
+ * twemoji.parse(string, Object);
+ *
+ * HTMLElement tree parsing for safer operations over existing DOM
+ * twemoji.parse(HTMLElement);
+ * twemoji.parse(HTMLElement, Function);
+ * twemoji.parse(HTMLElement, Object);
+ *
+ * @param string|HTMLElement the source to parse and enrich with emoji.
+ *
+ * string replace emoji matches with tags.
+ * Mainly used to inject emoji via `innerHTML`
+ * It does **not** parse the string or validate it,
+ * it simply replaces found emoji with a tag.
+ * NOTE: be sure this won't affect security.
+ *
+ * HTMLElement walk through the DOM tree and find emoji
+ * that are inside **text node only** (nodeType === 3)
+ * Mainly used to put emoji in already generated DOM
+ * without compromising surrounding nodes and
+ * **avoiding** the usage of `innerHTML`.
+ * NOTE: Using DOM elements instead of strings should
+ * improve security without compromising too much
+ * performance compared with a less safe `innerHTML`.
+ *
+ * @param Function|Object [optional]
+ * either the callback that will be invoked or an object
+ * with all properties to use per each found emoji.
+ *
+ * Function if specified, this will be invoked per each emoji
+ * that has been found through the RegExp except
+ * those follwed by the invariant \uFE0E ("as text").
+ * Once invoked, parameters will be:
+ *
+ * codePoint:string the lower case HEX code point
+ * i.e. "1f4a9"
+ *
+ * options:Object all info for this parsing operation
+ *
+ * variant:char the optional \uFE0F ("as image")
+ * variant, in case this info
+ * is anyhow meaningful.
+ * By default this is ignored.
+ *
+ * If such callback will return a falsy value instead
+ * of a valid `src` to use for the image, nothing will
+ * actually change for that specific emoji.
+ *
+ *
+ * Object if specified, an object containing the following properties
+ *
+ * callback Function the callback to invoke per each found emoji.
+ * base string the base url, by default twemoji.base
+ * ext string the image extension, by default twemoji.ext
+ * size string the assets size, by default twemoji.size
+ *
+ * @example
+ *
+ * twemoji.parse("I \u2764\uFE0F emoji!");
+ * // I emoji!
+ *
+ *
+ * twemoji.parse("I \u2764\uFE0F emoji!", function(icon, options, variant) {
+ * return '/assets/' + icon + '.gif';
+ * });
+ * // I emoji!
+ *
+ *
+ * twemoji.parse("I \u2764\uFE0F emoji!", {
+ * size: 72,
+ * callback: function(icon, options, variant) {
+ * return '/assets/' + options.size + '/' + icon + options.ext;
+ * }
+ * });
+ * // I emoji!
+ *
+ */
+ parse: parse,
+
+ /**
+ * Given a string, invokes the callback argument
+ * per each emoji found in such string.
+ * This is the most raw version used by
+ * the .parse(string) method itself.
+ *
+ * @param string generic string to parse
+ * @param Function a generic callback that will be
+ * invoked to replace the content.
+ * This calback wil receive standard
+ * String.prototype.replace(str, callback)
+ * arguments such:
+ * callback(
+ * match, // the emoji match
+ * icon, // the emoji text (same as text)
+ * variant // either '\uFE0E' or '\uFE0F', if present
+ * );
+ *
+ * and others commonly received via replace.
+ *
+ * NOTE: When the variant \uFE0E is found, remember this is an explicit intent
+ * from the user: the emoji should **not** be replaced with an image.
+ * In \uFE0F case one, it's the opposite, it should be graphic.
+ * This utility convetion is that only \uFE0E are not translated into images.
+ */
+ replace: replace,
+
+ /**
+ * Simplify string tests against emoji.
+ *
+ * @param string some text that might contain emoji
+ * @return boolean true if any emoji was found, false otherwise.
+ *
+ * @example
+ *
+ * if (twemoji.test(someContent)) {
+ * console.log("emoji All The Things!");
+ * }
+ */
+ test: test
+ },
+
+ // used to escape HTML special chars in attributes
+ escaper = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ "'": ''',
+ '"': '"'
+ },
+
+ // RegExp based on emoji's official Unicode standards
+ // http://www.unicode.org/Public/UNIDATA/EmojiSources.txt
+ re = /((?:\ud83c\udde8\ud83c\uddf3|\ud83c\uddfa\ud83c\uddf8|\ud83c\uddf7\ud83c\uddfa|\ud83c\uddf0\ud83c\uddf7|\ud83c\uddef\ud83c\uddf5|\ud83c\uddee\ud83c\uddf9|\ud83c\uddec\ud83c\udde7|\ud83c\uddeb\ud83c\uddf7|\ud83c\uddea\ud83c\uddf8|\ud83c\udde9\ud83c\uddea|\u0039\ufe0f?\u20e3|\u0038\ufe0f?\u20e3|\u0037\ufe0f?\u20e3|\u0036\ufe0f?\u20e3|\u0035\ufe0f?\u20e3|\u0034\ufe0f?\u20e3|\u0033\ufe0f?\u20e3|\u0032\ufe0f?\u20e3|\u0031\ufe0f?\u20e3|\u0030\ufe0f?\u20e3|\u0023\ufe0f?\u20e3|\ud83d\udeb3|\ud83d\udeb1|\ud83d\udeb0|\ud83d\udeaf|\ud83d\udeae|\ud83d\udea6|\ud83d\udea3|\ud83d\udea1|\ud83d\udea0|\ud83d\ude9f|\ud83d\ude9e|\ud83d\ude9d|\ud83d\ude9c|\ud83d\ude9b|\ud83d\ude98|\ud83d\ude96|\ud83d\ude94|\ud83d\ude90|\ud83d\ude8e|\ud83d\ude8d|\ud83d\ude8b|\ud83d\ude8a|\ud83d\ude88|\ud83d\ude86|\ud83d\ude82|\ud83d\ude81|\ud83d\ude36|\ud83d\ude34|\ud83d\ude2f|\ud83d\ude2e|\ud83d\ude2c|\ud83d\ude27|\ud83d\ude26|\ud83d\ude1f|\ud83d\ude1b|\ud83d\ude19|\ud83d\ude17|\ud83d\ude15|\ud83d\ude11|\ud83d\ude10|\ud83d\ude0e|\ud83d\ude08|\ud83d\ude07|\ud83d\ude00|\ud83d\udd67|\ud83d\udd66|\ud83d\udd65|\ud83d\udd64|\ud83d\udd63|\ud83d\udd62|\ud83d\udd61|\ud83d\udd60|\ud83d\udd5f|\ud83d\udd5e|\ud83d\udd5d|\ud83d\udd5c|\ud83d\udd2d|\ud83d\udd2c|\ud83d\udd15|\ud83d\udd09|\ud83d\udd08|\ud83d\udd07|\ud83d\udd06|\ud83d\udd05|\ud83d\udd04|\ud83d\udd02|\ud83d\udd01|\ud83d\udd00|\ud83d\udcf5|\ud83d\udcef|\ud83d\udced|\ud83d\udcec|\ud83d\udcb7|\ud83d\udcb6|\ud83d\udcad|\ud83d\udc6d|\ud83d\udc6c|\ud83d\udc65|\ud83d\udc2a|\ud83d\udc16|\ud83d\udc15|\ud83d\udc13|\ud83d\udc10|\ud83d\udc0f|\ud83d\udc0b|\ud83d\udc0a|\ud83d\udc09|\ud83d\udc08|\ud83d\udc07|\ud83d\udc06|\ud83d\udc05|\ud83d\udc04|\ud83d\udc03|\ud83d\udc02|\ud83d\udc01|\ud83d\udc00|\ud83c\udfe4|\ud83c\udfc9|\ud83c\udfc7|\ud83c\udf7c|\ud83c\udf50|\ud83c\udf4b|\ud83c\udf33|\ud83c\udf32|\ud83c\udf1e|\ud83c\udf1d|\ud83c\udf1c|\ud83c\udf1a|\ud83c\udf18|\ud83c\udccf|\ud83c\udd8e|\ud83c\udd91|\ud83c\udd92|\ud83c\udd93|\ud83c\udd94|\ud83c\udd95|\ud83c\udd96|\ud83c\udd97|\ud83c\udd98|\ud83c\udd99|\ud83c\udd9a|\ud83d\udc77|\ud83d\udec5|\ud83d\udec4|\ud83d\udec3|\ud83d\udec2|\ud83d\udec1|\ud83d\udebf|\ud83d\udeb8|\ud83d\udeb7|\ud83d\udeb5|\ud83c\ude01|\ud83c\ude32|\ud83c\ude33|\ud83c\ude34|\ud83c\ude35|\ud83c\ude36|\ud83c\ude38|\ud83c\ude39|\ud83c\ude3a|\ud83c\ude50|\ud83c\ude51|\ud83c\udf00|\ud83c\udf01|\ud83c\udf02|\ud83c\udf03|\ud83c\udf04|\ud83c\udf05|\ud83c\udf06|\ud83c\udf07|\ud83c\udf08|\ud83c\udf09|\ud83c\udf0a|\ud83c\udf0b|\ud83c\udf0c|\ud83c\udf0f|\ud83c\udf11|\ud83c\udf13|\ud83c\udf14|\ud83c\udf15|\ud83c\udf19|\ud83c\udf1b|\ud83c\udf1f|\ud83c\udf20|\ud83c\udf30|\ud83c\udf31|\ud83c\udf34|\ud83c\udf35|\ud83c\udf37|\ud83c\udf38|\ud83c\udf39|\ud83c\udf3a|\ud83c\udf3b|\ud83c\udf3c|\ud83c\udf3d|\ud83c\udf3e|\ud83c\udf3f|\ud83c\udf40|\ud83c\udf41|\ud83c\udf42|\ud83c\udf43|\ud83c\udf44|\ud83c\udf45|\ud83c\udf46|\ud83c\udf47|\ud83c\udf48|\ud83c\udf49|\ud83c\udf4a|\ud83c\udf4c|\ud83c\udf4d|\ud83c\udf4e|\ud83c\udf4f|\ud83c\udf51|\ud83c\udf52|\ud83c\udf53|\ud83c\udf54|\ud83c\udf55|\ud83c\udf56|\ud83c\udf57|\ud83c\udf58|\ud83c\udf59|\ud83c\udf5a|\ud83c\udf5b|\ud83c\udf5c|\ud83c\udf5d|\ud83c\udf5e|\ud83c\udf5f|\ud83c\udf60|\ud83c\udf61|\ud83c\udf62|\ud83c\udf63|\ud83c\udf64|\ud83c\udf65|\ud83c\udf66|\ud83c\udf67|\ud83c\udf68|\ud83c\udf69|\ud83c\udf6a|\ud83c\udf6b|\ud83c\udf6c|\ud83c\udf6d|\ud83c\udf6e|\ud83c\udf6f|\ud83c\udf70|\ud83c\udf71|\ud83c\udf72|\ud83c\udf73|\ud83c\udf74|\ud83c\udf75|\ud83c\udf76|\ud83c\udf77|\ud83c\udf78|\ud83c\udf79|\ud83c\udf7a|\ud83c\udf7b|\ud83c\udf80|\ud83c\udf81|\ud83c\udf82|\ud83c\udf83|\ud83c\udf84|\ud83c\udf85|\ud83c\udf86|\ud83c\udf87|\ud83c\udf88|\ud83c\udf89|\ud83c\udf8a|\ud83c\udf8b|\ud83c\udf8c|\ud83c\udf8d|\ud83c\udf8e|\ud83c\udf8f|\ud83c\udf90|\ud83c\udf91|\ud83c\udf92|\ud83c\udf93|\ud83c\udfa0|\ud83c\udfa1|\ud83c\udfa2|\ud83c\udfa3|\ud83c\udfa4|\ud83c\udfa5|\ud83c\udfa6|\ud83c\udfa7|\ud83c\udfa8|\ud83c\udfa9|\ud83c\udfaa|\ud83c\udfab|\ud83c\udfac|\ud83c\udfad|\ud83c\udfae|\ud83c\udfaf|\ud83c\udfb0|\ud83c\udfb1|\ud83c\udfb2|\ud83c\udfb3|\ud83c\udfb4|\ud83c\udfb5|\ud83c\udfb6|\ud83c\udfb7|\ud83c\udfb8|\ud83c\udfb9|\ud83c\udfba|\ud83c\udfbb|\ud83c\udfbc|\ud83c\udfbd|\ud83c\udfbe|\ud83c\udfbf|\ud83c\udfc0|\ud83c\udfc1|\ud83c\udfc2|\ud83c\udfc3|\ud83c\udfc4|\ud83c\udfc6|\ud83c\udfc8|\ud83c\udfca|\ud83c\udfe0|\ud83c\udfe1|\ud83c\udfe2|\ud83c\udfe3|\ud83c\udfe5|\ud83c\udfe6|\ud83c\udfe7|\ud83c\udfe8|\ud83c\udfe9|\ud83c\udfea|\ud83c\udfeb|\ud83c\udfec|\ud83c\udfed|\ud83c\udfee|\ud83c\udfef|\ud83c\udff0|\ud83d\udc0c|\ud83d\udc0d|\ud83d\udc0e|\ud83d\udc11|\ud83d\udc12|\ud83d\udc14|\ud83d\udc17|\ud83d\udc18|\ud83d\udc19|\ud83d\udc1a|\ud83d\udc1b|\ud83d\udc1c|\ud83d\udc1d|\ud83d\udc1e|\ud83d\udc1f|\ud83d\udc20|\ud83d\udc21|\ud83d\udc22|\ud83d\udc23|\ud83d\udc24|\ud83d\udc25|\ud83d\udc26|\ud83d\udc27|\ud83d\udc28|\ud83d\udc29|\ud83d\udc2b|\ud83d\udc2c|\ud83d\udc2d|\ud83d\udc2e|\ud83d\udc2f|\ud83d\udc30|\ud83d\udc31|\ud83d\udc32|\ud83d\udc33|\ud83d\udc34|\ud83d\udc35|\ud83d\udc36|\ud83d\udc37|\ud83d\udc38|\ud83d\udc39|\ud83d\udc3a|\ud83d\udc3b|\ud83d\udc3c|\ud83d\udc3d|\ud83d\udc3e|\ud83d\udc40|\ud83d\udc42|\ud83d\udc43|\ud83d\udc44|\ud83d\udc45|\ud83d\udc46|\ud83d\udc47|\ud83d\udc48|\ud83d\udc49|\ud83d\udc4a|\ud83d\udc4b|\ud83d\udc4c|\ud83d\udc4d|\ud83d\udc4e|\ud83d\udc4f|\ud83d\udc50|\ud83d\udc51|\ud83d\udc52|\ud83d\udc53|\ud83d\udc54|\ud83d\udc55|\ud83d\udc56|\ud83d\udc57|\ud83d\udc58|\ud83d\udc59|\ud83d\udc5a|\ud83d\udc5b|\ud83d\udc5c|\ud83d\udc5d|\ud83d\udc5e|\ud83d\udc5f|\ud83d\udc60|\ud83d\udc61|\ud83d\udc62|\ud83d\udc63|\ud83d\udc64|\ud83d\udc66|\ud83d\udc67|\ud83d\udc68|\ud83d\udc69|\ud83d\udc6a|\ud83d\udc6b|\ud83d\udc6e|\ud83d\udc6f|\ud83d\udc70|\ud83d\udc71|\ud83d\udc72|\ud83d\udc73|\ud83d\udc74|\ud83d\udc75|\ud83d\udc76|\ud83d\udeb4|\ud83d\udc78|\ud83d\udc79|\ud83d\udc7a|\ud83d\udc7b|\ud83d\udc7c|\ud83d\udc7d|\ud83d\udc7e|\ud83d\udc7f|\ud83d\udc80|\ud83d\udc81|\ud83d\udc82|\ud83d\udc83|\ud83d\udc84|\ud83d\udc85|\ud83d\udc86|\ud83d\udc87|\ud83d\udc88|\ud83d\udc89|\ud83d\udc8a|\ud83d\udc8b|\ud83d\udc8c|\ud83d\udc8d|\ud83d\udc8e|\ud83d\udc8f|\ud83d\udc90|\ud83d\udc91|\ud83d\udc92|\ud83d\udc93|\ud83d\udc94|\ud83d\udc95|\ud83d\udc96|\ud83d\udc97|\ud83d\udc98|\ud83d\udc99|\ud83d\udc9a|\ud83d\udc9b|\ud83d\udc9c|\ud83d\udc9d|\ud83d\udc9e|\ud83d\udc9f|\ud83d\udca0|\ud83d\udca1|\ud83d\udca2|\ud83d\udca3|\ud83d\udca4|\ud83d\udca5|\ud83d\udca6|\ud83d\udca7|\ud83d\udca8|\ud83d\udca9|\ud83d\udcaa|\ud83d\udcab|\ud83d\udcac|\ud83d\udcae|\ud83d\udcaf|\ud83d\udcb0|\ud83d\udcb1|\ud83d\udcb2|\ud83d\udcb3|\ud83d\udcb4|\ud83d\udcb5|\ud83d\udcb8|\ud83d\udcb9|\ud83d\udcba|\ud83d\udcbb|\ud83d\udcbc|\ud83d\udcbd|\ud83d\udcbe|\ud83d\udcbf|\ud83d\udcc0|\ud83d\udcc1|\ud83d\udcc2|\ud83d\udcc3|\ud83d\udcc4|\ud83d\udcc5|\ud83d\udcc6|\ud83d\udcc7|\ud83d\udcc8|\ud83d\udcc9|\ud83d\udcca|\ud83d\udccb|\ud83d\udccc|\ud83d\udccd|\ud83d\udcce|\ud83d\udccf|\ud83d\udcd0|\ud83d\udcd1|\ud83d\udcd2|\ud83d\udcd3|\ud83d\udcd4|\ud83d\udcd5|\ud83d\udcd6|\ud83d\udcd7|\ud83d\udcd8|\ud83d\udcd9|\ud83d\udcda|\ud83d\udcdb|\ud83d\udcdc|\ud83d\udcdd|\ud83d\udcde|\ud83d\udcdf|\ud83d\udce0|\ud83d\udce1|\ud83d\udce2|\ud83d\udce3|\ud83d\udce4|\ud83d\udce5|\ud83d\udce6|\ud83d\udce7|\ud83d\udce8|\ud83d\udce9|\ud83d\udcea|\ud83d\udceb|\ud83d\udcee|\ud83d\udcf0|\ud83d\udcf1|\ud83d\udcf2|\ud83d\udcf3|\ud83d\udcf4|\ud83d\udcf6|\ud83d\udcf7|\ud83d\udcf9|\ud83d\udcfa|\ud83d\udcfb|\ud83d\udcfc|\ud83d\udd03|\ud83d\udd0a|\ud83d\udd0b|\ud83d\udd0c|\ud83d\udd0d|\ud83d\udd0e|\ud83d\udd0f|\ud83d\udd10|\ud83d\udd11|\ud83d\udd12|\ud83d\udd13|\ud83d\udd14|\ud83d\udd16|\ud83d\udd17|\ud83d\udd18|\ud83d\udd19|\ud83d\udd1a|\ud83d\udd1b|\ud83d\udd1c|\ud83d\udd1d|\ud83d\udd1e|\ud83d\udd1f|\ud83d\udd20|\ud83d\udd21|\ud83d\udd22|\ud83d\udd23|\ud83d\udd24|\ud83d\udd25|\ud83d\udd26|\ud83d\udd27|\ud83d\udd28|\ud83d\udd29|\ud83d\udd2a|\ud83d\udd2b|\ud83d\udd2e|\ud83d\udd2f|\ud83d\udd30|\ud83d\udd31|\ud83d\udd32|\ud83d\udd33|\ud83d\udd34|\ud83d\udd35|\ud83d\udd36|\ud83d\udd37|\ud83d\udd38|\ud83d\udd39|\ud83d\udd3a|\ud83d\udd3b|\ud83d\udd3c|\ud83d\udd3d|\ud83d\udd50|\ud83d\udd51|\ud83d\udd52|\ud83d\udd53|\ud83d\udd54|\ud83d\udd55|\ud83d\udd56|\ud83d\udd57|\ud83d\udd58|\ud83d\udd59|\ud83d\udd5a|\ud83d\udd5b|\ud83d\uddfb|\ud83d\uddfc|\ud83d\uddfd|\ud83d\uddfe|\ud83d\uddff|\ud83d\ude01|\ud83d\ude02|\ud83d\ude03|\ud83d\ude04|\ud83d\ude05|\ud83d\ude06|\ud83d\ude09|\ud83d\ude0a|\ud83d\ude0b|\ud83d\ude0c|\ud83d\ude0d|\ud83d\ude0f|\ud83d\ude12|\ud83d\ude13|\ud83d\ude14|\ud83d\ude16|\ud83d\ude18|\ud83d\ude1a|\ud83d\ude1c|\ud83d\ude1d|\ud83d\ude1e|\ud83d\ude20|\ud83d\ude21|\ud83d\ude22|\ud83d\ude23|\ud83d\ude24|\ud83d\ude25|\ud83d\ude28|\ud83d\ude29|\ud83d\ude2a|\ud83d\ude2b|\ud83d\ude2d|\ud83d\ude30|\ud83d\ude31|\ud83d\ude32|\ud83d\ude33|\ud83d\ude35|\ud83d\ude37|\ud83d\ude38|\ud83d\ude39|\ud83d\ude3a|\ud83d\ude3b|\ud83d\ude3c|\ud83d\ude3d|\ud83d\ude3e|\ud83d\ude3f|\ud83d\ude40|\ud83d\ude45|\ud83d\ude46|\ud83d\ude47|\ud83d\ude48|\ud83d\ude49|\ud83d\ude4a|\ud83d\ude4b|\ud83d\ude4c|\ud83d\ude4d|\ud83d\ude4e|\ud83d\ude4f|\ud83d\ude80|\ud83d\ude83|\ud83d\ude84|\ud83d\ude85|\ud83d\ude87|\ud83d\ude89|\ud83d\ude8c|\ud83d\ude8f|\ud83d\ude91|\ud83d\ude92|\ud83d\ude93|\ud83d\ude95|\ud83d\ude97|\ud83d\ude99|\ud83d\ude9a|\ud83d\udea2|\ud83d\udea4|\ud83d\udea5|\ud83d\udea7|\ud83d\udea8|\ud83d\udea9|\ud83d\udeaa|\ud83d\udeab|\ud83d\udeac|\ud83d\udead|\ud83d\udeb2|\ud83d\udeb6|\ud83d\udeb9|\ud83d\udeba|\ud83d\udebb|\ud83d\udebc|\ud83d\udebd|\ud83d\udebe|\ud83d\udec0|\ud83c\udde6|\ud83c\udde7|\ud83c\udde8|\ud83c\udde9|\ud83c\uddea|\ud83c\uddeb|\ud83c\uddec|\ud83c\udded|\ud83c\uddee|\ud83c\uddef|\ud83c\uddf0|\ud83c\uddf1|\ud83c\uddf2|\ud83c\uddf3|\ud83c\uddf4|\ud83c\uddf5|\ud83c\uddf6|\ud83c\uddf7|\ud83c\uddf8|\ud83c\uddf9|\ud83c\uddfa|\ud83c\uddfb|\ud83c\uddfc|\ud83c\uddfd|\ud83c\uddfe|\ud83c\uddff|\ud83c\udf0d|\ud83c\udf0e|\ud83c\udf10|\ud83c\udf12|\ud83c\udf16|\ud83c\udf17|\ue50a|\u27b0|\u2797|\u2796|\u2795|\u2755|\u2754|\u2753|\u274e|\u274c|\u2728|\u270b|\u270a|\u2705|\u26ce|\u23f3|\u23f0|\u23ec|\u23eb|\u23ea|\u23e9|\u27bf|\u00a9|\u00ae)|(?:(?:\ud83c\udc04|\ud83c\udd70|\ud83c\udd71|\ud83c\udd7e|\ud83c\udd7f|\ud83c\ude02|\ud83c\ude1a|\ud83c\ude2f|\ud83c\ude37|\u3299|\u303d|\u3030|\u2b55|\u2b50|\u2b1c|\u2b1b|\u2b07|\u2b06|\u2b05|\u2935|\u2934|\u27a1|\u2764|\u2757|\u2747|\u2744|\u2734|\u2733|\u2716|\u2714|\u2712|\u270f|\u270c|\u2709|\u2708|\u2702|\u26fd|\u26fa|\u26f5|\u26f3|\u26f2|\u26ea|\u26d4|\u26c5|\u26c4|\u26be|\u26bd|\u26ab|\u26aa|\u26a1|\u26a0|\u2693|\u267f|\u267b|\u3297|\u2666|\u2665|\u2663|\u2660|\u2653|\u2652|\u2651|\u2650|\u264f|\u264e|\u264d|\u264c|\u264b|\u264a|\u2649|\u2648|\u263a|\u261d|\u2615|\u2614|\u2611|\u260e|\u2601|\u2600|\u25fe|\u25fd|\u25fc|\u25fb|\u25c0|\u25b6|\u25ab|\u25aa|\u24c2|\u231b|\u231a|\u21aa|\u21a9|\u2199|\u2198|\u2197|\u2196|\u2195|\u2194|\u2139|\u2122|\u2049|\u203c|\u2668)([\uFE0E\uFE0F]?)))/g,
+
+ // used to find HTML special chars in attributes
+ rescaper = /[&<>'"]/g,
+
+ // nodes with type 1 which should **not** be parsed (including lower case svg)
+ shouldntBeParsed = /IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,
+
+ // just a private shortcut
+ fromCharCode = String.fromCharCode;
+
+ return twemoji;
+
+
+ /////////////////////////
+ // private functions //
+ // declaration //
+ /////////////////////////
+
+ /**
+ * Shortcut to create text nodes
+ * @param string text used to create DOM text node
+ * @return Node a DOM node with that text
+ */
+ function createText(text) {
+ return document.createTextNode(text);
+ }
+
+ /**
+ * Utility function to escape html attribute text
+ * @param string text use in HTML attribute
+ * @return string text encoded to use in HTML attribute
+ */
+ function escapeHTML(s) {
+ return s.replace(rescaper, replacer);
+ }
+
+ /**
+ * Default callback used to generate emoji src
+ * based on Twitter CDN
+ * @param string the emoji codepoint string
+ * @param string the default size to use, i.e. "36x36"
+ * @param string optional "\uFE0F" variant char, ignored by default
+ * @return string the image source to use
+ */
+ function defaultImageSrcGenerator(icon, options) {
+ return ''.concat(options.base, options.size, '/', icon, options.ext);
+ }
+
+ /**
+ * Given a generic DOM nodeType 1, walk through all children
+ * and store every nodeType 3 (#text) found in the tree.
+ * @param Element a DOM Element with probably some text in it
+ * @param Array the list of previously discovered text nodes
+ * @return Array same list with new discovered nodes, if any
+ */
+ function grabAllTextNodes(node, allText) {
+ var
+ childNodes = node.childNodes,
+ length = childNodes.length,
+ subnode,
+ nodeType;
+ while (length--) {
+ subnode = childNodes[length];
+ nodeType = subnode.nodeType;
+ // parse emoji only in text nodes
+ if (nodeType === 3) {
+ // collect them to process emoji later
+ allText.push(subnode);
+ }
+ // ignore all nodes that are not type 1 or that
+ // should not be parsed as script, style, and others
+ else if (nodeType === 1 && !shouldntBeParsed.test(subnode.nodeName)) {
+ grabAllTextNodes(subnode, allText);
+ }
+ }
+ return allText;
+ }
+
+ /**
+ * Used to both remove the possible variant
+ * and to convert utf16 into code points
+ * @param string the emoji surrogate pair
+ * @param string the optional variant char, if any
+ */
+ function grabTheRightIcon(icon, variant) {
+ // if variant is present as \uFE0F
+ return toCodePoint(
+ variant === '\uFE0F' ?
+ // the icon should not contain it
+ icon.slice(0, -1) :
+ // fix non standard OSX behavior
+ (icon.length === 3 && icon.charAt(1) === '\uFE0F' ?
+ icon.charAt(0) + icon.charAt(2) : icon)
+ );
+ }
+
+ /**
+ * DOM version of the same logic / parser:
+ * emojify all found sub-text nodes placing images node instead.
+ * @param Element generic DOM node with some text in some child node
+ * @param Object options containing info about how to parse
+ *
+ * .callback Function the callback to invoke per each found emoji.
+ * .base string the base url, by default twemoji.base
+ * .ext string the image extension, by default twemoji.ext
+ * .size string the assets size, by default twemoji.size
+ *
+ * @return Element same generic node with emoji in place, if any.
+ */
+ function parseNode(node, options) {
+ var
+ allText = grabAllTextNodes(node, []),
+ length = allText.length,
+ attrib,
+ attrname,
+ modified,
+ fragment,
+ subnode,
+ text,
+ match,
+ i,
+ index,
+ img,
+ alt,
+ icon,
+ variant,
+ src;
+ while (length--) {
+ modified = false;
+ fragment = document.createDocumentFragment();
+ subnode = allText[length];
+ text = subnode.nodeValue;
+ i = 0;
+ while ((match = re.exec(text))) {
+ index = match.index;
+ if (index !== i) {
+ fragment.appendChild(
+ createText(text.slice(i, index))
+ );
+ }
+ alt = match[0];
+ icon = match[1];
+ variant = match[2];
+ i = index + alt.length;
+ if (variant !== '\uFE0E') {
+ src = options.callback(
+ grabTheRightIcon(icon, variant),
+ options,
+ variant
+ );
+ if (src) {
+ img = new Image();
+ img.onerror = options.onerror;
+ img.setAttribute('draggable', 'false');
+ attrib = options.attributes(icon, variant);
+ for (attrname in attrib) {
+ if (
+ attrib.hasOwnProperty(attrname) &&
+ // don't allow any handlers to be set + don't allow overrides
+ attrname.indexOf('on') !== 0 &&
+ !img.hasAttribute(attrname)
+ ) {
+ img.setAttribute(attrname, attrib[attrname]);
+ }
+ }
+ img.className = options.className;
+ img.alt = alt;
+ img.src = src;
+ modified = true;
+ fragment.appendChild(img);
+ }
+ }
+ if (!img) fragment.appendChild(createText(alt));
+ img = null;
+ }
+ // is there actually anything to replace in here ?
+ if (modified) {
+ // any text left to be added ?
+ if (i < text.length) {
+ fragment.appendChild(
+ createText(text.slice(i))
+ );
+ }
+ // replace the text node only, leave intact
+ // anything else surrounding such text
+ subnode.parentNode.replaceChild(fragment, subnode);
+ }
+ }
+ return node;
+ }
+
+ /**
+ * String/HTML version of the same logic / parser:
+ * emojify a generic text placing images tags instead of surrogates pair.
+ * @param string generic string with possibly some emoji in it
+ * @param Object options containing info about how to parse
+ *
+ * .callback Function the callback to invoke per each found emoji.
+ * .base string the base url, by default twemoji.base
+ * .ext string the image extension, by default twemoji.ext
+ * .size string the assets size, by default twemoji.size
+ *
+ * @return the string with replacing all found and parsed emoji
+ */
+ function parseString(str, options) {
+ return replace(str, function (match, icon, variant) {
+ var
+ ret = match,
+ attrib,
+ attrname,
+ src;
+ // verify the variant is not the FE0E one
+ // this variant means "emoji as text" and should not
+ // require any action/replacement
+ // http://unicode.org/Public/UNIDATA/StandardizedVariants.html
+ if (variant !== '\uFE0E') {
+ src = options.callback(
+ grabTheRightIcon(icon, variant),
+ options,
+ variant
+ );
+ if (src) {
+ // recycle the match string replacing the emoji
+ // with its image counter part
+ ret = ' ');
+ }
+ }
+ return ret;
+ });
+ }
+
+ /**
+ * Function used to actually replace HTML special chars
+ * @param string HTML special char
+ * @return string encoded HTML special char
+ */
+ function replacer(m) {
+ return escaper[m];
+ }
+
+ /**
+ * Default options.attribute callback
+ * @return null
+ */
+ function returnNull() {
+ return null;
+ }
+
+ /**
+ * Given a generic value, creates its squared counterpart if it's a number.
+ * As example, number 36 will return '36x36'.
+ * @param any a generic value.
+ * @return any a string representing asset size, i.e. "36x36"
+ * only in case the value was a number.
+ * Returns initial value otherwise.
+ */
+ function toSizeSquaredAsset(value) {
+ return typeof value === 'number' ?
+ value + 'x' + value :
+ value;
+ }
+
+
+ /////////////////////////
+ // exported functions //
+ // declaration //
+ /////////////////////////
+
+ function fromCodePoint(codepoint) {
+ var code = typeof codepoint === 'string' ?
+ parseInt(codepoint, 16) : codepoint;
+ if (code < 0x10000) {
+ return fromCharCode(code);
+ }
+ code -= 0x10000;
+ return fromCharCode(
+ 0xD800 + (code >> 10),
+ 0xDC00 + (code & 0x3FF)
+ );
+ }
+
+ function parse(what, how) {
+ if (!how || typeof how === 'function') {
+ how = {callback: how};
+ }
+ // if first argument is string, inject html tags
+ // otherwise use the DOM tree and parse text nodes only
+ return (typeof what === 'string' ? parseString : parseNode)(what, {
+ callback: how.callback || defaultImageSrcGenerator,
+ attributes: typeof how.attributes === 'function' ? how.attributes : returnNull,
+ base: typeof how.base === 'string' ? how.base : twemoji.base,
+ ext: how.ext || twemoji.ext,
+ size: how.folder || toSizeSquaredAsset(how.size || twemoji.size),
+ className: how.className || twemoji.className,
+ onerror: how.onerror || twemoji.onerror
+ });
+ }
+
+ function replace(text, callback) {
+ return String(text).replace(re, callback);
+ }
+
+ function test(text) {
+ // IE6 needs a reset before too
+ re.lastIndex = 0;
+ var result = re.test(text);
+ re.lastIndex = 0;
+ return result;
+ }
+
+ function toCodePoint(unicodeSurrogates, sep) {
+ var
+ r = [],
+ c = 0,
+ p = 0,
+ i = 0;
+ while (i < unicodeSurrogates.length) {
+ c = unicodeSurrogates.charCodeAt(i++);
+ if (p) {
+ r.push((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).toString(16));
+ p = 0;
+ } else if (0xD800 <= c && c <= 0xDBFF) {
+ p = c;
+ } else {
+ r.push(c.toString(16));
+ }
+ }
+ return r.join(sep || '-');
+ }
+
+ }());
+
+})(window.StickersModule);
+
+window.StickersModule.Service = {};
+
+(function(Plugin) {
+
+ Plugin.Service.Ajax = function(options) {
+ options = options || {};
+
+ if (!options.url) {
+ return;
+ }
+
+ options.type = (options.type && options.type.toUpperCase()) || 'GET';
+ options.headers = options.headers || {};
+ options.data = options.data || {};
+ options.success = options.success || function() {};
+ options.error = options.error || function() {};
+ options.complete = options.complete || function() {};
+
+ options.headers.Apikey = Plugin.Configs.apiKey;
+ options.headers.Platform = 'JS';
+ options.headers.Localization = Plugin.Configs.lang;
+ options.headers.UserId = Plugin.Configs.userId;
+
+ if (options.type == 'POST' || options.type == 'PUT') {
+ options.headers['Content-Type'] = options.headers['Content-Type'] || 'application/json';
+ options.headers['DeviceId'] = Plugin.Service.Storage.getDeviceId();
+ }
+
+
+ var xmlhttp = new XMLHttpRequest();
+ xmlhttp.open(options.type, options.url, true);
+
+ for (var name in options.headers) {
+ xmlhttp.setRequestHeader(name, options.headers[name]);
+ }
+
+ xmlhttp.onreadystatechange = function() {
+ if (xmlhttp.readyState == 4) {
+ if (xmlhttp.status == 200) {
+ options.success(JSON.parse(xmlhttp.responseText), xmlhttp);
+ } else {
+ var response = {};
+ try {
+ response = JSON.parse(xmlhttp.responseText);
+ } catch (ex) {
+ response = {}
+ }
+ options.error(response, xmlhttp);
+ }
+
+ options.complete(JSON.parse(xmlhttp.responseText), xmlhttp);
+ }
+ };
+
+ xmlhttp.send(JSON.stringify(options.data));
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ var API_VERSION = 2;
+
+ Plugin.Service.Api = {
+
+ getApiVersion: function() {
+ return API_VERSION;
+ },
+
+ getPacks: function(successCallback) {
+ Plugin.Service.Ajax({
+ type: 'get',
+ url: Plugin.Service.Url.getUserPacksUrl(),
+ success: function(response) {
+ response = response || {};
+ response.meta = response.meta || {};
+ response.meta.shop_last_modified = response.meta.shop_last_modified || 0;
+
+ Plugin.Service.Storage.setStoreLastModified(response.meta.shop_last_modified * 1000);
+
+ successCallback && successCallback(response.data);
+ }
+ });
+ },
+
+ getPackPreview: function(packName, successCallback) {
+ Plugin.Service.Ajax({
+ type: 'get',
+ url: Plugin.Service.Url.getPackPreviewUrl(packName),
+ success: function(response) {
+ successCallback && successCallback(response.data);
+ }
+ });
+ },
+
+ sendStatistic: function(statistic) {
+ Plugin.Service.Ajax({
+ type: 'post',
+ url: Plugin.Service.Url.getStatisticUrl(),
+ data: statistic
+ });
+ },
+
+ updateUserData: function(userData) {
+ return Plugin.Service.Ajax({
+ type: 'put',
+ url: Plugin.Service.Url.getUserDataUrl(),
+ data: userData,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+ },
+
+ purchasePack: function(packName, pricePoint, successCallback, failCallback) {
+ Plugin.Service.Ajax({
+ type: 'post',
+ url: Plugin.Service.Url.getPurchaseUrl(packName, pricePoint),
+ success: function(response) {
+ successCallback && successCallback(response.data);
+ },
+ error: function() {
+ var pr = Plugin.Service.PendingRequest;
+ pr.add(pr.tasks.purchasePack, {
+ packName: packName,
+ pricePoint: pricePoint
+ });
+
+ failCallback && failCallback();
+ }
+ });
+ },
+
+ getContentById: function(contentId, successCallback) {
+ Plugin.Service.Ajax({
+ type: 'get',
+ url: Plugin.Service.Url.getContentByIdUrl(contentId),
+ success: function(response) {
+ successCallback && successCallback(response.data);
+ }
+ });
+ },
+
+ hidePack: function(packName, successCallback, failCallback) {
+ return Plugin.Service.Ajax({
+ type: 'DELETE',
+ url: Plugin.Service.Url.getHidePackUrl(packName),
+ success: function(response) {
+ successCallback && successCallback(response.data);
+ },
+ error: function() {
+ failCallback && failCallback();
+ }
+ });
+ }
+ };
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.El = {
+
+ css: function(el, property) {
+ // todo: getComputedStyle add IE 8 supporting
+
+ return (el.style && el.style[property])
+ || (el.currentStyle && el.currentStyle[property])
+ || (getComputedStyle(el)[property]);
+
+ },
+
+ outerWidth: function(el) {
+ var width = el.offsetWidth;
+ width += parseInt(this.css(el, 'marginLeft')) + parseInt(this.css(el, 'marginRight'));
+ return width;
+ },
+
+ appendAfter: function(newNode, referenceNode) {
+ referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+ },
+
+ getParents: function (elem, selector) {
+
+ var parents = [];
+ if ( selector ) {
+ var firstChar = selector.charAt(0);
+ }
+
+ // Get matches
+ for ( ; elem && elem !== document; elem = elem.parentNode ) {
+ if ( selector ) {
+
+ // If selector is a class
+ if ( firstChar === '.' ) {
+ if ( elem.classList.contains( selector.substr(1) ) ) {
+ parents.push( elem );
+ }
+ }
+
+ // If selector is an ID
+ if ( firstChar === '#' ) {
+ if ( elem.id === selector.substr(1) ) {
+ parents.push( elem );
+ }
+ }
+
+ // If selector is a data attribute
+ if ( firstChar === '[' ) {
+ if ( elem.hasAttribute( selector.substr(1, selector.length - 1) )) {
+ parents.push( elem );
+ }
+ }
+
+ // If selector is a tag
+ if ( elem.tagName.toLowerCase() === selector ) {
+ parents.push( elem );
+ }
+
+ } else {
+ parents.push( elem );
+ }
+
+ }
+
+ // Return parents if any exist
+ if ( parents.length === 0 ) {
+ return null;
+ } else {
+ return parents;
+ }
+
+ }
+ };
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.Emoji = {
+
+ emojiProvider: null,
+
+ init: function(emojiProvider) {
+ this.emojiProvider = emojiProvider;
+ },
+
+ parseEmojiFromText: function(text) {
+ return this.emojiProvider.parse(text, {
+ size: (window.devicePixelRatio == 2) ? 72 : 36
+ });
+ },
+
+ parseEmojiFromHtml: function(html) {
+ var content = document.createElement('div');
+ content.innerHTML = html;
+
+ var emojisEls = content.getElementsByClassName('emoji');
+
+ for (var i = emojisEls.length - 1; i >= 0; i--) {
+ var emoji = emojisEls[i].getAttribute('alt');
+ content.replaceChild(document.createTextNode(emoji), emojisEls[i]);
+ }
+
+ return content.innerHTML;
+ }
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.Event = {
+
+ events: {
+ resize: 'resize',
+ popoverShown: 'sp:popover:shown',
+ popoverHidden: 'sp:popover:hidden',
+ showContentHighlight: 'sp:content:highlight:show',
+ hideContentHighlight: 'sp:content:highlight:hide'
+ },
+
+ dispatch: function(eventName, el) {
+ if (!eventName) {
+ return;
+ }
+
+ el = el || window;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent('HTMLEvents');
+ event.initEvent(eventName, true, true);
+ } else if (document.createEventObject) { // IE < 9
+ event = document.createEventObject();
+ event.eventType = eventName;
+ }
+
+ event.eventName = eventName;
+
+ if (el.dispatchEvent) {
+ el.dispatchEvent(event);
+ } else if (el.fireEvent) { // IE < 9
+ el.fireEvent('on' + event.eventType, event);// can trigger only real event (e.g. 'click')
+ } else if (el[eventName]) {
+ el[eventName]();
+ } else if (el['on' + eventName]) {
+ el['on' + eventName]();
+ }
+ },
+
+ popoverShown: function() {
+ this.dispatch(this.events.popoverShown);
+ },
+
+ popoverHidden: function() {
+ this.dispatch(this.events.popoverHidden);
+ },
+
+ changeContentHighlight: function(value) {
+ this.dispatch((value) ? this.events.showContentHighlight : this.events.hideContentHighlight);
+ },
+
+ resize: function(el) {
+ this.dispatch(this.events.resize, el);
+ }
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.Helper = {
+
+ extend: function(out) {
+ out = out || {};
+
+ for (var i = 1; i < arguments.length; i++) {
+ if (!arguments[i])
+ continue;
+
+ for (var key in arguments[i]) {
+ if (arguments[i].hasOwnProperty(key))
+ out[key] = arguments[i][key];
+ }
+ }
+
+ return out;
+ },
+
+ setConfig: function(config) {
+ Plugin.Configs = this.extend({}, Plugin.Configs || {}, config);
+ },
+
+ setEvent: function(eventType, el, className, callback) {
+
+ el.addEventListener(eventType, function (event) {
+
+ var el = event.target, found;
+
+ while (el && !(found = el.className.match(className))) {
+ el = el.parentElement;
+ }
+
+ if (found) {
+ callback(el, event);
+ }
+ });
+ },
+
+ urlParamsSerialize: function(params) {
+ var str = [];
+ for(var p in params)
+ if (params.hasOwnProperty(p)) {
+ str.push(encodeURIComponent(p) + "=" + encodeURIComponent(params[p]));
+ }
+ return str.join('&');
+ },
+
+ isIE: function() {
+ return ((navigator.appName == 'Microsoft Internet Explorer') ||
+ (navigator.userAgent.match(/MSIE\s+\d+\.\d+/)) ||
+ (navigator.userAgent.match(/Trident\/\d+\.\d+/)));
+ },
+
+ md5: function(string) {
+ return Plugin.Libs.MD5(string);
+ },
+
+ getLocation: function(url) {
+ var location = document.createElement('a');
+ location.href = url;
+ return location;
+ },
+
+ getDomain: function(url) {
+ var location = this.getLocation(url);
+ return location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '');
+ },
+
+ getMobileOS: function() {
+ var userAgent = navigator.userAgent || navigator.vendor || window.opera;
+
+ if(userAgent.match( /iPad/i ) || userAgent.match( /iPhone/i ) || userAgent.match( /iPod/i )) {
+ return 'ios';
+ } else if(userAgent.match( /Android/i )) {
+ return 'android';
+ } else {
+ return 'other';
+ }
+ }
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.Highlight = {
+
+ check: function() {
+
+ var showContentHighlight = Plugin.Service.Packs.isExistUnwatched();
+ if (!showContentHighlight && Plugin.Service.Storage.getRecentStickers().length == 0) {
+ showContentHighlight = true;
+ }
+
+ if (!showContentHighlight &&
+ Plugin.Service.Storage.getStoreLastModified() > Plugin.Service.Storage.getStoreLastVisit()) {
+ showContentHighlight = true;
+ }
+ Plugin.Service.Event.changeContentHighlight(showContentHighlight);
+ }
+
+ };
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ var stickerpipe;
+
+ Plugin.Service.Pack = {
+
+ init: function(_stickerpipe) {
+ stickerpipe = _stickerpipe;
+ },
+
+ purchase: function(packName, pricePoint, isUnwatched, successCallback, failCallback) {
+ isUnwatched = (typeof isUnwatched == 'undefined') ? true : isUnwatched;
+
+ Plugin.Service.Api.purchasePack(packName, pricePoint, function(pack) {
+ pack.isUnwatched = isUnwatched;
+
+ var packContentIds = [];
+ for (var i = 0; i < pack.stickers.length; i++) {
+ var sticker = pack.stickers[i];
+ sticker.pack = packName;
+
+ Plugin.Service.Storage.setContentById(sticker.content_id, sticker);
+
+ packContentIds.push(sticker.content_id);
+ }
+
+ pack.stickers = packContentIds;
+
+ Plugin.Service.Storage.setPack(pack.pack_name, pack, true);
+
+ if (stickerpipe && stickerpipe.view.isRendered) {
+ stickerpipe.view.tabsView.renderPacks();
+ }
+
+ successCallback && successCallback(pack);
+ }, function() {
+ failCallback && failCallback();
+ });
+ },
+
+ remove: function(packName, successCallback, failCallback) {
+ Plugin.Service.Api.hidePack(packName, function() {
+
+ var pack = Plugin.Service.Storage.getPack(packName);
+ pack.user_status = 'hidden';
+ Plugin.Service.Storage.setPack(packName, pack);
+
+ if (stickerpipe && stickerpipe.view.isRendered) {
+ stickerpipe.view.tabsView.renderPacks();
+ stickerpipe.view.tabsView.controls.history.el.click();
+ }
+
+ successCallback && successCallback();
+ }, function() {
+ failCallback && failCallback();
+ });
+ },
+
+ getMainIcon: function(packName, successCallback) {
+ Plugin.Service.Api.getPackPreview(packName, function(pack) {
+ var url = (pack && pack.main_icon && pack.main_icon[Plugin.Configs.stickerResolutionType]) || null;
+
+ successCallback && successCallback(url);
+ });
+ },
+
+ isHidden: function(pack) {
+ return pack.user_status == 'hidden';
+ }
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ function filterRecentStickers() {
+
+ var packs = Plugin.Service.Storage.getPacks(),
+ recentStickersIds = Plugin.Service.Storage.getRecentStickers();
+
+ for (var i = 0; i < recentStickersIds.length; i++) {
+
+ Plugin.Service.Sticker.getById(recentStickersIds[i], function(sticker) {
+
+ // check existing sticker pack
+ var pack = null;
+
+ for (var j = 0; j < packs.length; j++) {
+ if (packs[j].pack_name == sticker.pack) {
+ pack = packs[j];
+ break;
+ }
+ }
+
+ if (pack == null) {
+ recentStickersIds.splice(i, 1);
+ Plugin.Service.Storage.setRecentStickers(recentStickersIds);
+ return;
+ }
+
+ // check existing sticker in pack
+ var exist = false;
+ for (var j = 0; j < pack.stickers.length; j++) {
+ if (pack.stickers[j] == sticker.content_id) {
+ exist = true;
+ break;
+ }
+ }
+
+ if (!exist) {
+ recentStickersIds.splice(i, 1);
+ Plugin.Service.Storage.setRecentStickers(recentStickersIds);
+ return;
+ }
+ });
+
+ }
+ }
+
+ Plugin.Service.Packs = {
+
+ fetch: function(callback) {
+
+ Plugin.Service.Api.getPacks(function(packs) {
+
+ var packsInStorage = Plugin.Service.Storage.getPacks(),
+ undefinedPacksInStorage = [];
+
+ if (!packsInStorage.length) {
+ undefinedPacksInStorage = packs;
+ } else {
+ for (var i = 0; i < packs.length; i++) {
+ var packInStorage = null;
+
+ for (var j = 0; j < packsInStorage.length; j++) {
+ if (packs[i].pack_name == packsInStorage[j].pack_name) {
+ packInStorage = packsInStorage[j];
+ break;
+ }
+ }
+
+ if (packInStorage && packs[i].updated_at == packInStorage.updated_at) {
+ packs[i] = packInStorage;
+ } else {
+ undefinedPacksInStorage.push(packs[i]);
+ }
+ }
+ }
+
+ Plugin.Service.Storage.setPacks(packs);
+
+ for (var i = 0; i < undefinedPacksInStorage.length; i++) {
+ if (Plugin.Service.Pack.isHidden(undefinedPacksInStorage[i])) {
+ continue;
+ }
+
+ Plugin.Service.Pack.purchase(
+ undefinedPacksInStorage[i].pack_name,
+ undefinedPacksInStorage[i].pricepoint,
+ (packsInStorage.length) ? true : false
+ );
+ }
+
+ filterRecentStickers();
+
+ Plugin.Service.Highlight.check();
+
+ callback && callback();
+ });
+ },
+
+ isExistUnwatched: function() {
+ var packs = Plugin.Service.Storage.getPacks();
+
+ for(var i = 0; i < packs.length; i++) {
+ if (!!packs[i].isUnwatched) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ function purchasePack(taskData) {
+ Plugin.Service.Pack.purchase(taskData.packName, taskData.pricePoint);
+ }
+
+ Plugin.Service.PendingRequest = {
+
+ tasks: {
+ activateUserPack: 'activateUserPack',
+ purchasePack: 'purchasePack'
+ },
+
+ init: function() {
+ this.run();
+ },
+
+ add: function(taskName, taskData) {
+ Plugin.Service.Storage.addPendingRequestTask({
+ name: taskName,
+ data: taskData
+ });
+ },
+
+ run: function() {
+ var task = Plugin.Service.Storage.popPendingRequestTask();
+
+ while(task) {
+ switch (task.name) {
+ case this.tasks.activateUserPack:
+ case this.tasks.purchasePack:
+ purchasePack(task.data);
+ break;
+ default :
+ break;
+ }
+
+ task = Plugin.Service.Storage.popPendingRequestTask();
+ }
+ }
+
+ };
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ function trackStatistic(category, action, label) {
+ Plugin.Service.Api.sendStatistic([{
+ category: category,
+ action: action,
+ label: label
+ }]);
+
+ ga('stickerTracker.send', 'event', category, action, label);
+ }
+
+ Plugin.Service.Statistic = {
+
+ messageSend: function(isSticker) {
+ trackStatistic('message', 'send', ((isSticker) ? 'sticker' : 'text'));
+ },
+
+ useSticker: function(stickerId) {
+ trackStatistic('sticker', 'use', stickerId);
+ },
+
+ useEmoji: function(emoji) {
+ trackStatistic('emoji', 'use', emoji);
+ }
+
+ };
+
+})(StickersModule);
+
+
+(function(Plugin) {
+
+
+ Plugin.Service.Sticker = {
+
+ parseStickerId: function(text) {
+ if (!text) {
+ return null;
+ }
+
+ var stickerId = null,
+ formatV1 = text.match(/\[\[(\S+)_(\S+)\]\]/),
+ formatV2 = text.match(/\[\[(\d+)\]\]/);
+
+ if (formatV1) {
+ stickerId = formatV1[1] + '_' + formatV1[2];
+ } else if (formatV2) {
+ stickerId = formatV2[1];
+ }
+
+ return stickerId;
+ },
+
+ parse: function(text, callback) {
+
+ var stickerId = this.parseStickerId(text);
+
+ if (!stickerId) {
+ callback && callback(null);
+ return;
+ }
+
+ Plugin.Service.Sticker.getById(stickerId, function(sticker, async) {
+ var url = sticker.image && sticker.image[Plugin.Configs.stickerResolutionType];
+
+ callback && callback({
+ id: stickerId,
+ url: url,
+ html: ' '
+ }, async);
+ });
+ },
+
+ getById: function(contentId, successCallback) {
+ var sticker = Plugin.Service.Storage.getContentById(contentId);
+
+ if (sticker) {
+ successCallback && successCallback(sticker, false);
+ return;
+ }
+
+ Plugin.Service.Api.getContentById(contentId, function(sticker) {
+ Plugin.Service.Storage.setContentById(contentId, sticker);
+ successCallback && successCallback(sticker, true);
+ });
+ },
+
+ isSticker: function(text) {
+ return !!this.parseStickerId(text);
+ }
+ };
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ var lockr = Plugin.Libs.Lockr;
+
+ Plugin.Service.Storage = {
+
+ get: function(key) {
+ lockr.prefix = Plugin.Configs.storagePrefix;
+ return lockr.get(key);
+ },
+ set: function(key, data) {
+ lockr.prefix = Plugin.Configs.storagePrefix;
+ return lockr.set(key, data);
+ },
+
+ ///////////////////////////////////////
+ // Used stickers
+ ///////////////////////////////////////
+ getRecentStickers: function() {
+ return this.get('recent_stickers') || [];
+ },
+ setRecentStickers: function(recentStickers) {
+ return this.set('recent_stickers', recentStickers);
+ },
+ addRecentSticker: function(stickerId) {
+
+ var recentStickers = this.getRecentStickers();
+
+ for (var i = 0; i < recentStickers.length; i++) {
+ if (recentStickers[i] == stickerId) {
+ recentStickers.splice(i, 1);
+ }
+ }
+
+ recentStickers.unshift(stickerId);
+
+ this.setRecentStickers(recentStickers);
+ },
+
+ ///////////////////////////////////////
+ // Packs
+ ///////////////////////////////////////
+ getPacks: function() {
+ return this.get('packs') || [];
+ },
+ setPacks: function(packs) {
+ return this.set('packs', packs)
+ },
+
+ getPack: function(packName) {
+ var packs = this.getPacks();
+
+ for (var i = 0; i < packs.length; i++) {
+ if (packName == packs[i].pack_name) {
+ return packs[i];
+ }
+ }
+
+ return null;
+ },
+ setPack: function(packName, pack, toBeginning) {
+ toBeginning = (typeof toBeginning != 'undefined') ? toBeginning : false;
+
+ var packExist = false,
+ packs = this.getPacks();
+
+ for (var i = 0; i < packs.length; i++) {
+ if (packName == packs[i].pack_name) {
+ packs[i] = pack;
+ packExist = true;
+
+ if (toBeginning) {
+ packs.splice(i, 1);
+ }
+ break;
+ }
+ }
+
+ if (!packExist || toBeginning) {
+ packs.unshift(pack);
+ }
+
+ this.setPacks(packs);
+ },
+
+ ///////////////////////////////////////
+ // Content
+ ///////////////////////////////////////
+ getContent: function() {
+ return this.get('content') || {};
+ },
+ setContent: function(content) {
+ return this.set('content', content || {})
+ },
+
+ getContentById: function(id) {
+ return this.getContent()['id' + id] || null;
+ },
+ setContentById: function(id, data) {
+ var content = this.getContent();
+ content['id' + id] = data || null;
+ this.setContent(content);
+ },
+ ///////////////////////////////////////
+ // Device ID
+ ///////////////////////////////////////
+ getDeviceId: function() {
+ var deviceId = this.get('device_id');
+
+ if (typeof deviceId == 'undefined') {
+ deviceId = + new Date();
+ this.set('device_id', deviceId);
+ }
+
+ return deviceId;
+ },
+
+ ///////////////////////////////////////
+ // User ID
+ ///////////////////////////////////////
+ getUserId: function() {
+ return this.get('user_id');
+ },
+ setUserId: function(userId) {
+ return this.set('user_id', userId);
+ },
+
+ ///////////////////////////////////////
+ // User data
+ ///////////////////////////////////////
+ getUserData: function() {
+ return this.get('user_data');
+ },
+ setUserData: function(userData) {
+ return this.set('user_data', userData);
+ },
+
+ ///////////////////////////////////////
+ // Pending request
+ ///////////////////////////////////////
+ getPendingRequestTasks: function() {
+ return this.get('pending_request_tasks') || [];
+ },
+ setPendingRequestTasks: function(tasks) {
+ return this.set('pending_request_tasks', tasks);
+ },
+ addPendingRequestTask: function(task) {
+
+ var tasks = this.getPendingRequestTasks();
+
+ tasks.push(task);
+
+ this.setPendingRequestTasks(tasks);
+ },
+ popPendingRequestTask: function() {
+ var tasks = this.getPendingRequestTasks(),
+ task = tasks.pop();
+
+ this.setPendingRequestTasks(tasks);
+
+ return task;
+ },
+
+ ///////////////////////////////////////
+ // Metadata
+ ///////////////////////////////////////
+ getMetadata: function(key) {
+ var metadata = this.get('metadata');
+
+ if (key) {
+ metadata = metadata[key];
+ }
+
+ return metadata;
+ },
+ setMetadata: function(key, value) {
+ var metadata = this.getMetadata() || {};
+
+ metadata[key] = value;
+
+ return this.set('metadata', metadata);
+ },
+
+ // todo: create Metadata service
+ ///////////////////////////////////////
+ // Last store visit
+ ///////////////////////////////////////
+ getStoreLastVisit: function() {
+ return this.getMetadata()['last_store_visit'] || 0;
+ },
+ setStoreLastVisit: function(time) {
+ return this.setMetadata('last_store_visit', time);
+ },
+
+ ///////////////////////////////////////
+ // Last store visit
+ ///////////////////////////////////////
+ getStoreLastModified: function() {
+ return this.getMetadata()['shop_last_modified'];
+ },
+ setStoreLastModified: function(time) {
+ return this.setMetadata('shop_last_modified', time);
+ }
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.Url = {
+
+ buildStoreUrl: function(uri) {
+ uri = uri || '';
+
+ var platform = 'JS',
+ style = platform,
+ primaryColor = Plugin.Configs.primaryColor;
+
+ if (Plugin.Service.Helper.getMobileOS() == 'ios' || navigator.appVersion.indexOf('Mac') != -1) {
+ style = 'ios';
+ }
+
+ if (primaryColor.charAt(0) == '#') {
+ primaryColor = primaryColor.substr(1);
+ }
+
+ var params = {
+ apiKey: Plugin.Configs.apiKey,
+ platform: platform,
+ userId: Plugin.Configs.userId,
+ density: Plugin.Configs.stickerResolutionType,
+ priceB: Plugin.Configs.priceB,
+ priceC: Plugin.Configs.priceC,
+ is_subscriber: (Plugin.Configs.userPremium ? 1 : 0),
+ localization: Plugin.Configs.lang,
+ style: style,
+ primaryColor: primaryColor
+ };
+
+ var url = Plugin.Configs.storeUrl || this.buildApiUrl('/web');
+
+ url += ((url.indexOf('?') == -1) ? '?' : '&')
+ + Plugin.Service.Helper.urlParamsSerialize(params)
+ + '#/' + uri;
+
+ return url;
+ },
+
+ buildApiUrl: function(uri) {
+ uri = uri || '';
+
+ return Plugin.Configs.apiUrl + '/api/v' + Plugin.Service.Api.getApiVersion() + uri;
+ },
+
+ getUserPacksUrl: function() {
+ var url = this.buildApiUrl('/shop/my');
+
+ if (Plugin.Configs.userPremium) {
+ url += '?is_subscriber=1';
+ }
+
+ return url;
+ },
+
+ getPackPreviewUrl: function(packName) {
+ var url = this.buildApiUrl('/packs/' + packName);
+
+ if (Plugin.Configs.userPremium) {
+ url += '?is_subscriber=1';
+ }
+
+ return url;
+ },
+
+ getStatisticUrl: function() {
+ return this.buildApiUrl('/statistics');
+ },
+
+ getUserDataUrl: function() {
+ return this.buildApiUrl('/user');
+ },
+
+ getPurchaseUrl: function(packName, pricePoint) {
+
+ // detect purchase type
+ var purchaseType = 'free';
+ if (pricePoint == 'B') {
+ purchaseType = 'oneoff';
+ if (Plugin.Configs.userPremium) {
+ purchaseType = 'subscription';
+ }
+ } else if (pricePoint == 'C') {
+ purchaseType = 'oneoff';
+ }
+
+ // build url
+ var url = this.buildApiUrl('/packs/' + packName);
+ url += '?' + Plugin.Service.Helper.urlParamsSerialize({
+ purchase_type: purchaseType
+ });
+
+ return url;
+ },
+
+ getContentByIdUrl: function(contentId) {
+ return this.buildApiUrl('/content/' + contentId);
+ },
+
+ getHidePackUrl: function(packName) {
+ return this.buildApiUrl('/packs/' + packName);
+ },
+
+ getStoreUrl: function() {
+ return this.buildStoreUrl('store/');
+ },
+
+ getStorePackUrl: function(packName) {
+ return this.buildStoreUrl('packs/' + packName);
+ }
+
+ };
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.User = {
+
+ init: function() {
+ this.updateUserData();
+ },
+
+ updateUserData: function() {
+ if (!Plugin.Configs.userData) {
+ return;
+ }
+
+ var storedUserData = Plugin.Service.Storage.getUserData() || {};
+
+ if (JSON.stringify(storedUserData) != JSON.stringify(Plugin.Configs.userData)) {
+ Plugin.Service.Api.updateUserData(Plugin.Configs.userData);
+ Plugin.Service.Storage.setUserData(Plugin.Configs.userData);
+ }
+ }
+ };
+
+})(window.StickersModule);
+
+window.StickersModule.Configs = {};
+
+(function(Plugin) {
+
+ Plugin.Service.Helper.setConfig({
+
+ elId: 'stickerPipe',
+
+ // todo: more than 2 resolution
+ stickerResolutionType : (window.devicePixelRatio == 1) ? 'mdpi' : 'xhdpi',
+ tabResolutionType: (window.devicePixelRatio == 1) ? 'hdpi' : 'xxhdpi',
+
+ tabItemClass: 'sp-tab-item',
+ stickerItemClass: 'sp-sticker-item',
+ emojiItemClass: 'sp-emoji',
+
+ htmlForEmptyRecent: 'No recent stickers',
+
+ apiKey: null,
+
+ apiUrl: 'https://api.stickerpipe.com',
+
+ storagePrefix: 'stickerpipe_',
+
+ enableEmojiTab: false,
+ enableHistoryTab: false,
+ enableSettingsTab: false,
+ enableStoreTab: false,
+
+ userId: null,
+ userPremium: false,
+ userData: {},
+
+ priceB: null,
+ priceC: null,
+
+ primaryColor: '',
+
+ // todo: block or popover
+ display: 'block',
+ height: '350px',
+ width: '320px',
+
+ lang: document.documentElement.lang.substr(0, 2) || 'en'
+ });
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.Service.Helper.setConfig({
+ emojiList: [
+ // Emoticons
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ฆ",
+ "๐ง",
+ "๐ฌ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ด",
+ "๐ถ",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ญ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ต",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐ฟ",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+// Dingbats
+ "โ",
+ "โ
",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โจ",
+ "โณ",
+ "โด",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โค",
+ "โ",
+ "โ",
+ "โ",
+ "โก",
+ "โฐ",
+// Transport and map symbols
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ข",
+ "๐ค",
+ "๐ฅ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฌ",
+ "๐ญ",
+ "๐ฒ",
+ "๐ถ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐",
+// Enclosed characters
+ "โ",
+ "๐
ฐ",
+ "๐
ฑ",
+ "๐
พ",
+ "๐
ฟ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ฉ๐ช",
+ "๐ฌ๐ง",
+ "๐จ๐ณ",
+ "๐ฏ๐ต",
+ "๐ฐ๐ท",
+ "๐ซ๐ท",
+ "๐ช๐ธ",
+ "๐ฎ๐น",
+ "๐บ๐ธ",
+ "๐ท๐บ",
+ "๐",
+ "๐",
+ "๐",
+ "๐ฏ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ถ",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐",
+ "๐",
+// Uncategorized
+ "ยฉ",
+ "ยฎ",
+ "โผ",
+ "โ",
+ "8โฃ",
+ "9โฃ",
+ "7โฃ",
+ "6โฃ",
+ "1โฃ",
+ "0โฃ",
+ "2โฃ",
+ "3โฃ",
+ "5โฃ",
+ "4โฃ",
+ "#โฃ",
+ "โข",
+ "โน",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โฉ",
+ "โช",
+ "โ",
+ "โ",
+ "โฉ",
+ "โช",
+ "โซ",
+ "โฌ",
+ "โฐ",
+ "โณ",
+ "โช",
+ "โซ",
+ "โถ",
+ "โ",
+ "โป",
+ "โผ",
+ "โฝ",
+ "โพ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โบ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ",
+ "โ ",
+ "โฃ",
+ "โฅ",
+ "โฆ",
+ "โจ",
+ "โป",
+ "โฟ",
+ "โ",
+ "โ ",
+ "โก",
+ "โช",
+ "โซ",
+ "โฝ",
+ "โพ",
+ "โ",
+ "โ
",
+ "โ",
+ "โ",
+ "โช",
+ "โฒ",
+ "โณ",
+ "โต",
+ "โบ",
+ "โฝ",
+ "โคด",
+ "โคต",
+ "โฌ
",
+ "โฌ",
+ "โฌ",
+ "โฌ",
+ "โฌ",
+ "โญ",
+ "โญ",
+ "ใฐ",
+ "ใฝ",
+ "ใ",
+ "ใ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ด",
+ "๐ต",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐ฟ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฌ",
+ "๐ญ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ถ",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฌ",
+ "๐ญ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ถ",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐ฟ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฌ",
+ "๐ญ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ซ",
+ "๐ฌ",
+ "๐ญ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ถ",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ถ",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐ฟ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฌ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐ฟ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฎ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ถ",
+ "๐ท",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง",
+ "๐จ",
+ "๐ฉ",
+ "๐ช",
+ "๐ซ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ฒ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ถ",
+ "๐ท",
+ "๐ธ",
+ "๐น",
+ "๐บ",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ป",
+ "๐ผ",
+ "๐ฝ",
+ "๐พ",
+ "๐ฟ",
+// Additional transport and map symbols
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ฃ",
+ "๐ฆ",
+ "๐ฎ",
+ "๐ฏ",
+ "๐ฐ",
+ "๐ฑ",
+ "๐ณ",
+ "๐ด",
+ "๐ต",
+ "๐ท",
+ "๐ธ",
+ "๐ฟ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+// Other additional symbols
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ฒ",
+ "๐ณ",
+ "๐",
+ "๐",
+ "๐ผ",
+ "๐",
+ "๐",
+ "๐ค",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ช",
+ "๐ฅ",
+ "๐ฌ",
+ "๐ญ",
+ "๐ญ",
+ "๐ถ",
+ "๐ท",
+ "๐ฌ",
+ "๐ญ",
+ "๐ฏ",
+ "๐ต",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐
",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ฌ",
+ "๐ญ",
+ "๐",
+ "๐",
+ "๐",
+ "๐",
+ "๐ ",
+ "๐ก",
+ "๐ข",
+ "๐ฃ",
+ "๐ค",
+ "๐ฅ",
+ "๐ฆ",
+ "๐ง"
+ ]
+ });
+
+})(window.StickersModule);
+
+
+
+/////////////////////////////////////////////////////////////
+// Load modules
+/////////////////////////////////////////////////////////////
+window.StickersModule.Module = {};
+
+(function(Plugin) {
+
+ Plugin.Module.Store = {
+
+ init: function(stickerpipe) {
+ Plugin.Module.Store.View.init();
+ Plugin.Module.Store.ApiListener.init();
+ Plugin.Module.Store.Api.init(stickerpipe);
+ },
+
+ open: function(contentId) {
+ Plugin.Module.Store.View.open(contentId);
+ },
+
+ close: function() {
+ Plugin.Module.Store.View.close();
+ },
+
+ setOnPurchaseCallback: function(callback) {
+ Plugin.Module.Store.Controller.onPurchaseCallback = callback;
+ },
+
+ purchaseSuccess: function(packName, pricePoint) {
+ Plugin.Module.Store.Controller.onPurchaseSuccess(packName, pricePoint);
+ },
+
+ purchaseFail: function() {
+ Plugin.Module.Store.Controller.onPurchaseFail();
+ }
+ };
+
+})(StickersModule);
+
+
+(function(Plugin, Module) {
+
+ var stickerpipe;
+
+ function isPackHidden(packName) {
+ var packs = Plugin.Service.Storage.getPacks();
+
+ for (var i = 0; i < packs.length; i++) {
+ if (packs[i].pack_name == packName) {
+ return Plugin.Service.Pack.isHidden(packs[i]);
+ }
+ }
+
+ return false;
+ }
+
+ Module.Api= {
+
+ init: function(_stickerpipe) {
+ stickerpipe = _stickerpipe;
+ },
+
+ showPack: function(data) {
+ Module.View.close();
+ stickerpipe.open(data.attrs.packName);
+ },
+
+ purchasePack: function(data) {
+ var packName = data.attrs.packName,
+ packTitle = data.attrs.packTitle,
+ pricePoint = data.attrs.pricePoint;
+
+ var isHidden = isPackHidden(packName);
+
+ if (pricePoint == 'A' || (pricePoint == 'B' && Plugin.Configs.userPremium) || isHidden) {
+ Module.Controller.downloadPack(packName, pricePoint);
+ } else {
+ Module.Controller.onPurchaseCallback &&
+ Module.Controller.onPurchaseCallback(packName, packTitle, pricePoint);
+ }
+ },
+
+ showPagePreloader: function(data) {
+ Module.View.showPagePreloader(data.attrs.show);
+ },
+
+ removePack: function(data) {
+ Module.Controller.removePack(data.attrs.packName);
+ },
+
+ showBackButton: function(data) {
+ Module.View.showBackButton(data.attrs.show);
+ },
+
+ setYScroll: function(data) {
+ Module.View.setYScroll(data.attrs.yPosition);
+ },
+
+ keyUp: function(data) {
+ var ESC_CODE = 27;
+
+ if (data.attrs.keyCode == ESC_CODE) {
+ Module.View.close();
+ }
+ }
+ };
+
+})(StickersModule, StickersModule.Module.Store);
+
+
+(function(Plugin, Module) {
+
+ var initialized = false;
+
+ Module.ApiListener = {
+
+ init: function() {
+ if (initialized) {
+ return;
+ }
+
+ window.addEventListener('message', function(e) {
+ var data = JSON.parse(e.data);
+
+ if (!data.action) {
+ return;
+ }
+
+ var api = Module.Api;
+ api[data.action] && api[data.action](data);
+ });
+
+ initialized = true;
+ }
+ };
+
+})(window.StickersModule, StickersModule.Module.Store);
+
+(function(Plugin, Module) {
+
+ function callStoreMethod(action, attrs) {
+ var iframe = Module.View.iframe;
+
+ iframe && iframe.contentWindow.postMessage(JSON.stringify({
+ action: action,
+ attrs: attrs
+ }), Plugin.Service.Helper.getDomain(Plugin.Service.Url.buildStoreUrl('/')));
+ }
+
+ Module.Controller = {
+
+ onPurchaseCallback: null,
+
+ configureStore: function() {
+ callStoreMethod('configure', {
+ canShowPack: true,
+ canRemovePack: true
+ });
+ },
+
+ downloadPack: function(packName, pricePoint) {
+ Plugin.Service.Pack.purchase(packName, pricePoint, true, function() {
+ callStoreMethod('onPackPurchaseSuccess');
+ }, function() {
+ callStoreMethod('onPackPurchaseFail');
+ });
+ },
+
+ removePack: function(packName) {
+ Plugin.Service.Pack.remove(packName, function() {
+ callStoreMethod('onPackRemoveSuccess');
+ }, function() {
+ callStoreMethod('onPackRemoveFail');
+ });
+ },
+
+ goBack: function() {
+ callStoreMethod('goBack');
+ },
+
+ ///////////////////////////////////////////
+ // Callbacks
+ ///////////////////////////////////////////
+
+ onPurchaseSuccess: function(packName, pricePoint) {
+ this.downloadPack(packName, pricePoint);
+ },
+
+ onPurchaseFail: function() {
+ callStoreMethod('onPackPurchaseFail');
+ },
+
+ onScrollContent: function(yPosition) {
+ callStoreMethod('onScrollContent', {
+ yPosition: yPosition
+ });
+ }
+ };
+
+})(StickersModule, StickersModule.Module.Store);
+
+
+(function(Plugin, Module) {
+
+ Module.View = {
+
+ modal: null,
+ iframe: null,
+
+ modalBody: null,
+
+ preloader: null,
+
+ init: function() {
+ this.iframe = document.createElement('iframe');
+
+ this.iframe.style.width = '100%';
+ this.iframe.style.height = '100%';
+ this.iframe.style.border = '0';
+
+ this.modal = Plugin.Module.Modal.init(this.iframe, {
+ onOpen: (function(contentEl, modalEl, overlay) {
+ Plugin.Service.Event.resize();
+ Module.ApiListener.init();
+
+ if (Plugin.Service.Helper.getMobileOS() == 'ios') {
+ var modalBody = modalEl.getElementsByClassName('sp-modal-body')[0];
+ modalBody.style.overflowY = 'scroll';
+
+ modalBody.addEventListener('scroll', (function() {
+ Module.Controller.onScrollContent(modalBody.scrollTop);
+ }).bind(this));
+
+ this.modalBody = modalBody;
+ }
+
+ this.iframe.onload = function() {
+ Module.Controller.configureStore();
+ };
+
+
+ if (!this.preloader) {
+ var modalDialog = modalEl.getElementsByClassName('sp-modal-dialog')[0];
+ this.preloader = new Plugin.View.Preloader(modalDialog);
+ this.preloader.hide();
+ }
+ }).bind(this)
+ });
+
+ this.modal.backButton.addEventListener('click', (function() {
+ Module.Controller.goBack();
+ }).bind(this));
+
+ window.addEventListener('resize', (function() {
+ this.onWindowResize();
+ }).bind(this));
+ },
+
+ open: function(contentId) {
+
+ var self = this;
+
+ self.iframe.src = Plugin.Service.Url.getStoreUrl();
+
+ if (contentId) {
+ Plugin.Service.Sticker.getById(contentId, function (sticker) {
+ self.iframe.src = Plugin.Service.Url.getStorePackUrl(sticker.pack);
+ });
+ }
+
+ this.modal.open();
+ },
+
+ close: function() {
+ if (this.modal && this.modal.hasGlobalOpened()) {
+ this.modal.close();
+ }
+ },
+
+ showPagePreloader: function(show) {
+ this.preloader[(show ? 'show' : 'hide')]();
+ },
+
+ showBackButton: function(show) {
+ var modal = this.modal;
+ modal.backButton.style.display = (show) ? 'block' : 'none';
+ },
+
+ setYScroll: function(yPosition) {
+ if (this.modalBody) {
+ this.modalBody.scrollTop = yPosition;
+ }
+ },
+
+ onWindowResize: function() {
+ var dialog = this.modal.modalEl.getElementsByClassName('sp-modal-dialog')[0];
+ dialog.style.height = '';
+
+ if (window.innerWidth > 700) {
+
+ var marginTop = parseInt(Plugin.Service.El.css(dialog, 'marginTop'), 10),
+ marginBottom = parseInt(Plugin.Service.El.css(dialog, 'marginBottom'), 10);
+
+ var minHeight = window.innerHeight - marginTop - marginBottom;
+
+ dialog.style.height = minHeight + 'px';
+ }
+ }
+ };
+
+})(window.StickersModule, StickersModule.Module.Store);
+
+(function(Plugin) {
+
+ // todo: + bind & unbind methods for events (error on ESC two modals)
+
+ var modalsStack = [],
+ KEY_CODE_A = 65,
+ KEY_CODE_TAB = 9,
+ KEY_CODE_ESC = 27,
+
+ oMargin = {},
+ ieBodyTopMargin = 0,
+
+ classes = {
+ lock: 'sp-modal-lock',
+ overlay: 'sp-modal-overlay',
+ modal: 'sp-modal',
+ modalDialog: 'sp-modal-dialog',
+ dialogHeader: 'sp-modal-header',
+ dialogBody: 'sp-modal-body',
+ back: 'sp-modal-back',
+ close: 'sp-modal-close'
+ },
+
+ defaultOptions = {
+ closeOnEsc: true,
+ closeOnOverlayClick: true,
+
+ onBeforeClose: null,
+ onClose: null,
+ onOpen: null
+ },
+
+ isOpen = false,
+
+ overlay = null;
+
+ function lockContainer() {
+ if (overlay) {
+ return;
+ }
+
+ overlay = document.createElement('div');
+ overlay.className = classes.overlay;
+
+ document.body.insertBefore(overlay, document.body.firstChild);
+
+ var bodyOuterWidth = Plugin.Service.El.outerWidth(document.body);
+ document.body.classList.add(classes.lock);
+ document.getElementsByTagName('html')[0].classList.add(classes.lock);
+
+ var scrollbarWidth = Plugin.Service.El.outerWidth(document.body) - bodyOuterWidth;
+
+ if (Plugin.Service.Helper.isIE()) {
+ ieBodyTopMargin = Plugin.Service.El.css(document.body, 'marginTop');
+ document.body.style.marginTop = 0;
+ }
+
+ if (scrollbarWidth != 0) {
+ var tags = ['html', 'body'];
+ for (var i = 0 ; i < tags.length; i++) {
+ var tag = tags[i],
+ tagEl = document.getElementsByTagName(tag)[0];
+
+ oMargin[tag.toLowerCase()] = parseInt(Plugin.Service.El.css(tagEl, 'marginRight'));
+ }
+
+ document.getElementsByTagName('html')[0].style.marginRight = oMargin['html'] + scrollbarWidth + 'px';
+
+ overlay.style.left = 0 - scrollbarWidth + 'px';
+ }
+ }
+
+ function unlockContainer() {
+ overlay.parentNode.removeChild(overlay);
+ overlay = null;
+
+ if (Plugin.Service.Helper.isIE()) {
+ document.body.style.marginTop = ieBodyTopMargin + 'px';
+ }
+
+ var bodyOuterWidth = Plugin.Service.El.outerWidth(document.body);
+ document.body.classList.remove(classes.lock);
+ document.getElementsByTagName('html')[0].classList.remove(classes.lock);
+ var scrollbarWidth = Plugin.Service.El.outerWidth(document.body) - bodyOuterWidth;
+
+ if (scrollbarWidth != 0) {
+ var tags = ['html', 'body'];
+ for (var i = 0 ; i < tags.length; i++) {
+ var tag = tags[i],
+ tagEl = document.getElementsByTagName(tag)[0];
+
+ tagEl.style.marginRight = oMargin[tag.toLowerCase()] + 'px';
+ }
+ }
+ }
+
+ Plugin.Module.Modal = {
+
+ init: function(contentEl, options) {
+
+ options = Plugin.Service.Helper.extend({}, defaultOptions, (options || {}));
+
+ var modalInstance = {};
+
+ // ****************************************************************************
+
+ // MODAL
+ var modalEl = document.createElement('div');
+ modalEl.style.display = 'none';
+ modalEl.className = classes.modal;
+
+ if (options.closeOnOverlayClick) {
+ modalEl.addEventListener('click', (function() {
+ modalInstance.close(options);
+ }).bind(this));
+ }
+
+
+ // DIALOG
+ var dialogEl = document.createElement('div');
+ dialogEl.className = classes.modalDialog;
+
+
+ // HEADER
+ var dialogHeader = document.createElement('div');
+ dialogHeader.className = classes.dialogHeader;
+
+
+ // BODY
+ var dialogBody = document.createElement('div');
+ dialogBody.className = classes.dialogBody;
+
+
+ modalEl.appendChild(dialogEl);
+
+ dialogEl.appendChild(dialogBody);
+ dialogEl.appendChild(dialogHeader);
+
+ var backButton = document.createElement('div');
+ backButton.className = classes.back;
+ backButton.innerHTML = '
';
+ modalInstance.backButton = backButton;
+
+ var closeButton = document.createElement('div');
+ closeButton.className = classes.close;
+ closeButton.innerHTML = '
';
+ closeButton.addEventListener('click', (function() {
+ this.close();
+ }).bind(modalInstance));
+
+ dialogHeader.appendChild(backButton);
+ dialogHeader.appendChild(closeButton);
+
+ modalInstance.modalEl = modalEl;
+
+ // ****************************************************************************
+
+ if (!contentEl || !contentEl.nodeType) {
+
+ try {
+ contentEl = document.querySelector(contentEl);
+ } catch (e) {}
+
+ if (!contentEl) {
+ contentEl = document.createElement('div');
+ }
+ }
+
+ dialogBody.appendChild(contentEl);
+
+ document.body.appendChild(modalInstance.modalEl);
+
+ // on Ctrl+A click fire `onSelectAll` event
+ window.addEventListener('keydown', function(e) {
+ // todo
+ //if (!(e.ctrlKey && e.keyCode == KEY_CODE_A)) {
+ // return true;
+ //}
+ //
+ //if ( $('input:focus, textarea:focus').length > 0 ) {
+ // return true;
+ //}
+ //
+ //var selectAllEvent = new $.Event('onSelectAll');
+ //selectAllEvent.parentEvent = e;
+ //$(window).trigger(selectAllEvent);
+ //return true;
+ });
+
+ // todo line 6
+ //els.bind('keydown',function(e) {
+ // var modalFocusableElements = $(':focusable',$(this));
+ // if(modalFocusableElements.filter(':last').is(':focus') && (e.which || e.keyCode) == KEY_CODE_TAB){
+ // e.preventDefault();
+ // modalFocusableElements.filter(':first').focus();
+ // }
+ //});
+
+ return Plugin.Service.Helper.extend(modalInstance, {
+
+ options: options,
+ contentEl: contentEl,
+
+ open: function() {
+
+ if (modalsStack.length) {
+ modalsStack[modalsStack.length - 1].modalEl.style.display = 'none';
+ }
+
+ modalsStack.push(this);
+
+ // todo: close modal if opened
+ //if (document.getElementsByClassName(classes.overlay).length) {
+ // this.close();
+ //}
+
+ lockContainer();
+
+
+ //overlay.appendChild(this.modalEl); // openedModalElement
+ Plugin.Service.El.appendAfter(this.modalEl, overlay);
+
+ this.modalEl.style.display = 'block';
+
+ if (this.options.closeOnEsc) {
+ window.addEventListener('keyup', (function(e) {
+ if(e.keyCode === KEY_CODE_ESC && isOpen) {
+ this.close(this.options);
+ }
+ }).bind(this));
+ }
+
+ if (this.options.closeOnOverlayClick) {
+ for (var i = this.modalEl.children.length; i--;) {
+ if (this.modalEl.children[i].nodeType != 8) {
+ this.modalEl.children[i].addEventListener('click', function(e) {
+ e.stopPropagation();
+ });
+ }
+ }
+ }
+
+ //document.addEventListener('touchmove', (function(e) {
+ // //helper function (see below)
+ // function collectionHas(a, b) {
+ // for(var i = 0, len = a.length; i < len; i ++) {
+ // if(a[i] == b) return true;
+ // }
+ // return false;
+ // }
+ //
+ // function findParentBySelector(elm, selector) {
+ // var all = document.querySelectorAll(selector),
+ // cur = elm.parentNode;
+ //
+ // //keep going up until you find a match
+ // while (cur && !collectionHas(all, cur)) {
+ // cur = cur.parentNode; //go up
+ // }
+ //
+ // //will return null if not found
+ // return cur;
+ // }
+ //
+ // var selector = '.' + classes.overlay;
+ // var parent = findParentBySelector(e.target, selector);
+ //
+ // if(!parent) {
+ // e.preventDefault();
+ // }
+ //}).bind(this));
+
+ //document.addEventListener('touchmove', (function(e) {
+ // e.preventDefault();
+ //}).bind(this));
+
+ document.addEventListener('touchmove', function(e) {
+
+ //var q = Plugin.Service.El.getParents(e.target, '.' + classes.overlay);
+ //if (!q.length) {
+ // e.preventDefault();
+ //}
+
+ //if(!$(e).parents('.' + localOptions.overlayClass)) {
+ // e.preventDefault();
+ //}
+ });
+
+ window.addEventListener('onSelectAll',function(e) {
+ //e.parentEvent.preventDefault();
+
+ // todo
+ //var range = null,
+ // selection = null,
+ // selectionElement = openedModalElement.get(0);
+ //
+ //if (document.body.createTextRange) { //ms
+ // range = document.body.createTextRange();
+ // range.moveToElementText(selectionElement);
+ // range.select();
+ //} else if (window.getSelection) { //all others
+ // selection = window.getSelection();
+ // range = document.createRange();
+ // range.selectNodeContents(selectionElement);
+ // selection.removeAllRanges();
+ // selection.addRange(range);
+ //}
+ });
+
+ if (this.options.onOpen) {
+ this.options.onOpen(this.contentEl, this.modalEl, overlay, this.options);
+ }
+
+ isOpen = true;
+ },
+
+ close: function() {
+
+ // todo
+ //if ($.isFunction(this.options.onBeforeClose)) {
+ // if (this.options.onBeforeClose(overlay, this.options) === false) {
+ // return;
+ // }
+ //}
+
+ // todo
+ //if (!this.options.cloning) {
+ // if (!modalEl) {
+ // modalEl = overlay.data(pluginNamespace+'.modalEl');
+ // }
+ // $(modalEl).hide().appendTo($(modalEl).data(pluginNamespace+'.parent'));
+ //}
+
+ if (this.options.onClose) {
+ this.options.onClose(this.contentEl, this.modalEl, overlay, this.options);
+ }
+
+ document.body.removeChild(this.modalEl);
+ modalsStack.pop();
+
+ if (!modalsStack.length) {
+ unlockContainer();
+ } else {
+ modalsStack[modalsStack.length - 1].modalEl.style.display = 'block';
+ }
+
+ isOpen = false;
+ },
+
+ // todo
+ hasGlobalOpened: function() {
+ return isOpen;
+ }
+ });
+ },
+
+ setDefaultOptions: function(options) {
+ defaultOptions = Plugin.Service.Helper.extend({}, defaultOptions, options);
+ }
+ };
+
+})(window.StickersModule);
+
+/////////////////////////////////////////////////////////////
+
+window.StickersModule.View = {};
+
+(function(Plugin) {
+
+ Plugin.View.Block = Plugin.Libs.Class({
+
+ emojisOffset: 0,
+ emojisLimit: 100,
+
+ // todo
+ isRendered: false,
+
+ el: null,
+ contentEl: null,
+
+ tabsView: null,
+
+ scrollableEl: null,
+
+ _constructor: function() {
+
+ this.el = document.getElementById(Plugin.Configs.elId);
+ this.contentEl = document.createElement('div');
+
+ this.tabsView = new Plugin.View.Tabs();
+
+ window.addEventListener('resize', (function() {
+ this.onWindowResize();
+ }).bind(this));
+ },
+
+ render: function() {
+
+ this.tabsView.render();
+
+ this.el.innerHTML = '';
+ this.el.className ='sticker-pipe';
+ this.el.style.width = Plugin.Configs.width;
+
+ this.scrollableEl = document.createElement('div');
+ this.scrollableEl.className = 'sp-scroll-content';
+ this.scrollableEl.style.height = parseInt(Plugin.Configs.height, 10) - 49 + 'px';
+ this.scrollableEl.appendChild(this.contentEl);
+
+ this.scrollableEl.addEventListener('ps-y-reach-end', (function () {
+ if (this.contentEl.className == 'sp-emojis') {
+ this.renderEmojis(this.emojisOffset);
+ }
+ }).bind(this));
+
+ this.el.appendChild(this.tabsView.el);
+ this.el.appendChild(this.scrollableEl);
+
+ Plugin.Libs.PerfectScrollbar.initialize(this.scrollableEl);
+
+ this.isRendered = true;
+
+ this.tabsView.onWindowResize();
+ this.onWindowResize();
+ },
+ renderRecentStickers: function() {
+
+ var recentStickers = Plugin.Service.Storage.getRecentStickers();
+
+ if (!recentStickers.length) {
+ this.contentEl.className = 'sp-recent-empty';
+ this.contentEl.innerHTML = Plugin.Configs.htmlForEmptyRecent;
+ this.updateScroll('top');
+ return false;
+ }
+
+ this.renderStickers(recentStickers);
+ },
+ renderEmojiBlock: function() {
+
+ this.contentEl.innerHTML = '';
+ this.contentEl.className = 'sp-emojis';
+
+ this.emojisOffset = 0;
+ this.renderEmojis(this.emojisOffset);
+
+ this.updateScroll('top');
+ },
+ renderPack: function(pack) {
+ this.renderStickers(pack.stickers);
+ },
+ renderStickers: function(stickersIds) {
+ var self = this;
+
+ this.contentEl.innerHTML = '';
+ this.contentEl.className = 'sp-stickers';
+
+ function appendSticker(stickerId) {
+ var stickersSpanEl = document.createElement('span');
+ stickersSpanEl.className = 'sp-sticker-placeholder';
+ stickersSpanEl.style.background = Plugin.Configs.primaryColor || '#e1e1e1';
+ stickersSpanEl.setAttribute('data-sticker-id', stickerId);
+
+ var image = new Image();
+ image.onload = function() {
+ stickersSpanEl.className = Plugin.Configs.stickerItemClass;
+ stickersSpanEl.style.background = '';
+ stickersSpanEl.appendChild(image);
+ };
+ image.onerror = function() {};
+
+ Plugin.Service.Sticker.getById(stickerId, function(sticker) {
+ image.src = sticker.image[Plugin.Configs.stickerResolutionType];
+ });
+
+ self.contentEl.appendChild(stickersSpanEl);
+ }
+
+ for (var i = 0; i < stickersIds.length; i++) {
+ var stickerId = stickersIds[i];
+ appendSticker(stickerId);
+ }
+
+ this.updateScroll('top');
+ },
+ renderEmojis: function(offset) {
+
+ if (offset > Plugin.Configs.emojiList.length - 1) {
+ return;
+ }
+
+ var limit = offset + this.emojisLimit;
+ if (limit > Plugin.Configs.emojiList.length - 1) {
+ limit = Plugin.Configs.emojiList.length;
+ }
+
+ for (var i = offset; i < limit; i++) {
+ var emoji = Plugin.Configs.emojiList[i],
+ emojiEl = document.createElement('span'),
+ emojiImgHtml = Plugin.Service.Emoji.parseEmojiFromText(emoji);
+
+ emojiEl.className = Plugin.Configs.emojiItemClass;
+ emojiEl.innerHTML = emojiImgHtml;
+
+ this.contentEl.appendChild(emojiEl);
+ }
+
+ this.emojisOffset = limit;
+
+ this.updateScroll();
+ },
+
+ handleClickOnSticker: function(callback) {
+ // todo: create static Plugin.Configs.stickerItemClass
+ Plugin.Service.Helper.setEvent('click', this.contentEl, Plugin.Configs.stickerItemClass, callback);
+ },
+ handleClickOnEmoji: function(callback) {
+ // todo: create static Plugin.Configs.emojiItemClass
+ Plugin.Service.Helper.setEvent('click', this.contentEl, Plugin.Configs.emojiItemClass, callback);
+ },
+
+ open: function(tabName) {
+ tabName = tabName || null;
+
+ if (tabName) {
+ this.tabsView.activeTab(tabName);
+ }
+
+ if (!this.tabsView.hasActiveTab) {
+ this.tabsView.activeLastUsedStickersTab();
+ }
+ },
+ close: function() {},
+
+ updateScroll: function(position) {
+ position = position || 'relative';
+
+ if (position == 'top') {
+ this.scrollableEl.scrollTop = 0;
+ }
+
+ Plugin.Libs.PerfectScrollbar.update(this.scrollableEl);
+ },
+
+ onWindowResize: function() {}
+ });
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ var parent = Plugin.View.Block;
+
+ Plugin.View.Popover = parent.extend({
+
+ popoverEl: null,
+ triangleEl: null,
+ toggleEl: null,
+
+ active: false,
+
+ _constructor: function() {
+ parent.prototype._constructor.apply(this, arguments);
+
+ this.toggleEl = document.getElementById(Plugin.Configs.elId);
+ this.toggleEl.addEventListener('click', (function() {
+ this.toggle();
+ }).bind(this));
+
+ this.popoverEl = document.createElement('div');
+ this.popoverEl.className = 'sp-popover';
+
+ this.el = document.createElement('div');
+
+ this.triangleEl = document.createElement('div');
+ this.triangleEl.className = 'sp-arrow';
+
+ this.popoverEl.appendChild(this.el);
+ this.popoverEl.appendChild(this.triangleEl);
+
+ this.handleClickOnSticker((function() {
+ this.toggle();
+ }).bind(this));
+
+ document.getElementsByTagName('body')[0].addEventListener('click', (function(e) {
+ function isDescendant(parent, child) {
+ var node = child.parentNode;
+ while (node != null) {
+ if (node == parent) {
+ return true;
+ }
+ node = node.parentNode;
+ }
+ return false;
+ }
+
+ if (!this.active) {
+ return;
+ }
+
+ if (!isDescendant(this.popoverEl, e.target) && !isDescendant(this.toggleEl.parentElement, e.target)) {
+ this.toggle();
+ }
+ }).bind(this));
+
+ window.addEventListener(Plugin.Service.Event.events.showContentHighlight, (function() {
+ this.toggleEl.classList.add('stickerpipe-content-highlight');
+ }).bind(this));
+
+ window.addEventListener(Plugin.Service.Event.events.hideContentHighlight, (function() {
+ this.toggleEl.classList.remove('stickerpipe-content-highlight');
+ }).bind(this));
+
+ // todo: addEventListener --> DOMEventService
+ if (window.addEventListener) {
+ window.addEventListener(Plugin.Service.Event.events.popoverShown, function() {
+ Plugin.Service.Event.resize();
+ });
+ } else {
+ window.attachEvent('on' + Plugin.Service.Event.events.popoverShown, function() {
+ Plugin.Service.Event.resize();
+ });
+ }
+ },
+
+ toggle: function() {
+ if (!this.active) {
+ this.open();
+ } else {
+ this.close();
+ }
+ },
+
+ open: function() {
+ if (!this.active) {
+
+ this.active = true;
+
+ this.toggleEl.parentElement.appendChild(this.popoverEl);
+ this.positioned();
+ Plugin.Service.Event.popoverShown();
+ }
+
+ parent.prototype.open.apply(this, arguments);
+ },
+
+ close: function() {
+ this.active = false;
+ this.toggleEl.parentElement.removeChild(this.popoverEl);
+ Plugin.Service.Event.popoverHidden();
+ // todo
+ this.popoverEl.style.marginTop = 0;
+ },
+
+ positioned: function() {
+ var arrowOffset = 0;
+
+ // todo: check
+ if (this.triangleEl) {
+ var style = this.toggleEl.currentStyle || window.getComputedStyle(this.toggleEl);
+ var marginLeft = parseInt(style.marginLeft, 10);
+
+ this.popoverEl.style.marginLeft = marginLeft + 'px';
+
+ //if (this.popoverEl.getBoundingClientRect().left + this.popoverEl.offsetWidth > window.innerWidth) {
+ // this.popoverEl.style.marginLeft = marginLeft - (this.popoverEl.offsetWidth / 2) + (this.toggleEl.clientWidth / 2) + 'px';
+ //}
+
+ this.triangleEl.style.marginLeft = this.toggleEl.getBoundingClientRect().left
+ - this.popoverEl.getBoundingClientRect().left
+ + (this.toggleEl.clientWidth / 2) - (this.triangleEl.offsetWidth / 2)
+ + 'px';
+
+ var arrowStyle = this.triangleEl.currentStyle || window.getComputedStyle(this.triangleEl);
+ if (arrowStyle.display != 'none') {
+ arrowOffset = 15;
+ }
+
+ var elOffset = this.toggleEl.getBoundingClientRect().top + this.toggleEl.offsetHeight - this.popoverEl.getBoundingClientRect().top;
+
+ // todo 5px remove
+ this.popoverEl.style.marginTop = -(this.popoverEl.offsetHeight + this.toggleEl.offsetHeight + arrowOffset - elOffset + 5) + 'px';
+ } else {
+ console && console.error('error: triangle not found');
+ }
+ }
+
+ });
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+ Plugin.View.Preloader = function(parentEl) {
+
+ // Constructor
+
+ var el = document.createElement('div');
+ el.className = 'sp-preloader';
+
+ el.innerHTML = '' +
+ '';
+
+ if (parentEl) {
+ parentEl.appendChild(el);
+ }
+
+ // ***********
+
+ return {
+
+ getEl: function() {
+ return el;
+ },
+
+ show: function() {
+ el.style.display = '';
+ },
+
+ hide: function() {
+ el.style.display = 'none';
+ }
+ };
+ };
+
+})(window.StickersModule);
+
+(function(Plugin) {
+
+
+ var packTabSize = 48,
+ classes = {
+ scrollableContainer: 'sp-tabs-scrollable-container',
+ scrollableContent: 'sp-tabs-scrollable-content',
+ controlTab: 'sp-control-tab',
+ controlButton: 'sp-control-button',
+ unwatched: 'sp-unwatched-content',
+ packTab: 'sp-pack-tab',
+ tabActive: 'sp-tab-active',
+ tabs: 'sp-tabs'
+ };
+
+ Plugin.View.Tabs = Plugin.Libs.Class({
+
+ el: null,
+ scrollableContainerEl: null,
+ scrollableContentEl: null,
+
+ packTabs: {},
+ packTabsIndexes: {},
+
+ hasActiveTab: false,
+
+ controls: {
+ emoji: {
+ id: 'spTabEmoji',
+ class: 'sp-tab-emoji',
+ icon: 'sp-icon-face',
+ el: null,
+ isTab: true
+ },
+ history: {
+ id: 'spTabHistory',
+ class: 'sp-tab-history',
+ icon: 'sp-icon-clock',
+ el: null,
+ isTab: true
+ },
+ settings: {
+ id: 'spTabSettings',
+ class: 'sp-tab-settings',
+ icon: 'sp-icon-settings',
+ el: null,
+ isTab: false
+ },
+ store: {
+ id: 'spTabStore',
+ class: 'sp-tab-store',
+ icon: 'sp-icon-plus',
+ el: null,
+ isTab: false
+ },
+ prevPacks: {
+ id: 'spTabPrevPacks',
+ class: 'sp-tab-prev-packs',
+ icon: 'sp-icon-arrow-back',
+ el: null,
+ isTab: false
+ },
+ nextPacks: {
+ id: 'spTabNextPacks',
+ class: 'sp-tab-next-packs',
+ icon: 'sp-icon-arrow-forward',
+ el: null,
+ isTab: false
+ }
+ },
+
+ _constructor: function() {
+
+ this.el = document.createElement('div');
+
+ window.addEventListener('resize', (function() {
+ this.onWindowResize();
+ }).bind(this));
+ },
+
+
+ render: function() {
+
+ this.el.className = classes.tabs;
+ this.el.innerHTML = '';
+
+ this.renderPrevPacksTab();
+
+ this.renderScrollableContainer();
+
+ this.renderPacks();
+
+ this.renderNextPacksTab();
+
+ this.renderStoreTab();
+ },
+ renderScrollableContainer: function() {
+
+ this.scrollableContentEl = document.createElement('div');
+ this.scrollableContentEl.className = classes.scrollableContent;
+
+ this.scrollableContainerEl = document.createElement('div');
+ this.scrollableContainerEl.className = classes.scrollableContainer;
+
+ this.scrollableContainerEl.appendChild(this.scrollableContentEl);
+ this.el.appendChild(this.scrollableContainerEl);
+ },
+ renderControlButton: function(controlButton) {
+ controlButton.isTab = controlButton.isTab || false;
+
+ var buttonClasses = [controlButton.class];
+ buttonClasses.push((controlButton.isTab) ? classes.controlTab : classes.controlButton);
+
+ var content = ' ';
+
+ controlButton.el = this.renderTab(controlButton.id, buttonClasses, content);
+ return controlButton.el;
+ },
+ renderPackTab: function(pack) {
+ var tabClasses = [classes.packTab];
+
+ if (pack.isUnwatched) {
+ tabClasses.push(classes.unwatched);
+ }
+
+ var content = ' ';
+
+ var tabEl = this.renderTab(null, tabClasses, content, {
+ 'data-pack-name': pack.pack_name
+ });
+
+ tabEl.addEventListener('click', (function() {
+ tabEl.classList.remove(classes.unwatched);
+ }).bind(this));
+
+ this.packTabs[pack.pack_name] = tabEl;
+
+ return tabEl;
+ },
+ renderTab: function(id, tabClasses, content, attrs) {
+ tabClasses = tabClasses || [];
+ attrs = attrs || {};
+
+ var tabEl = document.createElement('span');
+
+ if (id) {
+ tabEl.id = id;
+ }
+
+ tabClasses.push(Plugin.Configs.tabItemClass);
+
+ tabEl.classList.add.apply(tabEl.classList, tabClasses);
+
+ for (var name in attrs) {
+ tabEl.setAttribute(name, attrs[name]);
+ }
+
+ tabEl.innerHTML = content;
+
+ tabEl.addEventListener('click', (function() {
+ if (!tabEl.classList.contains(classes.controlTab) &&
+ !tabEl.classList.contains(classes.packTab)) {
+ return;
+ }
+
+ for (var tabName in this.packTabs) {
+ this.packTabs[tabName].classList.remove(classes.tabActive);
+ }
+
+ for (var controlName in this.controls) {
+ var controlTab = this.controls[controlName];
+ if (controlTab && controlTab.el) {
+ controlTab.el.classList.remove(classes.tabActive);
+ }
+ }
+
+ tabEl.classList.add(classes.tabActive);
+ }).bind(this));
+
+ return tabEl;
+ },
+
+
+ renderPacks: function() {
+ this.scrollableContentEl.innerHTML = '';
+
+ this.renderEmojiTab();
+ this.renderHistoryTab();
+
+ var packs = Plugin.Service.Storage.getPacks();
+
+ for (var i = 0; i < packs.length; i++) {
+ var pack = packs[i];
+
+ if (Plugin.Service.Pack.isHidden(pack)) {
+ continue;
+ }
+
+ this.scrollableContentEl.appendChild(this.renderPackTab(pack));
+ this.packTabsIndexes[pack.pack_name] = i;
+ }
+
+ this.renderSettingsTab();
+ },
+ renderEmojiTab: function() {
+ if (Plugin.Configs.enableEmojiTab) {
+ this.scrollableContentEl.appendChild(this.renderControlButton(this.controls.emoji));
+ }
+ },
+ renderHistoryTab: function() {
+ if (Plugin.Configs.enableHistoryTab) {
+ this.scrollableContentEl.appendChild(this.renderControlButton(this.controls.history));
+ }
+ },
+ renderSettingsTab: function() {
+ if (Plugin.Configs.enableSettingsTab) {
+ this.scrollableContentEl.appendChild(this.renderControlButton(this.controls.settings));
+ }
+ },
+ renderStoreTab: function() {
+ if (Plugin.Configs.enableStoreTab) {
+ this.el.appendChild(this.renderControlButton(this.controls.store));
+
+ if (Plugin.Service.Storage.getStoreLastModified() > Plugin.Service.Storage.getStoreLastVisit()) {
+ this.controls.store.el.classList.add('sp-unwatched-content');
+ }
+ }
+ },
+ renderPrevPacksTab: function() {
+ this.el.appendChild(this.renderControlButton(this.controls.prevPacks));
+ Plugin.Service.Helper.setEvent('click', this.el, this.controls.prevPacks.class, this.onClickPrevPacksButton.bind(this));
+ },
+ renderNextPacksTab: function() {
+ this.el.appendChild(this.renderControlButton(this.controls.nextPacks));
+ Plugin.Service.Helper.setEvent('click', this.el, this.controls.nextPacks.class, this.onClickNextPacksButton.bind(this));
+ },
+
+
+ onClickPrevPacksButton: function() {
+ var containerWidth = this.scrollableContainerEl.offsetWidth;
+ var contentOffset = parseInt(this.scrollableContentEl.style.left, 10) || 0;
+ var countFullShownTabs = parseInt((containerWidth / packTabSize), 10);
+
+ var offset = contentOffset + (packTabSize * countFullShownTabs);
+ offset = (offset > 0) ? 0 : offset;
+ this.scrollableContentEl.style.left = offset + 'px';
+ this.onWindowResize();
+ },
+ onClickNextPacksButton: function() {
+ var containerWidth = this.scrollableContainerEl.offsetWidth;
+ var contentOffset = parseInt(this.scrollableContentEl.style.left, 10) || 0;
+ var countFullShownTabs = parseInt((containerWidth / packTabSize), 10);
+
+ var offset = -(packTabSize * countFullShownTabs) + contentOffset;
+ this.scrollableContentEl.style.left = offset + 'px';
+ this.onWindowResize();
+ },
+
+
+ activeTab: function(tabName) {
+ var i = this.packTabsIndexes[tabName];
+
+ if (Plugin.Configs.enableEmojiTab) {
+ i++;
+ }
+ if (Plugin.Configs.enableHistoryTab) {
+ i++;
+ }
+
+ this.packTabs[tabName].click();
+ this.hasActiveTab = true;
+
+ var packTabSize = this.scrollableContentEl.getElementsByClassName(classes.packTab)[0].offsetWidth;
+ var containerWidth = this.scrollableContainerEl.offsetWidth;
+ var countFullShownTabs = parseInt((containerWidth / packTabSize), 10);
+
+ var offset = -(parseInt((i / countFullShownTabs), 10) * containerWidth);
+ //offset = (offset > 0) ? 0 : offset + 6; // old code
+ offset = (-offset < countFullShownTabs * packTabSize) ? 0 : offset + 6; // bugfix todo
+
+ this.scrollableContentEl.style.left = offset + 'px';
+
+ this.onWindowResize();
+ },
+ activeLastUsedStickersTab: function() {
+ this.controls.history.el.click();
+ this.hasActiveTab = true;
+ },
+
+
+ handleClickOnEmojiTab: function(callback) {
+ Plugin.Service.Helper.setEvent('click', this.el, this.controls.emoji.class, callback);
+ },
+ handleClickOnRecentTab: function(callback) {
+ Plugin.Service.Helper.setEvent('click', this.el, this.controls.history.class, callback);
+ },
+ handleClickOnPackTab: function(callback) {
+ Plugin.Service.Helper.setEvent('click', this.el, classes.packTab, callback);
+ },
+ handleClickOnStoreTab: function(callback) {
+ Plugin.Service.Helper.setEvent('click', this.el, this.controls.store.class, callback);
+ },
+
+
+ onWindowResize: function() {
+
+ if (!this.el.parentElement) {
+ return;
+ }
+
+ if (this.controls.prevPacks.el) {
+ if (parseInt(this.scrollableContentEl.style.left, 10) < 0) {
+ this.controls.prevPacks.el.style.display = 'block';
+ } else {
+ this.controls.prevPacks.el.style.display = 'none';
+ }
+ }
+
+
+ if (this.controls.nextPacks.el) {
+ var contentWidth = this.scrollableContentEl.scrollWidth;
+ var contentOffset = parseInt(this.scrollableContentEl.style.left, 10) || 0;
+
+ if (contentWidth + contentOffset > this.scrollableContainerEl.offsetWidth) {
+ this.controls.nextPacks.el.style.display = 'block';
+ } else {
+ this.controls.nextPacks.el.style.display = 'none';
+ }
+ }
+ }
+ });
+
+})(window.StickersModule);
+
+(function(window, Plugin) {
+
+ // todo: rename Stickers --> StickerPipe
+ window.Stickers = Plugin.Libs.Class({
+
+ view: null,
+
+ _constructor: function(config) {
+
+ Plugin.Service.Helper.setConfig(config);
+
+ // ***** Init Emoji tab *****
+ var mobileOS = Plugin.Service.Helper.getMobileOS();
+ if (mobileOS == 'ios' || mobileOS == 'android') {
+ config.enableEmojiTab = false;
+ }
+
+ // ***** Check required params *****
+ if (!Plugin.Configs.apiKey || !Plugin.Configs.userId) {
+ throw new Error('Empty one of required data [apiKey, userId]');
+ }
+
+ // ***** Init UserId *****
+ Plugin.Configs.userId = Plugin.Service.Helper.md5(Plugin.Configs.userId + Plugin.Configs.apiKey);
+
+ if (Plugin.Configs.userId != Plugin.Service.Storage.getUserId()) {
+ Plugin.Service.Storage.setPacks([]);
+ Plugin.Service.Storage.setRecentStickers([]);
+ Plugin.Service.Storage.setUserData({});
+ Plugin.Service.Storage.setPendingRequestTasks([]);
+ Plugin.Service.Storage.setStoreLastVisit(0);
+ }
+
+ Plugin.Service.Storage.setUserId(Plugin.Configs.userId);
+
+ // ***** Init modules *****
+ Plugin.Module.Store.init(this);
+
+ // ***** Init services ******
+ Plugin.Service.User.init();
+ Plugin.Service.Pack.init(this);
+ Plugin.Service.Emoji.init(Plugin.Libs.Twemoji);
+ Plugin.Service.PendingRequest.init();
+ },
+
+ ////////////////////
+ // Functions
+ ////////////////////
+
+ render: function(callback, elId) {
+ Plugin.Configs.elId = elId || Plugin.Configs.elId;
+
+ var self = this;
+
+ this.view = new Plugin.View.Popover();
+
+ this.delegateEvents();
+
+ // todo
+ Plugin.Service.Packs.fetch(function() {
+ self.view.render();
+
+ callback && callback();
+ });
+
+ setInterval(function() {
+ Plugin.Service.Packs.fetch();
+ }, 1000 * 60 * 60);
+ },
+
+ delegateEvents: function() {
+ var self = this;
+
+ this.view.tabsView.handleClickOnEmojiTab(function() {
+ self.view.renderEmojiBlock();
+ });
+
+ this.view.tabsView.handleClickOnRecentTab(function() {
+ self.view.renderRecentStickers();
+ });
+
+ this.view.tabsView.handleClickOnStoreTab(function() {
+ Plugin.Module.Store.open();
+
+ Plugin.Service.Storage.setStoreLastVisit(+(new Date()));
+ Plugin.Service.Highlight.check();
+
+ self.view.tabsView.controls.store.el.classList.remove('sp-unwatched-content');
+ });
+
+ this.view.tabsView.handleClickOnPackTab(function(el) {
+ var packName = el.getAttribute('data-pack-name'),
+ pack = Plugin.Service.Storage.getPack(packName);
+
+ if (pack) {
+ pack.isUnwatched = false;
+ Plugin.Service.Storage.setPack(packName, pack);
+ self.view.renderPack(pack);
+ }
+
+ Plugin.Service.Highlight.check();
+ });
+
+ this.view.handleClickOnSticker(function(el) {
+
+ var stickerId = el.getAttribute('data-sticker-id');
+
+ Plugin.Service.Statistic.useSticker(stickerId);
+ Plugin.Service.Storage.addRecentSticker(stickerId);
+
+ Plugin.Service.Highlight.check();
+ });
+
+ this.view.handleClickOnEmoji(function(el) {
+ var emoji = Plugin.Service.Emoji.parseEmojiFromHtml(el.innerHTML);
+ Plugin.Service.Statistic.useEmoji(emoji);
+ });
+ },
+
+ fetchPacks: function(callback) {
+ Plugin.Service.Packs.fetch(callback);
+ },
+
+ isSticker: function(text) {
+ return Plugin.Service.Sticker.isSticker(text);
+ },
+
+ parseStickerFromText: function(text, callback) {
+ return Plugin.Service.Sticker.parse(text, callback);
+ },
+
+ parseEmojiFromText: function(text) {
+ return Plugin.Service.Emoji.parseEmojiFromText(text);
+ },
+
+ parseEmojiFromHtml: function(html) {
+ return Plugin.Service.Emoji.parseEmojiFromHtml(html);
+ },
+
+ onUserMessageSent: function(isSticker) {
+ Plugin.Service.Statistic.messageSend(isSticker);
+ },
+
+ purchaseSuccess: function(packName, pricePoint) {
+ Plugin.Module.Store.purchaseSuccess(packName, pricePoint);
+ },
+
+ purchaseFail: function() {
+ Plugin.Module.Store.purchaseFail();
+ },
+
+ open: function(tabName) {
+ this.view.open(tabName);
+ },
+
+ close: function() {
+ this.view.close();
+ },
+
+ openStore: function(contentId) {
+ Plugin.Module.Store.open(contentId);
+ },
+
+ closeStore: function() {
+ Plugin.Module.Store.close();
+ },
+
+ getPackMainIcon: function(packName, callback) {
+ Plugin.Service.Pack.getMainIcon(packName, callback);
+ },
+
+ ////////////////////
+ // Callbacks
+ ////////////////////
+
+ onClickSticker: function(callback, context) {
+ this.view.handleClickOnSticker(function(el) {
+ callback.call(context, '[[' + el.getAttribute('data-sticker-id') + ']]');
+ });
+ },
+
+ onClickEmoji: function(callback, context) {
+ this.view.handleClickOnEmoji((function(el) {
+ var emoji = this.parseEmojiFromHtml(el.innerHTML);
+
+ callback.call(context, emoji);
+ }).bind(this));
+ },
+
+ onPurchase: function(callback) {
+ Plugin.Module.Store.setOnPurchaseCallback(callback);
+ }
+ });
+
+})(window, window.StickersModule);
diff --git a/samples/chat/libs/stickerpipe/js/stickerpipe.min.js b/samples/chat/libs/stickerpipe/js/stickerpipe.min.js
new file mode 100755
index 000000000..0054e1dd3
--- /dev/null
+++ b/samples/chat/libs/stickerpipe/js/stickerpipe.min.js
@@ -0,0 +1,4 @@
+window.StickersModule={},window.StickersModule.Libs={},function(Plugin){var Class=function(){function _rewriteStatics(fnc,statics){for(var prop in statics)if("extend"!==prop&&"static"!==prop&&"typeOf"!==prop&&"mixin"!==prop){if("object"==typeof statics[prop]||"function"==typeof statics[prop])return void(fnc[prop]=statics[prop]);prop===prop.toUpperCase()?(Object.defineProperty(fnc,prop,{writable:!1,configurable:!1,enumerable:!0,value:statics[prop]}),Object.defineProperty(fnc.prototype,prop,{writable:!1,configurable:!1,enumerable:!0,value:statics[prop]})):(Object.defineProperty(fnc,prop,{get:function(){return statics[prop]},set:function(val){statics[prop]=val}}),Object.defineProperty(fnc.prototype,prop,{get:function(){return statics[prop]},set:function(val){statics[prop]=val}}))}}function _extend(base,source,overrideConstructor){overrideConstructor=overrideConstructor||!1;for(var p in source)"_constructor"===p&&!overrideConstructor||"typeOf"===p||"mixin"===p||"static"===p||"extend"===p||(base[p]=source[p])}return function(classBody){var _preventCreateCall=!1;return function createClass(self,classBody){var instance,_mixins=[],isSingleton=classBody.hasOwnProperty("singleton")&&classBody.singleton,classConstructor=function(){if("function"==typeof this._constructor&&_preventCreateCall===!1&&this._constructor.apply(this,arguments),classBody.hasOwnProperty("get"))for(var p in classBody.get){var setter="set"in classBody&&p in classBody.set?classBody.set[p]:null;null===setter&&Object.defineProperty(this,p,{get:classBody.get[p]})}if(classBody.hasOwnProperty("set"))for(var p in classBody.set){var getter="get"in classBody&&p in classBody.get?classBody.get[p]:null;null!==getter?Object.defineProperty(this,p,{set:classBody.set[p],get:classBody.get[p]}):Object.defineProperty(this,p,{set:classBody.set[p]})}if(isSingleton&&"undefined"!=typeof this)throw new Error("Singleton object cannot have more than one instance, call instance method instead");this.constructor=classConstructor};null!==self&&(_preventCreateCall=!0,classConstructor.prototype=new self,_preventCreateCall=!1);var classPrototype=classConstructor.prototype;return classPrototype.typeOf=function(cls){if("object"==typeof cls)return _mixins.indexOf(cls)>=0;if("function"==typeof cls){if(this instanceof cls)return!0;if(_mixins.indexOf(cls)>=0)return!0}return!1},"function"==typeof classBody&&(classBody=classBody()),_extend(classPrototype,classBody,!0),classConstructor["static"]=function(statics){return _rewriteStatics(classConstructor,statics),classConstructor},classConstructor.mixin=function(){for(var i=0,l=arguments.length;l>i;i++){var mixin=arguments[i];if("function"==typeof mixin)var methods=mixin.prototype;else{if("object"!=typeof mixin)throw new Error("js.class mixin method accepts only types: object, function - `"+typeof mixin+"` type given");var methods=mixin}_extend(classPrototype,methods,!1),_mixins.push(mixin)}return classConstructor},isSingleton?(classConstructor.extend=function(){throw new Error("Singleton class cannot be extended")},classConstructor.instance=function(){return instance||(isSingleton=!1,instance=new classConstructor,isSingleton=!0),instance}):classConstructor.extend=function(classBody){return createClass(this,classBody)},classConstructor}(null,classBody)}}();"undefined"!=typeof module?module.exports=Class:Plugin.Libs.Class=Class}(window.StickersModule),"document"in self&&("classList"in document.createElement("_")?!function(){"use strict";var testElement=document.createElement("_");if(testElement.classList.add("c1","c2"),!testElement.classList.contains("c2")){var createMethod=function(method){var original=DOMTokenList.prototype[method];DOMTokenList.prototype[method]=function(token){var i,len=arguments.length;for(i=0;len>i;i++)token=arguments[i],original.call(this,token)}};createMethod("add"),createMethod("remove")}if(testElement.classList.toggle("c3",!1),testElement.classList.contains("c3")){var _toggle=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(token,force){return 1 in arguments&&!this.contains(token)==!force?force:_toggle.call(this,token)}}testElement=null}():!function(view){"use strict";if("Element"in view){var classListProp="classList",protoProp="prototype",elemCtrProto=view.Element[protoProp],objCtr=Object,strTrim=String[protoProp].trim||function(){return this.replace(/^\s+|\s+$/g,"")},arrIndexOf=Array[protoProp].indexOf||function(item){for(var i=0,len=this.length;len>i;i++)if(i in this&&this[i]===item)return i;return-1},DOMEx=function(type,message){this.name=type,this.code=DOMException[type],this.message=message},checkTokenAndGetIndex=function(classList,token){if(""===token)throw new DOMEx("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(token))throw new DOMEx("INVALID_CHARACTER_ERR","String contains an invalid character");return arrIndexOf.call(classList,token)},ClassList=function(elem){for(var trimmedClasses=strTrim.call(elem.getAttribute("class")||""),classes=trimmedClasses?trimmedClasses.split(/\s+/):[],i=0,len=classes.length;len>i;i++)this.push(classes[i]);this._updateClassName=function(){elem.setAttribute("class",this.toString())}},classListProto=ClassList[protoProp]=[],classListGetter=function(){return new ClassList(this)};if(DOMEx[protoProp]=Error[protoProp],classListProto.item=function(i){return this[i]||null},classListProto.contains=function(token){return token+="",-1!==checkTokenAndGetIndex(this,token)},classListProto.add=function(){var token,tokens=arguments,i=0,l=tokens.length,updated=!1;do token=tokens[i]+"",-1===checkTokenAndGetIndex(this,token)&&(this.push(token),updated=!0);while(++i-1)return null;try{values.push(value),json=JSON.stringify({data:values}),localStorage.setItem(query_key,json)}catch(e){console&&(console.log(e),console.warn("Lockr didn't successfully add the "+value+" to "+key+" set, because the localStorage is full."))}},smembers:function(key,options){var value,query_key=this._getPrefixedKey(key,options);try{value=JSON.parse(localStorage.getItem(query_key))}catch(e){value=null}return null===value?[]:value.data||[]},sismember:function(key,value,options){this._getPrefixedKey(key,options);return this.smembers(key).indexOf(value)>-1},getAll:function(){var keys=Object.keys(localStorage);return keys.map(function(key){return this.get(key)}.bind(this))},srem:function(key,value,options){var json,index,query_key=this._getPrefixedKey(key,options),values=this.smembers(key,value);index=values.indexOf(value),index>-1&&values.splice(index,1),json=JSON.stringify({data:values});try{localStorage.setItem(query_key,json)}catch(e){console&&console.warn("Lockr couldn't remove the "+value+" from the set "+key)}},rm:function(key){localStorage.removeItem(key)},flush:function(){localStorage.clear()}}}(window.StickersModule),function(Plugin){Plugin.Libs.MD5=function(string){function RotateLeft(lValue,iShiftBits){return lValue<>>32-iShiftBits}function AddUnsigned(lX,lY){var lX4,lY4,lX8,lY8,lResult;return lX8=2147483648&lX,lY8=2147483648&lY,lX4=1073741824&lX,lY4=1073741824&lY,lResult=(1073741823&lX)+(1073741823&lY),lX4&lY4?2147483648^lResult^lX8^lY8:lX4|lY4?1073741824&lResult?3221225472^lResult^lX8^lY8:1073741824^lResult^lX8^lY8:lResult^lX8^lY8}function F(x,y,z){return x&y|~x&z}function G(x,y,z){return x&z|y&~z}function H(x,y,z){return x^y^z}function I(x,y,z){return y^(x|~z)}function FF(a,b,c,d,x,s,ac){return a=AddUnsigned(a,AddUnsigned(AddUnsigned(F(b,c,d),x),ac)),AddUnsigned(RotateLeft(a,s),b)}function GG(a,b,c,d,x,s,ac){return a=AddUnsigned(a,AddUnsigned(AddUnsigned(G(b,c,d),x),ac)),AddUnsigned(RotateLeft(a,s),b)}function HH(a,b,c,d,x,s,ac){return a=AddUnsigned(a,AddUnsigned(AddUnsigned(H(b,c,d),x),ac)),AddUnsigned(RotateLeft(a,s),b)}function II(a,b,c,d,x,s,ac){return a=AddUnsigned(a,AddUnsigned(AddUnsigned(I(b,c,d),x),ac)),AddUnsigned(RotateLeft(a,s),b)}function ConvertToWordArray(string){for(var lWordCount,lMessageLength=string.length,lNumberOfWords_temp1=lMessageLength+8,lNumberOfWords_temp2=(lNumberOfWords_temp1-lNumberOfWords_temp1%64)/64,lNumberOfWords=16*(lNumberOfWords_temp2+1),lWordArray=Array(lNumberOfWords-1),lBytePosition=0,lByteCount=0;lMessageLength>lByteCount;)lWordCount=(lByteCount-lByteCount%4)/4,lBytePosition=lByteCount%4*8,lWordArray[lWordCount]=lWordArray[lWordCount]|string.charCodeAt(lByteCount)<>>29,lWordArray}function WordToHex(lValue){var lByte,lCount,WordToHexValue="",WordToHexValue_temp="";for(lCount=0;3>=lCount;lCount++)lByte=lValue>>>8*lCount&255,WordToHexValue_temp="0"+lByte.toString(16),WordToHexValue+=WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);return WordToHexValue}function Utf8Encode(string){string=string.replace(/\r\n/g,"\n");for(var utftext="",n=0;nc?utftext+=String.fromCharCode(c):c>127&&2048>c?(utftext+=String.fromCharCode(c>>6|192),utftext+=String.fromCharCode(63&c|128)):(utftext+=String.fromCharCode(c>>12|224),utftext+=String.fromCharCode(c>>6&63|128),utftext+=String.fromCharCode(63&c|128))}return utftext}string=string.toString();var k,AA,BB,CC,DD,a,b,c,d,x=Array(),S11=7,S12=12,S13=17,S14=22,S21=5,S22=9,S23=14,S24=20,S31=4,S32=11,S33=16,S34=23,S41=6,S42=10,S43=15,S44=21;for(string=Utf8Encode(string),x=ConvertToWordArray(string),a=1732584193,b=4023233417,c=2562383102,d=271733878,k=0;k=0&&classes.splice(idx,1),element.className=classes.join(" ")}exports.add=function(element,className){element.classList?element.classList.add(className):oldAdd(element,className)},exports.remove=function(element,className){element.classList?element.classList.remove(className):oldRemove(element,className)},exports.list=function(element){return element.classList?Array.prototype.slice.apply(element.classList):element.className.split(" ")}},{}],3:[function(require,module,exports){"use strict";function cssGet(element,styleName){return window.getComputedStyle(element)[styleName]}function cssSet(element,styleName,styleValue){return"number"==typeof styleValue&&(styleValue=styleValue.toString()+"px"),element.style[styleName]=styleValue,element}function cssMultiSet(element,obj){for(var key in obj){var val=obj[key];"number"==typeof val&&(val=val.toString()+"px"),element.style[key]=val}return element}var DOM={};DOM.e=function(tagName,className){var element=document.createElement(tagName);return element.className=className,element},DOM.appendTo=function(child,parent){return parent.appendChild(child),child},DOM.css=function(element,styleNameOrObject,styleValue){return"object"==typeof styleNameOrObject?cssMultiSet(element,styleNameOrObject):"undefined"==typeof styleValue?cssGet(element,styleNameOrObject):cssSet(element,styleNameOrObject,styleValue)},DOM.matches=function(element,query){return"undefined"!=typeof element.matches?element.matches(query):"undefined"!=typeof element.matchesSelector?element.matchesSelector(query):"undefined"!=typeof element.webkitMatchesSelector?element.webkitMatchesSelector(query):"undefined"!=typeof element.mozMatchesSelector?element.mozMatchesSelector(query):"undefined"!=typeof element.msMatchesSelector?element.msMatchesSelector(query):void 0},DOM.remove=function(element){"undefined"!=typeof element.remove?element.remove():element.parentNode&&element.parentNode.removeChild(element)},DOM.queryChildren=function(element,selector){return Array.prototype.filter.call(element.childNodes,function(child){return DOM.matches(child,selector)})},module.exports=DOM},{}],4:[function(require,module,exports){"use strict";var EventElement=function(element){this.element=element,this.events={}};EventElement.prototype.bind=function(eventName,handler){"undefined"==typeof this.events[eventName]&&(this.events[eventName]=[]),this.events[eventName].push(handler),this.element.addEventListener(eventName,handler,!1)},EventElement.prototype.unbind=function(eventName,handler){var isHandlerProvided="undefined"!=typeof handler;this.events[eventName]=this.events[eventName].filter(function(hdlr){return isHandlerProvided&&hdlr!==handler?!0:(this.element.removeEventListener(eventName,hdlr,!1),!1)},this)},EventElement.prototype.unbindAll=function(){for(var name in this.events)this.unbind(name)};var EventManager=function(){this.eventElements=[]};EventManager.prototype.eventElement=function(element){var ee=this.eventElements.filter(function(eventElement){return eventElement.element===element})[0];return"undefined"==typeof ee&&(ee=new EventElement(element),this.eventElements.push(ee)),ee},EventManager.prototype.bind=function(element,eventName,handler){this.eventElement(element).bind(eventName,handler)},EventManager.prototype.unbind=function(element,eventName,handler){this.eventElement(element).unbind(eventName,handler)},EventManager.prototype.unbindAll=function(){for(var i=0;ipositionRatio?positionRatio=0:positionRatio>1&&(positionRatio=1),updateScroll(element,"top",(i.contentHeight-i.containerHeight)*positionRatio),updateGeometry(element),e.stopPropagation()}),i.settings.stopPropagationOnClick&&i.event.bind(i.scrollbarX,"click",stopPropagation),i.event.bind(i.scrollbarXRail,"click",function(e){var halfOfScrollbarLength=h.toInt(i.scrollbarXWidth/2),positionLeft=i.railXRatio*(e.pageX-window.pageXOffset-pageOffset(i.scrollbarXRail).left-halfOfScrollbarLength),maxPositionLeft=i.railXRatio*(i.railXWidth-i.scrollbarXWidth),positionRatio=positionLeft/maxPositionLeft;0>positionRatio?positionRatio=0:positionRatio>1&&(positionRatio=1),updateScroll(element,"left",(i.contentWidth-i.containerWidth)*positionRatio-i.negativeScrollAdjustment),updateGeometry(element),e.stopPropagation()})}var h=require("../../lib/helper"),instances=require("../instances"),updateGeometry=require("../update-geometry"),updateScroll=require("../update-scroll");module.exports=function(element){var i=instances.get(element);bindClickRailHandler(element,i)}},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){"use strict";function bindMouseScrollXHandler(element,i){function updateScrollLeft(deltaX){var newLeft=currentLeft+deltaX*i.railXRatio,maxLeft=Math.max(0,i.scrollbarXRail.getBoundingClientRect().left)+i.railXRatio*(i.railXWidth-i.scrollbarXWidth);0>newLeft?i.scrollbarXLeft=0:newLeft>maxLeft?i.scrollbarXLeft=maxLeft:i.scrollbarXLeft=newLeft;var scrollLeft=h.toInt(i.scrollbarXLeft*(i.contentWidth-i.containerWidth)/(i.containerWidth-i.railXRatio*i.scrollbarXWidth))-i.negativeScrollAdjustment;updateScroll(element,"left",scrollLeft)}var currentLeft=null,currentPageX=null,mouseMoveHandler=function(e){updateScrollLeft(e.pageX-currentPageX),updateGeometry(element),e.stopPropagation(),e.preventDefault()},mouseUpHandler=function(){h.stopScrolling(element,"x"),i.event.unbind(i.ownerDocument,"mousemove",mouseMoveHandler)};i.event.bind(i.scrollbarX,"mousedown",function(e){currentPageX=e.pageX,currentLeft=h.toInt(d.css(i.scrollbarX,"left"))*i.railXRatio,h.startScrolling(element,"x"),i.event.bind(i.ownerDocument,"mousemove",mouseMoveHandler),i.event.once(i.ownerDocument,"mouseup",mouseUpHandler),e.stopPropagation(),e.preventDefault()})}function bindMouseScrollYHandler(element,i){function updateScrollTop(deltaY){var newTop=currentTop+deltaY*i.railYRatio,maxTop=Math.max(0,i.scrollbarYRail.getBoundingClientRect().top)+i.railYRatio*(i.railYHeight-i.scrollbarYHeight);0>newTop?i.scrollbarYTop=0:newTop>maxTop?i.scrollbarYTop=maxTop:i.scrollbarYTop=newTop;var scrollTop=h.toInt(i.scrollbarYTop*(i.contentHeight-i.containerHeight)/(i.containerHeight-i.railYRatio*i.scrollbarYHeight));updateScroll(element,"top",scrollTop)}var currentTop=null,currentPageY=null,mouseMoveHandler=function(e){updateScrollTop(e.pageY-currentPageY),updateGeometry(element),e.stopPropagation(),e.preventDefault()},mouseUpHandler=function(){h.stopScrolling(element,"y"),i.event.unbind(i.ownerDocument,"mousemove",mouseMoveHandler)};i.event.bind(i.scrollbarY,"mousedown",function(e){currentPageY=e.pageY,currentTop=h.toInt(d.css(i.scrollbarY,"top"))*i.railYRatio,h.startScrolling(element,"y"),i.event.bind(i.ownerDocument,"mousemove",mouseMoveHandler),i.event.once(i.ownerDocument,"mouseup",mouseUpHandler),e.stopPropagation(),e.preventDefault()})}var d=require("../../lib/dom"),h=require("../../lib/helper"),instances=require("../instances"),updateGeometry=require("../update-geometry"),updateScroll=require("../update-scroll");module.exports=function(element){var i=instances.get(element);bindMouseScrollXHandler(element,i),bindMouseScrollYHandler(element,i)}},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){"use strict";function bindKeyboardHandler(element,i){function shouldPreventDefault(deltaX,deltaY){var scrollTop=element.scrollTop;if(0===deltaX){if(!i.scrollbarYActive)return!1;if(0===scrollTop&&deltaY>0||scrollTop>=i.contentHeight-i.containerHeight&&0>deltaY)return!i.settings.wheelPropagation}var scrollLeft=element.scrollLeft;if(0===deltaY){if(!i.scrollbarXActive)return!1;if(0===scrollLeft&&0>deltaX||scrollLeft>=i.contentWidth-i.containerWidth&&deltaX>0)return!i.settings.wheelPropagation}return!0}var hovered=!1;i.event.bind(element,"mouseenter",function(){hovered=!0}),i.event.bind(element,"mouseleave",function(){hovered=!1});var shouldPrevent=!1;i.event.bind(i.ownerDocument,"keydown",function(e){if(!e.isDefaultPrevented||!e.isDefaultPrevented()){var focused=d.matches(i.scrollbarX,":focus")||d.matches(i.scrollbarY,":focus");if(hovered||focused){var activeElement=document.activeElement?document.activeElement:i.ownerDocument.activeElement;if(activeElement){for(;activeElement.shadowRoot;)activeElement=activeElement.shadowRoot.activeElement;if(h.isEditable(activeElement))return}var deltaX=0,deltaY=0;switch(e.which){case 37:deltaX=-30;break;case 38:deltaY=30;break;case 39:deltaX=30;break;case 40:deltaY=-30;break;case 33:deltaY=90;break;case 32:deltaY=e.shiftKey?90:-90;break;case 34:deltaY=-90;break;case 35:deltaY=e.ctrlKey?-i.contentHeight:-i.containerHeight;break;case 36:deltaY=e.ctrlKey?element.scrollTop:i.containerHeight;break;default:return}updateScroll(element,"top",element.scrollTop-deltaY),updateScroll(element,"left",element.scrollLeft+deltaX),updateGeometry(element),shouldPrevent=shouldPreventDefault(deltaX,deltaY),shouldPrevent&&e.preventDefault()}}})}var h=require("../../lib/helper"),d=require("../../lib/dom"),instances=require("../instances"),updateGeometry=require("../update-geometry"),updateScroll=require("../update-scroll");module.exports=function(element){var i=instances.get(element);bindKeyboardHandler(element,i)}},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){"use strict";function bindMouseWheelHandler(element,i){function shouldPreventDefault(deltaX,deltaY){var scrollTop=element.scrollTop;if(0===deltaX){if(!i.scrollbarYActive)return!1;if(0===scrollTop&&deltaY>0||scrollTop>=i.contentHeight-i.containerHeight&&0>deltaY)return!i.settings.wheelPropagation}var scrollLeft=element.scrollLeft;if(0===deltaY){if(!i.scrollbarXActive)return!1;if(0===scrollLeft&&0>deltaX||scrollLeft>=i.contentWidth-i.containerWidth&&deltaX>0)return!i.settings.wheelPropagation}return!0}function getDeltaFromEvent(e){var deltaX=e.deltaX,deltaY=-1*e.deltaY;return("undefined"==typeof deltaX||"undefined"==typeof deltaY)&&(deltaX=-1*e.wheelDeltaX/6,deltaY=e.wheelDeltaY/6),e.deltaMode&&1===e.deltaMode&&(deltaX*=10,deltaY*=10),deltaX!==deltaX&&deltaY!==deltaY&&(deltaX=0,deltaY=e.wheelDelta),[deltaX,deltaY]}function shouldBeConsumedByTextarea(deltaX,deltaY){var hoveredTextarea=element.querySelector("textarea:hover");if(hoveredTextarea){var maxScrollTop=hoveredTextarea.scrollHeight-hoveredTextarea.clientHeight;if(maxScrollTop>0&&!(0===hoveredTextarea.scrollTop&&deltaY>0||hoveredTextarea.scrollTop===maxScrollTop&&0>deltaY))return!0;var maxScrollLeft=hoveredTextarea.scrollLeft-hoveredTextarea.clientWidth;if(maxScrollLeft>0&&!(0===hoveredTextarea.scrollLeft&&0>deltaX||hoveredTextarea.scrollLeft===maxScrollLeft&&deltaX>0))return!0}return!1}function mousewheelHandler(e){var delta=getDeltaFromEvent(e),deltaX=delta[0],deltaY=delta[1];shouldBeConsumedByTextarea(deltaX,deltaY)||(shouldPrevent=!1,i.settings.useBothWheelAxes?i.scrollbarYActive&&!i.scrollbarXActive?(deltaY?updateScroll(element,"top",element.scrollTop-deltaY*i.settings.wheelSpeed):updateScroll(element,"top",element.scrollTop+deltaX*i.settings.wheelSpeed),shouldPrevent=!0):i.scrollbarXActive&&!i.scrollbarYActive&&(deltaX?updateScroll(element,"left",element.scrollLeft+deltaX*i.settings.wheelSpeed):updateScroll(element,"left",element.scrollLeft-deltaY*i.settings.wheelSpeed),shouldPrevent=!0):(updateScroll(element,"top",element.scrollTop-deltaY*i.settings.wheelSpeed),updateScroll(element,"left",element.scrollLeft+deltaX*i.settings.wheelSpeed)),updateGeometry(element),shouldPrevent=shouldPrevent||shouldPreventDefault(deltaX,deltaY),shouldPrevent&&(e.stopPropagation(),e.preventDefault()))}var shouldPrevent=!1;"undefined"!=typeof window.onwheel?i.event.bind(element,"wheel",mousewheelHandler):"undefined"!=typeof window.onmousewheel&&i.event.bind(element,"mousewheel",mousewheelHandler)}var instances=require("../instances"),updateGeometry=require("../update-geometry"),updateScroll=require("../update-scroll");module.exports=function(element){var i=instances.get(element);bindMouseWheelHandler(element,i)}},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){"use strict";function bindNativeScrollHandler(element,i){i.event.bind(element,"scroll",function(){updateGeometry(element)})}var instances=require("../instances"),updateGeometry=require("../update-geometry");module.exports=function(element){var i=instances.get(element);bindNativeScrollHandler(element,i)}},{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){"use strict";function bindSelectionHandler(element,i){function getRangeNode(){
+var selection=window.getSelection?window.getSelection():document.getSelection?document.getSelection():"";return 0===selection.toString().length?null:selection.getRangeAt(0).commonAncestorContainer}function startScrolling(){scrollingLoop||(scrollingLoop=setInterval(function(){return instances.get(element)?(updateScroll(element,"top",element.scrollTop+scrollDiff.top),updateScroll(element,"left",element.scrollLeft+scrollDiff.left),void updateGeometry(element)):void clearInterval(scrollingLoop)},50))}function stopScrolling(){scrollingLoop&&(clearInterval(scrollingLoop),scrollingLoop=null),h.stopScrolling(element)}var scrollingLoop=null,scrollDiff={top:0,left:0},isSelected=!1;i.event.bind(i.ownerDocument,"selectionchange",function(){element.contains(getRangeNode())?isSelected=!0:(isSelected=!1,stopScrolling())}),i.event.bind(window,"mouseup",function(){isSelected&&(isSelected=!1,stopScrolling())}),i.event.bind(window,"mousemove",function(e){if(isSelected){var mousePosition={x:e.pageX,y:e.pageY},containerGeometry={left:element.offsetLeft,right:element.offsetLeft+element.offsetWidth,top:element.offsetTop,bottom:element.offsetTop+element.offsetHeight};mousePosition.xcontainerGeometry.right-3?(scrollDiff.left=5,h.startScrolling(element,"x")):scrollDiff.left=0,mousePosition.ycontainerGeometry.bottom-3?(mousePosition.y-containerGeometry.bottom+3<5?scrollDiff.top=5:scrollDiff.top=20,h.startScrolling(element,"y")):scrollDiff.top=0,0===scrollDiff.top&&0===scrollDiff.left?stopScrolling():startScrolling()}})}var h=require("../../lib/helper"),instances=require("../instances"),updateGeometry=require("../update-geometry"),updateScroll=require("../update-scroll");module.exports=function(element){var i=instances.get(element);bindSelectionHandler(element,i)}},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){"use strict";function bindTouchHandler(element,i,supportsTouch,supportsIePointer){function shouldPreventDefault(deltaX,deltaY){var scrollTop=element.scrollTop,scrollLeft=element.scrollLeft,magnitudeX=Math.abs(deltaX),magnitudeY=Math.abs(deltaY);if(magnitudeY>magnitudeX){if(0>deltaY&&scrollTop===i.contentHeight-i.containerHeight||deltaY>0&&0===scrollTop)return!i.settings.swipePropagation}else if(magnitudeX>magnitudeY&&(0>deltaX&&scrollLeft===i.contentWidth-i.containerWidth||deltaX>0&&0===scrollLeft))return!i.settings.swipePropagation;return!0}function applyTouchMove(differenceX,differenceY){updateScroll(element,"top",element.scrollTop-differenceY),updateScroll(element,"left",element.scrollLeft-differenceX),updateGeometry(element)}function globalTouchStart(){inGlobalTouch=!0}function globalTouchEnd(){inGlobalTouch=!1}function getTouch(e){return e.targetTouches?e.targetTouches[0]:e}function shouldHandle(e){return e.targetTouches&&1===e.targetTouches.length?!0:e.pointerType&&"mouse"!==e.pointerType&&e.pointerType!==e.MSPOINTER_TYPE_MOUSE?!0:!1}function touchStart(e){if(shouldHandle(e)){inLocalTouch=!0;var touch=getTouch(e);startOffset.pageX=touch.pageX,startOffset.pageY=touch.pageY,startTime=(new Date).getTime(),null!==easingLoop&&clearInterval(easingLoop),e.stopPropagation()}}function touchMove(e){if(!inGlobalTouch&&inLocalTouch&&shouldHandle(e)){var touch=getTouch(e),currentOffset={pageX:touch.pageX,pageY:touch.pageY},differenceX=currentOffset.pageX-startOffset.pageX,differenceY=currentOffset.pageY-startOffset.pageY;applyTouchMove(differenceX,differenceY),startOffset=currentOffset;var currentTime=(new Date).getTime(),timeGap=currentTime-startTime;timeGap>0&&(speed.x=differenceX/timeGap,speed.y=differenceY/timeGap,startTime=currentTime),shouldPreventDefault(differenceX,differenceY)&&(e.stopPropagation(),e.preventDefault())}}function touchEnd(){!inGlobalTouch&&inLocalTouch&&(inLocalTouch=!1,clearInterval(easingLoop),easingLoop=setInterval(function(){return instances.get(element)?Math.abs(speed.x)<.01&&Math.abs(speed.y)<.01?void clearInterval(easingLoop):(applyTouchMove(30*speed.x,30*speed.y),speed.x*=.8,void(speed.y*=.8)):void clearInterval(easingLoop)},10))}var startOffset={},startTime=0,speed={},easingLoop=null,inGlobalTouch=!1,inLocalTouch=!1;supportsTouch&&(i.event.bind(window,"touchstart",globalTouchStart),i.event.bind(window,"touchend",globalTouchEnd),i.event.bind(element,"touchstart",touchStart),i.event.bind(element,"touchmove",touchMove),i.event.bind(element,"touchend",touchEnd)),supportsIePointer&&(window.PointerEvent?(i.event.bind(window,"pointerdown",globalTouchStart),i.event.bind(window,"pointerup",globalTouchEnd),i.event.bind(element,"pointerdown",touchStart),i.event.bind(element,"pointermove",touchMove),i.event.bind(element,"pointerup",touchEnd)):window.MSPointerEvent&&(i.event.bind(window,"MSPointerDown",globalTouchStart),i.event.bind(window,"MSPointerUp",globalTouchEnd),i.event.bind(element,"MSPointerDown",touchStart),i.event.bind(element,"MSPointerMove",touchMove),i.event.bind(element,"MSPointerUp",touchEnd)))}var instances=require("../instances"),updateGeometry=require("../update-geometry"),updateScroll=require("../update-scroll");module.exports=function(element,supportsTouch,supportsIePointer){var i=instances.get(element);bindTouchHandler(element,i,supportsTouch,supportsIePointer)}},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){"use strict";var cls=require("../lib/class"),h=require("../lib/helper"),instances=require("./instances"),updateGeometry=require("./update-geometry"),clickRailHandler=require("./handler/click-rail"),dragScrollbarHandler=require("./handler/drag-scrollbar"),keyboardHandler=require("./handler/keyboard"),mouseWheelHandler=require("./handler/mouse-wheel"),nativeScrollHandler=require("./handler/native-scroll"),selectionHandler=require("./handler/selection"),touchHandler=require("./handler/touch");module.exports=function(element,userSettings){userSettings="object"==typeof userSettings?userSettings:{},cls.add(element,"ps-container");var i=instances.add(element);i.settings=h.extend(i.settings,userSettings),cls.add(element,"ps-theme-"+i.settings.theme),clickRailHandler(element),dragScrollbarHandler(element),mouseWheelHandler(element),nativeScrollHandler(element),i.settings.useSelectionScroll&&selectionHandler(element),(h.env.supportsTouch||h.env.supportsIePointer)&&touchHandler(element,h.env.supportsTouch,h.env.supportsIePointer),i.settings.useKeyboard&&keyboardHandler(element),updateGeometry(element)}},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){"use strict";function Instance(element){function focus(){cls.add(element,"ps-focus")}function blur(){cls.remove(element,"ps-focus")}var i=this;i.settings=h.clone(defaultSettings),i.containerWidth=null,i.containerHeight=null,i.contentWidth=null,i.contentHeight=null,i.isRtl="rtl"===d.css(element,"direction"),i.isNegativeScroll=function(){var originalScrollLeft=element.scrollLeft,result=null;return element.scrollLeft=-1,result=element.scrollLeft<0,element.scrollLeft=originalScrollLeft,result}(),i.negativeScrollAdjustment=i.isNegativeScroll?element.scrollWidth-element.clientWidth:0,i.event=new EventManager,i.ownerDocument=element.ownerDocument||document,i.scrollbarXRail=d.appendTo(d.e("div","ps-scrollbar-x-rail"),element),i.scrollbarX=d.appendTo(d.e("div","ps-scrollbar-x"),i.scrollbarXRail),i.scrollbarX.setAttribute("tabindex",0),i.event.bind(i.scrollbarX,"focus",focus),i.event.bind(i.scrollbarX,"blur",blur),i.scrollbarXActive=null,i.scrollbarXWidth=null,i.scrollbarXLeft=null,i.scrollbarXBottom=h.toInt(d.css(i.scrollbarXRail,"bottom")),i.isScrollbarXUsingBottom=i.scrollbarXBottom===i.scrollbarXBottom,i.scrollbarXTop=i.isScrollbarXUsingBottom?null:h.toInt(d.css(i.scrollbarXRail,"top")),i.railBorderXWidth=h.toInt(d.css(i.scrollbarXRail,"borderLeftWidth"))+h.toInt(d.css(i.scrollbarXRail,"borderRightWidth")),d.css(i.scrollbarXRail,"display","block"),i.railXMarginWidth=h.toInt(d.css(i.scrollbarXRail,"marginLeft"))+h.toInt(d.css(i.scrollbarXRail,"marginRight")),d.css(i.scrollbarXRail,"display",""),i.railXWidth=null,i.railXRatio=null,i.scrollbarYRail=d.appendTo(d.e("div","ps-scrollbar-y-rail"),element),i.scrollbarY=d.appendTo(d.e("div","ps-scrollbar-y"),i.scrollbarYRail),i.scrollbarY.setAttribute("tabindex",0),i.event.bind(i.scrollbarY,"focus",focus),i.event.bind(i.scrollbarY,"blur",blur),i.scrollbarYActive=null,i.scrollbarYHeight=null,i.scrollbarYTop=null,i.scrollbarYRight=h.toInt(d.css(i.scrollbarYRail,"right")),i.isScrollbarYUsingRight=i.scrollbarYRight===i.scrollbarYRight,i.scrollbarYLeft=i.isScrollbarYUsingRight?null:h.toInt(d.css(i.scrollbarYRail,"left")),i.scrollbarYOuterWidth=i.isRtl?h.outerWidth(i.scrollbarY):null,i.railBorderYWidth=h.toInt(d.css(i.scrollbarYRail,"borderTopWidth"))+h.toInt(d.css(i.scrollbarYRail,"borderBottomWidth")),d.css(i.scrollbarYRail,"display","block"),i.railYMarginHeight=h.toInt(d.css(i.scrollbarYRail,"marginTop"))+h.toInt(d.css(i.scrollbarYRail,"marginBottom")),d.css(i.scrollbarYRail,"display",""),i.railYHeight=null,i.railYRatio=null}function getId(element){return"undefined"==typeof element.dataset?element.getAttribute("data-ps-id"):element.dataset.psId}function setId(element,id){"undefined"==typeof element.dataset?element.setAttribute("data-ps-id",id):element.dataset.psId=id}function removeId(element){"undefined"==typeof element.dataset?element.removeAttribute("data-ps-id"):delete element.dataset.psId}var cls=require("../lib/class"),d=require("../lib/dom"),defaultSettings=require("./default-setting"),EventManager=require("../lib/event-manager"),guid=require("../lib/guid"),h=require("../lib/helper"),instances={};exports.add=function(element){var newId=guid();return setId(element,newId),instances[newId]=new Instance(element),instances[newId]},exports.remove=function(element){delete instances[getId(element)],removeId(element)},exports.get=function(element){return instances[getId(element)]}},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){"use strict";function getThumbSize(i,thumbSize){return i.settings.minScrollbarLength&&(thumbSize=Math.max(thumbSize,i.settings.minScrollbarLength)),i.settings.maxScrollbarLength&&(thumbSize=Math.min(thumbSize,i.settings.maxScrollbarLength)),thumbSize}function updateCss(element,i){var xRailOffset={width:i.railXWidth};i.isRtl?xRailOffset.left=i.negativeScrollAdjustment+element.scrollLeft+i.containerWidth-i.contentWidth:xRailOffset.left=element.scrollLeft,i.isScrollbarXUsingBottom?xRailOffset.bottom=i.scrollbarXBottom-element.scrollTop:xRailOffset.top=i.scrollbarXTop+element.scrollTop,d.css(i.scrollbarXRail,xRailOffset);var yRailOffset={top:element.scrollTop,height:i.railYHeight};i.isScrollbarYUsingRight?i.isRtl?yRailOffset.right=i.contentWidth-(i.negativeScrollAdjustment+element.scrollLeft)-i.scrollbarYRight-i.scrollbarYOuterWidth:yRailOffset.right=i.scrollbarYRight-element.scrollLeft:i.isRtl?yRailOffset.left=i.negativeScrollAdjustment+element.scrollLeft+2*i.containerWidth-i.contentWidth-i.scrollbarYLeft-i.scrollbarYOuterWidth:yRailOffset.left=i.scrollbarYLeft+element.scrollLeft,d.css(i.scrollbarYRail,yRailOffset),d.css(i.scrollbarX,{left:i.scrollbarXLeft,width:i.scrollbarXWidth-i.railBorderXWidth}),d.css(i.scrollbarY,{top:i.scrollbarYTop,height:i.scrollbarYHeight-i.railBorderYWidth})}var cls=require("../lib/class"),d=require("../lib/dom"),h=require("../lib/helper"),instances=require("./instances"),updateScroll=require("./update-scroll");module.exports=function(element){var i=instances.get(element);i.containerWidth=element.clientWidth,i.containerHeight=element.clientHeight,i.contentWidth=element.scrollWidth,i.contentHeight=element.scrollHeight;var existingRails;element.contains(i.scrollbarXRail)||(existingRails=d.queryChildren(element,".ps-scrollbar-x-rail"),existingRails.length>0&&existingRails.forEach(function(rail){d.remove(rail)}),d.appendTo(i.scrollbarXRail,element)),element.contains(i.scrollbarYRail)||(existingRails=d.queryChildren(element,".ps-scrollbar-y-rail"),existingRails.length>0&&existingRails.forEach(function(rail){d.remove(rail)}),d.appendTo(i.scrollbarYRail,element)),!i.settings.suppressScrollX&&i.containerWidth+i.settings.scrollXMarginOffset=i.railXWidth-i.scrollbarXWidth&&(i.scrollbarXLeft=i.railXWidth-i.scrollbarXWidth),i.scrollbarYTop>=i.railYHeight-i.scrollbarYHeight&&(i.scrollbarYTop=i.railYHeight-i.scrollbarYHeight),updateCss(element,i),i.scrollbarXActive?cls.add(element,"ps-active-x"):(cls.remove(element,"ps-active-x"),i.scrollbarXWidth=0,i.scrollbarXLeft=0,updateScroll(element,"left",0)),i.scrollbarYActive?cls.add(element,"ps-active-y"):(cls.remove(element,"ps-active-y"),i.scrollbarYHeight=0,i.scrollbarYTop=0,updateScroll(element,"top",0))}},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){"use strict";var lastTop,lastLeft,instances=require("./instances"),upEvent=document.createEvent("Event"),downEvent=document.createEvent("Event"),leftEvent=document.createEvent("Event"),rightEvent=document.createEvent("Event"),yEvent=document.createEvent("Event"),xEvent=document.createEvent("Event"),xStartEvent=document.createEvent("Event"),xEndEvent=document.createEvent("Event"),yStartEvent=document.createEvent("Event"),yEndEvent=document.createEvent("Event");upEvent.initEvent("ps-scroll-up",!0,!0),downEvent.initEvent("ps-scroll-down",!0,!0),leftEvent.initEvent("ps-scroll-left",!0,!0),rightEvent.initEvent("ps-scroll-right",!0,!0),yEvent.initEvent("ps-scroll-y",!0,!0),xEvent.initEvent("ps-scroll-x",!0,!0),xStartEvent.initEvent("ps-x-reach-start",!0,!0),xEndEvent.initEvent("ps-x-reach-end",!0,!0),yStartEvent.initEvent("ps-y-reach-start",!0,!0),yEndEvent.initEvent("ps-y-reach-end",!0,!0),module.exports=function(element,axis,value){if("undefined"==typeof element)throw"You must provide an element to the update-scroll function";if("undefined"==typeof axis)throw"You must provide an axis to the update-scroll function";if("undefined"==typeof value)throw"You must provide a value to the update-scroll function";"top"===axis&&0>=value&&(element.scrollTop=value=0,element.dispatchEvent(yStartEvent)),"left"===axis&&0>=value&&(element.scrollLeft=value=0,element.dispatchEvent(xStartEvent));var i=instances.get(element);"top"===axis&&value>=i.contentHeight-i.containerHeight&&(element.scrollTop=value=i.contentHeight-i.containerHeight,element.dispatchEvent(yEndEvent)),"left"===axis&&value>=i.contentWidth-i.containerWidth&&(element.scrollLeft=value=i.contentWidth-i.containerWidth,element.dispatchEvent(xEndEvent)),lastTop||(lastTop=element.scrollTop),lastLeft||(lastLeft=element.scrollLeft),"top"===axis&&lastTop>value&&element.dispatchEvent(upEvent),"top"===axis&&value>lastTop&&element.dispatchEvent(downEvent),"left"===axis&&lastLeft>value&&element.dispatchEvent(leftEvent),"left"===axis&&value>lastLeft&&element.dispatchEvent(rightEvent),"top"===axis&&(element.scrollTop=lastTop=value,element.dispatchEvent(yEvent)),"left"===axis&&(element.scrollLeft=lastLeft=value,element.dispatchEvent(xEvent))}},{"./instances":18}],21:[function(require,module,exports){"use strict";var d=require("../lib/dom"),h=require("../lib/helper"),instances=require("./instances"),updateGeometry=require("./update-geometry"),updateScroll=require("./update-scroll");module.exports=function(element){var i=instances.get(element);i&&(i.negativeScrollAdjustment=i.isNegativeScroll?element.scrollWidth-element.clientWidth:0,d.css(i.scrollbarXRail,"display","block"),d.css(i.scrollbarYRail,"display","block"),i.railXMarginWidth=h.toInt(d.css(i.scrollbarXRail,"marginLeft"))+h.toInt(d.css(i.scrollbarXRail,"marginRight")),i.railYMarginHeight=h.toInt(d.css(i.scrollbarYRail,"marginTop"))+h.toInt(d.css(i.scrollbarYRail,"marginBottom")),d.css(i.scrollbarXRail,"display","none"),d.css(i.scrollbarYRail,"display","none"),updateGeometry(element),updateScroll(element,"top",element.scrollTop),updateScroll(element,"left",element.scrollLeft),d.css(i.scrollbarXRail,"display",""),d.css(i.scrollbarYRail,"display",""))}},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]),function(Plugin){Plugin.Libs.Twemoji=function(){"use strict";function createText(text){return document.createTextNode(text)}function escapeHTML(s){return s.replace(rescaper,replacer)}function defaultImageSrcGenerator(icon,options){return"".concat(options.base,options.size,"/",icon,options.ext)}function grabAllTextNodes(node,allText){for(var subnode,nodeType,childNodes=node.childNodes,length=childNodes.length;length--;)subnode=childNodes[length],nodeType=subnode.nodeType,3===nodeType?allText.push(subnode):1!==nodeType||shouldntBeParsed.test(subnode.nodeName)||grabAllTextNodes(subnode,allText);return allText}function grabTheRightIcon(icon,variant){return toCodePoint("๏ธ"===variant?icon.slice(0,-1):3===icon.length&&"๏ธ"===icon.charAt(1)?icon.charAt(0)+icon.charAt(2):icon)}function parseNode(node,options){for(var attrib,attrname,modified,fragment,subnode,text,match,i,index,img,alt,icon,variant,src,allText=grabAllTextNodes(node,[]),length=allText.length;length--;){for(modified=!1,fragment=document.createDocumentFragment(),subnode=allText[length],text=subnode.nodeValue,i=0;match=re.exec(text);){if(index=match.index,index!==i&&fragment.appendChild(createText(text.slice(i,index))),alt=match[0],icon=match[1],variant=match[2],i=index+alt.length,"๏ธ"!==variant&&(src=options.callback(grabTheRightIcon(icon,variant),options,variant))){img=new Image,img.onerror=options.onerror,img.setAttribute("draggable","false"),attrib=options.attributes(icon,variant);for(attrname in attrib)attrib.hasOwnProperty(attrname)&&0!==attrname.indexOf("on")&&!img.hasAttribute(attrname)&&img.setAttribute(attrname,attrib[attrname]);img.className=options.className,img.alt=alt,img.src=src,modified=!0,fragment.appendChild(img)}img||fragment.appendChild(createText(alt)),img=null}modified&&(i")}return ret})}function replacer(m){return escaper[m]}function returnNull(){return null}function toSizeSquaredAsset(value){return"number"==typeof value?value+"x"+value:value}function fromCodePoint(codepoint){var code="string"==typeof codepoint?parseInt(codepoint,16):codepoint;return 65536>code?fromCharCode(code):(code-=65536,fromCharCode(55296+(code>>10),56320+(1023&code)))}function parse(what,how){return how&&"function"!=typeof how||(how={callback:how}),("string"==typeof what?parseString:parseNode)(what,{callback:how.callback||defaultImageSrcGenerator,attributes:"function"==typeof how.attributes?how.attributes:returnNull,base:"string"==typeof how.base?how.base:twemoji.base,ext:how.ext||twemoji.ext,size:how.folder||toSizeSquaredAsset(how.size||twemoji.size),className:how.className||twemoji.className,onerror:how.onerror||twemoji.onerror})}function replace(text,callback){return String(text).replace(re,callback)}function test(text){re.lastIndex=0;var result=re.test(text);return re.lastIndex=0,result}function toCodePoint(unicodeSurrogates,sep){for(var r=[],c=0,p=0,i=0;i=55296&&56319>=c?p=c:r.push(c.toString(16));return r.join(sep||"-")}var twemoji={base:("https:"===location.protocol?"https:":"http:")+"//twemoji.maxcdn.com/",ext:".png",size:"36x36",className:"emoji",convert:{fromCodePoint:fromCodePoint,toCodePoint:toCodePoint},onerror:function(){this.parentNode&&this.parentNode.replaceChild(createText(this.alt),this)},parse:parse,replace:replace,test:test},escaper={"&":"&","<":"<",">":">","'":"'",'"':"""},re=/((?:\ud83c\udde8\ud83c\uddf3|\ud83c\uddfa\ud83c\uddf8|\ud83c\uddf7\ud83c\uddfa|\ud83c\uddf0\ud83c\uddf7|\ud83c\uddef\ud83c\uddf5|\ud83c\uddee\ud83c\uddf9|\ud83c\uddec\ud83c\udde7|\ud83c\uddeb\ud83c\uddf7|\ud83c\uddea\ud83c\uddf8|\ud83c\udde9\ud83c\uddea|\u0039\ufe0f?\u20e3|\u0038\ufe0f?\u20e3|\u0037\ufe0f?\u20e3|\u0036\ufe0f?\u20e3|\u0035\ufe0f?\u20e3|\u0034\ufe0f?\u20e3|\u0033\ufe0f?\u20e3|\u0032\ufe0f?\u20e3|\u0031\ufe0f?\u20e3|\u0030\ufe0f?\u20e3|\u0023\ufe0f?\u20e3|\ud83d\udeb3|\ud83d\udeb1|\ud83d\udeb0|\ud83d\udeaf|\ud83d\udeae|\ud83d\udea6|\ud83d\udea3|\ud83d\udea1|\ud83d\udea0|\ud83d\ude9f|\ud83d\ude9e|\ud83d\ude9d|\ud83d\ude9c|\ud83d\ude9b|\ud83d\ude98|\ud83d\ude96|\ud83d\ude94|\ud83d\ude90|\ud83d\ude8e|\ud83d\ude8d|\ud83d\ude8b|\ud83d\ude8a|\ud83d\ude88|\ud83d\ude86|\ud83d\ude82|\ud83d\ude81|\ud83d\ude36|\ud83d\ude34|\ud83d\ude2f|\ud83d\ude2e|\ud83d\ude2c|\ud83d\ude27|\ud83d\ude26|\ud83d\ude1f|\ud83d\ude1b|\ud83d\ude19|\ud83d\ude17|\ud83d\ude15|\ud83d\ude11|\ud83d\ude10|\ud83d\ude0e|\ud83d\ude08|\ud83d\ude07|\ud83d\ude00|\ud83d\udd67|\ud83d\udd66|\ud83d\udd65|\ud83d\udd64|\ud83d\udd63|\ud83d\udd62|\ud83d\udd61|\ud83d\udd60|\ud83d\udd5f|\ud83d\udd5e|\ud83d\udd5d|\ud83d\udd5c|\ud83d\udd2d|\ud83d\udd2c|\ud83d\udd15|\ud83d\udd09|\ud83d\udd08|\ud83d\udd07|\ud83d\udd06|\ud83d\udd05|\ud83d\udd04|\ud83d\udd02|\ud83d\udd01|\ud83d\udd00|\ud83d\udcf5|\ud83d\udcef|\ud83d\udced|\ud83d\udcec|\ud83d\udcb7|\ud83d\udcb6|\ud83d\udcad|\ud83d\udc6d|\ud83d\udc6c|\ud83d\udc65|\ud83d\udc2a|\ud83d\udc16|\ud83d\udc15|\ud83d\udc13|\ud83d\udc10|\ud83d\udc0f|\ud83d\udc0b|\ud83d\udc0a|\ud83d\udc09|\ud83d\udc08|\ud83d\udc07|\ud83d\udc06|\ud83d\udc05|\ud83d\udc04|\ud83d\udc03|\ud83d\udc02|\ud83d\udc01|\ud83d\udc00|\ud83c\udfe4|\ud83c\udfc9|\ud83c\udfc7|\ud83c\udf7c|\ud83c\udf50|\ud83c\udf4b|\ud83c\udf33|\ud83c\udf32|\ud83c\udf1e|\ud83c\udf1d|\ud83c\udf1c|\ud83c\udf1a|\ud83c\udf18|\ud83c\udccf|\ud83c\udd8e|\ud83c\udd91|\ud83c\udd92|\ud83c\udd93|\ud83c\udd94|\ud83c\udd95|\ud83c\udd96|\ud83c\udd97|\ud83c\udd98|\ud83c\udd99|\ud83c\udd9a|\ud83d\udc77|\ud83d\udec5|\ud83d\udec4|\ud83d\udec3|\ud83d\udec2|\ud83d\udec1|\ud83d\udebf|\ud83d\udeb8|\ud83d\udeb7|\ud83d\udeb5|\ud83c\ude01|\ud83c\ude32|\ud83c\ude33|\ud83c\ude34|\ud83c\ude35|\ud83c\ude36|\ud83c\ude38|\ud83c\ude39|\ud83c\ude3a|\ud83c\ude50|\ud83c\ude51|\ud83c\udf00|\ud83c\udf01|\ud83c\udf02|\ud83c\udf03|\ud83c\udf04|\ud83c\udf05|\ud83c\udf06|\ud83c\udf07|\ud83c\udf08|\ud83c\udf09|\ud83c\udf0a|\ud83c\udf0b|\ud83c\udf0c|\ud83c\udf0f|\ud83c\udf11|\ud83c\udf13|\ud83c\udf14|\ud83c\udf15|\ud83c\udf19|\ud83c\udf1b|\ud83c\udf1f|\ud83c\udf20|\ud83c\udf30|\ud83c\udf31|\ud83c\udf34|\ud83c\udf35|\ud83c\udf37|\ud83c\udf38|\ud83c\udf39|\ud83c\udf3a|\ud83c\udf3b|\ud83c\udf3c|\ud83c\udf3d|\ud83c\udf3e|\ud83c\udf3f|\ud83c\udf40|\ud83c\udf41|\ud83c\udf42|\ud83c\udf43|\ud83c\udf44|\ud83c\udf45|\ud83c\udf46|\ud83c\udf47|\ud83c\udf48|\ud83c\udf49|\ud83c\udf4a|\ud83c\udf4c|\ud83c\udf4d|\ud83c\udf4e|\ud83c\udf4f|\ud83c\udf51|\ud83c\udf52|\ud83c\udf53|\ud83c\udf54|\ud83c\udf55|\ud83c\udf56|\ud83c\udf57|\ud83c\udf58|\ud83c\udf59|\ud83c\udf5a|\ud83c\udf5b|\ud83c\udf5c|\ud83c\udf5d|\ud83c\udf5e|\ud83c\udf5f|\ud83c\udf60|\ud83c\udf61|\ud83c\udf62|\ud83c\udf63|\ud83c\udf64|\ud83c\udf65|\ud83c\udf66|\ud83c\udf67|\ud83c\udf68|\ud83c\udf69|\ud83c\udf6a|\ud83c\udf6b|\ud83c\udf6c|\ud83c\udf6d|\ud83c\udf6e|\ud83c\udf6f|\ud83c\udf70|\ud83c\udf71|\ud83c\udf72|\ud83c\udf73|\ud83c\udf74|\ud83c\udf75|\ud83c\udf76|\ud83c\udf77|\ud83c\udf78|\ud83c\udf79|\ud83c\udf7a|\ud83c\udf7b|\ud83c\udf80|\ud83c\udf81|\ud83c\udf82|\ud83c\udf83|\ud83c\udf84|\ud83c\udf85|\ud83c\udf86|\ud83c\udf87|\ud83c\udf88|\ud83c\udf89|\ud83c\udf8a|\ud83c\udf8b|\ud83c\udf8c|\ud83c\udf8d|\ud83c\udf8e|\ud83c\udf8f|\ud83c\udf90|\ud83c\udf91|\ud83c\udf92|\ud83c\udf93|\ud83c\udfa0|\ud83c\udfa1|\ud83c\udfa2|\ud83c\udfa3|\ud83c\udfa4|\ud83c\udfa5|\ud83c\udfa6|\ud83c\udfa7|\ud83c\udfa8|\ud83c\udfa9|\ud83c\udfaa|\ud83c\udfab|\ud83c\udfac|\ud83c\udfad|\ud83c\udfae|\ud83c\udfaf|\ud83c\udfb0|\ud83c\udfb1|\ud83c\udfb2|\ud83c\udfb3|\ud83c\udfb4|\ud83c\udfb5|\ud83c\udfb6|\ud83c\udfb7|\ud83c\udfb8|\ud83c\udfb9|\ud83c\udfba|\ud83c\udfbb|\ud83c\udfbc|\ud83c\udfbd|\ud83c\udfbe|\ud83c\udfbf|\ud83c\udfc0|\ud83c\udfc1|\ud83c\udfc2|\ud83c\udfc3|\ud83c\udfc4|\ud83c\udfc6|\ud83c\udfc8|\ud83c\udfca|\ud83c\udfe0|\ud83c\udfe1|\ud83c\udfe2|\ud83c\udfe3|\ud83c\udfe5|\ud83c\udfe6|\ud83c\udfe7|\ud83c\udfe8|\ud83c\udfe9|\ud83c\udfea|\ud83c\udfeb|\ud83c\udfec|\ud83c\udfed|\ud83c\udfee|\ud83c\udfef|\ud83c\udff0|\ud83d\udc0c|\ud83d\udc0d|\ud83d\udc0e|\ud83d\udc11|\ud83d\udc12|\ud83d\udc14|\ud83d\udc17|\ud83d\udc18|\ud83d\udc19|\ud83d\udc1a|\ud83d\udc1b|\ud83d\udc1c|\ud83d\udc1d|\ud83d\udc1e|\ud83d\udc1f|\ud83d\udc20|\ud83d\udc21|\ud83d\udc22|\ud83d\udc23|\ud83d\udc24|\ud83d\udc25|\ud83d\udc26|\ud83d\udc27|\ud83d\udc28|\ud83d\udc29|\ud83d\udc2b|\ud83d\udc2c|\ud83d\udc2d|\ud83d\udc2e|\ud83d\udc2f|\ud83d\udc30|\ud83d\udc31|\ud83d\udc32|\ud83d\udc33|\ud83d\udc34|\ud83d\udc35|\ud83d\udc36|\ud83d\udc37|\ud83d\udc38|\ud83d\udc39|\ud83d\udc3a|\ud83d\udc3b|\ud83d\udc3c|\ud83d\udc3d|\ud83d\udc3e|\ud83d\udc40|\ud83d\udc42|\ud83d\udc43|\ud83d\udc44|\ud83d\udc45|\ud83d\udc46|\ud83d\udc47|\ud83d\udc48|\ud83d\udc49|\ud83d\udc4a|\ud83d\udc4b|\ud83d\udc4c|\ud83d\udc4d|\ud83d\udc4e|\ud83d\udc4f|\ud83d\udc50|\ud83d\udc51|\ud83d\udc52|\ud83d\udc53|\ud83d\udc54|\ud83d\udc55|\ud83d\udc56|\ud83d\udc57|\ud83d\udc58|\ud83d\udc59|\ud83d\udc5a|\ud83d\udc5b|\ud83d\udc5c|\ud83d\udc5d|\ud83d\udc5e|\ud83d\udc5f|\ud83d\udc60|\ud83d\udc61|\ud83d\udc62|\ud83d\udc63|\ud83d\udc64|\ud83d\udc66|\ud83d\udc67|\ud83d\udc68|\ud83d\udc69|\ud83d\udc6a|\ud83d\udc6b|\ud83d\udc6e|\ud83d\udc6f|\ud83d\udc70|\ud83d\udc71|\ud83d\udc72|\ud83d\udc73|\ud83d\udc74|\ud83d\udc75|\ud83d\udc76|\ud83d\udeb4|\ud83d\udc78|\ud83d\udc79|\ud83d\udc7a|\ud83d\udc7b|\ud83d\udc7c|\ud83d\udc7d|\ud83d\udc7e|\ud83d\udc7f|\ud83d\udc80|\ud83d\udc81|\ud83d\udc82|\ud83d\udc83|\ud83d\udc84|\ud83d\udc85|\ud83d\udc86|\ud83d\udc87|\ud83d\udc88|\ud83d\udc89|\ud83d\udc8a|\ud83d\udc8b|\ud83d\udc8c|\ud83d\udc8d|\ud83d\udc8e|\ud83d\udc8f|\ud83d\udc90|\ud83d\udc91|\ud83d\udc92|\ud83d\udc93|\ud83d\udc94|\ud83d\udc95|\ud83d\udc96|\ud83d\udc97|\ud83d\udc98|\ud83d\udc99|\ud83d\udc9a|\ud83d\udc9b|\ud83d\udc9c|\ud83d\udc9d|\ud83d\udc9e|\ud83d\udc9f|\ud83d\udca0|\ud83d\udca1|\ud83d\udca2|\ud83d\udca3|\ud83d\udca4|\ud83d\udca5|\ud83d\udca6|\ud83d\udca7|\ud83d\udca8|\ud83d\udca9|\ud83d\udcaa|\ud83d\udcab|\ud83d\udcac|\ud83d\udcae|\ud83d\udcaf|\ud83d\udcb0|\ud83d\udcb1|\ud83d\udcb2|\ud83d\udcb3|\ud83d\udcb4|\ud83d\udcb5|\ud83d\udcb8|\ud83d\udcb9|\ud83d\udcba|\ud83d\udcbb|\ud83d\udcbc|\ud83d\udcbd|\ud83d\udcbe|\ud83d\udcbf|\ud83d\udcc0|\ud83d\udcc1|\ud83d\udcc2|\ud83d\udcc3|\ud83d\udcc4|\ud83d\udcc5|\ud83d\udcc6|\ud83d\udcc7|\ud83d\udcc8|\ud83d\udcc9|\ud83d\udcca|\ud83d\udccb|\ud83d\udccc|\ud83d\udccd|\ud83d\udcce|\ud83d\udccf|\ud83d\udcd0|\ud83d\udcd1|\ud83d\udcd2|\ud83d\udcd3|\ud83d\udcd4|\ud83d\udcd5|\ud83d\udcd6|\ud83d\udcd7|\ud83d\udcd8|\ud83d\udcd9|\ud83d\udcda|\ud83d\udcdb|\ud83d\udcdc|\ud83d\udcdd|\ud83d\udcde|\ud83d\udcdf|\ud83d\udce0|\ud83d\udce1|\ud83d\udce2|\ud83d\udce3|\ud83d\udce4|\ud83d\udce5|\ud83d\udce6|\ud83d\udce7|\ud83d\udce8|\ud83d\udce9|\ud83d\udcea|\ud83d\udceb|\ud83d\udcee|\ud83d\udcf0|\ud83d\udcf1|\ud83d\udcf2|\ud83d\udcf3|\ud83d\udcf4|\ud83d\udcf6|\ud83d\udcf7|\ud83d\udcf9|\ud83d\udcfa|\ud83d\udcfb|\ud83d\udcfc|\ud83d\udd03|\ud83d\udd0a|\ud83d\udd0b|\ud83d\udd0c|\ud83d\udd0d|\ud83d\udd0e|\ud83d\udd0f|\ud83d\udd10|\ud83d\udd11|\ud83d\udd12|\ud83d\udd13|\ud83d\udd14|\ud83d\udd16|\ud83d\udd17|\ud83d\udd18|\ud83d\udd19|\ud83d\udd1a|\ud83d\udd1b|\ud83d\udd1c|\ud83d\udd1d|\ud83d\udd1e|\ud83d\udd1f|\ud83d\udd20|\ud83d\udd21|\ud83d\udd22|\ud83d\udd23|\ud83d\udd24|\ud83d\udd25|\ud83d\udd26|\ud83d\udd27|\ud83d\udd28|\ud83d\udd29|\ud83d\udd2a|\ud83d\udd2b|\ud83d\udd2e|\ud83d\udd2f|\ud83d\udd30|\ud83d\udd31|\ud83d\udd32|\ud83d\udd33|\ud83d\udd34|\ud83d\udd35|\ud83d\udd36|\ud83d\udd37|\ud83d\udd38|\ud83d\udd39|\ud83d\udd3a|\ud83d\udd3b|\ud83d\udd3c|\ud83d\udd3d|\ud83d\udd50|\ud83d\udd51|\ud83d\udd52|\ud83d\udd53|\ud83d\udd54|\ud83d\udd55|\ud83d\udd56|\ud83d\udd57|\ud83d\udd58|\ud83d\udd59|\ud83d\udd5a|\ud83d\udd5b|\ud83d\uddfb|\ud83d\uddfc|\ud83d\uddfd|\ud83d\uddfe|\ud83d\uddff|\ud83d\ude01|\ud83d\ude02|\ud83d\ude03|\ud83d\ude04|\ud83d\ude05|\ud83d\ude06|\ud83d\ude09|\ud83d\ude0a|\ud83d\ude0b|\ud83d\ude0c|\ud83d\ude0d|\ud83d\ude0f|\ud83d\ude12|\ud83d\ude13|\ud83d\ude14|\ud83d\ude16|\ud83d\ude18|\ud83d\ude1a|\ud83d\ude1c|\ud83d\ude1d|\ud83d\ude1e|\ud83d\ude20|\ud83d\ude21|\ud83d\ude22|\ud83d\ude23|\ud83d\ude24|\ud83d\ude25|\ud83d\ude28|\ud83d\ude29|\ud83d\ude2a|\ud83d\ude2b|\ud83d\ude2d|\ud83d\ude30|\ud83d\ude31|\ud83d\ude32|\ud83d\ude33|\ud83d\ude35|\ud83d\ude37|\ud83d\ude38|\ud83d\ude39|\ud83d\ude3a|\ud83d\ude3b|\ud83d\ude3c|\ud83d\ude3d|\ud83d\ude3e|\ud83d\ude3f|\ud83d\ude40|\ud83d\ude45|\ud83d\ude46|\ud83d\ude47|\ud83d\ude48|\ud83d\ude49|\ud83d\ude4a|\ud83d\ude4b|\ud83d\ude4c|\ud83d\ude4d|\ud83d\ude4e|\ud83d\ude4f|\ud83d\ude80|\ud83d\ude83|\ud83d\ude84|\ud83d\ude85|\ud83d\ude87|\ud83d\ude89|\ud83d\ude8c|\ud83d\ude8f|\ud83d\ude91|\ud83d\ude92|\ud83d\ude93|\ud83d\ude95|\ud83d\ude97|\ud83d\ude99|\ud83d\ude9a|\ud83d\udea2|\ud83d\udea4|\ud83d\udea5|\ud83d\udea7|\ud83d\udea8|\ud83d\udea9|\ud83d\udeaa|\ud83d\udeab|\ud83d\udeac|\ud83d\udead|\ud83d\udeb2|\ud83d\udeb6|\ud83d\udeb9|\ud83d\udeba|\ud83d\udebb|\ud83d\udebc|\ud83d\udebd|\ud83d\udebe|\ud83d\udec0|\ud83c\udde6|\ud83c\udde7|\ud83c\udde8|\ud83c\udde9|\ud83c\uddea|\ud83c\uddeb|\ud83c\uddec|\ud83c\udded|\ud83c\uddee|\ud83c\uddef|\ud83c\uddf0|\ud83c\uddf1|\ud83c\uddf2|\ud83c\uddf3|\ud83c\uddf4|\ud83c\uddf5|\ud83c\uddf6|\ud83c\uddf7|\ud83c\uddf8|\ud83c\uddf9|\ud83c\uddfa|\ud83c\uddfb|\ud83c\uddfc|\ud83c\uddfd|\ud83c\uddfe|\ud83c\uddff|\ud83c\udf0d|\ud83c\udf0e|\ud83c\udf10|\ud83c\udf12|\ud83c\udf16|\ud83c\udf17|\ue50a|\u27b0|\u2797|\u2796|\u2795|\u2755|\u2754|\u2753|\u274e|\u274c|\u2728|\u270b|\u270a|\u2705|\u26ce|\u23f3|\u23f0|\u23ec|\u23eb|\u23ea|\u23e9|\u27bf|\u00a9|\u00ae)|(?:(?:\ud83c\udc04|\ud83c\udd70|\ud83c\udd71|\ud83c\udd7e|\ud83c\udd7f|\ud83c\ude02|\ud83c\ude1a|\ud83c\ude2f|\ud83c\ude37|\u3299|\u303d|\u3030|\u2b55|\u2b50|\u2b1c|\u2b1b|\u2b07|\u2b06|\u2b05|\u2935|\u2934|\u27a1|\u2764|\u2757|\u2747|\u2744|\u2734|\u2733|\u2716|\u2714|\u2712|\u270f|\u270c|\u2709|\u2708|\u2702|\u26fd|\u26fa|\u26f5|\u26f3|\u26f2|\u26ea|\u26d4|\u26c5|\u26c4|\u26be|\u26bd|\u26ab|\u26aa|\u26a1|\u26a0|\u2693|\u267f|\u267b|\u3297|\u2666|\u2665|\u2663|\u2660|\u2653|\u2652|\u2651|\u2650|\u264f|\u264e|\u264d|\u264c|\u264b|\u264a|\u2649|\u2648|\u263a|\u261d|\u2615|\u2614|\u2611|\u260e|\u2601|\u2600|\u25fe|\u25fd|\u25fc|\u25fb|\u25c0|\u25b6|\u25ab|\u25aa|\u24c2|\u231b|\u231a|\u21aa|\u21a9|\u2199|\u2198|\u2197|\u2196|\u2195|\u2194|\u2139|\u2122|\u2049|\u203c|\u2668)([\uFE0E\uFE0F]?)))/g,rescaper=/[&<>'"]/g,shouldntBeParsed=/IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,fromCharCode=String.fromCharCode;
+return twemoji}()}(window.StickersModule),window.StickersModule.Service={},function(Plugin){Plugin.Service.Ajax=function(options){if(options=options||{},options.url){options.type=options.type&&options.type.toUpperCase()||"GET",options.headers=options.headers||{},options.data=options.data||{},options.success=options.success||function(){},options.error=options.error||function(){},options.complete=options.complete||function(){},options.headers.Apikey=Plugin.Configs.apiKey,options.headers.Platform="JS",options.headers.Localization=Plugin.Configs.lang,options.headers.UserId=Plugin.Configs.userId,("POST"==options.type||"PUT"==options.type)&&(options.headers["Content-Type"]=options.headers["Content-Type"]||"application/json",options.headers.DeviceId=Plugin.Service.Storage.getDeviceId());var xmlhttp=new XMLHttpRequest;xmlhttp.open(options.type,options.url,!0);for(var name in options.headers)xmlhttp.setRequestHeader(name,options.headers[name]);xmlhttp.onreadystatechange=function(){if(4==xmlhttp.readyState){if(200==xmlhttp.status)options.success(JSON.parse(xmlhttp.responseText),xmlhttp);else{var response={};try{response=JSON.parse(xmlhttp.responseText)}catch(ex){response={}}options.error(response,xmlhttp)}options.complete(JSON.parse(xmlhttp.responseText),xmlhttp)}},xmlhttp.send(JSON.stringify(options.data))}}}(window.StickersModule),function(Plugin){var API_VERSION=2;Plugin.Service.Api={getApiVersion:function(){return API_VERSION},getPacks:function(successCallback){Plugin.Service.Ajax({type:"get",url:Plugin.Service.Url.getUserPacksUrl(),success:function(response){response=response||{},response.meta=response.meta||{},response.meta.shop_last_modified=response.meta.shop_last_modified||0,Plugin.Service.Storage.setStoreLastModified(1e3*response.meta.shop_last_modified),successCallback&&successCallback(response.data)}})},getPackPreview:function(packName,successCallback){Plugin.Service.Ajax({type:"get",url:Plugin.Service.Url.getPackPreviewUrl(packName),success:function(response){successCallback&&successCallback(response.data)}})},sendStatistic:function(statistic){Plugin.Service.Ajax({type:"post",url:Plugin.Service.Url.getStatisticUrl(),data:statistic})},updateUserData:function(userData){return Plugin.Service.Ajax({type:"put",url:Plugin.Service.Url.getUserDataUrl(),data:userData,headers:{"Content-Type":"application/json"}})},purchasePack:function(packName,pricePoint,successCallback,failCallback){Plugin.Service.Ajax({type:"post",url:Plugin.Service.Url.getPurchaseUrl(packName,pricePoint),success:function(response){successCallback&&successCallback(response.data)},error:function(){var pr=Plugin.Service.PendingRequest;pr.add(pr.tasks.purchasePack,{packName:packName,pricePoint:pricePoint}),failCallback&&failCallback()}})},getContentById:function(contentId,successCallback){Plugin.Service.Ajax({type:"get",url:Plugin.Service.Url.getContentByIdUrl(contentId),success:function(response){successCallback&&successCallback(response.data)}})},hidePack:function(packName,successCallback,failCallback){return Plugin.Service.Ajax({type:"DELETE",url:Plugin.Service.Url.getHidePackUrl(packName),success:function(response){successCallback&&successCallback(response.data)},error:function(){failCallback&&failCallback()}})}}}(window.StickersModule),function(Plugin){Plugin.Service.El={css:function(el,property){return el.style&&el.style[property]||el.currentStyle&&el.currentStyle[property]||getComputedStyle(el)[property]},outerWidth:function(el){var width=el.offsetWidth;return width+=parseInt(this.css(el,"marginLeft"))+parseInt(this.css(el,"marginRight"))},appendAfter:function(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)},getParents:function(elem,selector){var parents=[];if(selector)var firstChar=selector.charAt(0);for(;elem&&elem!==document;elem=elem.parentNode)selector?("."===firstChar&&elem.classList.contains(selector.substr(1))&&parents.push(elem),"#"===firstChar&&elem.id===selector.substr(1)&&parents.push(elem),"["===firstChar&&elem.hasAttribute(selector.substr(1,selector.length-1))&&parents.push(elem),elem.tagName.toLowerCase()===selector&&parents.push(elem)):parents.push(elem);return 0===parents.length?null:parents}}}(window.StickersModule),function(Plugin){Plugin.Service.Emoji={emojiProvider:null,init:function(emojiProvider){this.emojiProvider=emojiProvider},parseEmojiFromText:function(text){return this.emojiProvider.parse(text,{size:2==window.devicePixelRatio?72:36})},parseEmojiFromHtml:function(html){var content=document.createElement("div");content.innerHTML=html;for(var emojisEls=content.getElementsByClassName("emoji"),i=emojisEls.length-1;i>=0;i--){var emoji=emojisEls[i].getAttribute("alt");content.replaceChild(document.createTextNode(emoji),emojisEls[i])}return content.innerHTML}}}(window.StickersModule),function(Plugin){Plugin.Service.Event={events:{resize:"resize",popoverShown:"sp:popover:shown",popoverHidden:"sp:popover:hidden",showContentHighlight:"sp:content:highlight:show",hideContentHighlight:"sp:content:highlight:hide"},dispatch:function(eventName,el){if(eventName){el=el||window;var event;document.createEvent?(event=document.createEvent("HTMLEvents"),event.initEvent(eventName,!0,!0)):document.createEventObject&&(event=document.createEventObject(),event.eventType=eventName),event.eventName=eventName,el.dispatchEvent?el.dispatchEvent(event):el.fireEvent?el.fireEvent("on"+event.eventType,event):el[eventName]?el[eventName]():el["on"+eventName]&&el["on"+eventName]()}},popoverShown:function(){this.dispatch(this.events.popoverShown)},popoverHidden:function(){this.dispatch(this.events.popoverHidden)},changeContentHighlight:function(value){this.dispatch(value?this.events.showContentHighlight:this.events.hideContentHighlight)},resize:function(el){this.dispatch(this.events.resize,el)}}}(window.StickersModule),function(Plugin){Plugin.Service.Helper={extend:function(out){out=out||{};for(var i=1;iPlugin.Service.Storage.getStoreLastVisit()&&(showContentHighlight=!0),Plugin.Service.Event.changeContentHighlight(showContentHighlight)}}}(window.StickersModule),function(Plugin){var stickerpipe;Plugin.Service.Pack={init:function(_stickerpipe){stickerpipe=_stickerpipe},purchase:function(packName,pricePoint,isUnwatched,successCallback,failCallback){isUnwatched="undefined"==typeof isUnwatched?!0:isUnwatched,Plugin.Service.Api.purchasePack(packName,pricePoint,function(pack){pack.isUnwatched=isUnwatched;for(var packContentIds=[],i=0;i'},async)}):void(callback&&callback(null))},getById:function(contentId,successCallback){var sticker=Plugin.Service.Storage.getContentById(contentId);return sticker?void(successCallback&&successCallback(sticker,!1)):void Plugin.Service.Api.getContentById(contentId,function(sticker){Plugin.Service.Storage.setContentById(contentId,sticker),successCallback&&successCallback(sticker,!0)})},isSticker:function(text){return!!this.parseStickerId(text)}}}(window.StickersModule),function(Plugin){var lockr=Plugin.Libs.Lockr;Plugin.Service.Storage={get:function(key){return lockr.prefix=Plugin.Configs.storagePrefix,lockr.get(key)},set:function(key,data){return lockr.prefix=Plugin.Configs.storagePrefix,lockr.set(key,data)},getRecentStickers:function(){return this.get("recent_stickers")||[]},setRecentStickers:function(recentStickers){return this.set("recent_stickers",recentStickers)},addRecentSticker:function(stickerId){for(var recentStickers=this.getRecentStickers(),i=0;i700){var marginTop=parseInt(Plugin.Service.El.css(dialog,"marginTop"),10),marginBottom=parseInt(Plugin.Service.El.css(dialog,"marginBottom"),10),minHeight=window.innerHeight-marginTop-marginBottom;dialog.style.height=minHeight+"px"}}}}(window.StickersModule,StickersModule.Module.Store),function(Plugin){function lockContainer(){if(!overlay){overlay=document.createElement("div"),overlay.className=classes.overlay,document.body.insertBefore(overlay,document.body.firstChild);var bodyOuterWidth=Plugin.Service.El.outerWidth(document.body);document.body.classList.add(classes.lock),document.getElementsByTagName("html")[0].classList.add(classes.lock);var scrollbarWidth=Plugin.Service.El.outerWidth(document.body)-bodyOuterWidth;if(Plugin.Service.Helper.isIE()&&(ieBodyTopMargin=Plugin.Service.El.css(document.body,"marginTop"),document.body.style.marginTop=0),0!=scrollbarWidth){for(var tags=["html","body"],i=0;i',modalInstance.backButton=backButton;var closeButton=document.createElement("div");if(closeButton.className=classes.close,closeButton.innerHTML='
',closeButton.addEventListener("click",function(){this.close()}.bind(modalInstance)),dialogHeader.appendChild(backButton),dialogHeader.appendChild(closeButton),modalInstance.modalEl=modalEl,
+!contentEl||!contentEl.nodeType){try{contentEl=document.querySelector(contentEl)}catch(e){}contentEl||(contentEl=document.createElement("div"))}return dialogBody.appendChild(contentEl),document.body.appendChild(modalInstance.modalEl),window.addEventListener("keydown",function(e){}),Plugin.Service.Helper.extend(modalInstance,{options:options,contentEl:contentEl,open:function(){if(modalsStack.length&&(modalsStack[modalsStack.length-1].modalEl.style.display="none"),modalsStack.push(this),lockContainer(),Plugin.Service.El.appendAfter(this.modalEl,overlay),this.modalEl.style.display="block",this.options.closeOnEsc&&window.addEventListener("keyup",function(e){e.keyCode===KEY_CODE_ESC&&isOpen&&this.close(this.options)}.bind(this)),this.options.closeOnOverlayClick)for(var i=this.modalEl.children.length;i--;)8!=this.modalEl.children[i].nodeType&&this.modalEl.children[i].addEventListener("click",function(e){e.stopPropagation()});document.addEventListener("touchmove",function(e){}),window.addEventListener("onSelectAll",function(e){}),this.options.onOpen&&this.options.onOpen(this.contentEl,this.modalEl,overlay,this.options),isOpen=!0},close:function(){this.options.onClose&&this.options.onClose(this.contentEl,this.modalEl,overlay,this.options),document.body.removeChild(this.modalEl),modalsStack.pop(),modalsStack.length?modalsStack[modalsStack.length-1].modalEl.style.display="block":unlockContainer(),isOpen=!1},hasGlobalOpened:function(){return isOpen}})},setDefaultOptions:function(options){defaultOptions=Plugin.Service.Helper.extend({},defaultOptions,options)}}}(window.StickersModule),window.StickersModule.View={},function(Plugin){Plugin.View.Block=Plugin.Libs.Class({emojisOffset:0,emojisLimit:100,isRendered:!1,el:null,contentEl:null,tabsView:null,scrollableEl:null,_constructor:function(){this.el=document.getElementById(Plugin.Configs.elId),this.contentEl=document.createElement("div"),this.tabsView=new Plugin.View.Tabs,window.addEventListener("resize",function(){this.onWindowResize()}.bind(this))},render:function(){this.tabsView.render(),this.el.innerHTML="",this.el.className="sticker-pipe",this.el.style.width=Plugin.Configs.width,this.scrollableEl=document.createElement("div"),this.scrollableEl.className="sp-scroll-content",this.scrollableEl.style.height=parseInt(Plugin.Configs.height,10)-49+"px",this.scrollableEl.appendChild(this.contentEl),this.scrollableEl.addEventListener("ps-y-reach-end",function(){"sp-emojis"==this.contentEl.className&&this.renderEmojis(this.emojisOffset)}.bind(this)),this.el.appendChild(this.tabsView.el),this.el.appendChild(this.scrollableEl),Plugin.Libs.PerfectScrollbar.initialize(this.scrollableEl),this.isRendered=!0,this.tabsView.onWindowResize(),this.onWindowResize()},renderRecentStickers:function(){var recentStickers=Plugin.Service.Storage.getRecentStickers();return recentStickers.length?void this.renderStickers(recentStickers):(this.contentEl.className="sp-recent-empty",this.contentEl.innerHTML=Plugin.Configs.htmlForEmptyRecent,this.updateScroll("top"),!1)},renderEmojiBlock:function(){this.contentEl.innerHTML="",this.contentEl.className="sp-emojis",this.emojisOffset=0,this.renderEmojis(this.emojisOffset),this.updateScroll("top")},renderPack:function(pack){this.renderStickers(pack.stickers)},renderStickers:function(stickersIds){function appendSticker(stickerId){var stickersSpanEl=document.createElement("span");stickersSpanEl.className="sp-sticker-placeholder",stickersSpanEl.style.background=Plugin.Configs.primaryColor||"#e1e1e1",stickersSpanEl.setAttribute("data-sticker-id",stickerId);var image=new Image;image.onload=function(){stickersSpanEl.className=Plugin.Configs.stickerItemClass,stickersSpanEl.style.background="",stickersSpanEl.appendChild(image)},image.onerror=function(){},Plugin.Service.Sticker.getById(stickerId,function(sticker){image.src=sticker.image[Plugin.Configs.stickerResolutionType]}),self.contentEl.appendChild(stickersSpanEl)}var self=this;this.contentEl.innerHTML="",this.contentEl.className="sp-stickers";for(var i=0;iPlugin.Configs.emojiList.length-1)){var limit=offset+this.emojisLimit;limit>Plugin.Configs.emojiList.length-1&&(limit=Plugin.Configs.emojiList.length);for(var i=offset;limit>i;i++){var emoji=Plugin.Configs.emojiList[i],emojiEl=document.createElement("span"),emojiImgHtml=Plugin.Service.Emoji.parseEmojiFromText(emoji);emojiEl.className=Plugin.Configs.emojiItemClass,emojiEl.innerHTML=emojiImgHtml,this.contentEl.appendChild(emojiEl)}this.emojisOffset=limit,this.updateScroll()}},handleClickOnSticker:function(callback){Plugin.Service.Helper.setEvent("click",this.contentEl,Plugin.Configs.stickerItemClass,callback)},handleClickOnEmoji:function(callback){Plugin.Service.Helper.setEvent("click",this.contentEl,Plugin.Configs.emojiItemClass,callback)},open:function(tabName){tabName=tabName||null,tabName&&this.tabsView.activeTab(tabName),this.tabsView.hasActiveTab||this.tabsView.activeLastUsedStickersTab()},close:function(){},updateScroll:function(position){position=position||"relative","top"==position&&(this.scrollableEl.scrollTop=0),Plugin.Libs.PerfectScrollbar.update(this.scrollableEl)},onWindowResize:function(){}})}(window.StickersModule),function(Plugin){var parent=Plugin.View.Block;Plugin.View.Popover=parent.extend({popoverEl:null,triangleEl:null,toggleEl:null,active:!1,_constructor:function(){parent.prototype._constructor.apply(this,arguments),this.toggleEl=document.getElementById(Plugin.Configs.elId),this.toggleEl.addEventListener("click",function(){this.toggle()}.bind(this)),this.popoverEl=document.createElement("div"),this.popoverEl.className="sp-popover",this.el=document.createElement("div"),this.triangleEl=document.createElement("div"),this.triangleEl.className="sp-arrow",this.popoverEl.appendChild(this.el),this.popoverEl.appendChild(this.triangleEl),this.handleClickOnSticker(function(){this.toggle()}.bind(this)),document.getElementsByTagName("body")[0].addEventListener("click",function(e){function isDescendant(parent,child){for(var node=child.parentNode;null!=node;){if(node==parent)return!0;node=node.parentNode}return!1}this.active&&(isDescendant(this.popoverEl,e.target)||isDescendant(this.toggleEl.parentElement,e.target)||this.toggle())}.bind(this)),window.addEventListener(Plugin.Service.Event.events.showContentHighlight,function(){this.toggleEl.classList.add("stickerpipe-content-highlight")}.bind(this)),window.addEventListener(Plugin.Service.Event.events.hideContentHighlight,function(){this.toggleEl.classList.remove("stickerpipe-content-highlight")}.bind(this)),window.addEventListener?window.addEventListener(Plugin.Service.Event.events.popoverShown,function(){Plugin.Service.Event.resize()}):window.attachEvent("on"+Plugin.Service.Event.events.popoverShown,function(){Plugin.Service.Event.resize()})},toggle:function(){this.active?this.close():this.open()},open:function(){this.active||(this.active=!0,this.toggleEl.parentElement.appendChild(this.popoverEl),this.positioned(),Plugin.Service.Event.popoverShown()),parent.prototype.open.apply(this,arguments)},close:function(){this.active=!1,this.toggleEl.parentElement.removeChild(this.popoverEl),Plugin.Service.Event.popoverHidden(),this.popoverEl.style.marginTop=0},positioned:function(){var arrowOffset=0;if(this.triangleEl){var style=this.toggleEl.currentStyle||window.getComputedStyle(this.toggleEl),marginLeft=parseInt(style.marginLeft,10);this.popoverEl.style.marginLeft=marginLeft+"px",this.triangleEl.style.marginLeft=this.toggleEl.getBoundingClientRect().left-this.popoverEl.getBoundingClientRect().left+this.toggleEl.clientWidth/2-this.triangleEl.offsetWidth/2+"px";var arrowStyle=this.triangleEl.currentStyle||window.getComputedStyle(this.triangleEl);"none"!=arrowStyle.display&&(arrowOffset=15);var elOffset=this.toggleEl.getBoundingClientRect().top+this.toggleEl.offsetHeight-this.popoverEl.getBoundingClientRect().top;this.popoverEl.style.marginTop=-(this.popoverEl.offsetHeight+this.toggleEl.offsetHeight+arrowOffset-elOffset+5)+"px"}else console&&console.error("error: triangle not found")}})}(window.StickersModule),function(Plugin){Plugin.View.Preloader=function(parentEl){var el=document.createElement("div");return el.className="sp-preloader",el.innerHTML='',parentEl&&parentEl.appendChild(el),{getEl:function(){return el},show:function(){el.style.display=""},hide:function(){el.style.display="none"}}}}(window.StickersModule),function(Plugin){var packTabSize=48,classes={scrollableContainer:"sp-tabs-scrollable-container",scrollableContent:"sp-tabs-scrollable-content",controlTab:"sp-control-tab",controlButton:"sp-control-button",unwatched:"sp-unwatched-content",packTab:"sp-pack-tab",tabActive:"sp-tab-active",tabs:"sp-tabs"};Plugin.View.Tabs=Plugin.Libs.Class({el:null,scrollableContainerEl:null,scrollableContentEl:null,packTabs:{},packTabsIndexes:{},hasActiveTab:!1,controls:{emoji:{id:"spTabEmoji","class":"sp-tab-emoji",icon:"sp-icon-face",el:null,isTab:!0},history:{id:"spTabHistory","class":"sp-tab-history",icon:"sp-icon-clock",el:null,isTab:!0},settings:{id:"spTabSettings","class":"sp-tab-settings",icon:"sp-icon-settings",el:null,isTab:!1},store:{id:"spTabStore","class":"sp-tab-store",icon:"sp-icon-plus",el:null,isTab:!1},prevPacks:{id:"spTabPrevPacks","class":"sp-tab-prev-packs",icon:"sp-icon-arrow-back",el:null,isTab:!1},nextPacks:{id:"spTabNextPacks","class":"sp-tab-next-packs",icon:"sp-icon-arrow-forward",el:null,isTab:!1}},_constructor:function(){this.el=document.createElement("div"),window.addEventListener("resize",function(){this.onWindowResize()}.bind(this))},render:function(){this.el.className=classes.tabs,this.el.innerHTML="",this.renderPrevPacksTab(),this.renderScrollableContainer(),this.renderPacks(),this.renderNextPacksTab(),this.renderStoreTab()},renderScrollableContainer:function(){this.scrollableContentEl=document.createElement("div"),this.scrollableContentEl.className=classes.scrollableContent,this.scrollableContainerEl=document.createElement("div"),this.scrollableContainerEl.className=classes.scrollableContainer,this.scrollableContainerEl.appendChild(this.scrollableContentEl),this.el.appendChild(this.scrollableContainerEl)},renderControlButton:function(controlButton){controlButton.isTab=controlButton.isTab||!1;var buttonClasses=[controlButton["class"]];buttonClasses.push(controlButton.isTab?classes.controlTab:classes.controlButton);var content=' ';return controlButton.el=this.renderTab(controlButton.id,buttonClasses,content),controlButton.el},renderPackTab:function(pack){var tabClasses=[classes.packTab];pack.isUnwatched&&tabClasses.push(classes.unwatched);var content=" ",tabEl=this.renderTab(null,tabClasses,content,{"data-pack-name":pack.pack_name});return tabEl.addEventListener("click",function(){tabEl.classList.remove(classes.unwatched)}.bind(this)),this.packTabs[pack.pack_name]=tabEl,tabEl},renderTab:function(id,tabClasses,content,attrs){tabClasses=tabClasses||[],attrs=attrs||{};var tabEl=document.createElement("span");id&&(tabEl.id=id),tabClasses.push(Plugin.Configs.tabItemClass),tabEl.classList.add.apply(tabEl.classList,tabClasses);for(var name in attrs)tabEl.setAttribute(name,attrs[name]);return tabEl.innerHTML=content,tabEl.addEventListener("click",function(){if(tabEl.classList.contains(classes.controlTab)||tabEl.classList.contains(classes.packTab)){for(var tabName in this.packTabs)this.packTabs[tabName].classList.remove(classes.tabActive);for(var controlName in this.controls){var controlTab=this.controls[controlName];controlTab&&controlTab.el&&controlTab.el.classList.remove(classes.tabActive)}tabEl.classList.add(classes.tabActive)}}.bind(this)),tabEl},renderPacks:function(){this.scrollableContentEl.innerHTML="",this.renderEmojiTab(),this.renderHistoryTab();for(var packs=Plugin.Service.Storage.getPacks(),i=0;iPlugin.Service.Storage.getStoreLastVisit()&&this.controls.store.el.classList.add("sp-unwatched-content"))},renderPrevPacksTab:function(){this.el.appendChild(this.renderControlButton(this.controls.prevPacks)),Plugin.Service.Helper.setEvent("click",this.el,this.controls.prevPacks["class"],this.onClickPrevPacksButton.bind(this))},renderNextPacksTab:function(){this.el.appendChild(this.renderControlButton(this.controls.nextPacks)),Plugin.Service.Helper.setEvent("click",this.el,this.controls.nextPacks["class"],this.onClickNextPacksButton.bind(this))},onClickPrevPacksButton:function(){var containerWidth=this.scrollableContainerEl.offsetWidth,contentOffset=parseInt(this.scrollableContentEl.style.left,10)||0,countFullShownTabs=parseInt(containerWidth/packTabSize,10),offset=contentOffset+packTabSize*countFullShownTabs;offset=offset>0?0:offset,this.scrollableContentEl.style.left=offset+"px",this.onWindowResize()},onClickNextPacksButton:function(){var containerWidth=this.scrollableContainerEl.offsetWidth,contentOffset=parseInt(this.scrollableContentEl.style.left,10)||0,countFullShownTabs=parseInt(containerWidth/packTabSize,10),offset=-(packTabSize*countFullShownTabs)+contentOffset;this.scrollableContentEl.style.left=offset+"px",this.onWindowResize()},activeTab:function(tabName){var i=this.packTabsIndexes[tabName];Plugin.Configs.enableEmojiTab&&i++,Plugin.Configs.enableHistoryTab&&i++,this.packTabs[tabName].click(),this.hasActiveTab=!0;var packTabSize=this.scrollableContentEl.getElementsByClassName(classes.packTab)[0].offsetWidth,containerWidth=this.scrollableContainerEl.offsetWidth,countFullShownTabs=parseInt(containerWidth/packTabSize,10),offset=-(parseInt(i/countFullShownTabs,10)*containerWidth);offset=countFullShownTabs*packTabSize>-offset?0:offset+6,this.scrollableContentEl.style.left=offset+"px",this.onWindowResize()},activeLastUsedStickersTab:function(){this.controls.history.el.click(),this.hasActiveTab=!0},handleClickOnEmojiTab:function(callback){Plugin.Service.Helper.setEvent("click",this.el,this.controls.emoji["class"],callback)},handleClickOnRecentTab:function(callback){Plugin.Service.Helper.setEvent("click",this.el,this.controls.history["class"],callback)},handleClickOnPackTab:function(callback){Plugin.Service.Helper.setEvent("click",this.el,classes.packTab,callback)},handleClickOnStoreTab:function(callback){Plugin.Service.Helper.setEvent("click",this.el,this.controls.store["class"],callback)},onWindowResize:function(){if(this.el.parentElement&&(this.controls.prevPacks.el&&(parseInt(this.scrollableContentEl.style.left,10)<0?this.controls.prevPacks.el.style.display="block":this.controls.prevPacks.el.style.display="none"),this.controls.nextPacks.el)){var contentWidth=this.scrollableContentEl.scrollWidth,contentOffset=parseInt(this.scrollableContentEl.style.left,10)||0;contentWidth+contentOffset>this.scrollableContainerEl.offsetWidth?this.controls.nextPacks.el.style.display="block":this.controls.nextPacks.el.style.display="none"}}})}(window.StickersModule),function(window,Plugin){window.Stickers=Plugin.Libs.Class({view:null,_constructor:function(config){Plugin.Service.Helper.setConfig(config);var mobileOS=Plugin.Service.Helper.getMobileOS();if(("ios"==mobileOS||"android"==mobileOS)&&(config.enableEmojiTab=!1),!Plugin.Configs.apiKey||!Plugin.Configs.userId)throw new Error("Empty one of required data [apiKey, userId]");Plugin.Configs.userId=Plugin.Service.Helper.md5(Plugin.Configs.userId+Plugin.Configs.apiKey),Plugin.Configs.userId!=Plugin.Service.Storage.getUserId()&&(Plugin.Service.Storage.setPacks([]),Plugin.Service.Storage.setRecentStickers([]),Plugin.Service.Storage.setUserData({}),Plugin.Service.Storage.setPendingRequestTasks([]),Plugin.Service.Storage.setStoreLastVisit(0)),Plugin.Service.Storage.setUserId(Plugin.Configs.userId),Plugin.Module.Store.init(this),Plugin.Service.User.init(),Plugin.Service.Pack.init(this),Plugin.Service.Emoji.init(Plugin.Libs.Twemoji),Plugin.Service.PendingRequest.init()},render:function(callback,elId){Plugin.Configs.elId=elId||Plugin.Configs.elId;var self=this;this.view=new Plugin.View.Popover,this.delegateEvents(),Plugin.Service.Packs.fetch(function(){self.view.render(),callback&&callback()}),setInterval(function(){Plugin.Service.Packs.fetch()},36e5)},delegateEvents:function(){var self=this;this.view.tabsView.handleClickOnEmojiTab(function(){self.view.renderEmojiBlock()}),this.view.tabsView.handleClickOnRecentTab(function(){self.view.renderRecentStickers()}),this.view.tabsView.handleClickOnStoreTab(function(){Plugin.Module.Store.open(),Plugin.Service.Storage.setStoreLastVisit(+new Date),Plugin.Service.Highlight.check(),self.view.tabsView.controls.store.el.classList.remove("sp-unwatched-content")}),this.view.tabsView.handleClickOnPackTab(function(el){var packName=el.getAttribute("data-pack-name"),pack=Plugin.Service.Storage.getPack(packName);pack&&(pack.isUnwatched=!1,Plugin.Service.Storage.setPack(packName,pack),self.view.renderPack(pack)),Plugin.Service.Highlight.check()}),this.view.handleClickOnSticker(function(el){var stickerId=el.getAttribute("data-sticker-id");Plugin.Service.Statistic.useSticker(stickerId),Plugin.Service.Storage.addRecentSticker(stickerId),Plugin.Service.Highlight.check()}),this.view.handleClickOnEmoji(function(el){var emoji=Plugin.Service.Emoji.parseEmojiFromHtml(el.innerHTML);Plugin.Service.Statistic.useEmoji(emoji)})},fetchPacks:function(callback){Plugin.Service.Packs.fetch(callback)},isSticker:function(text){return Plugin.Service.Sticker.isSticker(text)},parseStickerFromText:function(text,callback){return Plugin.Service.Sticker.parse(text,callback)},parseEmojiFromText:function(text){return Plugin.Service.Emoji.parseEmojiFromText(text)},parseEmojiFromHtml:function(html){return Plugin.Service.Emoji.parseEmojiFromHtml(html)},onUserMessageSent:function(isSticker){Plugin.Service.Statistic.messageSend(isSticker)},purchaseSuccess:function(packName,pricePoint){Plugin.Module.Store.purchaseSuccess(packName,pricePoint)},purchaseFail:function(){Plugin.Module.Store.purchaseFail()},open:function(tabName){this.view.open(tabName)},close:function(){this.view.close()},openStore:function(contentId){Plugin.Module.Store.open(contentId)},closeStore:function(){Plugin.Module.Store.close()},getPackMainIcon:function(packName,callback){Plugin.Service.Pack.getMainIcon(packName,callback)},onClickSticker:function(callback,context){this.view.handleClickOnSticker(function(el){callback.call(context,"[["+el.getAttribute("data-sticker-id")+"]]")})},onClickEmoji:function(callback,context){this.view.handleClickOnEmoji(function(el){var emoji=this.parseEmojiFromHtml(el.innerHTML);callback.call(context,emoji)}.bind(this))},onPurchase:function(callback){Plugin.Module.Store.setOnPurchaseCallback(callback)}})}(window,window.StickersModule);
\ No newline at end of file