frontend/kniferain/gameapi.js
2023-09-26 21:07:54 -04:00

10342 lines
364 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
// gameapi.js
window.famobi_gameID = window.famobi_gameID || '';
window.famobi_gameJS = window.famobi_gameJS || [];
var detection = (function() {
var mod = {is:{}},
d,
ua = navigator.userAgent;
mod.detect = {
html5: function() {
return document.createElement('canvas').getContext !== undefined;
},
touch: function() {
var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
return !!supportsTouch;
},
android: function() {
return !!ua.match(/Android/i);
},
ios: function() {
return !!ua.match(/iPhone|iPad|iPod/i);
},
ios7: function(){
return mod.detect.ios && ua.match(/version\/7\./i);
},
bb10: function() {
return !!ua.match(/BB10/i);
},
windows: function() {
return !!ua.match(/Windows/i);
},
webkitVersion: function() {
var regex = new RegExp(/AppleWebKit\/([\d.]+)/),
result = regex.exec(ua),
webkitVersion = result === null ? false : parseFloat(result[1]);
return webkitVersion;
},
androidStockBrowser: function() {
if (mod.is.android && mod.is.webkitVersion && mod.is.webkitVersion < 537) {
return true;
}
return false;
},
standalone: function() {
return !!window.navigator.standalone;
},
smartphone: function() {
return (ua.match(/Android.*Mobile|iPhone|IEMobile|WPDesktop|BB10/i)) ? true : false;
},
tablet: function() {
// Android smartphones have the combination Android...Mobile, tablets only Android
var androidTablet = (mod.is.android && !mod.is.smartphone),
iPad = ua.match(/iPad/i) ? true : false;
return (androidTablet || iPad);
},
pc: function() {
return (!mod.is.smartphone && !mod.is.tablet);
},
phantom: function() {
return !!(window.callPhantom || ua.match(/PhantomJS/));
},
iframe: function() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
};
for (d in mod.detect) {
if (typeof mod.detect[d] === 'function') {
mod.is[d] = mod.detect[d]();
}
}
return mod;
})();
/*!
* @overview es6-promise - a tiny implementation of Promises/A+.
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
* @license Licensed under MIT license
* See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
* @version 3.2.1
*/
(function(){"use strict";function t(t){return"function"==typeof t||"object"==typeof t&&null!==t}function e(t){return"function"==typeof t}function n(t){G=t}function r(t){Q=t}function o(){return function(){process.nextTick(a)}}function i(){return function(){B(a)}}function s(){var t=0,e=new X(a),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function u(){var t=new MessageChannel;return t.port1.onmessage=a,function(){t.port2.postMessage(0)}}function c(){return function(){setTimeout(a,1)}}function a(){for(var t=0;J>t;t+=2){var e=tt[t],n=tt[t+1];e(n),tt[t]=void 0,tt[t+1]=void 0}J=0}function f(){try{var t=require,e=t("vertx");return B=e.runOnLoop||e.runOnContext,i()}catch(n){return c()}}function l(t,e){var n=this,r=new this.constructor(p);void 0===r[rt]&&k(r);var o=n._state;if(o){var i=arguments[o-1];Q(function(){x(o,r,i,n._result)})}else E(n,r,t,e);return r}function h(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(p);return g(n,t),n}function p(){}function _(){return new TypeError("You cannot resolve a promise with itself")}function d(){return new TypeError("A promises callback cannot return that same promise.")}function v(t){try{return t.then}catch(e){return ut.error=e,ut}}function y(t,e,n,r){try{t.call(e,n,r)}catch(o){return o}}function m(t,e,n){Q(function(t){var r=!1,o=y(n,e,function(n){r||(r=!0,e!==n?g(t,n):S(t,n))},function(e){r||(r=!0,j(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&o&&(r=!0,j(t,o))},t)}function b(t,e){e._state===it?S(t,e._result):e._state===st?j(t,e._result):E(e,void 0,function(e){g(t,e)},function(e){j(t,e)})}function w(t,n,r){n.constructor===t.constructor&&r===et&&constructor.resolve===nt?b(t,n):r===ut?j(t,ut.error):void 0===r?S(t,n):e(r)?m(t,n,r):S(t,n)}function g(e,n){e===n?j(e,_()):t(n)?w(e,n,v(n)):S(e,n)}function A(t){t._onerror&&t._onerror(t._result),T(t)}function S(t,e){t._state===ot&&(t._result=e,t._state=it,0!==t._subscribers.length&&Q(T,t))}function j(t,e){t._state===ot&&(t._state=st,t._result=e,Q(A,t))}function E(t,e,n,r){var o=t._subscribers,i=o.length;t._onerror=null,o[i]=e,o[i+it]=n,o[i+st]=r,0===i&&t._state&&Q(T,t)}function T(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r,o,i=t._result,s=0;s<e.length;s+=3)r=e[s],o=e[s+n],r?x(n,r,o,i):o(i);t._subscribers.length=0}}function M(){this.error=null}function P(t,e){try{return t(e)}catch(n){return ct.error=n,ct}}function x(t,n,r,o){var i,s,u,c,a=e(r);if(a){if(i=P(r,o),i===ct?(c=!0,s=i.error,i=null):u=!0,n===i)return void j(n,d())}else i=o,u=!0;n._state!==ot||(a&&u?g(n,i):c?j(n,s):t===it?S(n,i):t===st&&j(n,i))}function C(t,e){try{e(function(e){g(t,e)},function(e){j(t,e)})}catch(n){j(t,n)}}function O(){return at++}function k(t){t[rt]=at++,t._state=void 0,t._result=void 0,t._subscribers=[]}function Y(t){return new _t(this,t).promise}function q(t){var e=this;return new e(I(t)?function(n,r){for(var o=t.length,i=0;o>i;i++)e.resolve(t[i]).then(n,r)}:function(t,e){e(new TypeError("You must pass an array to race."))})}function F(t){var e=this,n=new e(p);return j(n,t),n}function D(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function K(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function L(t){this[rt]=O(),this._result=this._state=void 0,this._subscribers=[],p!==t&&("function"!=typeof t&&D(),this instanceof L?C(this,t):K())}function N(t,e){this._instanceConstructor=t,this.promise=new t(p),this.promise[rt]||k(this.promise),I(e)?(this._input=e,this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?S(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&S(this.promise,this._result))):j(this.promise,U())}function U(){return new Error("Array Methods must be provided an Array")}function W(){var t;if("undefined"!=typeof global)t=global;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;(!n||"[object Promise]"!==Object.prototype.toString.call(n.resolve())||n.cast)&&(t.Promise=pt)}var z;z=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var B,G,H,I=z,J=0,Q=function(t,e){tt[J]=t,tt[J+1]=e,J+=2,2===J&&(G?G(a):H())},R="undefined"!=typeof window?window:void 0,V=R||{},X=V.MutationObserver||V.WebKitMutationObserver,Z="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),$="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,tt=new Array(1e3);H=Z?o():X?s():$?u():void 0===R&&"function"==typeof require?f():c();var et=l,nt=h,rt=Math.random().toString(36).substring(16),ot=void 0,it=1,st=2,ut=new M,ct=new M,at=0,ft=Y,lt=q,ht=F,pt=L;L.all=ft,L.race=lt,L.resolve=nt,L.reject=ht,L._setScheduler=n,L._setAsap=r,L._asap=Q,L.prototype={constructor:L,then:et,"catch":function(t){return this.then(null,t)}};var _t=N;N.prototype._enumerate=function(){for(var t=this.length,e=this._input,n=0;this._state===ot&&t>n;n++)this._eachEntry(e[n],n)},N.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,r=n.resolve;if(r===nt){var o=v(t);if(o===et&&t._state!==ot)this._settledAt(t._state,e,t._result);else if("function"!=typeof o)this._remaining--,this._result[e]=t;else if(n===pt){var i=new n(p);w(i,t,o),this._willSettleAt(i,e)}else this._willSettleAt(new n(function(e){e(t)}),e)}else this._willSettleAt(r(t),e)},N.prototype._settledAt=function(t,e,n){var r=this.promise;r._state===ot&&(this._remaining--,t===st?j(r,n):this._result[e]=n),0===this._remaining&&S(r,this._result)},N.prototype._willSettleAt=function(t,e){var n=this;E(t,void 0,function(t){n._settledAt(it,e,t)},function(t){n._settledAt(st,e,t)})};var dt=W,vt={Promise:pt,polyfill:dt};"function"==typeof define&&define.amd?define(function(){return vt}):"undefined"!=typeof module&&module.exports?module.exports=vt:"undefined"!=typeof this&&(this.ES6Promise=vt),dt()}).call(this);
/* Zepto v1.2.0 - zepto event ajax form ie - zeptojs.com/license */
!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t)}):e(t)}(this,function(t){var e=function(){function $(t){return null==t?String(t):S[C.call(t)]||"object"}function F(t){return"function"==$(t)}function k(t){return null!=t&&t==t.window}function M(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function R(t){return"object"==$(t)}function Z(t){return R(t)&&!k(t)&&Object.getPrototypeOf(t)==Object.prototype}function z(t){var e=!!t&&"length"in t&&t.length,n=r.type(t);return"function"!=n&&!k(t)&&("array"==n||0===e||"number"==typeof e&&e>0&&e-1 in t)}function q(t){return a.call(t,function(t){return null!=t})}function H(t){return t.length>0?r.fn.concat.apply([],t):t}function I(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function V(t){return t in l?l[t]:l[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function _(t,e){return"number"!=typeof e||h[I(t)]?e:e+"px"}function B(t){var e,n;return c[t]||(e=f.createElement(t),f.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),c[t]=n),c[t]}function U(t){return"children"in t?u.call(t.children):r.map(t.childNodes,function(t){return 1==t.nodeType?t:void 0})}function X(t,e){var n,r=t?t.length:0;for(n=0;r>n;n++)this[n]=t[n];this.length=r,this.selector=e||""}function J(t,r,i){for(n in r)i&&(Z(r[n])||L(r[n]))?(Z(r[n])&&!Z(t[n])&&(t[n]={}),L(r[n])&&!L(t[n])&&(t[n]=[]),J(t[n],r[n],i)):r[n]!==e&&(t[n]=r[n])}function W(t,e){return null==e?r(t):r(t).filter(e)}function Y(t,e,n,r){return F(e)?e.call(t,n,r):e}function G(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function K(t,n){var r=t.className||"",i=r&&r.baseVal!==e;return n===e?i?r.baseVal:r:void(i?r.baseVal=n:t.className=n)}function Q(t){try{return t?"true"==t||("false"==t?!1:"null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?r.parseJSON(t):t):t}catch(e){return t}}function tt(t,e){e(t);for(var n=0,r=t.childNodes.length;r>n;n++)tt(t.childNodes[n],e)}var e,n,r,i,O,P,o=[],s=o.concat,a=o.filter,u=o.slice,f=t.document,c={},l={},h={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},p=/^\s*<(\w+|!)[^>]*>/,d=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,m=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,g=/^(?:body|html)$/i,v=/([A-Z])/g,y=["val","css","html","text","data","width","height","offset"],x=["after","prepend","before","append"],b=f.createElement("table"),E=f.createElement("tr"),j={tr:f.createElement("tbody"),tbody:b,thead:b,tfoot:b,td:E,th:E,"*":f.createElement("div")},w=/complete|loaded|interactive/,T=/^[\w-]*$/,S={},C=S.toString,N={},A=f.createElement("div"),D={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},L=Array.isArray||function(t){return t instanceof Array};return N.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=A).appendChild(t),r=~N.qsa(i,e).indexOf(t),o&&A.removeChild(t),r},O=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},P=function(t){return a.call(t,function(e,n){return t.indexOf(e)==n})},N.fragment=function(t,n,i){var o,s,a;return d.test(t)&&(o=r(f.createElement(RegExp.$1))),o||(t.replace&&(t=t.replace(m,"<$1></$2>")),n===e&&(n=p.test(t)&&RegExp.$1),n in j||(n="*"),a=j[n],a.innerHTML=""+t,o=r.each(u.call(a.childNodes),function(){a.removeChild(this)})),Z(i)&&(s=r(o),r.each(i,function(t,e){y.indexOf(t)>-1?s[t](e):s.attr(t,e)})),o},N.Z=function(t,e){return new X(t,e)},N.isZ=function(t){return t instanceof N.Z},N.init=function(t,n){var i;if(!t)return N.Z();if("string"==typeof t)if(t=t.trim(),"<"==t[0]&&p.test(t))i=N.fragment(t,RegExp.$1,n),t=null;else{if(n!==e)return r(n).find(t);i=N.qsa(f,t)}else{if(F(t))return r(f).ready(t);if(N.isZ(t))return t;if(L(t))i=q(t);else if(R(t))i=[t],t=null;else if(p.test(t))i=N.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==e)return r(n).find(t);i=N.qsa(f,t)}}return N.Z(i,t)},r=function(t,e){return N.init(t,e)},r.extend=function(t){var e,n=u.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){J(t,n,e)}),t},N.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,s=T.test(o);return t.getElementById&&s&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:u.call(s&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},r.contains=f.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},r.type=$,r.isFunction=F,r.isWindow=k,r.isArray=L,r.isPlainObject=Z,r.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},r.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},r.inArray=function(t,e,n){return o.indexOf.call(e,t,n)},r.camelCase=O,r.trim=function(t){return null==t?"":String.prototype.trim.call(t)},r.uuid=0,r.support={},r.expr={},r.noop=function(){},r.map=function(t,e){var n,i,o,r=[];if(z(t))for(i=0;i<t.length;i++)n=e(t[i],i),null!=n&&r.push(n);else for(o in t)n=e(t[o],o),null!=n&&r.push(n);return H(r)},r.each=function(t,e){var n,r;if(z(t)){for(n=0;n<t.length;n++)if(e.call(t[n],n,t[n])===!1)return t}else for(r in t)if(e.call(t[r],r,t[r])===!1)return t;return t},r.grep=function(t,e){return a.call(t,e)},t.JSON&&(r.parseJSON=JSON.parse),r.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(t,e){S["[object "+e+"]"]=e.toLowerCase()}),r.fn={constructor:N.Z,length:0,forEach:o.forEach,reduce:o.reduce,push:o.push,sort:o.sort,splice:o.splice,indexOf:o.indexOf,concat:function(){var t,e,n=[];for(t=0;t<arguments.length;t++)e=arguments[t],n[t]=N.isZ(e)?e.toArray():e;return s.apply(N.isZ(this)?this.toArray():this,n)},map:function(t){return r(r.map(this,function(e,n){return t.call(e,n,e)}))},slice:function(){return r(u.apply(this,arguments))},ready:function(t){return w.test(f.readyState)&&f.body?t(r):f.addEventListener("DOMContentLoaded",function(){t(r)},!1),this},get:function(t){return t===e?u.call(this):this[t>=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return o.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return F(t)?this.not(this.not(t)):r(a.call(this,function(e){return N.matches(e,t)}))},add:function(t,e){return r(P(this.concat(r(t,e))))},is:function(t){return this.length>0&&N.matches(this[0],t)},not:function(t){var n=[];if(F(t)&&t.call!==e)this.each(function(e){t.call(this,e)||n.push(this)});else{var i="string"==typeof t?this.filter(t):z(t)&&F(t.item)?u.call(t):r(t);this.forEach(function(t){i.indexOf(t)<0&&n.push(t)})}return r(n)},has:function(t){return this.filter(function(){return R(t)?r.contains(this,t):r(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!R(t)?t:r(t)},last:function(){var t=this[this.length-1];return t&&!R(t)?t:r(t)},find:function(t){var e,n=this;return e=t?"object"==typeof t?r(t).filter(function(){var t=this;return o.some.call(n,function(e){return r.contains(e,t)})}):1==this.length?r(N.qsa(this[0],t)):this.map(function(){return N.qsa(this,t)}):r()},closest:function(t,e){var n=[],i="object"==typeof t&&r(t);return this.each(function(r,o){for(;o&&!(i?i.indexOf(o)>=0:N.matches(o,t));)o=o!==e&&!M(o)&&o.parentNode;o&&n.indexOf(o)<0&&n.push(o)}),r(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=r.map(n,function(t){return(t=t.parentNode)&&!M(t)&&e.indexOf(t)<0?(e.push(t),t):void 0});return W(e,t)},parent:function(t){return W(P(this.pluck("parentNode")),t)},children:function(t){return W(this.map(function(){return U(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||u.call(this.childNodes)})},siblings:function(t){return W(this.map(function(t,e){return a.call(U(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return r.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=B(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=F(t);if(this[0]&&!e)var n=r(t).get(0),i=n.parentNode||this.length>1;return this.each(function(o){r(this).wrapAll(e?t.call(this,o):i?n.cloneNode(!0):n)})},wrapAll:function(t){if(this[0]){r(this[0]).before(t=r(t));for(var e;(e=t.children()).length;)t=e.first();r(t).append(this)}return this},wrapInner:function(t){var e=F(t);return this.each(function(n){var i=r(this),o=i.contents(),s=e?t.call(this,n):t;o.length?o.wrapAll(s):i.append(s)})},unwrap:function(){return this.parent().each(function(){r(this).replaceWith(r(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var n=r(this);(t===e?"none"==n.css("display"):t)?n.show():n.hide()})},prev:function(t){return r(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return r(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;r(this).empty().append(Y(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=Y(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,r){var i;return"string"!=typeof t||1 in arguments?this.each(function(e){if(1===this.nodeType)if(R(t))for(n in t)G(this,n,t[n]);else G(this,t,Y(this,r,e,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(i=this[0].getAttribute(t))?i:e},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){G(this,t)},this)})},prop:function(t,e){return t=D[t]||t,1 in arguments?this.each(function(n){this[t]=Y(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=D[t]||t,this.each(function(){delete this[t]})},data:function(t,n){var r="data-"+t.replace(v,"-$1").toLowerCase(),i=1 in arguments?this.attr(r,n):this.attr(r);return null!==i?Q(i):e},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each(function(e){this.value=Y(this,t,e,this.value)})):this[0]&&(this[0].multiple?r(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(e){if(e)return this.each(function(t){var n=r(this),i=Y(this,e,t,n.offset()),o=n.offsetParent().offset(),s={top:i.top-o.top,left:i.left-o.left};"static"==n.css("position")&&(s.position="relative"),n.css(s)});if(!this.length)return null;if(f.documentElement!==this[0]&&!r.contains(f.documentElement,this[0]))return{top:0,left:0};var n=this[0].getBoundingClientRect();return{left:n.left+t.pageXOffset,top:n.top+t.pageYOffset,width:Math.round(n.width),height:Math.round(n.height)}},css:function(t,e){if(arguments.length<2){var i=this[0];if("string"==typeof t){if(!i)return;return i.style[O(t)]||getComputedStyle(i,"").getPropertyValue(t)}if(L(t)){if(!i)return;var o={},s=getComputedStyle(i,"");return r.each(t,function(t,e){o[e]=i.style[O(e)]||s.getPropertyValue(e)}),o}}var a="";if("string"==$(t))e||0===e?a=I(t)+":"+_(t,e):this.each(function(){this.style.removeProperty(I(t))});else for(n in t)t[n]||0===t[n]?a+=I(n)+":"+_(n,t[n])+";":this.each(function(){this.style.removeProperty(I(n))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(r(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return t?o.some.call(this,function(t){return this.test(K(t))},V(t)):!1},addClass:function(t){return t?this.each(function(e){if("className"in this){i=[];var n=K(this),o=Y(this,t,e,n);o.split(/\s+/g).forEach(function(t){r(this).hasClass(t)||i.push(t)},this),i.length&&K(this,n+(n?" ":"")+i.join(" "))}}):this},removeClass:function(t){return this.each(function(n){if("className"in this){if(t===e)return K(this,"");i=K(this),Y(this,t,n,i).split(/\s+/g).forEach(function(t){i=i.replace(V(t)," ")}),K(this,i.trim())}})},toggleClass:function(t,n){return t?this.each(function(i){var o=r(this),s=Y(this,t,i,K(this));s.split(/\s+/g).forEach(function(t){(n===e?!o.hasClass(t):n)?o.addClass(t):o.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var n="scrollTop"in this[0];return t===e?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var n="scrollLeft"in this[0];return t===e?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),i=g.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(r(t).css("margin-top"))||0,n.left-=parseFloat(r(t).css("margin-left"))||0,i.top+=parseFloat(r(e[0]).css("border-top-width"))||0,i.left+=parseFloat(r(e[0]).css("border-left-width"))||0,{top:n.top-i.top,left:n.left-i.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||f.body;t&&!g.test(t.nodeName)&&"static"==r(t).css("position");)t=t.offsetParent;return t})}},r.fn.detach=r.fn.remove,["width","height"].forEach(function(t){var n=t.replace(/./,function(t){return t[0].toUpperCase()});r.fn[t]=function(i){var o,s=this[0];return i===e?k(s)?s["inner"+n]:M(s)?s.documentElement["scroll"+n]:(o=this.offset())&&o[t]:this.each(function(e){s=r(this),s.css(t,Y(this,i,e,s[t]()))})}}),x.forEach(function(n,i){var o=i%2;r.fn[n]=function(){var n,a,s=r.map(arguments,function(t){var i=[];return n=$(t),"array"==n?(t.forEach(function(t){return t.nodeType!==e?i.push(t):r.zepto.isZ(t)?i=i.concat(t.get()):void(i=i.concat(N.fragment(t)))}),i):"object"==n||null==t?t:N.fragment(t)}),u=this.length>1;return s.length<1?this:this.each(function(e,n){a=o?n:n.parentNode,n=0==i?n.nextSibling:1==i?n.firstChild:2==i?n:null;var c=r.contains(f.documentElement,a);s.forEach(function(e){if(u)e=e.cloneNode(!0);else if(!a)return r(e).remove();a.insertBefore(e,n),c&&tt(e,function(e){if(!(null==e.nodeName||"SCRIPT"!==e.nodeName.toUpperCase()||e.type&&"text/javascript"!==e.type||e.src)){var n=e.ownerDocument?e.ownerDocument.defaultView:t;n.eval.call(n,e.innerHTML)}})})})},r.fn[o?n+"To":"insert"+(i?"Before":"After")]=function(t){return r(t)[n](this),this}}),N.Z.prototype=X.prototype=r.fn,N.uniq=P,N.deserializeValue=Q,r.zepto=N,r}();return t.Zepto=e,void 0===t.$&&(t.$=e),function(e){function h(t){return t._zid||(t._zid=n++)}function p(t,e,n,r){if(e=d(e),e.ns)var i=m(e.ns);return(a[h(t)]||[]).filter(function(t){return t&&(!e.e||t.e==e.e)&&(!e.ns||i.test(t.ns))&&(!n||h(t.fn)===h(n))&&(!r||t.sel==r)})}function d(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function m(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function g(t,e){return t.del&&!f&&t.e in c||!!e}function v(t){return l[t]||f&&c[t]||t}function y(t,n,i,o,s,u,f){var c=h(t),p=a[c]||(a[c]=[]);n.split(/\s/).forEach(function(n){if("ready"==n)return e(document).ready(i);var a=d(n);a.fn=i,a.sel=s,a.e in l&&(i=function(t){var n=t.relatedTarget;return!n||n!==this&&!e.contains(this,n)?a.fn.apply(this,arguments):void 0}),a.del=u;var c=u||i;a.proxy=function(e){if(e=T(e),!e.isImmediatePropagationStopped()){e.data=o;var n=c.apply(t,e._args==r?[e]:[e].concat(e._args));return n===!1&&(e.preventDefault(),e.stopPropagation()),n}},a.i=p.length,p.push(a),"addEventListener"in t&&t.addEventListener(v(a.e),a.proxy,g(a,f))})}function x(t,e,n,r,i){var o=h(t);(e||"").split(/\s/).forEach(function(e){p(t,e,n,r).forEach(function(e){delete a[o][e.i],"removeEventListener"in t&&t.removeEventListener(v(e.e),e.proxy,g(e,i))})})}function T(t,n){return(n||!t.isDefaultPrevented)&&(n||(n=t),e.each(w,function(e,r){var i=n[e];t[e]=function(){return this[r]=b,i&&i.apply(n,arguments)},t[r]=E}),t.timeStamp||(t.timeStamp=Date.now()),(n.defaultPrevented!==r?n.defaultPrevented:"returnValue"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(t.isDefaultPrevented=b)),t}function S(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===r||(n[e]=t[e]);return T(n,t)}var r,n=1,i=Array.prototype.slice,o=e.isFunction,s=function(t){return"string"==typeof t},a={},u={},f="onfocusin"in t,c={focus:"focusin",blur:"focusout"},l={mouseenter:"mouseover",mouseleave:"mouseout"};u.click=u.mousedown=u.mouseup=u.mousemove="MouseEvents",e.event={add:y,remove:x},e.proxy=function(t,n){var r=2 in arguments&&i.call(arguments,2);if(o(t)){var a=function(){return t.apply(n,r?r.concat(i.call(arguments)):arguments)};return a._zid=h(t),a}if(s(n))return r?(r.unshift(t[n],t),e.proxy.apply(null,r)):e.proxy(t[n],t);throw new TypeError("expected function")},e.fn.bind=function(t,e,n){return this.on(t,e,n)},e.fn.unbind=function(t,e){return this.off(t,e)},e.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var b=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,w={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};e.fn.delegate=function(t,e,n){return this.on(e,t,n)},e.fn.undelegate=function(t,e,n){return this.off(e,t,n)},e.fn.live=function(t,n){return e(document.body).delegate(this.selector,t,n),this},e.fn.die=function(t,n){return e(document.body).undelegate(this.selector,t,n),this},e.fn.on=function(t,n,a,u,f){var c,l,h=this;return t&&!s(t)?(e.each(t,function(t,e){h.on(t,n,a,e,f)}),h):(s(n)||o(u)||u===!1||(u=a,a=n,n=r),(u===r||a===!1)&&(u=a,a=r),u===!1&&(u=E),h.each(function(r,o){f&&(c=function(t){return x(o,t.type,u),u.apply(this,arguments)}),n&&(l=function(t){var r,s=e(t.target).closest(n,o).get(0);return s&&s!==o?(r=e.extend(S(t),{currentTarget:s,liveFired:o}),(c||u).apply(s,[r].concat(i.call(arguments,1)))):void 0}),y(o,t,u,a,n,l||c)}))},e.fn.off=function(t,n,i){var a=this;return t&&!s(t)?(e.each(t,function(t,e){a.off(t,n,e)}),a):(s(n)||o(i)||i===!1||(i=n,n=r),i===!1&&(i=E),a.each(function(){x(this,t,i,n)}))},e.fn.trigger=function(t,n){return t=s(t)||e.isPlainObject(t)?e.Event(t):T(t),t._args=n,this.each(function(){t.type in c&&"function"==typeof this[t.type]?this[t.type]():"dispatchEvent"in this?this.dispatchEvent(t):e(this).triggerHandler(t,n)})},e.fn.triggerHandler=function(t,n){var r,i;return this.each(function(o,a){r=S(s(t)?e.Event(t):t),r._args=n,r.target=a,e.each(p(a,t.type||t),function(t,e){return i=e.proxy(r),r.isImmediatePropagationStopped()?!1:void 0})}),i},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(t){e.fn[t]=function(e){return 0 in arguments?this.bind(t,e):this.trigger(t)}}),e.Event=function(t,e){s(t)||(e=t,t=e.type);var n=document.createEvent(u[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),T(n)}}(e),function(e){function p(t,n,r){var i=e.Event(n);return e(t).trigger(i,r),!i.isDefaultPrevented()}function d(t,e,n,i){return t.global?p(e||r,n,i):void 0}function m(t){t.global&&0===e.active++&&d(t,null,"ajaxStart")}function g(t){t.global&&!--e.active&&d(t,null,"ajaxStop")}function v(t,e){var n=e.context;return e.beforeSend.call(n,t,e)===!1||d(e,n,"ajaxBeforeSend",[t,e])===!1?!1:void d(e,n,"ajaxSend",[t,e])}function y(t,e,n,r){var i=n.context,o="success";n.success.call(i,t,o,e),r&&r.resolveWith(i,[t,o,e]),d(n,i,"ajaxSuccess",[e,n,t]),b(o,e,n)}function x(t,e,n,r,i){var o=r.context;r.error.call(o,n,e,t),i&&i.rejectWith(o,[n,e,t]),d(r,o,"ajaxError",[n,r,t||e]),b(e,n,r)}function b(t,e,n){var r=n.context;n.complete.call(r,e,t),d(n,r,"ajaxComplete",[e,n]),g(n)}function E(t,e,n){if(n.dataFilter==j)return t;var r=n.context;return n.dataFilter.call(r,t,e)}function j(){}function w(t){return t&&(t=t.split(";",2)[0]),t&&(t==c?"html":t==f?"json":a.test(t)?"script":u.test(t)&&"xml")||"text"}function T(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function S(t){t.processData&&t.data&&"string"!=e.type(t.data)&&(t.data=e.param(t.data,t.traditional)),!t.data||t.type&&"GET"!=t.type.toUpperCase()&&"jsonp"!=t.dataType||(t.url=T(t.url,t.data),t.data=void 0)}function C(t,n,r,i){return e.isFunction(n)&&(i=r,r=n,n=void 0),e.isFunction(r)||(i=r,r=void 0),{url:t,data:n,success:r,dataType:i}}function O(t,n,r,i){var o,s=e.isArray(n),a=e.isPlainObject(n);e.each(n,function(n,u){o=e.type(u),i&&(n=r?i:i+"["+(a||"object"==o||"array"==o?n:"")+"]"),!i&&s?t.add(u.name,u.value):"array"==o||!r&&"object"==o?O(t,u,r,n):t.add(n,u)})}var i,o,n=+new Date,r=t.document,s=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,a=/^(?:text|application)\/javascript/i,u=/^(?:text|application)\/xml/i,f="application/json",c="text/html",l=/^\s*$/,h=r.createElement("a");h.href=t.location.href,e.active=0,e.ajaxJSONP=function(i,o){if(!("type"in i))return e.ajax(i);var c,p,s=i.jsonpCallback,a=(e.isFunction(s)?s():s)||"Zepto"+n++,u=r.createElement("script"),f=t[a],l=function(t){e(u).triggerHandler("error",t||"abort")},h={abort:l};return o&&o.promise(h),e(u).on("load error",function(n,r){clearTimeout(p),e(u).off().remove(),"error"!=n.type&&c?y(c[0],h,i,o):x(null,r||"error",h,i,o),t[a]=f,c&&e.isFunction(f)&&f(c[0]),f=c=void 0}),v(h,i)===!1?(l("abort"),h):(t[a]=function(){c=arguments},u.src=i.url.replace(/\?(.+)=\?/,"?$1="+a),r.head.appendChild(u),i.timeout>0&&(p=setTimeout(function(){l("timeout")},i.timeout)),h)},e.ajaxSettings={type:"GET",beforeSend:j,success:j,error:j,complete:j,context:null,global:!0,xhr:function(){return new t.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:f,xml:"application/xml, text/xml",html:c,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:j},e.ajax=function(n){var u,f,s=e.extend({},n||{}),a=e.Deferred&&e.Deferred();for(i in e.ajaxSettings)void 0===s[i]&&(s[i]=e.ajaxSettings[i]);m(s),s.crossDomain||(u=r.createElement("a"),u.href=s.url,u.href=u.href,s.crossDomain=h.protocol+"//"+h.host!=u.protocol+"//"+u.host),s.url||(s.url=t.location.toString()),(f=s.url.indexOf("#"))>-1&&(s.url=s.url.slice(0,f)),S(s);var c=s.dataType,p=/\?.+=\?/.test(s.url);if(p&&(c="jsonp"),s.cache!==!1&&(n&&n.cache===!0||"script"!=c&&"jsonp"!=c)||(s.url=T(s.url,"_="+Date.now())),"jsonp"==c)return p||(s.url=T(s.url,s.jsonp?s.jsonp+"=?":s.jsonp===!1?"":"callback=?")),e.ajaxJSONP(s,a);var P,d=s.accepts[c],g={},b=function(t,e){g[t.toLowerCase()]=[t,e]},C=/^([\w-]+:)\/\//.test(s.url)?RegExp.$1:t.location.protocol,N=s.xhr(),O=N.setRequestHeader;if(a&&a.promise(N),s.crossDomain||b("X-Requested-With","XMLHttpRequest"),b("Accept",d||"*/*"),(d=s.mimeType||d)&&(d.indexOf(",")>-1&&(d=d.split(",",2)[0]),N.overrideMimeType&&N.overrideMimeType(d)),(s.contentType||s.contentType!==!1&&s.data&&"GET"!=s.type.toUpperCase())&&b("Content-Type",s.contentType||"application/x-www-form-urlencoded"),s.headers)for(o in s.headers)b(o,s.headers[o]);if(N.setRequestHeader=b,N.onreadystatechange=function(){if(4==N.readyState){N.onreadystatechange=j,clearTimeout(P);var t,n=!1;if(N.status>=200&&N.status<300||304==N.status||0==N.status&&"file:"==C){if(c=c||w(s.mimeType||N.getResponseHeader("content-type")),"arraybuffer"==N.responseType||"blob"==N.responseType)t=N.response;else{t=N.responseText;try{t=E(t,c,s),"script"==c?(1,eval)(t):"xml"==c?t=N.responseXML:"json"==c&&(t=l.test(t)?null:e.parseJSON(t))}catch(r){n=r}if(n)return x(n,"parsererror",N,s,a)}y(t,N,s,a)}else x(N.statusText||null,N.status?"error":"abort",N,s,a)}},v(N,s)===!1)return N.abort(),x(null,"abort",N,s,a),N;var A="async"in s?s.async:!0;if(N.open(s.type,s.url,A,s.username,s.password),s.xhrFields)for(o in s.xhrFields)N[o]=s.xhrFields[o];for(o in g)O.apply(N,g[o]);return s.timeout>0&&(P=setTimeout(function(){N.onreadystatechange=j,N.abort(),x(null,"timeout",N,s,a)},s.timeout)),N.send(s.data?s.data:null),N},e.get=function(){return e.ajax(C.apply(null,arguments))},e.post=function(){var t=C.apply(null,arguments);return t.type="POST",e.ajax(t)},e.getJSON=function(){var t=C.apply(null,arguments);return t.dataType="json",e.ajax(t)},e.fn.load=function(t,n,r){if(!this.length)return this;var a,i=this,o=t.split(/\s/),u=C(t,n,r),f=u.success;return o.length>1&&(u.url=o[0],a=o[1]),u.success=function(t){i.html(a?e("<div>").html(t.replace(s,"")).find(a):t),f&&f.apply(i,arguments)},e.ajax(u),this};var N=encodeURIComponent;e.param=function(t,n){var r=[];return r.add=function(t,n){e.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(N(t)+"="+N(n))},O(r,t,n),r.join("&").replace(/%20/g,"+")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(e){var n=getComputedStyle;t.getComputedStyle=function(t,e){try{return n(t,e)}catch(r){return null}}}}(),e});
// see https://github.com/blai/fashionista/issues/2
;(function ($) {
$.getScript = function(src, func, error_func) {
var script = document.createElement('script');
script.async = "async";
script.src = src;
if (func) {
script.onload = func;
}
if (error_func) {
script.onerror = error_func;
}
document.getElementsByTagName("head")[0].appendChild( script );
}
})(Zepto);
/* sockjs-client v1.0.3 | http://sockjs.org | MIT license */
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.SockJS=t()}}(function(){var t;return function e(t,n,r){function i(s,a){if(!n[s]){if(!t[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var c=n[s]={exports:{}};t[s][0].call(c.exports,function(e){var n=t[s][1][e];return i(n?n:e)},c,c.exports,e,t,n,r)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;s<r.length;s++)i(r[s]);return i}({1:[function(t,e){(function(n){"use strict";var r=t("./transport-list");e.exports=t("./main")(r),"_sockjs_onload"in n&&setTimeout(n._sockjs_onload,1)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./main":14,"./transport-list":16}],2:[function(t,e){"use strict";function n(){i.call(this),this.initEvent("close",!1,!1),this.wasClean=!1,this.code=0,this.reason=""}var r=t("inherits"),i=t("./event");r(n,i),e.exports=n},{"./event":4,inherits:54}],3:[function(t,e){"use strict";function n(){i.call(this)}var r=t("inherits"),i=t("./eventtarget");r(n,i),n.prototype.removeAllListeners=function(t){t?delete this._listeners[t]:this._listeners={}},n.prototype.once=function(t,e){function n(){r.removeListener(t,n),i||(i=!0,e.apply(this,arguments))}var r=this,i=!1;this.on(t,n)},n.prototype.emit=function(t){var e=this._listeners[t];if(e)for(var n=Array.prototype.slice.call(arguments,1),r=0;r<e.length;r++)e[r].apply(this,n)},n.prototype.on=n.prototype.addListener=i.prototype.addEventListener,n.prototype.removeListener=i.prototype.removeEventListener,e.exports.EventEmitter=n},{"./eventtarget":5,inherits:54}],4:[function(t,e){"use strict";function n(t){this.type=t}n.prototype.initEvent=function(t,e,n){return this.type=t,this.bubbles=e,this.cancelable=n,this.timeStamp=+new Date,this},n.prototype.stopPropagation=function(){},n.prototype.preventDefault=function(){},n.CAPTURING_PHASE=1,n.AT_TARGET=2,n.BUBBLING_PHASE=3,e.exports=n},{}],5:[function(t,e){"use strict";function n(){this._listeners={}}n.prototype.addEventListener=function(t,e){t in this._listeners||(this._listeners[t]=[]);var n=this._listeners[t];-1===n.indexOf(e)&&(n=n.concat([e])),this._listeners[t]=n},n.prototype.removeEventListener=function(t,e){var n=this._listeners[t];if(n){var r=n.indexOf(e);return-1!==r?void(n.length>1?this._listeners[t]=n.slice(0,r).concat(n.slice(r+1)):delete this._listeners[t]):void 0}},n.prototype.dispatchEvent=function(t){var e=t.type,n=Array.prototype.slice.call(arguments,0);if(this["on"+e]&&this["on"+e].apply(this,n),e in this._listeners)for(var r=this._listeners[e],i=0;i<r.length;i++)r[i].apply(this,n)},e.exports=n},{}],6:[function(t,e){"use strict";function n(t){i.call(this),this.initEvent("message",!1,!1),this.data=t}var r=t("inherits"),i=t("./event");r(n,i),e.exports=n},{"./event":4,inherits:54}],7:[function(t,e){"use strict";function n(t){this._transport=t,t.on("message",this._transportMessage.bind(this)),t.on("close",this._transportClose.bind(this))}var r=t("json3"),i=t("./utils/iframe");n.prototype._transportClose=function(t,e){i.postMessage("c",r.stringify([t,e]))},n.prototype._transportMessage=function(t){i.postMessage("t",t)},n.prototype._send=function(t){this._transport.send(t)},n.prototype._close=function(){this._transport.close(),this._transport.removeAllListeners()},e.exports=n},{"./utils/iframe":47,json3:55}],8:[function(t,e){"use strict";var n=t("./utils/url"),r=t("./utils/event"),i=t("json3"),o=t("./facade"),s=t("./info-iframe-receiver"),a=t("./utils/iframe"),u=t("./location");e.exports=function(t,e){var l={};e.forEach(function(t){t.facadeTransport&&(l[t.facadeTransport.transportName]=t.facadeTransport)}),l[s.transportName]=s;var c;t.bootstrap_iframe=function(){var e;a.currentWindowId=u.hash.slice(1);var s=function(r){if(r.source===parent&&("undefined"==typeof c&&(c=r.origin),r.origin===c)){var s;try{s=i.parse(r.data)}catch(f){return}if(s.windowId===a.currentWindowId)switch(s.type){case"s":var h;try{h=i.parse(s.data)}catch(f){break}var d=h[0],p=h[1],v=h[2],m=h[3];if(d!==t.version)throw new Error('Incompatibile SockJS! Main site uses: "'+d+'", the iframe: "'+t.version+'".');if(!n.isOriginEqual(v,u.href)||!n.isOriginEqual(m,u.href))throw new Error("Can't connect to different domain from within an iframe. ("+u.href+", "+v+", "+m+")");e=new o(new l[p](v,m));break;case"m":e._send(s.data);break;case"c":e&&e._close(),e=null}}};r.attachEvent("message",s),a.postMessage("s")}}},{"./facade":7,"./info-iframe-receiver":10,"./location":13,"./utils/event":46,"./utils/iframe":47,"./utils/url":52,debug:void 0,json3:55}],9:[function(t,e){"use strict";function n(t,e){r.call(this);var n=this,i=+new Date;this.xo=new e("GET",t),this.xo.once("finish",function(t,e){var r,a;if(200===t){if(a=+new Date-i,e)try{r=o.parse(e)}catch(u){}s.isObject(r)||(r={})}n.emit("finish",r,a),n.removeAllListeners()})}var r=t("events").EventEmitter,i=t("inherits"),o=t("json3"),s=t("./utils/object");i(n,r),n.prototype.close=function(){this.removeAllListeners(),this.xo.close()},e.exports=n},{"./utils/object":49,debug:void 0,events:3,inherits:54,json3:55}],10:[function(t,e){"use strict";function n(t){var e=this;i.call(this),this.ir=new a(t,s),this.ir.once("finish",function(t,n){e.ir=null,e.emit("message",o.stringify([t,n]))})}var r=t("inherits"),i=t("events").EventEmitter,o=t("json3"),s=t("./transport/sender/xhr-local"),a=t("./info-ajax");r(n,i),n.transportName="iframe-info-receiver",n.prototype.close=function(){this.ir&&(this.ir.close(),this.ir=null),this.removeAllListeners()},e.exports=n},{"./info-ajax":9,"./transport/sender/xhr-local":37,events:3,inherits:54,json3:55}],11:[function(t,e){(function(n){"use strict";function r(t,e){var r=this;i.call(this);var o=function(){var n=r.ifr=new u(l.transportName,e,t);n.once("message",function(t){if(t){var e;try{e=s.parse(t)}catch(n){return r.emit("finish"),void r.close()}var i=e[0],o=e[1];r.emit("finish",i,o)}r.close()}),n.once("close",function(){r.emit("finish"),r.close()})};n.document.body?o():a.attachEvent("load",o)}var i=t("events").EventEmitter,o=t("inherits"),s=t("json3"),a=t("./utils/event"),u=t("./transport/iframe"),l=t("./info-iframe-receiver");o(r,i),r.enabled=function(){return u.enabled()},r.prototype.close=function(){this.ifr&&this.ifr.close(),this.removeAllListeners(),this.ifr=null},e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./info-iframe-receiver":10,"./transport/iframe":22,"./utils/event":46,debug:void 0,events:3,inherits:54,json3:55}],12:[function(t,e){"use strict";function n(t,e){var n=this;r.call(this),setTimeout(function(){n.doXhr(t,e)},0)}var r=t("events").EventEmitter,i=t("inherits"),o=t("./utils/url"),s=t("./transport/sender/xdr"),a=t("./transport/sender/xhr-cors"),u=t("./transport/sender/xhr-local"),l=t("./transport/sender/xhr-fake"),c=t("./info-iframe"),f=t("./info-ajax");i(n,r),n._getReceiver=function(t,e,n){return n.sameOrigin?new f(e,u):a.enabled?new f(e,a):s.enabled&&n.sameScheme?new f(e,s):c.enabled()?new c(t,e):new f(e,l)},n.prototype.doXhr=function(t,e){var r=this,i=o.addPath(t,"/info");this.xo=n._getReceiver(t,i,e),this.timeoutRef=setTimeout(function(){r._cleanup(!1),r.emit("finish")},n.timeout),this.xo.once("finish",function(t,e){r._cleanup(!0),r.emit("finish",t,e)})},n.prototype._cleanup=function(t){clearTimeout(this.timeoutRef),this.timeoutRef=null,!t&&this.xo&&this.xo.close(),this.xo=null},n.prototype.close=function(){this.removeAllListeners(),this._cleanup(!1)},n.timeout=8e3,e.exports=n},{"./info-ajax":9,"./info-iframe":11,"./transport/sender/xdr":34,"./transport/sender/xhr-cors":35,"./transport/sender/xhr-fake":36,"./transport/sender/xhr-local":37,"./utils/url":52,debug:void 0,events:3,inherits:54}],13:[function(t,e){(function(t){"use strict";e.exports=t.location||{origin:"http://localhost:80",protocol:"http",host:"localhost",port:80,href:"http://localhost/",hash:""}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],14:[function(t,e){(function(n){"use strict";function r(t,e,n){if(!(this instanceof r))return new r(t,e,n);if(arguments.length<1)throw new TypeError("Failed to construct 'SockJS: 1 argument required, but only 0 present");b.call(this),this.readyState=r.CONNECTING,this.extensions="",this.protocol="",n=n||{},n.protocols_whitelist&&m.warn("'protocols_whitelist' is DEPRECATED. Use 'transports' instead."),this._transportsWhitelist=n.transports;var i=n.sessionId||8;if("function"==typeof i)this._generateSessionId=i;else{if("number"!=typeof i)throw new TypeError("If sessionId is used in the options, it needs to be a number or a function.");this._generateSessionId=function(){return l.string(i)}}this._server=n.server||l.numberString(1e3);var o=new s(t);if(!o.host||!o.protocol)throw new SyntaxError("The URL '"+t+"' is invalid");if(o.hash)throw new SyntaxError("The URL must not contain a fragment");if("http:"!==o.protocol&&"https:"!==o.protocol)throw new SyntaxError("The URL's scheme must be either 'http:' or 'https:'. '"+o.protocol+"' is not allowed.");var a="https:"===o.protocol;if("https"===g.protocol&&!a)throw new Error("SecurityError: An insecure SockJS connection may not be initiated from a page loaded over HTTPS");e?Array.isArray(e)||(e=[e]):e=[];var u=e.sort();u.forEach(function(t,e){if(!t)throw new SyntaxError("The protocols entry '"+t+"' is invalid.");if(e<u.length-1&&t===u[e+1])throw new SyntaxError("The protocols entry '"+t+"' is duplicated.")});var c=f.getOrigin(g.href);this._origin=c?c.toLowerCase():null,o.set("pathname",o.pathname.replace(/\/+$/,"")),this.url=o.href,this._urlInfo={nullOrigin:!v.hasDomain(),sameOrigin:f.isOriginEqual(this.url,g.href),sameScheme:f.isSchemeEqual(this.url,g.href)},this._ir=new _(this.url,this._urlInfo),this._ir.once("finish",this._receiveInfo.bind(this))}function i(t){return 1e3===t||t>=3e3&&4999>=t}t("./shims");var o,s=t("url-parse"),a=t("inherits"),u=t("json3"),l=t("./utils/random"),c=t("./utils/escape"),f=t("./utils/url"),h=t("./utils/event"),d=t("./utils/transport"),p=t("./utils/object"),v=t("./utils/browser"),m=t("./utils/log"),y=t("./event/event"),b=t("./event/eventtarget"),g=t("./location"),w=t("./event/close"),x=t("./event/trans-message"),_=t("./info-receiver");a(r,b),r.prototype.close=function(t,e){if(t&&!i(t))throw new Error("InvalidAccessError: Invalid code");if(e&&e.length>123)throw new SyntaxError("reason argument has an invalid length");if(this.readyState!==r.CLOSING&&this.readyState!==r.CLOSED){var n=!0;this._close(t||1e3,e||"Normal closure",n)}},r.prototype.send=function(t){if("string"!=typeof t&&(t=""+t),this.readyState===r.CONNECTING)throw new Error("InvalidStateError: The connection has not been established yet");this.readyState===r.OPEN&&this._transport.send(c.quote(t))},r.version=t("./version"),r.CONNECTING=0,r.OPEN=1,r.CLOSING=2,r.CLOSED=3,r.prototype._receiveInfo=function(t,e){if(this._ir=null,!t)return void this._close(1002,"Cannot connect to server");this._rto=this.countRTO(e),this._transUrl=t.base_url?t.base_url:this.url,t=p.extend(t,this._urlInfo);var n=o.filterToEnabled(this._transportsWhitelist,t);this._transports=n.main,this._connect()},r.prototype._connect=function(){for(var t=this._transports.shift();t;t=this._transports.shift()){if(t.needBody&&(!n.document.body||"undefined"!=typeof n.document.readyState&&"complete"!==n.document.readyState&&"interactive"!==n.document.readyState))return this._transports.unshift(t),void h.attachEvent("load",this._connect.bind(this));var e=this._rto*t.roundTrips||5e3;this._transportTimeoutId=setTimeout(this._transportTimeout.bind(this),e);var r=f.addPath(this._transUrl,"/"+this._server+"/"+this._generateSessionId()),i=new t(r,this._transUrl);return i.on("message",this._transportMessage.bind(this)),i.once("close",this._transportClose.bind(this)),i.transportName=t.transportName,void(this._transport=i)}this._close(2e3,"All transports failed",!1)},r.prototype._transportTimeout=function(){this.readyState===r.CONNECTING&&this._transportClose(2007,"Transport timed out")},r.prototype._transportMessage=function(t){var e,n=this,r=t.slice(0,1),i=t.slice(1);switch(r){case"o":return void this._open();case"h":return void this.dispatchEvent(new y("heartbeat"))}if(i)try{e=u.parse(i)}catch(o){}if("undefined"!=typeof e)switch(r){case"a":Array.isArray(e)&&e.forEach(function(t){n.dispatchEvent(new x(t))});break;case"m":this.dispatchEvent(new x(e));break;case"c":Array.isArray(e)&&2===e.length&&this._close(e[0],e[1],!0)}},r.prototype._transportClose=function(t,e){return this._transport&&(this._transport.removeAllListeners(),this._transport=null,this.transport=null),i(t)||2e3===t||this.readyState!==r.CONNECTING?void this._close(t,e):void this._connect()},r.prototype._open=function(){this.readyState===r.CONNECTING?(this._transportTimeoutId&&(clearTimeout(this._transportTimeoutId),this._transportTimeoutId=null),this.readyState=r.OPEN,this.transport=this._transport.transportName,this.dispatchEvent(new y("open"))):this._close(1006,"Server lost session")},r.prototype._close=function(t,e,n){var i=!1;if(this._ir&&(i=!0,this._ir.close(),this._ir=null),this._transport&&(this._transport.close(),this._transport=null,this.transport=null),this.readyState===r.CLOSED)throw new Error("InvalidStateError: SockJS has already been closed");this.readyState=r.CLOSING,setTimeout(function(){this.readyState=r.CLOSED,i&&this.dispatchEvent(new y("error"));var o=new w("close");o.wasClean=n||!1,o.code=t||1e3,o.reason=e,this.dispatchEvent(o),this.onmessage=this.onclose=this.onerror=null}.bind(this),0)},r.prototype.countRTO=function(t){return t>100?4*t:300+t},e.exports=function(e){return o=d(e),t("./iframe-bootstrap")(r,e),r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./event/close":2,"./event/event":4,"./event/eventtarget":5,"./event/trans-message":6,"./iframe-bootstrap":8,"./info-receiver":12,"./location":13,"./shims":15,"./utils/browser":44,"./utils/escape":45,"./utils/event":46,"./utils/log":48,"./utils/object":49,"./utils/random":50,"./utils/transport":51,"./utils/url":52,"./version":53,debug:void 0,inherits:54,json3:55,"url-parse":56}],15:[function(){"use strict";function t(t){var e=+t;return e!==e?e=0:0!==e&&e!==1/0&&e!==-(1/0)&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function e(t){return t>>>0}function n(){}var r,i=Array.prototype,o=Object.prototype,s=Function.prototype,a=String.prototype,u=i.slice,l=o.toString,c=function(t){return"[object Function]"===o.toString.call(t)},f=function(t){return"[object Array]"===l.call(t)},h=function(t){return"[object String]"===l.call(t)},d=Object.defineProperty&&function(){try{return Object.defineProperty({},"x",{}),!0}catch(t){return!1}}();r=d?function(t,e,n,r){!r&&e in t||Object.defineProperty(t,e,{configurable:!0,enumerable:!1,writable:!0,value:n})}:function(t,e,n,r){!r&&e in t||(t[e]=n)};var p=function(t,e,n){for(var i in e)o.hasOwnProperty.call(e,i)&&r(t,i,e[i],n)},v=function(t){if(null==t)throw new TypeError("can't convert "+t+" to object");return Object(t)};p(s,{bind:function(t){var e=this;if(!c(e))throw new TypeError("Function.prototype.bind called on incompatible "+e);for(var r=u.call(arguments,1),i=function(){if(this instanceof l){var n=e.apply(this,r.concat(u.call(arguments)));return Object(n)===n?n:this}return e.apply(t,r.concat(u.call(arguments)))},o=Math.max(0,e.length-r.length),s=[],a=0;o>a;a++)s.push("$"+a);var l=Function("binder","return function ("+s.join(",")+"){ return binder.apply(this, arguments); }")(i);return e.prototype&&(n.prototype=e.prototype,l.prototype=new n,n.prototype=null),l}}),p(Array,{isArray:f});var m=Object("a"),y="a"!==m[0]||!(0 in m),b=function(t){var e=!0,n=!0;return t&&(t.call("foo",function(t,n,r){"object"!=typeof r&&(e=!1)}),t.call([1],function(){n="string"==typeof this},"x")),!!t&&e&&n};p(i,{forEach:function(t){var e=v(this),n=y&&h(this)?this.split(""):e,r=arguments[1],i=-1,o=n.length>>>0;if(!c(t))throw new TypeError;for(;++i<o;)i in n&&t.call(r,n[i],i,e)}},!b(i.forEach));var g=Array.prototype.indexOf&&-1!==[0,1].indexOf(1,2);p(i,{indexOf:function(e){var n=y&&h(this)?this.split(""):v(this),r=n.length>>>0;if(!r)return-1;var i=0;for(arguments.length>1&&(i=t(arguments[1])),i=i>=0?i:Math.max(0,r+i);r>i;i++)if(i in n&&n[i]===e)return i;return-1}},g);var w=a.split;2!=="ab".split(/(?:ab)*/).length||4!==".".split(/(.?)(.?)/).length||"t"==="tesst".split(/(s)*/)[1]||4!=="test".split(/(?:)/,-1).length||"".split(/.?/).length||".".split(/()()/).length>1?!function(){var t=void 0===/()??/.exec("")[1];a.split=function(n,r){var o=this;if(void 0===n&&0===r)return[];if("[object RegExp]"!==l.call(n))return w.call(this,n,r);var s,a,u,c,f=[],h=(n.ignoreCase?"i":"")+(n.multiline?"m":"")+(n.extended?"x":"")+(n.sticky?"y":""),d=0;for(n=new RegExp(n.source,h+"g"),o+="",t||(s=new RegExp("^"+n.source+"$(?!\\s)",h)),r=void 0===r?-1>>>0:e(r);(a=n.exec(o))&&(u=a.index+a[0].length,!(u>d&&(f.push(o.slice(d,a.index)),!t&&a.length>1&&a[0].replace(s,function(){for(var t=1;t<arguments.length-2;t++)void 0===arguments[t]&&(a[t]=void 0)}),a.length>1&&a.index<o.length&&i.push.apply(f,a.slice(1)),c=a[0].length,d=u,f.length>=r)));)n.lastIndex===a.index&&n.lastIndex++;return d===o.length?(c||!n.test(""))&&f.push(""):f.push(o.slice(d)),f.length>r?f.slice(0,r):f}}():"0".split(void 0,0).length&&(a.split=function(t,e){return void 0===t&&0===e?[]:w.call(this,t,e)});var x=" \n \f\r   \u2028\u2029",_="",E="["+x+"]",j=new RegExp("^"+E+E+"*"),T=new RegExp(E+E+"*$"),S=a.trim&&(x.trim()||!_.trim());p(a,{trim:function(){if(void 0===this||null===this)throw new TypeError("can't convert "+this+" to object");return String(this).replace(j,"").replace(T,"")}},S);var O=a.substr,C="".substr&&"b"!=="0b".substr(-1);p(a,{substr:function(t,e){return O.call(this,0>t&&(t=this.length+t)<0?0:t,e)}},C)},{}],16:[function(t,e){"use strict";e.exports=[t("./transport/websocket"),t("./transport/xhr-streaming"),t("./transport/xdr-streaming"),t("./transport/eventsource"),t("./transport/lib/iframe-wrap")(t("./transport/eventsource")),t("./transport/htmlfile"),t("./transport/lib/iframe-wrap")(t("./transport/htmlfile")),t("./transport/xhr-polling"),t("./transport/xdr-polling"),t("./transport/lib/iframe-wrap")(t("./transport/xhr-polling")),t("./transport/jsonp-polling")]},{"./transport/eventsource":20,"./transport/htmlfile":21,"./transport/jsonp-polling":23,"./transport/lib/iframe-wrap":26,"./transport/websocket":38,"./transport/xdr-polling":39,"./transport/xdr-streaming":40,"./transport/xhr-polling":41,"./transport/xhr-streaming":42}],17:[function(t,e){(function(n){"use strict";function r(t,e,n,r){var o=this;i.call(this),setTimeout(function(){o._start(t,e,n,r)},0)}var i=t("events").EventEmitter,o=t("inherits"),s=t("../../utils/event"),a=t("../../utils/url"),u=n.XMLHttpRequest;o(r,i),r.prototype._start=function(t,e,n,i){var o=this;try{this.xhr=new u}catch(l){}if(!this.xhr)return this.emit("finish",0,"no xhr support"),void this._cleanup();e=a.addQuery(e,"t="+ +new Date),this.unloadRef=s.unloadAdd(function(){o._cleanup(!0)});try{this.xhr.open(t,e,!0),this.timeout&&"timeout"in this.xhr&&(this.xhr.timeout=this.timeout,this.xhr.ontimeout=function(){o.emit("finish",0,""),o._cleanup(!1)})}catch(c){return this.emit("finish",0,""),void this._cleanup(!1)}if(i&&i.noCredentials||!r.supportsCORS||(this.xhr.withCredentials="true"),i&&i.headers)for(var f in i.headers)this.xhr.setRequestHeader(f,i.headers[f]);this.xhr.onreadystatechange=function(){if(o.xhr){var t,e,n=o.xhr;switch(n.readyState){case 3:try{e=n.status,t=n.responseText}catch(r){}1223===e&&(e=204),200===e&&t&&t.length>0&&o.emit("chunk",e,t);break;case 4:e=n.status,1223===e&&(e=204),(12005===e||12029===e)&&(e=0),o.emit("finish",e,n.responseText),o._cleanup(!1)}}};try{o.xhr.send(n)}catch(c){o.emit("finish",0,""),o._cleanup(!1)}},r.prototype._cleanup=function(t){if(this.xhr){if(this.removeAllListeners(),s.unloadDel(this.unloadRef),this.xhr.onreadystatechange=function(){},this.xhr.ontimeout&&(this.xhr.ontimeout=null),t)try{this.xhr.abort()}catch(e){}this.unloadRef=this.xhr=null}},r.prototype.close=function(){this._cleanup(!0)},r.enabled=!!u;var l=["Active"].concat("Object").join("X");!r.enabled&&l in n&&(u=function(){try{return new n[l]("Microsoft.XMLHTTP")}catch(t){return null}},r.enabled=!!new u);var c=!1;try{c="withCredentials"in new u}catch(f){}r.supportsCORS=c,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/event":46,"../../utils/url":52,debug:void 0,events:3,inherits:54}],18:[function(t,e){(function(t){e.exports=t.EventSource}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],19:[function(t,e){(function(t){e.exports=t.WebSocket||t.MozWebSocket}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],20:[function(t,e){"use strict";function n(t){if(!n.enabled())throw new Error("Transport created when disabled");i.call(this,t,"/eventsource",o,s)}var r=t("inherits"),i=t("./lib/ajax-based"),o=t("./receiver/eventsource"),s=t("./sender/xhr-cors"),a=t("eventsource");r(n,i),n.enabled=function(){return!!a},n.transportName="eventsource",n.roundTrips=2,e.exports=n},{"./lib/ajax-based":24,"./receiver/eventsource":29,"./sender/xhr-cors":35,eventsource:18,inherits:54}],21:[function(t,e){"use strict";function n(t){if(!i.enabled)throw new Error("Transport created when disabled");s.call(this,t,"/htmlfile",i,o)}var r=t("inherits"),i=t("./receiver/htmlfile"),o=t("./sender/xhr-local"),s=t("./lib/ajax-based");r(n,s),n.enabled=function(t){return i.enabled&&t.sameOrigin},n.transportName="htmlfile",n.roundTrips=2,e.exports=n},{"./lib/ajax-based":24,"./receiver/htmlfile":30,"./sender/xhr-local":37,inherits:54}],22:[function(t,e){"use strict";function n(t,e,r){if(!n.enabled())throw new Error("Transport created when disabled");o.call(this);var i=this;this.origin=a.getOrigin(r),this.baseUrl=r,this.transUrl=e,this.transport=t,this.windowId=c.string(8);var s=a.addPath(r,"/iframe.html")+"#"+this.windowId;this.iframeObj=u.createIframe(s,function(t){i.emit("close",1006,"Unable to load an iframe ("+t+")"),i.close()}),this.onmessageCallback=this._message.bind(this),l.attachEvent("message",this.onmessageCallback)}var r=t("inherits"),i=t("json3"),o=t("events").EventEmitter,s=t("../version"),a=t("../utils/url"),u=t("../utils/iframe"),l=t("../utils/event"),c=t("../utils/random");r(n,o),n.prototype.close=function(){if(this.removeAllListeners(),this.iframeObj){l.detachEvent("message",this.onmessageCallback);try{this.postMessage("c")}catch(t){}this.iframeObj.cleanup(),this.iframeObj=null,this.onmessageCallback=this.iframeObj=null}},n.prototype._message=function(t){if(a.isOriginEqual(t.origin,this.origin)){var e;try{e=i.parse(t.data)}catch(n){return}if(e.windowId===this.windowId)switch(e.type){case"s":this.iframeObj.loaded(),this.postMessage("s",i.stringify([s,this.transport,this.transUrl,this.baseUrl]));break;case"t":this.emit("message",e.data);break;case"c":var r;try{r=i.parse(e.data)}catch(n){return}this.emit("close",r[0],r[1]),this.close()}}},n.prototype.postMessage=function(t,e){this.iframeObj.post(i.stringify({windowId:this.windowId,type:t,data:e||""}),this.origin)},n.prototype.send=function(t){this.postMessage("m",t)},n.enabled=function(){return u.iframeEnabled},n.transportName="iframe",n.roundTrips=2,e.exports=n},{"../utils/event":46,"../utils/iframe":47,"../utils/random":50,"../utils/url":52,"../version":53,debug:void 0,events:3,inherits:54,json3:55}],23:[function(t,e){(function(n){"use strict";function r(t){if(!r.enabled())throw new Error("Transport created when disabled");o.call(this,t,"/jsonp",a,s)}var i=t("inherits"),o=t("./lib/sender-receiver"),s=t("./receiver/jsonp"),a=t("./sender/jsonp");i(r,o),r.enabled=function(){return!!n.document},r.transportName="jsonp-polling",r.roundTrips=1,r.needBody=!0,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./lib/sender-receiver":28,"./receiver/jsonp":31,"./sender/jsonp":33,inherits:54}],24:[function(t,e){"use strict";function n(t){return function(e,n,r){var i={};"string"==typeof n&&(i.headers={"Content-type":"text/plain"});var s=o.addPath(e,"/xhr_send"),a=new t("POST",s,n,i);return a.once("finish",function(t){return a=null,200!==t&&204!==t?r(new Error("http status "+t)):void r()}),function(){a.close(),a=null;var t=new Error("Aborted");t.code=1e3,r(t)}}}function r(t,e,r,i){s.call(this,t,e,n(i),r,i)}var i=t("inherits"),o=t("../../utils/url"),s=t("./sender-receiver");i(r,s),e.exports=r},{"../../utils/url":52,"./sender-receiver":28,debug:void 0,inherits:54}],25:[function(t,e){"use strict";function n(t,e){i.call(this),this.sendBuffer=[],this.sender=e,this.url=t}var r=t("inherits"),i=t("events").EventEmitter;r(n,i),n.prototype.send=function(t){this.sendBuffer.push(t),this.sendStop||this.sendSchedule()},n.prototype.sendScheduleWait=function(){var t,e=this;this.sendStop=function(){e.sendStop=null,clearTimeout(t)},t=setTimeout(function(){e.sendStop=null,e.sendSchedule()},25)},n.prototype.sendSchedule=function(){var t=this;if(this.sendBuffer.length>0){var e="["+this.sendBuffer.join(",")+"]";this.sendStop=this.sender(this.url,e,function(e){t.sendStop=null,e?(t.emit("close",e.code||1006,"Sending error: "+e),t._cleanup()):t.sendScheduleWait()}),this.sendBuffer=[]}},n.prototype._cleanup=function(){this.removeAllListeners()},n.prototype.stop=function(){this._cleanup(),this.sendStop&&(this.sendStop(),this.sendStop=null)},e.exports=n},{debug:void 0,events:3,inherits:54}],26:[function(t,e){(function(n){"use strict";var r=t("inherits"),i=t("../iframe"),o=t("../../utils/object");e.exports=function(t){function e(e,n){i.call(this,t.transportName,e,n)}return r(e,i),e.enabled=function(e,r){if(!n.document)return!1;var s=o.extend({},r);return s.sameOrigin=!0,t.enabled(s)&&i.enabled()},e.transportName="iframe-"+t.transportName,e.needBody=!0,e.roundTrips=i.roundTrips+t.roundTrips-1,e.facadeTransport=t,e}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/object":49,"../iframe":22,inherits:54}],27:[function(t,e){"use strict";function n(t,e,n){i.call(this),this.Receiver=t,this.receiveUrl=e,this.AjaxObject=n,this._scheduleReceiver()}var r=t("inherits"),i=t("events").EventEmitter;r(n,i),n.prototype._scheduleReceiver=function(){var t=this,e=this.poll=new this.Receiver(this.receiveUrl,this.AjaxObject);e.on("message",function(e){t.emit("message",e)}),e.once("close",function(n,r){t.poll=e=null,t.pollIsClosing||("network"===r?t._scheduleReceiver():(t.emit("close",n||1006,r),t.removeAllListeners()))})},n.prototype.abort=function(){this.removeAllListeners(),this.pollIsClosing=!0,this.poll&&this.poll.abort()},e.exports=n},{debug:void 0,events:3,inherits:54}],28:[function(t,e){"use strict";function n(t,e,n,r,a){var u=i.addPath(t,e),l=this;o.call(this,t,n),this.poll=new s(r,u,a),this.poll.on("message",function(t){l.emit("message",t)}),this.poll.once("close",function(t,e){l.poll=null,l.emit("close",t,e),l.close()})}var r=t("inherits"),i=t("../../utils/url"),o=t("./buffered-sender"),s=t("./polling");r(n,o),n.prototype.close=function(){this.removeAllListeners(),this.poll&&(this.poll.abort(),this.poll=null),this.stop()},e.exports=n},{"../../utils/url":52,"./buffered-sender":25,"./polling":27,debug:void 0,inherits:54}],29:[function(t,e){"use strict";function n(t){i.call(this);var e=this,n=this.es=new o(t);n.onmessage=function(t){e.emit("message",decodeURI(t.data))},n.onerror=function(t){var r=2!==n.readyState?"network":"permanent";e._cleanup(),e._close(r)}}var r=t("inherits"),i=t("events").EventEmitter,o=t("eventsource");r(n,i),n.prototype.abort=function(){this._cleanup(),this._close("user")},n.prototype._cleanup=function(){var t=this.es;t&&(t.onmessage=t.onerror=null,t.close(),this.es=null)},n.prototype._close=function(t){var e=this;setTimeout(function(){e.emit("close",null,t),e.removeAllListeners()},200)},e.exports=n},{debug:void 0,events:3,eventsource:18,inherits:54}],30:[function(t,e){(function(n){"use strict";function r(t){a.call(this);var e=this;o.polluteGlobalNamespace(),this.id="a"+u.string(6),t=s.addQuery(t,"c="+decodeURIComponent(o.WPrefix+"."+this.id));var i=r.htmlfileEnabled?o.createHtmlfile:o.createIframe;n[o.WPrefix][this.id]={start:function(){e.iframeObj.loaded()},message:function(t){e.emit("message",t)},stop:function(){e._cleanup(),e._close("network")}},this.iframeObj=i(t,function(){e._cleanup(),e._close("permanent")})}var i=t("inherits"),o=t("../../utils/iframe"),s=t("../../utils/url"),a=t("events").EventEmitter,u=t("../../utils/random");i(r,a),r.prototype.abort=function(){this._cleanup(),this._close("user")},r.prototype._cleanup=function(){this.iframeObj&&(this.iframeObj.cleanup(),this.iframeObj=null),delete n[o.WPrefix][this.id]},r.prototype._close=function(t){this.emit("close",null,t),this.removeAllListeners()},r.htmlfileEnabled=!1;var l=["Active"].concat("Object").join("X");if(l in n)try{r.htmlfileEnabled=!!new n[l]("htmlfile")}catch(c){}r.enabled=r.htmlfileEnabled||o.iframeEnabled,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/iframe":47,"../../utils/random":50,"../../utils/url":52,debug:void 0,events:3,inherits:54}],31:[function(t,e){(function(n){"use strict";function r(t){var e=this;l.call(this),i.polluteGlobalNamespace(),this.id="a"+o.string(6);var s=a.addQuery(t,"c="+encodeURIComponent(i.WPrefix+"."+this.id));n[i.WPrefix][this.id]=this._callback.bind(this),this._createScript(s),this.timeoutId=setTimeout(function(){e._abort(new Error("JSONP script loaded abnormally (timeout)"))},r.timeout)}var i=t("../../utils/iframe"),o=t("../../utils/random"),s=t("../../utils/browser"),a=t("../../utils/url"),u=t("inherits"),l=t("events").EventEmitter;u(r,l),r.prototype.abort=function(){if(n[i.WPrefix][this.id]){var t=new Error("JSONP user aborted read");t.code=1e3,this._abort(t)}},r.timeout=35e3,r.scriptErrorTimeout=1e3,r.prototype._callback=function(t){this._cleanup(),this.aborting||(t&&this.emit("message",t),this.emit("close",null,"network"),this.removeAllListeners())},r.prototype._abort=function(t){this._cleanup(),this.aborting=!0,this.emit("close",t.code,t.message),this.removeAllListeners()},r.prototype._cleanup=function(){if(clearTimeout(this.timeoutId),this.script2&&(this.script2.parentNode.removeChild(this.script2),this.script2=null),this.script){var t=this.script;t.parentNode.removeChild(t),t.onreadystatechange=t.onerror=t.onload=t.onclick=null,this.script=null}delete n[i.WPrefix][this.id]},r.prototype._scriptError=function(){var t=this;this.errorTimer||(this.errorTimer=setTimeout(function(){t.loadedOkay||t._abort(new Error("JSONP script loaded abnormally (onerror)"))},r.scriptErrorTimeout))},r.prototype._createScript=function(t){var e,r=this,i=this.script=n.document.createElement("script");if(i.id="a"+o.string(8),i.src=t,i.type="text/javascript",i.charset="UTF-8",i.onerror=this._scriptError.bind(this),i.onload=function(){r._abort(new Error("JSONP script loaded abnormally (onload)"))},i.onreadystatechange=function(){if(/loaded|closed/.test(i.readyState)){if(i&&i.htmlFor&&i.onclick){r.loadedOkay=!0;try{i.onclick()}catch(t){}}i&&r._abort(new Error("JSONP script loaded abnormally (onreadystatechange)"))}},"undefined"==typeof i.async&&n.document.attachEvent)if(s.isOpera())e=this.script2=n.document.createElement("script"),e.text="try{var a = document.getElementById('"+i.id+"'); if(a)a.onerror();}catch(x){};",i.async=e.async=!1;
else{try{i.htmlFor=i.id,i.event="onclick"}catch(a){}i.async=!0}"undefined"!=typeof i.async&&(i.async=!0);var u=n.document.getElementsByTagName("head")[0];u.insertBefore(i,u.firstChild),e&&u.insertBefore(e,u.firstChild)},e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/browser":44,"../../utils/iframe":47,"../../utils/random":50,"../../utils/url":52,debug:void 0,events:3,inherits:54}],32:[function(t,e){"use strict";function n(t,e){i.call(this);var n=this;this.bufferPosition=0,this.xo=new e("POST",t,null),this.xo.on("chunk",this._chunkHandler.bind(this)),this.xo.once("finish",function(t,e){n._chunkHandler(t,e),n.xo=null;var r=200===t?"network":"permanent";n.emit("close",null,r),n._cleanup()})}var r=t("inherits"),i=t("events").EventEmitter;r(n,i),n.prototype._chunkHandler=function(t,e){if(200===t&&e)for(var n=-1;;this.bufferPosition+=n+1){var r=e.slice(this.bufferPosition);if(n=r.indexOf("\n"),-1===n)break;var i=r.slice(0,n);i&&this.emit("message",i)}},n.prototype._cleanup=function(){this.removeAllListeners()},n.prototype.abort=function(){this.xo&&(this.xo.close(),this.emit("close",null,"user"),this.xo=null),this._cleanup()},e.exports=n},{debug:void 0,events:3,inherits:54}],33:[function(t,e){(function(n){"use strict";function r(t){try{return n.document.createElement('<iframe name="'+t+'">')}catch(e){var r=n.document.createElement("iframe");return r.name=t,r}}function i(){o=n.document.createElement("form"),o.style.display="none",o.style.position="absolute",o.method="POST",o.enctype="application/x-www-form-urlencoded",o.acceptCharset="UTF-8",s=n.document.createElement("textarea"),s.name="d",o.appendChild(s),n.document.body.appendChild(o)}var o,s,a=t("../../utils/random"),u=t("../../utils/url");e.exports=function(t,e,n){o||i();var l="a"+a.string(8);o.target=l,o.action=u.addQuery(u.addPath(t,"/jsonp_send"),"i="+l);var c=r(l);c.id=l,c.style.display="none",o.appendChild(c);try{s.value=e}catch(f){}o.submit();var h=function(t){c.onerror&&(c.onreadystatechange=c.onerror=c.onload=null,setTimeout(function(){c.parentNode.removeChild(c),c=null},500),s.value="",n(t))};return c.onerror=function(){h()},c.onload=function(){h()},c.onreadystatechange=function(t){"complete"===c.readyState&&h()},function(){h(new Error("Aborted"))}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/random":50,"../../utils/url":52,debug:void 0}],34:[function(t,e){(function(n){"use strict";function r(t,e,n){var r=this;i.call(this),setTimeout(function(){r._start(t,e,n)},0)}var i=t("events").EventEmitter,o=t("inherits"),s=t("../../utils/event"),a=t("../../utils/browser"),u=t("../../utils/url");o(r,i),r.prototype._start=function(t,e,r){var i=this,o=new n.XDomainRequest;e=u.addQuery(e,"t="+ +new Date),o.onerror=function(){i._error()},o.ontimeout=function(){i._error()},o.onprogress=function(){i.emit("chunk",200,o.responseText)},o.onload=function(){i.emit("finish",200,o.responseText),i._cleanup(!1)},this.xdr=o,this.unloadRef=s.unloadAdd(function(){i._cleanup(!0)});try{this.xdr.open(t,e),this.timeout&&(this.xdr.timeout=this.timeout),this.xdr.send(r)}catch(a){this._error()}},r.prototype._error=function(){this.emit("finish",0,""),this._cleanup(!1)},r.prototype._cleanup=function(t){if(this.xdr){if(this.removeAllListeners(),s.unloadDel(this.unloadRef),this.xdr.ontimeout=this.xdr.onerror=this.xdr.onprogress=this.xdr.onload=null,t)try{this.xdr.abort()}catch(e){}this.unloadRef=this.xdr=null}},r.prototype.close=function(){this._cleanup(!0)},r.enabled=!(!n.XDomainRequest||!a.hasDomain()),e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/browser":44,"../../utils/event":46,"../../utils/url":52,debug:void 0,events:3,inherits:54}],35:[function(t,e){"use strict";function n(t,e,n,r){i.call(this,t,e,n,r)}var r=t("inherits"),i=t("../driver/xhr");r(n,i),n.enabled=i.enabled&&i.supportsCORS,e.exports=n},{"../driver/xhr":17,inherits:54}],36:[function(t,e){"use strict";function n(){var t=this;r.call(this),this.to=setTimeout(function(){t.emit("finish",200,"{}")},n.timeout)}var r=t("events").EventEmitter,i=t("inherits");i(n,r),n.prototype.close=function(){clearTimeout(this.to)},n.timeout=2e3,e.exports=n},{events:3,inherits:54}],37:[function(t,e){"use strict";function n(t,e,n){i.call(this,t,e,n,{noCredentials:!0})}var r=t("inherits"),i=t("../driver/xhr");r(n,i),n.enabled=i.enabled,e.exports=n},{"../driver/xhr":17,inherits:54}],38:[function(t,e){"use strict";function n(t){if(!n.enabled())throw new Error("Transport created when disabled");s.call(this);var e=this,o=i.addPath(t,"/websocket");o="https"===o.slice(0,5)?"wss"+o.slice(5):"ws"+o.slice(4),this.url=o,this.ws=new a(this.url),this.ws.onmessage=function(t){e.emit("message",t.data)},this.unloadRef=r.unloadAdd(function(){e.ws.close()}),this.ws.onclose=function(t){e.emit("close",t.code,t.reason),e._cleanup()},this.ws.onerror=function(t){e.emit("close",1006,"WebSocket connection broken"),e._cleanup()}}var r=t("../utils/event"),i=t("../utils/url"),o=t("inherits"),s=t("events").EventEmitter,a=t("./driver/websocket");o(n,s),n.prototype.send=function(t){var e="["+t+"]";this.ws.send(e)},n.prototype.close=function(){this.ws&&this.ws.close(),this._cleanup()},n.prototype._cleanup=function(){var t=this.ws;t&&(t.onmessage=t.onclose=t.onerror=null),r.unloadDel(this.unloadRef),this.unloadRef=this.ws=null,this.removeAllListeners()},n.enabled=function(){return!!a},n.transportName="websocket",n.roundTrips=2,e.exports=n},{"../utils/event":46,"../utils/url":52,"./driver/websocket":19,debug:void 0,events:3,inherits:54}],39:[function(t,e){"use strict";function n(t){if(!a.enabled)throw new Error("Transport created when disabled");i.call(this,t,"/xhr",s,a)}var r=t("inherits"),i=t("./lib/ajax-based"),o=t("./xdr-streaming"),s=t("./receiver/xhr"),a=t("./sender/xdr");r(n,i),n.enabled=o.enabled,n.transportName="xdr-polling",n.roundTrips=2,e.exports=n},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xdr":34,"./xdr-streaming":40,inherits:54}],40:[function(t,e){"use strict";function n(t){if(!s.enabled)throw new Error("Transport created when disabled");i.call(this,t,"/xhr_streaming",o,s)}var r=t("inherits"),i=t("./lib/ajax-based"),o=t("./receiver/xhr"),s=t("./sender/xdr");r(n,i),n.enabled=function(t){return t.cookie_needed||t.nullOrigin?!1:s.enabled&&t.sameScheme},n.transportName="xdr-streaming",n.roundTrips=2,e.exports=n},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xdr":34,inherits:54}],41:[function(t,e){"use strict";function n(t){if(!a.enabled&&!s.enabled)throw new Error("Transport created when disabled");i.call(this,t,"/xhr",o,s)}var r=t("inherits"),i=t("./lib/ajax-based"),o=t("./receiver/xhr"),s=t("./sender/xhr-cors"),a=t("./sender/xhr-local");r(n,i),n.enabled=function(t){return t.nullOrigin?!1:a.enabled&&t.sameOrigin?!0:s.enabled},n.transportName="xhr-polling",n.roundTrips=2,e.exports=n},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xhr-cors":35,"./sender/xhr-local":37,inherits:54}],42:[function(t,e){(function(n){"use strict";function r(t){if(!u.enabled&&!a.enabled)throw new Error("Transport created when disabled");o.call(this,t,"/xhr_streaming",s,a)}var i=t("inherits"),o=t("./lib/ajax-based"),s=t("./receiver/xhr"),a=t("./sender/xhr-cors"),u=t("./sender/xhr-local"),l=t("../utils/browser");i(r,o),r.enabled=function(t){return t.nullOrigin?!1:l.isOpera()?!1:a.enabled},r.transportName="xhr-streaming",r.roundTrips=2,r.needBody=!!n.document,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils/browser":44,"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xhr-cors":35,"./sender/xhr-local":37,inherits:54}],43:[function(t,e){(function(t){"use strict";e.exports.randomBytes=t.crypto&&t.crypto.getRandomValues?function(e){var n=new Uint8Array(e);return t.crypto.getRandomValues(n),n}:function(t){for(var e=new Array(t),n=0;t>n;n++)e[n]=Math.floor(256*Math.random());return e}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],44:[function(t,e){(function(t){"use strict";e.exports={isOpera:function(){return t.navigator&&/opera/i.test(t.navigator.userAgent)},isKonqueror:function(){return t.navigator&&/konqueror/i.test(t.navigator.userAgent)},hasDomain:function(){if(!t.document)return!0;try{return!!t.document.domain}catch(e){return!1}}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],45:[function(t,e){"use strict";var n,r=t("json3"),i=/[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g,o=function(t){var e,n={},r=[];for(e=0;65536>e;e++)r.push(String.fromCharCode(e));return t.lastIndex=0,r.join("").replace(t,function(t){return n[t]="\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4),""}),t.lastIndex=0,n};e.exports={quote:function(t){var e=r.stringify(t);return i.lastIndex=0,i.test(e)?(n||(n=o(i)),e.replace(i,function(t){return n[t]})):e}}},{json3:55}],46:[function(t,e){(function(n){"use strict";var r=t("./random"),i={},o=!1,s=n.chrome&&n.chrome.app&&n.chrome.app.runtime;e.exports={attachEvent:function(t,e){"undefined"!=typeof n.addEventListener?n.addEventListener(t,e,!1):n.document&&n.attachEvent&&(n.document.attachEvent("on"+t,e),n.attachEvent("on"+t,e))},detachEvent:function(t,e){"undefined"!=typeof n.addEventListener?n.removeEventListener(t,e,!1):n.document&&n.detachEvent&&(n.document.detachEvent("on"+t,e),n.detachEvent("on"+t,e))},unloadAdd:function(t){if(s)return null;var e=r.string(8);return i[e]=t,o&&setTimeout(this.triggerUnloadCallbacks,0),e},unloadDel:function(t){t in i&&delete i[t]},triggerUnloadCallbacks:function(){for(var t in i)i[t](),delete i[t]}};var a=function(){o||(o=!0,e.exports.triggerUnloadCallbacks())};s||e.exports.attachEvent("unload",a)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./random":50}],47:[function(t,e){(function(n){"use strict";var r=t("./event"),i=t("json3"),o=t("./browser");e.exports={WPrefix:"_jp",currentWindowId:null,polluteGlobalNamespace:function(){e.exports.WPrefix in n||(n[e.exports.WPrefix]={})},postMessage:function(t,r){n.parent!==n&&n.parent.postMessage(i.stringify({windowId:e.exports.currentWindowId,type:t,data:r||""}),"*")},createIframe:function(t,e){var i,o,s=n.document.createElement("iframe"),a=function(){clearTimeout(i);try{s.onload=null}catch(t){}s.onerror=null},u=function(){s&&(a(),setTimeout(function(){s&&s.parentNode.removeChild(s),s=null},0),r.unloadDel(o))},l=function(t){s&&(u(),e(t))},c=function(t,e){try{setTimeout(function(){s&&s.contentWindow&&s.contentWindow.postMessage(t,e)},0)}catch(n){}};return s.src=t,s.style.display="none",s.style.position="absolute",s.onerror=function(){l("onerror")},s.onload=function(){clearTimeout(i),i=setTimeout(function(){l("onload timeout")},2e3)},n.document.body.appendChild(s),i=setTimeout(function(){l("timeout")},15e3),o=r.unloadAdd(u),{post:c,cleanup:u,loaded:a}},createHtmlfile:function(t,i){var o,s,a,u=["Active"].concat("Object").join("X"),l=new n[u]("htmlfile"),c=function(){clearTimeout(o),a.onerror=null},f=function(){l&&(c(),r.unloadDel(s),a.parentNode.removeChild(a),a=l=null,CollectGarbage())},h=function(t){l&&(f(),i(t))},d=function(t,e){try{setTimeout(function(){a&&a.contentWindow&&a.contentWindow.postMessage(t,e)},0)}catch(n){}};l.open(),l.write('<html><script>document.domain="'+n.document.domain+'";</script></html>'),l.close(),l.parentWindow[e.exports.WPrefix]=n[e.exports.WPrefix];var p=l.createElement("div");return l.body.appendChild(p),a=l.createElement("iframe"),p.appendChild(a),a.src=t,a.onerror=function(){h("onerror")},o=setTimeout(function(){h("timeout")},15e3),s=r.unloadAdd(f),{post:d,cleanup:f,loaded:c}}},e.exports.iframeEnabled=!1,n.document&&(e.exports.iframeEnabled=("function"==typeof n.postMessage||"object"==typeof n.postMessage)&&!o.isKonqueror())}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./browser":44,"./event":46,debug:void 0,json3:55}],48:[function(t,e){(function(t){"use strict";var n={};["log","debug","warn"].forEach(function(e){var r=t.console&&t.console[e]&&t.console[e].apply;n[e]=r?function(){return t.console[e].apply(t.console,arguments)}:"log"===e?function(){}:n.log}),e.exports=n}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],49:[function(t,e){"use strict";e.exports={isObject:function(t){var e=typeof t;return"function"===e||"object"===e&&!!t},extend:function(t){if(!this.isObject(t))return t;for(var e,n,r=1,i=arguments.length;i>r;r++){e=arguments[r];for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}return t}}},{}],50:[function(t,e){"use strict";var n=t("crypto"),r="abcdefghijklmnopqrstuvwxyz012345";e.exports={string:function(t){for(var e=r.length,i=n.randomBytes(t),o=[],s=0;t>s;s++)o.push(r.substr(i[s]%e,1));return o.join("")},number:function(t){return Math.floor(Math.random()*t)},numberString:function(t){var e=(""+(t-1)).length,n=new Array(e+1).join("0");return(n+this.number(t)).slice(-e)}}},{crypto:43}],51:[function(t,e){"use strict";e.exports=function(t){return{filterToEnabled:function(e,n){var r={main:[],facade:[]};return e?"string"==typeof e&&(e=[e]):e=[],t.forEach(function(t){t&&("websocket"!==t.transportName||n.websocket!==!1)&&(e.length&&-1===e.indexOf(t.transportName)||t.enabled(n)&&(r.main.push(t),t.facadeTransport&&r.facade.push(t.facadeTransport)))}),r}}}},{debug:void 0}],52:[function(t,e){"use strict";var n=t("url-parse");e.exports={getOrigin:function(t){if(!t)return null;var e=new n(t);if("file:"===e.protocol)return null;var r=e.port;return r||(r="https:"===e.protocol?"443":"80"),e.protocol+"//"+e.hostname+":"+r},isOriginEqual:function(t,e){var n=this.getOrigin(t)===this.getOrigin(e);return n},isSchemeEqual:function(t,e){return t.split(":")[0]===e.split(":")[0]},addPath:function(t,e){var n=t.split("?");return n[0]+e+(n[1]?"?"+n[1]:"")},addQuery:function(t,e){return t+(-1===t.indexOf("?")?"?"+e:"&"+e)}}},{debug:void 0,"url-parse":56}],53:[function(t,e){e.exports="1.0.3"},{}],54:[function(t,e){e.exports="function"==typeof Object.create?function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:function(t,e){t.super_=e;var n=function(){};n.prototype=e.prototype,t.prototype=new n,t.prototype.constructor=t}},{}],55:[function(e,n,r){(function(e){(function(){function i(t,e){function n(t){if(n[t]!==m)return n[t];var i;if("bug-string-char-index"==t)i="a"!="a"[0];else if("json"==t)i=n("json-stringify")&&n("json-parse");else{var s,a='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if("json-stringify"==t){var u=e.stringify,c="function"==typeof u&&g;if(c){(s=function(){return 1}).toJSON=s;try{c="0"===u(0)&&"0"===u(new r)&&'""'==u(new o)&&u(b)===m&&u(m)===m&&u()===m&&"1"===u(s)&&"[1]"==u([s])&&"[null]"==u([m])&&"null"==u(null)&&"[null,null,null]"==u([m,b,null])&&u({a:[s,!0,!1,null,"\x00\b\n\f\r "]})==a&&"1"===u(null,s)&&"[\n 1,\n 2\n]"==u([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==u(new l(-864e13))&&'"+275760-09-13T00:00:00.000Z"'==u(new l(864e13))&&'"-000001-01-01T00:00:00.000Z"'==u(new l(-621987552e5))&&'"1969-12-31T23:59:59.999Z"'==u(new l(-1))}catch(f){c=!1}}i=c}if("json-parse"==t){var h=e.parse;if("function"==typeof h)try{if(0===h("0")&&!h(!1)){s=h(a);var d=5==s.a.length&&1===s.a[0];if(d){try{d=!h('" "')}catch(f){}if(d)try{d=1!==h("01")}catch(f){}if(d)try{d=1!==h("1.")}catch(f){}}}}catch(f){d=!1}i=d}}return n[t]=!!i}t||(t=u.Object()),e||(e=u.Object());var r=t.Number||u.Number,o=t.String||u.String,a=t.Object||u.Object,l=t.Date||u.Date,c=t.SyntaxError||u.SyntaxError,f=t.TypeError||u.TypeError,h=t.Math||u.Math,d=t.JSON||u.JSON;"object"==typeof d&&d&&(e.stringify=d.stringify,e.parse=d.parse);var p,v,m,y=a.prototype,b=y.toString,g=new l(-0xc782b5b800cec);try{g=-109252==g.getUTCFullYear()&&0===g.getUTCMonth()&&1===g.getUTCDate()&&10==g.getUTCHours()&&37==g.getUTCMinutes()&&6==g.getUTCSeconds()&&708==g.getUTCMilliseconds()}catch(w){}if(!n("json")){var x="[object Function]",_="[object Date]",E="[object Number]",j="[object String]",T="[object Array]",S="[object Boolean]",O=n("bug-string-char-index");if(!g)var C=h.floor,A=[0,31,59,90,120,151,181,212,243,273,304,334],N=function(t,e){return A[e]+365*(t-1970)+C((t-1969+(e=+(e>1)))/4)-C((t-1901+e)/100)+C((t-1601+e)/400)};if((p=y.hasOwnProperty)||(p=function(t){var e,n={};return(n.__proto__=null,n.__proto__={toString:1},n).toString!=b?p=function(t){var e=this.__proto__,n=t in(this.__proto__=null,this);return this.__proto__=e,n}:(e=n.constructor,p=function(t){var n=(this.constructor||e).prototype;return t in this&&!(t in n&&this[t]===n[t])}),n=null,p.call(this,t)}),v=function(t,e){var n,r,i,o=0;(n=function(){this.valueOf=0}).prototype.valueOf=0,r=new n;for(i in r)p.call(r,i)&&o++;return n=r=null,o?v=2==o?function(t,e){var n,r={},i=b.call(t)==x;for(n in t)i&&"prototype"==n||p.call(r,n)||!(r[n]=1)||!p.call(t,n)||e(n)}:function(t,e){var n,r,i=b.call(t)==x;for(n in t)i&&"prototype"==n||!p.call(t,n)||(r="constructor"===n)||e(n);(r||p.call(t,n="constructor"))&&e(n)}:(r=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],v=function(t,e){var n,i,o=b.call(t)==x,a=!o&&"function"!=typeof t.constructor&&s[typeof t.hasOwnProperty]&&t.hasOwnProperty||p;for(n in t)o&&"prototype"==n||!a.call(t,n)||e(n);for(i=r.length;n=r[--i];a.call(t,n)&&e(n));}),v(t,e)},!n("json-stringify")){var k={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},I="000000",P=function(t,e){return(I+(e||0)).slice(-t)},L="\\u00",R=function(t){for(var e='"',n=0,r=t.length,i=!O||r>10,o=i&&(O?t.split(""):t);r>n;n++){var s=t.charCodeAt(n);switch(s){case 8:case 9:case 10:case 12:case 13:case 34:case 92:e+=k[s];break;default:if(32>s){e+=L+P(2,s.toString(16));break}e+=i?o[n]:t.charAt(n)}}return e+'"'},U=function(t,e,n,r,i,o,s){var a,u,l,c,h,d,y,g,w,x,O,A,k,I,L,M;try{a=e[t]}catch(q){}if("object"==typeof a&&a)if(u=b.call(a),u!=_||p.call(a,"toJSON"))"function"==typeof a.toJSON&&(u!=E&&u!=j&&u!=T||p.call(a,"toJSON"))&&(a=a.toJSON(t));else if(a>-1/0&&1/0>a){if(N){for(h=C(a/864e5),l=C(h/365.2425)+1970-1;N(l+1,0)<=h;l++);for(c=C((h-N(l,0))/30.42);N(l,c+1)<=h;c++);h=1+h-N(l,c),d=(a%864e5+864e5)%864e5,y=C(d/36e5)%24,g=C(d/6e4)%60,w=C(d/1e3)%60,x=d%1e3}else l=a.getUTCFullYear(),c=a.getUTCMonth(),h=a.getUTCDate(),y=a.getUTCHours(),g=a.getUTCMinutes(),w=a.getUTCSeconds(),x=a.getUTCMilliseconds();a=(0>=l||l>=1e4?(0>l?"-":"+")+P(6,0>l?-l:l):P(4,l))+"-"+P(2,c+1)+"-"+P(2,h)+"T"+P(2,y)+":"+P(2,g)+":"+P(2,w)+"."+P(3,x)+"Z"}else a=null;if(n&&(a=n.call(e,t,a)),null===a)return"null";if(u=b.call(a),u==S)return""+a;if(u==E)return a>-1/0&&1/0>a?""+a:"null";if(u==j)return R(""+a);if("object"==typeof a){for(I=s.length;I--;)if(s[I]===a)throw f();if(s.push(a),O=[],L=o,o+=i,u==T){for(k=0,I=a.length;I>k;k++)A=U(k,a,n,r,i,o,s),O.push(A===m?"null":A);M=O.length?i?"[\n"+o+O.join(",\n"+o)+"\n"+L+"]":"["+O.join(",")+"]":"[]"}else v(r||a,function(t){var e=U(t,a,n,r,i,o,s);e!==m&&O.push(R(t)+":"+(i?" ":"")+e)}),M=O.length?i?"{\n"+o+O.join(",\n"+o)+"\n"+L+"}":"{"+O.join(",")+"}":"{}";return s.pop(),M}};e.stringify=function(t,e,n){var r,i,o,a;if(s[typeof e]&&e)if((a=b.call(e))==x)i=e;else if(a==T){o={};for(var u,l=0,c=e.length;c>l;u=e[l++],a=b.call(u),(a==j||a==E)&&(o[u]=1));}if(n)if((a=b.call(n))==E){if((n-=n%1)>0)for(r="",n>10&&(n=10);r.length<n;r+=" ");}else a==j&&(r=n.length<=10?n:n.slice(0,10));return U("",(u={},u[""]=t,u),i,o,r,"",[])}}if(!n("json-parse")){var M,q,D=o.fromCharCode,W={92:"\\",34:'"',47:"/",98:"\b",116:" ",110:"\n",102:"\f",114:"\r"},J=function(){throw M=q=null,c()},B=function(){for(var t,e,n,r,i,o=q,s=o.length;s>M;)switch(i=o.charCodeAt(M)){case 9:case 10:case 13:case 32:M++;break;case 123:case 125:case 91:case 93:case 58:case 44:return t=O?o.charAt(M):o[M],M++,t;case 34:for(t="@",M++;s>M;)if(i=o.charCodeAt(M),32>i)J();else if(92==i)switch(i=o.charCodeAt(++M)){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:t+=W[i],M++;break;case 117:for(e=++M,n=M+4;n>M;M++)i=o.charCodeAt(M),i>=48&&57>=i||i>=97&&102>=i||i>=65&&70>=i||J();t+=D("0x"+o.slice(e,M));break;default:J()}else{if(34==i)break;for(i=o.charCodeAt(M),e=M;i>=32&&92!=i&&34!=i;)i=o.charCodeAt(++M);t+=o.slice(e,M)}if(34==o.charCodeAt(M))return M++,t;J();default:if(e=M,45==i&&(r=!0,i=o.charCodeAt(++M)),i>=48&&57>=i){for(48==i&&(i=o.charCodeAt(M+1),i>=48&&57>=i)&&J(),r=!1;s>M&&(i=o.charCodeAt(M),i>=48&&57>=i);M++);if(46==o.charCodeAt(M)){for(n=++M;s>n&&(i=o.charCodeAt(n),i>=48&&57>=i);n++);n==M&&J(),M=n}if(i=o.charCodeAt(M),101==i||69==i){for(i=o.charCodeAt(++M),(43==i||45==i)&&M++,n=M;s>n&&(i=o.charCodeAt(n),i>=48&&57>=i);n++);n==M&&J(),M=n}return+o.slice(e,M)}if(r&&J(),"true"==o.slice(M,M+4))return M+=4,!0;if("false"==o.slice(M,M+5))return M+=5,!1;if("null"==o.slice(M,M+4))return M+=4,null;J()}return"$"},G=function(t){var e,n;if("$"==t&&J(),"string"==typeof t){if("@"==(O?t.charAt(0):t[0]))return t.slice(1);if("["==t){for(e=[];t=B(),"]"!=t;n||(n=!0))n&&(","==t?(t=B(),"]"==t&&J()):J()),","==t&&J(),e.push(G(t));return e}if("{"==t){for(e={};t=B(),"}"!=t;n||(n=!0))n&&(","==t?(t=B(),"}"==t&&J()):J()),(","==t||"string"!=typeof t||"@"!=(O?t.charAt(0):t[0])||":"!=B())&&J(),e[t.slice(1)]=G(B());return e}J()}return t},F=function(t,e,n){var r=H(t,e,n);r===m?delete t[e]:t[e]=r},H=function(t,e,n){var r,i=t[e];if("object"==typeof i&&i)if(b.call(i)==T)for(r=i.length;r--;)F(i,r,n);else v(i,function(t){F(i,t,n)});return n.call(t,e,i)};e.parse=function(t,e){var n,r;return M=0,q=""+t,n=G(B()),"$"!=B()&&J(),M=q=null,e&&b.call(e)==x?H((r={},r[""]=n,r),"",e):n}}}return e.runInContext=i,e}var o="function"==typeof t&&t.amd,s={"function":!0,object:!0},a=s[typeof r]&&r&&!r.nodeType&&r,u=s[typeof window]&&window||this,l=a&&s[typeof n]&&n&&!n.nodeType&&"object"==typeof e&&e;if(!l||l.global!==l&&l.window!==l&&l.self!==l||(u=l),a&&!o)i(u,a);else{var c=u.JSON,f=u.JSON3,h=!1,d=i(u,u.JSON3={noConflict:function(){return h||(h=!0,u.JSON=c,u.JSON3=f,c=f=null),d}});u.JSON={parse:d.parse,stringify:d.stringify}}o&&t(function(){return d})}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],56:[function(t,e){"use strict";function n(t,e,u){if(!(this instanceof n))return new n(t,e,u);var l,c,f,h,d=s.test(t),p=typeof e,v=this,m=0;for("object"!==p&&"string"!==p&&(u=e,e=null),u&&"function"!=typeof u&&(u=o.parse),e=i(e);m<a.length;m++)c=a[m],l=c[0],h=c[1],l!==l?v[h]=t:"string"==typeof l?~(f=t.indexOf(l))&&("number"==typeof c[2]?(v[h]=t.slice(0,f),t=t.slice(f+c[2])):(v[h]=t.slice(f),t=t.slice(0,f))):(f=l.exec(t))&&(v[h]=f[1],t=t.slice(0,t.length-f[0].length)),v[h]=v[h]||(c[3]||"port"===h&&d?e[h]||"":""),c[4]&&(v[h]=v[h].toLowerCase());u&&(v.query=u(v.query)),r(v.port,v.protocol)||(v.host=v.hostname,v.port=""),v.username=v.password="",v.auth&&(c=v.auth.split(":"),v.username=c[0]||"",v.password=c[1]||""),v.href=v.toString()}var r=t("requires-port"),i=t("./lolcation"),o=t("querystringify"),s=/^\/(?!\/)/,a=[["#","hash"],["?","query"],["//","protocol",2,1,1],["/","pathname"],["@","auth",1],[0/0,"host",void 0,1,1],[/\:(\d+)$/,"port"],[0/0,"hostname",void 0,1,1]];n.prototype.set=function(t,e,n){var i=this;return"query"===t?("string"==typeof e&&(e=(n||o.parse)(e)),i[t]=e):"port"===t?(i[t]=e,r(e,i.protocol)?e&&(i.host=i.hostname+":"+e):(i.host=i.hostname,i[t]="")):"hostname"===t?(i[t]=e,i.port&&(e+=":"+i.port),i.host=e):"host"===t?(i[t]=e,/\:\d+/.test(e)&&(e=e.split(":"),i.hostname=e[0],i.port=e[1])):i[t]=e,i.href=i.toString(),i},n.prototype.toString=function(t){t&&"function"==typeof t||(t=o.stringify);var e,n=this,r=n.protocol+"//";return n.username&&(r+=n.username,n.password&&(r+=":"+n.password),r+="@"),r+=n.hostname,n.port&&(r+=":"+n.port),r+=n.pathname,n.query&&(e="object"==typeof n.query?t(n.query):n.query,r+=("?"===e.charAt(0)?"":"?")+e),n.hash&&(r+=n.hash),r},n.qs=o,n.location=i,e.exports=n},{"./lolcation":57,querystringify:58,"requires-port":59}],57:[function(t,e){(function(n){"use strict";var r,i={hash:1,query:1};e.exports=function(e){e=e||n.location||{},r=r||t("./");var o,s={},a=typeof e;if("blob:"===e.protocol)s=new r(unescape(e.pathname),{});else if("string"===a){s=new r(e,{});for(o in i)delete s[o]}else if("object"===a)for(o in e)o in i||(s[o]=e[o]);return s}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./":56}],58:[function(t,e,n){"use strict";function r(t){for(var e,n=/([^=?&]+)=([^&]*)/g,r={};e=n.exec(t);r[decodeURIComponent(e[1])]=decodeURIComponent(e[2]));return r}function i(t,e){e=e||"";var n=[];"string"!=typeof e&&(e="?");for(var r in t)o.call(t,r)&&n.push(encodeURIComponent(r)+"="+encodeURIComponent(t[r]));return n.length?e+n.join("&"):""}var o=Object.prototype.hasOwnProperty;n.stringify=i,n.parse=r},{}],59:[function(t,e){"use strict";e.exports=function(t,e){if(e=e.split(":")[0],t=+t,!t)return!1;switch(e){case"http":case"ws":return 80!==t;case"https":case"wss":return 443!==t;case"ftp":return 22!==t;case"gopher":return 70!==t;case"file":return!1}return 0!==t}},{}]},{},[1])(1)});
!function(t,s,e){"use strict";var i=function(t,s){var i=this;this.el=t,this.options={},Object.keys(r).forEach(function(t){i.options[t]=r[t]}),Object.keys(s).forEach(function(t){i.options[t]=s[t]}),this.isInput="input"===this.el.tagName.toLowerCase(),this.attr=this.options.attr,this.showCursor=!this.isInput&&this.options.showCursor,this.elContent=this.attr?this.el.getAttribute(this.attr):this.el.textContent,this.contentType=this.options.contentType,this.typeSpeed=this.options.typeSpeed,this.startDelay=this.options.startDelay,this.backSpeed=this.options.backSpeed,this.backDelay=this.options.backDelay,this.fadeOut=this.options.fadeOut,this.fadeOutClass=this.options.fadeOutClass,this.fadeOutDelay=this.options.fadeOutDelay,e&&this.options.stringsElement instanceof e?this.stringsElement=this.options.stringsElement[0]:this.stringsElement=this.options.stringsElement,this.strings=this.options.strings,this.strPos=0,this.arrayPos=0,this.stopNum=0,this.loop=this.options.loop,this.loopCount=this.options.loopCount,this.curLoop=0,this.stop=!1,this.cursorChar=this.options.cursorChar,this.shuffle=this.options.shuffle,this.sequence=[],this.build()};i.prototype={constructor:i,init:function(){var t=this;t.timeout=setTimeout(function(){for(var s=0;s<t.strings.length;++s)t.sequence[s]=s;t.shuffle&&(t.sequence=t.shuffleArray(t.sequence)),t.typewrite(t.strings[t.sequence[t.arrayPos]],t.strPos)},t.startDelay)},build:function(){var t=this;if(this.showCursor===!0&&(this.cursor=s.createElement("span"),this.cursor.className="typed-cursor",this.cursor.innerHTML=this.cursorChar,this.el.parentNode&&this.el.parentNode.insertBefore(this.cursor,this.el.nextSibling)),this.stringsElement){this.strings=[],this.stringsElement.style.display="none";var e=Array.prototype.slice.apply(this.stringsElement.children);e.forEach(function(s){t.strings.push(s.innerHTML)})}this.init()},typewrite:function(t,s){if(this.stop!==!0){this.fadeOut&&this.el.classList.contains(this.fadeOutClass)&&(this.el.classList.remove(this.fadeOutClass),this.cursor.classList.remove(this.fadeOutClass));var e=Math.round(70*Math.random())+this.typeSpeed,i=this;i.timeout=setTimeout(function(){var e=0,r=t.substr(s);if("^"===r.charAt(0)){var o=1;/^\^\d+/.test(r)&&(r=/\d+/.exec(r)[0],o+=r.length,e=parseInt(r)),t=t.substring(0,s)+t.substring(s+o)}if("html"===i.contentType){var n=t.substr(s).charAt(0);if("<"===n||"&"===n){var a="",h="";for(h="<"===n?">":";";t.substr(s+1).charAt(0)!==h&&(a+=t.substr(s).charAt(0),s++,!(s+1>t.length)););s++,a+=h}}i.timeout=setTimeout(function(){if(s===t.length){if(i.options.onStringTyped(i.arrayPos),i.arrayPos===i.strings.length-1&&(i.options.callback(),i.curLoop++,i.loop===!1||i.curLoop===i.loopCount))return;i.timeout=setTimeout(function(){i.backspace(t,s)},i.backDelay)}else{0===s&&i.options.preStringTyped(i.arrayPos);var e=t.substr(0,s+1);i.attr?i.el.setAttribute(i.attr,e):i.isInput?i.el.value=e:"html"===i.contentType?i.el.innerHTML=e:i.el.textContent=e,s++,i.typewrite(t,s)}},e)},e)}},backspace:function(t,s){var e=this;if(this.stop!==!0){if(this.fadeOut)return void this.initFadeOut();var i=Math.round(70*Math.random())+this.backSpeed;e.timeout=setTimeout(function(){if("html"===e.contentType&&">"===t.substr(s).charAt(0)){for(var i="";"<"!==t.substr(s-1).charAt(0)&&(i-=t.substr(s).charAt(0),s--,!(s<0)););s--,i+="<"}var r=t.substr(0,s);e.replaceText(r),s>e.stopNum?(s--,e.backspace(t,s)):s<=e.stopNum&&(e.arrayPos++,e.arrayPos===e.strings.length?(e.arrayPos=0,e.shuffle&&(e.sequence=e.shuffleArray(e.sequence)),e.init()):e.typewrite(e.strings[e.sequence[e.arrayPos]],s))},i)}},initFadeOut:function(){return self=this,this.el.className+=" "+this.fadeOutClass,this.cursor.className+=" "+this.fadeOutClass,setTimeout(function(){self.arrayPos++,self.replaceText(""),self.typewrite(self.strings[self.sequence[self.arrayPos]],0)},self.fadeOutDelay)},replaceText:function(t){this.attr?this.el.setAttribute(this.attr,t):this.isInput?this.el.value=t:"html"===this.contentType?this.el.innerHTML=t:this.el.textContent=t},shuffleArray:function(t){var s,e,i=t.length;if(i)for(;--i;)e=Math.floor(Math.random()*(i+1)),s=t[e],t[e]=t[i],t[i]=s;return t},reset:function(){var t=this;clearInterval(t.timeout);this.el.getAttribute("id");this.el.textContent="","undefined"!=typeof this.cursor&&"undefined"!=typeof this.cursor.parentNode&&this.cursor.parentNode.removeChild(this.cursor),this.strPos=0,this.arrayPos=0,this.curLoop=0,this.options.resetCallback()}},i["new"]=function(t,e){var r=Array.prototype.slice.apply(s.querySelectorAll(t));r.forEach(function(t){var s=t._typed,r="object"==typeof e&&e;s&&s.reset(),t._typed=s=new i(t,r),"string"==typeof e&&s[e]()})},e&&(e.fn.typed=function(t){return this.each(function(){var s=e(this),r=s.data("typed"),o="object"==typeof t&&t;r&&r.reset(),s.data("typed",r=new i(this,o)),"string"==typeof t&&r[t]()})}),t.Typed=i;var r={strings:["These are the default values...","You know what you should do?","Use your own!","Have a great day!"],stringsElement:null,typeSpeed:0,startDelay:0,backSpeed:0,shuffle:!1,backDelay:500,fadeOut:!1,fadeOutClass:"typed-fade-out",fadeOutDelay:500,loop:!1,loopCount:!1,showCursor:!0,cursorChar:"|",attr:null,contentType:"html",callback:function(){},preStringTyped:function(){},onStringTyped:function(){},resetCallback:function(){}}}(window,document,window.jQuery);
window.faZepto = Zepto;
window.googletag = window.googletag || {};
googletag.cmd = googletag.cmd || [];
if (detection.is.pc && window.top !== window.self) {
var keydownFn = function(e) {
// space and arrow keys
if ([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1
&& !(typeof e.target == 'object' && e.target instanceof HTMLInputElement)) {
e.preventDefault();
}
};
window.removeEventListener("keydown", keydownFn, false);
window.addEventListener("keydown", keydownFn, false);
}
/* eslint-disable max-params */
fg_api.prototype.adsModule = function() {
var self = this,
M;
function module() {
this.GAM_TEST_ADUNIT = "test-adx-for-games-video";
this.closeCallback = function() {};
// flag if the last ad request was filled
this.adDidLoad = false;
// flag if the last ad generated an impression
this.adDidShow = false;
// time in millis when the last ad was shown
this.lastAdCall = +self.now();
this.defaultReturnValue = {
"adType": "interstitial",
"adRequested": false,
"adDidLoad": false,
"adDidShow": false,
"adCount": 0,
"adRequestCount": 0,
"adImpressionCount": 0
};
this.click2play_triggered = false;
this.currentAdRequestReturnValue = {};
}
module.prototype.init = function() {
self.log("Famobi Ads Module Initializing");
self.config.ads = faZepto.extend(
{
off:
window.famobi_env === "vp" ||
self.config.gameParams.ad_type === "off",
show_initial: false,
show_video: false,
debug: false
},
self.config.ads
);
if (!M.isEnabled()) {
M.provider = "none";
} else {
M.provider = self.config.ads.provider;
}
M.adRequestCount = 0;
M.adImpressionCount = 0;
M.floodProtectionMap = {};
if (self.config.gameParams.show_initial === false) {
M.show_initial = false;
//M.adRequestCount = 0;
} else {
M.show_initial = self.config.ads.show_initial && !self.config.ads.off;
}
M.show_video = self.config.ads.show_video;
switch (M.provider) {
case "a4g":
case "aerserv":
case "redpm":
case "dfp":
// halt the loading of the game until showAd() callback is fired.
self.game.setWaiting(!self.config.ads.off);
M.dfp_network_code = "37336410";
if (self.config.ads.mcm_network_code &&
detection.is.iframe &&
!self.config.is_own_inventory) {
M.dfp_network_code += "," + self.config.ads.mcm_network_code;
M.mcm_required = true;
}
M.gam_sizes_mode = 0;
M.gam_demand_source = 0;
//M.dfp_ad_unit_code =
// "/41567730/InGameInterstitial//" + self.config.aid + "//d0";
faZepto.getScript(
(self.debug || self.config.ads.debug)
? "https://imasdk.googleapis.com/js/sdkloader/ima3_debug.js"
: "https://imasdk.googleapis.com/js/sdkloader/ima3.js",
sdkLoadedCallback,
function() {
self.log("failed to load ima sdk");
sdkLoadedCallback();
}
);
break;
case "custom":
// halt the loading of the game until showAd() callback is fired.
self.game.setWaiting(!self.config.ads.off);
// no external scripts neccessary
if (typeof sdkLoadedCallback == "function") {
sdkLoadedCallback();
}
break;
case "none":
self.config.ads.off = true;
// eslint-disable-next-line no-fallthrough
default:
// no external scripts neccessary
if (typeof sdkLoadedCallback == "function") {
sdkLoadedCallback();
}
break;
}
function sdkLoadedCallback() {
if (typeof google != "undefined" && google.ima) {
google.ima.settings.setLocale(
self.gametranslation.getNavigatorLanguage()
);
google.ima.settings.setVpaidMode(
google.ima.ImaSdkSettings.VpaidMode.ENABLED
);
google.ima.settings.setDisableFlashAds(true);
}
var showInitialAd = function() {
if (!self.config.ads.off)
self.click2play.showOverlay(function() {
function continueToGame() {
self.click2play.closeOverlay();
if (self.game.isWaiting()) {
self.game.setWaiting(false);
self.game.init();
}
}
if (M.show_initial) {
if (self.adapters.run("ads", "show", continueToGame, true)) {
return;
}
if (self.interstitial && self.interstitial.isEnabled()) {
self.log("ads module: attempt to load interstitial instead");
self.interstitial.showAd(continueToGame);
} else {
M.showVideoAd(continueToGame, true);
}
} else {
continueToGame();
}
}, true, true);
};
var geoReadyCallback = function() {
showInitialAd();
};
if (M.provider === "dfp") {
self.lsg.ready().then(
function() {
geoReadyCallback(self.lsg.getLocale());
},
function() {
self.geo
.getCountryCode()
.then(geoReadyCallback, geoReadyCallback);
}
);
} else if (M.provider === "sulvo") {
M.forceAd();
} else {
showInitialAd();
}
}
};
module.prototype.getAdCount = function() {
return +M.adRequestCount;
};
module.prototype.showVideoAd = function(callback, force, isAutoplay = false) {
var isInitialAd = (M.adRequestCount == 0);
if (!isInitialAd)
self.spinner.show();
try {
if (isInitialAd && M.show_initial) {
self.fullscreen.start();
}
} catch (error) {
self.log(error);
}
self.game.pause();
switch (M.provider) {
case "a4g":
case "aerserv":
case "redpm":
case "dfp":
M.showIMA(function() {
try {
self.orientation.lock();
} catch (error) {
self.log(error);
}
M.fireAdCallback(true);
self.game.resume();
}, force, !isInitialAd, isAutoplay);
break;
default:
callback();
break;
}
};
module.prototype.showAd = function(callback, force, click2play_triggered) {
if (self.adapters.run("ads", "show", callback, force)) {
return false;
}
M.closeCallback = callback;
if (M.delayNextAdModal(force)) {
if (typeof callback == "function")
callback.call(null);
return false;
}
switch (M.provider) {
case "dfp":
// click2play already triggered
// for example: by closing the highscore overlay
if (click2play_triggered) {
return M.showIMA(callback, force);
}
if (detection.is.ios)
self.click2play.showOverlay(function() {
function continueToGame(result) {
self.click2play.closeOverlay();
if (typeof callback == "function")
callback.call(null, result);
}
if (self.interstitial && self.interstitial.isEnabled()) {
self.log("ads module: attempt to load web interstitial instead of video ad");
self.interstitial.showAd(continueToGame);
} else {
M.showVideoAd(continueToGame, force);
}
}, false, false);
else {
if (self.interstitial && self.interstitial.isEnabled()) {
self.log("ads module: attempt to load web interstitial instead of video ad");
self.interstitial.showAd(callback);
} else {
M.showVideoAd(callback, force, true);
}
}
return;
case "blocker":
return M.showBlocker(callback, force);
default:
return M.fireAdCallback(false);
}
};
module.prototype.showInterstitialAd = function(isFlooded) {
return new Promise(function(resolve, reject) {
if (isFlooded) {
resolve();
}
if (self.adapters.run("ads", "show", null, true)) {
reject();
}
M.showAd(function() {
resolve();
});
});
};
module.prototype.forceAd = function(callback) {
if (self.adapters.run("ads", "show", callback, true)) {
return false;
}
return M.showAd(callback, true);
};
module.prototype.showAlsoLikedApps = function(callback, force) {
var opts = {
force: !!force,
iframeAllowed: true,
min_s_between: 0,
returnCallback: function() {},
title: self.__("api.people_also_like_headline")
};
if (!M.isEnabled()) {
self.log("ads disabled");
M.fireAdCallback(false);
return false;
}
if (M.delayNextAdModal(force)) {
M.fireAdCallback(false);
return false;
}
var backupApps = [
{
id: "famobi/fruita-crush",
name: "Fruita Crush",
thumb:
"https://img.cdn.famobi.com/portal/html5games/images/tmp/180/FruitaCrushTeaser.jpg"
},
{
id: "famobi/solitaire-classic",
name: "Solitaire Classic",
thumb:
"https://img.cdn.famobi.com/portal/html5games/images/tmp/180/SolitaireClassicTeaser.jpg"
},
{
id: "famobi/smarty-bubbles-xmas",
name: "Smarty Bubbles X-MAS EDITION",
thumb:
"https://img.cdn.famobi.com/portal/html5games/images/tmp/180/SmartyBubblesXmasTeaser.jpg"
},
{
id: "famobi/jewelish",
name: "Jewelish",
thumb:
"https://img.cdn.famobi.com/portal/html5games/images/tmp/180/Jewelish_Teaser.jpg"
},
{
id: "famobi/archery-world-tour",
name: "Archery World Tour",
thumb:
"https://img.cdn.famobi.com/portal/html5games/images/tmp/180/ArcheryWorldTourTeaser.jpg"
},
{
id: "famobi/penalty-shooters-2",
name: "Penalty Shooters 2",
thumb:
"https://img.cdn.famobi.com/portal/html5games/images/tmp/180/PenaltyShooters2Teaser.jpg"
},
{
id: "famobi/wedding-lily",
name: "Wedding Lily",
thumb:
"https://img.cdn.famobi.com/portal/html5games/images/tmp/180/WeddingLilyTeaser.jpg"
}
];
function listApps(apps) {
apps = apps || backupApps;
if (!apps.length) {
apps = backupApps;
}
var ulNode = self.createElement("ul");
apps.slice(0, 4).forEach(function(app) {
var liNode = self.createElement("li");
var parts = app.id.split("/");
var gameID = parts[1];
var aNode = self.createElement("a", {
href: "javascript:;",
"data-xhref":
"https://play.famobi.com/" +
gameID +
"/" +
self.config.aid +
"?original_ref=" +
encodeURIComponent(self.getShortLink()),
title: app.name,
target: "_blank"
});
var imgHolderNode = self.createElement("div", {
class: "fg-notify-imgHolder"
});
var imgNode = self.createElement("img", { src: app.thumb });
imgHolderNode.appendChild(imgNode);
aNode.appendChild(imgHolderNode);
liNode.appendChild(aNode);
ulNode.appendChild(liNode);
});
self.notify.create(opts);
self.notify.setContent(ulNode);
self.notify.setCloseCallback(callback);
}
listApps(self.config.gameParams.related);
};
module.prototype.getPriceRuleName = function() {
return M.priceRule && M.priceRule.name ? M.priceRule.name : "";
};
module.prototype.setPriceRule = function(name, value) {
if (typeof name === "object") {
value = name.value;
name = name.name;
}
return (M.priceRule = {
name: "" + name,
value: +value
});
};
module.prototype.showIMA = function(callback, force, controlSpinner = false, isAutoplay = false) {
if (
!M.initAdModal({
returnCallback: function() {
M.fireAdCallback();
},
force: force,
iframeAllowed: self.config.ads.dfp_available
})
) {
return false;
}
self.modal.setCloseCallback(function() {
if (M.adsManager) {
M.adsManager.destroy();
}
});
// @see https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/quickstart
M.adContainerElement = document.createElement("div");
M.adContainerElement.className = "fg-ad-container";
M.adContainerElement.style.zIndex = "9999990";
M.adContainerElement.style.margin = "0 auto 0";
M.adContainerElement.setAttribute("playsinline", "true");
self.rootElement.appendChild(M.adContainerElement);
M.adWidth = parseInt(window.innerWidth, 10);
M.adHeight = parseInt(window.innerHeight, 10);
M.adContainerElement.setAttribute("width", M.adWidth);
M.adContainerElement.setAttribute("height", M.adHeight);
M.adContainerElement.style.width = M.adWidth + "px";
M.adContainerElement.style.height = M.adHeight + "px";
try {
M.showAdModal(
{
overlayStyle: {
background: "transparent"
},
returnCallback: callback,
width: M.adWidth,
height: M.adHeight
},
M.adContainerElement
);
M.adDisplayContainer = new google.ima.AdDisplayContainer(
M.adContainerElement
);
M.adsLoader = new google.ima.AdsLoader(M.adDisplayContainer);
M.adsLoader.getSettings().setDisableFlashAds(true);
M.adsLoader
.getSettings()
.setDisableCustomPlaybackForIOS10Plus(true);
M.adDisplayContainer.initialize();
} catch (reason) {
if (self.debug) {
self.log(reason);
}
self.click2play.closeOverlay();
self.modal.close();
/*if (typeof google === "undefined" && detection.is.pc) {
var btn = faZepto("<div><h1 style='font-weight:normal;color:#647999; text-align: center; padding: 30px 0 10px 0 !important;'>Please disable your AdBlocker on this site to play our games!<img src='//games.cdn.famobi.com/html5games/gameapi/CandyInTears.png' alt='' style='margin: 0 auto; display: block; width: 270px; margin-top: 20px;'></h1><span style='display:inline-block;padding:15px;border:5px solid #647999;font-weight:bold; color: #647999;'>Done? Refresh this page.</span><br><br><span style='color:#647999; display: block; margin-bottom: 30px; opacity: 0.8;'><strong>Why?</strong> Some functionality is incorrectly blocked by AdBlockers</span><iframe src='//giphy.com/embed/RL6gd7A8xvLYA' width='320' height='246' frameBorder='0' allowFullScreen></iframe></div>").appendTo("body").css({"display": "block !important", "position": "absolute", "top": "0", "bottom": "0", "color": "#333", "width": "100%", "cursor": "pointer", "font-size": "14px", "background-color": "#d1f6ff", "overflow-y": "scroll", "font-family": "Helvetica, Arial, sans-serif", "text-align": "center", "z-index": self.rand(900000, 999999)});
self.handleClick(btn.get(0), function() {
window.location.reload();
});
setTimeout(function() {
btn.remove();
}, 15E3);
}*/
if (self.game.isWaiting()) {
self.game.setWaiting(false);
self.game.init();
}
return M.showAlsoLikedApps(callback);
}
if (controlSpinner)
self.spinner.show();
// self.game.hideCanvas();
module.prototype.onAdsManagerLoaded = function(adsManagerLoadedEvent) {
var adsRenderingSettings = new google.ima.AdsRenderingSettings();
adsRenderingSettings.enablePreloading = true;
adsRenderingSettings.loadVideoTimeout = 15e3;
// Get the ads manager.
M.adsManager = adsManagerLoadedEvent.getAdsManager(
M.adContainerElement,
adsRenderingSettings
);
// Listen to any additional events, if necessary.
faZepto.each(
[
"LOADED",
"IMPRESSION",
"STARTED",
"SKIPPABLE_STATE_CHANGED",
"FIRST_QUARTILE",
"MIDPOINT",
"THIRD_QUARTILE",
"USER_CLOSE",
"SKIPPED",
"COMPLETE",
"ALL_ADS_COMPLETED",
"DURATION_CHANGE",
"CONTENT_RESUME_REQUESTED",
"CONTENT_PAUSE_REQUESTED",
"LOG"
],
function(key, value) {
M.adsManager.addEventListener(
google.ima.AdEvent.Type[value],
M.onAdEvent
);
}
);
M.adsManager.init(
M.adWidth,
M.adHeight,
google.ima.ViewMode.NORMAL
);
M.adsManager.start();
};
module.prototype.onAdEvent = function(adEvent) {
var ad = adEvent.getAd();
self.log(adEvent);
switch (adEvent.type) {
case google.ima.AdEvent.Type.LOADED:
M.adDidLoad = true;
M.adImpressionCount++;
self.adapters.run("adEvent", "loaded", ad);
if (ad.isLinear() && M.adsManager.getRemainingTime() > 0) {
self.modal.setCloseBtnTimer(15);
}
faZepto(self.modal.overlay).css("background", "#000");
break;
case google.ima.AdEvent.Type.IMPRESSION:
M.adDidShow = true;
break;
case google.ima.AdEvent.Type.STARTED:
M.adDidLoad = true;
if (ad.isLinear() && M.adsManager.getRemainingTime() > 0) {
//self.tracking.trackEvent("Ad event", "DFP Video", adEvent.type);
} else {
//self.tracking.trackEvent("Ad event", "DFP", adEvent.type);
}
if (controlSpinner)
self.spinner.hide();
self.modal.clearCloseBtnTimer();
self.modal.activateCloseBtn(false);
break;
case google.ima.AdEvent.Type.DURATION_CHANGE:
M.delayNextAdModal(true);
break;
case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
self.click2play.closeOverlay();
break;
case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:
case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:
faZepto(self.modal.overlay).css(
"background",
"transparent"
);
if (controlSpinner)
self.spinner.hide();
// self.game.showCanvas();
self.modal.close();
break;
}
switch (adEvent.type) {
case google.ima.AdEvent.Type.STARTED:
self.adapters.run("adEvent", "displayed");
break;
case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:
self.adapters.run("adEvent", "completed", M.adRequestCount);
break;
case google.ima.AdEvent.Type.SKIPPED:
self.adapters.run("adEvent", "skipped");
break;
case google.ima.AdEvent.Type.USER_CLOSE:
self.adapters.run("adEvent", "userClosed", M.adRequestCount);
break;
}
};
module.prototype.onAdError = function(adErrorEvent) {
//self.tracking.trackEvent("Ad error event", "DFP", adErrorEvent.getError());
var adError = adErrorEvent.getError();
self.log(adError);
self.adapters.run("adEvent", "errored", adErrorEvent);
function closeAndResume() {
self.modal.close();
if (M.adsManager) {
M.adsManager.destroy();
}
if (controlSpinner)
self.spinner.hide();
}
if (adError.getType() == google.ima.AdError.Type.AD_LOAD) {
self.log("ads module: ad load error detected");
// // try to show web interstitial instead, if error was fillrate related
// if (M.adRequestCount >= 1 &&
// self.interstitial &&
// self.interstitial.isEnabled() &&
// self.interstitial.hasCooledDown()) {
// self.log("ads module: attempt to load interstitial instead");
// return self.interstitial.showAd(closeAndResume, false);
// }
}
closeAndResume();
};
// Add event listeners
M.adsLoader.addEventListener(
google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
M.onAdsManagerLoaded,
false
);
M.adsLoader.addEventListener(
google.ima.AdErrorEvent.Type.AD_ERROR,
M.onAdError,
false
);
var adsRequest = new google.ima.AdsRequest();
adsRequest.disableCompanionAds = true;
// Specify the linear and nonlinear slot sizes. This helps the SDK to
// select the correct creative if multiple are returned.
adsRequest.linearAdSlotWidth = parseInt(M.adWidth, 10);
adsRequest.linearAdSlotHeight = parseInt(M.adHeight, 10);
// 2015-10-29
// Force Full-Slot ad rendering
// Games publishers (mandatory):
// When using overlay ads with gaming content, you must ensure that all creative sizes are rendered with the Full-Slot interface by manually setting adsrequest.forceNonLinearFullSlot to true. This is required to comply with AdSense and Ad Exchange Policies.
adsRequest.forceNonLinearFullSlot = true;
adsRequest.nonLinearAdSlotWidth = parseInt(M.adWidth, 10);
adsRequest.nonLinearAdSlotHeight = parseInt(M.adHeight, 10);
adsRequest.contentDuration = 20 * 60;
adsRequest.contentTitle = document.title;
adsRequest.vastLoadTimeout = 10e3;
adsRequest.setAdWillAutoPlay(isAutoplay);
function sendAdRequest(custParamsQS, vastSizeString, requestType, adUnit) {
let myAdTagUrl = M.getAdTagUrl("", "", custParamsQS, vastSizeString, requestType, adUnit);
adsRequest.adTagUrl = myAdTagUrl;
M.adsLoader.requestAds(adsRequest);
M.adRequestCount += 1;
M.adDidLoad = false;
M.adDidShow = false;
M.show_initial = false;
};
// add-in UAM bidding, if enabled
if (self.apstag && self.apstag.isReadyToFetch()) {
// check supported GAM & APS video sizes
let supportedSizes = [
{w:640, h:480}, {w:400, h:300}, {w:320, h:480}
];
supportedSizes = supportedSizes.filter(function(size) {
// remove sizes not fitting in window
return size.w <= window.innerWidth && size.h <= window.innerHeight;
}).map(function(size){
// add area of creative
return {w: size.w, h: size.h, area: size.w * size.h};
}).sort(function(a, b){
// sort by area desc
return b.area - a.area;
});
// fallback to default size in case of no fit
if (supportedSizes.length == 0)
supportedSizes = [{w:640, h:480}];
// get APS video slot ID for biggest size
supportedSizes = supportedSizes.slice(0, 1);
let apsSlotID = self.apstag.getVideoSlotID(supportedSizes[0].w, supportedSizes[0].h);
// create VAST string of ad unit sizes
let vastSizeString = supportedSizes.reduce(function(str, size, index){
return str + (index > 0 ? "|" : "") + size.w + "x" + size.h;
}, "");
self.apstag.fetchVideoBids(apsSlotID)
.then(function(bids) {
self.log("video ads: append bid params to ad request")
sendAdRequest(bids[0].qsParams, vastSizeString, 'adxfgv-uamv');
}, function() {
self.log("video ads: failed to prefetch bids, will send std request instead")
sendAdRequest();
});
} else {
sendAdRequest();
}
};
module.prototype.getAdVastXML = function() {
var xml = self.config.adsVastXML;
var newAd = self.config.adTagXML;
var adTagUrls = [];
// Get XML with waterfall extension
return new Promise(function(resolve, reject) {
if (M.provider === "dfp") {
var rules = (function() {
var lsgRules = self.lsg.exportRules();
var sorted = [];
if (self.lsg.isSamplingAllRules()) {
sorted = self.shuffleArray(lsgRules).slice(0, 3);
} else {
sorted = lsgRules.sort(function(a, b) {
return b[1] - a[1];
});
}
var ruleNames = [];
faZepto.each(sorted, function(key, rule) {
ruleNames.push(rule[0]);
});
return ruleNames;
})();
var nbRules = 0;
var variant = "a";
var priceMode = "lsg-o";
var waterfallNumber = 0;
rules = rules.filter(function(x, i, a) {
return a.indexOf(x) == i;
});
self.log(rules);
nbRules = self.sizeOf(rules);
faZepto.each(rules, function(key, ruleName) {
var perRulePriceMode = priceMode;
M.setPriceRule(ruleName);
// last rule? add backfill
if (key === nbRules - 1) {
variant = "b";
}
if (self.lsg.isSamplingAllRules()) {
perRulePriceMode = (Math.random() < 0.5) ? "lsg-sf" : "lsg-s";
}
adTagUrls.push(M.getAdTagUrl(variant, perRulePriceMode));
if (!detection.is.iframe && key == 0) {
adTagUrls.push(M.getAdTagUrl("", ""));
}
adTagUrls.push(M.getAdTagUrl(variant, perRulePriceMode));
adTagUrls.push(M.getAdTagUrl(variant, perRulePriceMode));
});
// put it all together in one VAST Ad Tag
faZepto.each(adTagUrls, function(index, url) {
newAd = self.config.adTagXML;
newAd = newAd.replace("[index]", index + 1);
newAd = newAd.replace("[fallback_index]", index);
newAd = newAd.replace("[vast_ad_tag_url]", url);
xml += newAd + "\n";
});
xml += "</VAST>";
return resolve(xml);
} else {
return reject(
"Provider not supported, only (DFP): " + M.provider
);
}
});
};
module.prototype.getAdTagUrl = function(variant, priceMode, customParamsQueryString, sizeString, requestType, adUnit) {
variant = variant || "";
priceMode = priceMode || "";
customParamsQueryString = customParamsQueryString || "";
sizeString = sizeString || "640x480|400x300";
requestType = requestType || "adxfgv";
var myAdTagUrl = "";
var language = self.gametranslation.getNavigatorLanguage();
var locale = self.lsg.locale;
var vpos = (M.adRequestCount > 0) ? "midroll" : "preroll";
var descriptionUrl = self.config.ads.description_url;
var siteUrl = "";
if (detection.is.iframe) {
if (M.mcm_required) {
if (self.config.referrer_origin &&
!self.config.referrer_origin.endsWith("famobi.com"))
descriptionUrl = self.config.referrer_origin
else if (self.config.first_ancestor_origin &&
!self.config.first_ancestor_origin.endsWith("famobi.com"))
descriptionUrl = self.config.first_ancestor_origin
else if (self.config.last_ancestor_origin &&
!self.config.last_ancestor_origin.endsWith("famobi.com"))
descriptionUrl = self.config.last_ancestor_origin
else
descriptionUrl = self.getShortLink();
siteUrl = descriptionUrl;
} else {
siteUrl = self.getShortLink();
}
}
var gamePackageID = "" + (window.famobi_gameID || self.config.package_id);
if (gamePackageID.length == 0 || gamePackageID == "{FAMOBI_GAMEID}")
gamePackageID = "test-game";
M.dfp_custom_params = {
a: "" + self.config.aid,
game: gamePackageID,
gametype: "html5",
uuid: "" + self.config.uuid,
video: M.show_video ? "1" : "0",
arc:
M.adRequestCount > 20 ? "gt20" :
M.adRequestCount >= 10 ? "" + M.adRequestCount :
"0" + M.adRequestCount,
aic:
M.adImpressionCount > 20 ? "gt20" :
M.adImpressionCount >= 10 ? "" + M.adImpressionCount :
"0" + M.adImpressionCount
};
var paramPriceRuleName = M.getPriceRuleName();
if (paramPriceRuleName)
M.dfp_custom_params.pr = paramPriceRuleName;
if (priceMode)
M.dfp_custom_params.pm = priceMode;
if (variant)
M.dfp_custom_params.ab = variant;
M.dfp_custom_params.if = detection.is.iframe ? "1" : "0";
M.dfp_custom_params.rm = self.config.referrer_matched ? "1" : "0";
M.dfp_custom_params.rt = requestType;
// @see https://support.google.com/dfp_premium/answer/1068325?hl=de
myAdTagUrl =
"https://securepubads.g.doubleclick.net/gampad/ads?npa=[npa]&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&correlator=[timestamp]&ciu_szs=";
myAdTagUrl = myAdTagUrl.replace(
"[npa]",
self.config.ads.npa ? "1" : "0"
);
// myAdTagUrl = myAdTagUrl.replace(
// "[gdpr]",
// "0"
// );
var adUnitID = M.getAdUnitID(adUnit);
if (typeof adUnitID == 'string' && adUnitID.length > 0) {
myAdTagUrl = myAdTagUrl + "&iu=" + adUnitID;
}
myAdTagUrl = myAdTagUrl + "&sz=" + sizeString;
if (siteUrl != "") {
myAdTagUrl = myAdTagUrl + "&url=" + encodeURIComponent(siteUrl);
}
if (descriptionUrl != "") {
myAdTagUrl = myAdTagUrl + "&description_url=" + encodeURIComponent(descriptionUrl);
}
if (M.dfp_custom_params) {
var qs = faZepto.param(M.dfp_custom_params);
if (typeof customParamsQueryString == "string") {
if (qs.length > 0)
qs += customParamsQueryString;
else
qs = customParamsQueryString.substring(1);
}
myAdTagUrl += "&cust_params=" + encodeURIComponent(qs);
}
if (language != "") {
myAdTagUrl = myAdTagUrl + "&hl=" + language;
}
// if (locale != "") {
// myAdTagUrl = myAdTagUrl + "&cn=" + locale;
// }
if (vpos != "") {
myAdTagUrl = myAdTagUrl + "&vpos=" + vpos;
}
//if (M.adRequestCount == 0) {
//myAdTagUrl = myAdTagUrl + "&vpa=click";
//}
// overwrite ad tag in debugmode
if (self.config.ads.debug) {
myAdTagUrl = "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=";
if (vpos != "") {
myAdTagUrl = myAdTagUrl + "&vpos=" + vpos;
}
if (M.adRequestCount == 0) {
myAdTagUrl = myAdTagUrl + "&vpa=click";
}
}
return myAdTagUrl;
};
module.prototype.getVastTagUrl = function() {
self.adapters.run("ads", "vastUrl");
return new Promise(function(resolve) {
var vast_url = M.getAdTagUrl();
if (self.config.ads.vast_url) {
vast_url = self.config.ads.vast_url;
vast_url = vast_url.replace(
/\[UA\]/,
encodeURIComponent(navigator.userAgent)
);
vast_url = vast_url.replace(
/\[URL\]/,
encodeURIComponent(self.config.ads.description_url)
);
vast_url = vast_url.replace(
/\[DEVICECATEGORY\]/,
detection.is.tablet ? "tablet" : "phone"
);
vast_url = vast_url.replace(
/\[CACHEBUSTER\]/,
self.rand(100000, 999999)
);
resolve(vast_url);
} else {
resolve(vast_url);
}
});
};
module.prototype.initAdModal = function(options) {
var opts = faZepto.extend(
{
iframeAllowed: false,
force: false,
returnCallback: function() {}
},
options
);
// regard timeout between ads
if (M.delayNextAdModal(opts.force)) {
self.modal.setCloseCallback(opts.returnCallback);
return false;
}
return true;
};
module.prototype.showAdModal = function(options, contentDiv) {
var opts = faZepto.extend(
{
mode: "seamless",
closeBtnTimer: 15,
faketime: 3,
showCloseBtn: false,
returnCallback: function() {},
returnCallback2: function() {
var retVal = faZepto.extend(
{},
M.defaultReturnValue,
{
"adDidLoad": M.adDidLoad,
"adDidShow": M.adDidShow,
"adCount": M.adRequestCount - 1,
"adRequestCount": M.adRequestCount - 1
}
);
self.adapters.run("ads", "callback", retVal);
M.delayNextAdModal(true);
self.click2play.closeOverlay();
if (self.game.isWaiting()) {
self.game.setWaiting(false);
self.game.init();
}
if (self.lsg.is_active)
self.lsg.remix({
lastRequestWas: M.adDidLoad ? "fill" : "nofill"
});
}
},
options
);
M.delayNextAdModal(true);
self.modal.create(opts);
self.modal.updateCloseBtn(true);
self.modal.setCloseBtnTimer(opts.closeBtnTimer, {
faketime: opts.faketime
});
self.modal.setDimensions(opts.width, opts.height);
self.modal.setContent(contentDiv);
self.modal.setCloseCallback(opts.returnCallback);
self.modal.setCloseCallback(opts.returnCallback2);
return self;
};
module.prototype.delayNextAdModal = function(isSetter) {
// check if Ads are enabled
if (!M.isEnabled()) {
self.log("ads disabled");
return true;
}
// disable all Ads for X seconds
if (isSetter) {
M.lastAdCall = self.now();
} else if (!M.hasCooledDown()) {
self.log("skipped ad");
return true;
}
return false;
};
module.prototype.hasCooledDown = function() {
var min_s_between =
M.adRequestCount === 0 && +self.config.ads.min_s_before > 0
? +self.config.ads.min_s_before
: +self.config.ads.min_s_between;
var ret = self.now() - min_s_between * 1000 > M.lastAdCall;
return ret;
};
module.prototype.isAdvertisingActive = function(opts) {
if (!opts.iframeAllowed && window.top !== window.self) {
self.log("ads disabled in <iframe>");
return false;
}
return true;
};
module.prototype.isNthAdvertising = function(n) {
return +M.adRequestCount % n === 0;
};
module.prototype.lastAdCallWasNsecondsAgo = function(n) {
return self.now() - n * 1000 >= M.lastAdCall;
};
module.prototype.fireAdCallback = function(afterRequest) {
if (typeof M.closeCallback == "function") {
var retVal = faZepto.extend(
{},
M.defaultReturnValue,
{
"adDidLoad": M.adDidLoad,
"adDidShow": M.adDidShow,
"adCount": M.adRequestCount - (afterRequest ? 1 : 0),
"adRequestCount": M.adRequestCount - (afterRequest ? 1 : 0)
}
);
M.closeCallback.apply(self, [retVal]);
}
M.closeCallback = function() {};
};
module.prototype.isEnabled = function() {
return self.hasFeature("ads") && !self.config.ads.off;
};
module.prototype.floodProtect = function(eventName, delay) {
if (M.floodProtectionMap[eventName]) {
return true;
}
M.floodProtectionMap[eventName] = setTimeout(function() {
M.floodProtectionMap[eventName] = undefined;
}, delay);
return false;
};
module.prototype.getAdUnitID = function(adUnit) {
// select test ad unit in debug mode when no unit is defined
if ((self.debug || self.config.ads.debug) &&
!(typeof adUnit == 'string' && adUnit.length > 0)) {
adUnit = M.GAM_TEST_ADUNIT;
}
// create GAM ad unit ID (=path)
var adUnitID = "/" + M.dfp_network_code + "/" +
((typeof adUnit == 'string' && adUnit.length > 0) ?
adUnit :
("InGameInterstitial//" + self.config.aid + "//d0"));
return adUnitID;
}
M = new module();
M.init();
return M;
};
// show ad programmatically
// eslint-disable-next-line no-unused-vars
fg_api.prototype.showAd = function(callback, force, click2play_triggered) {
if (this.ads.floodProtect("Show Ad", 1e3)) {
if (typeof callback == "function")
callback(this.ads.defaultReturnValue);
return;
}
this.ads.showAd.apply(this, arguments);
};
fg_api.prototype.forceAd = function(callback) {
if (this.ads.floodProtect("Force Ad", 1e3)) {
if (typeof callback == "function") callback();
return;
}
this.ads.forceAd(callback);
};
fg_api.prototype.showInterstitialAd = function(eventId, callback) {
let params = {};
if(typeof eventId === "object") {
params = eventId;
} else {
params.callback = typeof eventId === "function" ? eventId : typeof callback === "function" ? callback : undefined;
params.eventId = typeof eventId === "string" ? eventId : typeof callback === "string" ? callback : undefined;
}
if(typeof params.callback === "function") {
params.callback();
}
return Promise.resolve();
// return this.ads.showInterstitialAd(this.ads.floodProtect("Interstitial Ad", 1e3));
};
fg_api.prototype.showTeaser = function(callback) {
if (this.ads.floodProtect("Teaser Ad", 1e3)) {
if (typeof callback == "function") callback();
return;
}
this.ads.showAlsoLikedApps(callback);
};
fg_api.prototype.rewardedadsModule = function() {
var self = this,
M;
function module() {
// number of consecutive failed preloads before timeout
this.NUM_MAX_FAILED_PRELOADS = 3;
// time to wait for next preload after multiple preloads failed
this.TIMEOUT_AFTER_FAILED_PRELOADS = 6e4;
// max time to wait for preload to finish
this.TIMEOUT_BEFORE_PRELOAD_CANCELLED = 5e3;
// time to wait for related gpt events after the first closing event
this.TIMEOUT_GPT_CLOSING_EVENTS = 100;
// time to wait before next preload is triggered after current ad closed
this.TIMEOUT_NEXT_PRELOAD = 1e3;
// time to wait between consecutive rewarded ad calls
this.TIMEOUT_FLOOD_PROTECTION = 1e3;
this.closeCallback = function() {};
// flag if the last ad request was filled
this.adDidLoad = false;
// flag if the last ad generated an impression
this.adDidShow = false;
// time in millis when the last ad was shown
this.lastAdCall = 0;
this.adCount = 0;
this.floodProtectionMap = {};
this.dfp_ad_unit_code = "";
this.gptInitialized = false;
this.rewardedAd = {
oldSlots: [],
slot: undefined,
event: undefined,
state: undefined,
rewardGranted: false,
preloadPromiseResolve: function(){},
preloadPromiseReject: function(){},
preloadPromise: undefined,
playPromiseResolve: function(){},
playPromiseReject: function(){},
playPromise: undefined
};
this.defaultReturnValue = {
"adType": "rewarded",
"adDidLoad": false,
"adDidShow": false,
"adCount": 0,
"rewardGranted": false
};
this.showAdActive = false;
this.preloadFailCount = 0;
this.preloadBlocked = false;
}
// enum to keep track of current ad slot state in GPT api
module.prototype.states = {
"PRELOADING": 1,
"READY": 2,
"PLAYING": 3,
"CLOSING": 4,
"FAILED": 5
};
module.prototype.init = function() {
// use google's predefined rewarded ad unit for local debugging
// use Famobi interstitial ad units on staging and production
// (optional) todo: setup new ad units for rewarded ads in reporting system
var urlParams = self.getUrlParams();
if (urlParams.fg_env && (urlParams.fg_env == "dev")) {
M.dfp_ad_unit_code = "/22639388115/rewarded_web_example"
} else {
M.dfp_ad_unit_code = "/37336410/InGameInterstitial//" + self.config.aid + "//d0";
}
if (self.hasFeature("rewarded")) {
faZepto.getScript(
"//securepubads.g.doubleclick.net/tag/js/gpt.js",
gptLoadedCallback,
function() {
self.log("failed to load google publisher tag library");
}
);
}
function gptLoadedCallback() {
// Make sure that googletag.cmd exists
// see https://developers.google.com/doubleclick-gpt/common_implementation_mistakes
window.googletag = window.googletag || {};
googletag.cmd = googletag.cmd || [];
// initialize gpt event handlers when library is ready
window.googletag.cmd.push(function() {
M.gptInitialized = true;
window.googletag
.pubads()
.setRequestNonPersonalizedAds(
self.config.ads.npa ? 1 : 0
);
setupGPTEventListeners()
M.preloadRewardedAd().catch(function(err){
self.log("rewarded ads: initial preload failed.", err);
});
});
}
function setupGPTEventListeners() {
// handle event: ad available, can be shown
window.googletag.pubads().addEventListener(
"rewardedSlotReady",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored rewardedSlotReady event");
return;
}
self.log("rewarded slot ready");
M.rewardedAd.event = evt;
M.rewardedAd.state = M.states.READY;
M.adDidLoad = true;
M.rewardedAd.preloadPromiseResolve(evt);
}
);
// handle event: user clicked close button in ad
window.googletag.pubads().addEventListener(
"rewardedSlotClosed",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored rewardedSlotClosed event");
return;
}
self.log("rewarded slot closed");
M.initiateClosing();
}
);
// // handle event: user canceled ad, no reward
// // attention! seems like this is called even if the user is granted
// // a reward. so don't use for reward determination atm.
// window.googletag.pubads().addEventListener(
// "rewardedSlotCanceled",
// function() {
// self.log("rewarded slot canceled");
// M.adDidShow = true;
// M.initiateClosing();
// }
// );
// handle event: user is granted reward
window.googletag.pubads().addEventListener(
"rewardedSlotGranted",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored rewardedSlotGranted event");
return;
}
self.log("rewarded slot granted");
M.rewardedAd.rewardGranted = true;
//M.initiateClosing();
}
);
// // handle event: video completed
// window.googletag.pubads().addEventListener(
// "rewardedSlotCompleted",
// function() {
// self.log("rewarded ad video completed");
// }
// );
// This event is fired when the creative code is injected into a slot,
// before(!) the creative's resources are fetched.
window.googletag.pubads().addEventListener(
"slotRenderEnded",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored slotRenderEnded event");
return;
}
self.log("rewarded slot render ended");
if (evt.isEmpty) {
self.log("No ad returned.");
M.rewardedAd.preloadPromiseReject();
}
}
);
window.googletag.pubads().addEventListener(
"slotResponseReceived",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored slotResponseReceived event");
return;
}
self.log("slot responce received", evt);
}
);
window.googletag.pubads().addEventListener(
"slotRequested",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored slotRequested event");
return;
}
self.log("slot requested", evt);
}
);
// This event is fired when the creative's iframe fires its load event.
window.googletag.pubads().addEventListener(
"slotOnload",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored slotOnload event");
return;
}
self.log("slot on load", evt);
}
);
window.googletag.pubads().addEventListener(
"slotAdded",
function(evt) {
if (evt.slot !== M.rewardedAd.slot) {
self.log("rewarded: ignored slotAdded event");
return;
}
self.log("slot added", evt);
}
);
}
};
module.prototype.initiateClosing = function() {
self.log("initiateClosing called");
if (M.rewardedAd.state == M.states.closing)
return;
M.rewardedAd.state = M.states.closing;
// wait for related gpt events to be triggered
// todo: remove delay once the event flow is predictable
self.wait(M.TIMEOUT_GPT_CLOSING_EVENTS).then(function() {
M.rewardedAd.playPromiseResolve();
});
};
module.prototype.destroyOldSlots = function() {
if (M.rewardedAd.oldSlots.length > 0) {
window.googletag.cmd.push(function() {
window.googletag.destroySlots(M.rewardedAd.oldSlots)
? self.log("destroyed rewarded ad slots")
: self.log("failed to destroy rewarded ad slots");
M.rewardedAd.oldSlots = [];
});
}
};
module.prototype.reset = function() {
self.log("reset called");
M.closeCallback = function(){};
M.adDidLoad = false;
M.adDidShow = false;
M.rewardedAd.slot = undefined;
M.rewardedAd.event = undefined;
M.rewardedAd.state = undefined;
M.rewardedAd.rewardGranted = false;
M.rewardedAd.preloadPromiseResolve = function(){};
M.rewardedAd.preloadPromiseReject = function(){};
M.rewardedAd.preloadPromise = undefined;
M.rewardedAd.playPromiseResolve = function(){};
M.rewardedAd.playPromiseReject = function(){};
M.rewardedAd.playPromise = undefined;
M.showAdActive = false;
};
module.prototype.isEnabled = function() {
return self.hasFeature("ads") && self.hasFeature("rewarded") && !self.config.ads.off;
};
module.prototype.hasAd = function() {
return M.isEnabled() && (M.rewardedAd.state == M.states.READY);
};
module.prototype.showAd = function(callback) {
if (self.adapters.run("ads", "rewarded", callback)) {
return false;
}
// cancel when
// - show ad already in progress
// - rewarded feature is disabled
// - gpt api is not initialized
// instead run callback with default parameters to prevent blocking
if (M.showAdActive || !M.isEnabled() || !M.gptInitialized) {
if (typeof callback == "function") {
callback(M.defaultReturnValue);
}
return false;
}
M.showAdActive = true;
M.closeCallback = callback;
self.spinner.show();
self.game.pause();
// fallback: preload first, if rewarded ad is not available
M.preloadRewardedAd()
.then(function() {
self.log("rewarded ads: preload succeeded.");
self.spinner.hide();
return M.playRewardedAd()
})
.then(function(){
self.log("rewarded ads: ad shown.");
return Promise.resolve();
})
.catch(function(err) {
self.log("rewarded ad failed", err);
self.spinner.hide();
})
.then(function(){
if (M.rewardedAd.slot)
M.rewardedAd.oldSlots.push(M.rewardedAd.slot);
if (M.showAdActive) {
M.fireAdCallback();
self.game.resume();
}
M.reset();
// trigger next preload after delay
// alert: we setup a new slot first and destroy previous ones afterwards, otherwise gpt events may fail to work
self.wait(M.TIMEOUT_NEXT_PRELOAD).then(function(){
M.preloadRewardedAd().catch(function(err){
self.log("rewarded ads: auto preload failed.", err);
});
M.destroyOldSlots();
});
})
};
module.prototype.playRewardedAd = function() {
if (M.rewardedAd.state != M.states.READY || !M.rewardedAd.event) {
return Promise.reject(new Error("invalid state after preload"));
}
M.rewardedAd.playPromise = new Promise(function(resolve, reject) {
// store resolve & reject for use in gpt event handlers
M.rewardedAd.playPromiseResolve = resolve;
M.rewardedAd.playPromiseReject = reject;
M.rewardedAd.state = M.states.PLAYING;
M.adCount++;
setTimeout(function(){
try {
M.rewardedAd.event.makeRewardedVisible();
M.adDidShow = true;
} catch (err) {
self.log("makeRewardedVisible failed", err);
reject(new Error("failed to make rewarded ad visible"));
}
}, 250);
// setup timeout in case gpt is stalled / network connection lost
/*self.wait(6e4).then(function() {
reject(new Error("show cancelled: timeout while waiting for gpt events"));
});*/
});
return M.rewardedAd.playPromise;
};
module.prototype.configureRewardedSlot = function() {
window.googletag.cmd.push(function() {
M.rewardedAd.slot = window.googletag
.defineOutOfPageSlot(
M.dfp_ad_unit_code,
window.googletag.enums.OutOfPageFormat.REWARDED
)
.addService(window.googletag.pubads())
.setTargeting("a", "" + self.config.aid)
.setTargeting("game", "" + window.famobi_gameID)
.setTargeting("gametype", "html5")
.setTargeting("video", "1")
.setTargeting("uuid", "" + self.config.uuid)
.setTargeting("adcount",
M.adCount > 20 ? "gt20" : M.adCount >= 10 ? "" + M.adCount : "0" + M.adCount
).setTargeting("adinterval",
M.lastAdCall > 0 ? "" + (Math.floor((self.now() - M.lastAdCall)/10000)*10) : ""
)
.setTargeting("rt", "adxfcr")
.setTargeting("if", detection.is.iframe ? "1" : "0");
// report preload as time of ad request
M.lastAdCall = self.now();
// enable services after slot setup & targeting to avoid race conditions
// see https://developers.google.com/doubleclick-gpt/common_implementation_mistakes#scenario-5:-mis-ordering-calls-to-gpt
if (!window.googletag.pubadsReady) {
//window.googletag.pubads().enableAsyncRendering();
window.googletag.enableServices();
self.log("enabled & initialized gpt services");
}
});
};
module.prototype.preloadRewardedAd = function() {
if (!M.gptInitialized)
return Promise.reject(new Error("preload cancelled: gpt not initialized"));
// prevent preload while ad is still active
if (M.rewardedAd.state == M.states.PLAYING || M.rewardedAd.state == M.states.CLOSING) {
return Promise.reject(new Error("preload cancelled: previous ad still active"));
}
// return current preloader promise if new ad is already requested
if (M.rewardedAd.state == M.states.PRELOADING || M.rewardedAd.state == M.states.READY) {
if (M.rewardedAd.preloadPromise instanceof Promise)
return M.rewardedAd.preloadPromise;
else
return Promise.reject(new Error("preload faulty: missing current preloader promise"));
}
// enable temporary preload block if too many attempts failed
if (M.preloadFailCount > M.NUM_MAX_FAILED_PRELOADS && !M.preloadBlocked) {
M.preloadBlocked = true;
self.wait(M.TIMEOUT_AFTER_FAILED_PRELOADS).then(function(){
M.preloadFailCount = 0;
M.preloadBlocked = false;
})
}
// apply block
if (M.preloadBlocked) {
return Promise.reject(new Error("preload cancelled: too many failed attempts"));
}
// initiate new preload promise if no ad requested or shown
M.rewardedAd.preloadPromise = new Promise(function(resolve, reject) {
// store resolve & reject for use in gpt event handlers
M.rewardedAd.preloadPromiseResolve = resolve;
M.rewardedAd.preloadPromiseReject = reject;
M.rewardedAd.state = M.states.PRELOADING;
// setup slot, request ad - gpt event handlers will handle the response
window.googletag.cmd.push(function() {
M.configureRewardedSlot();
window.googletag.display(M.rewardedAd.slot);
});
// setup timeout in case gpt is stalled / network connection lost
self.wait(M.TIMEOUT_BEFORE_PRELOAD_CANCELLED).then(function() {
reject(new Error("preload cancelled: timeout while waiting for gpt events"));
});
})
// handle failed preloads
// do not reset callbacks here
M.rewardedAd.preloadPromise.catch(function(){
M.rewardedAd.preloadPromise = undefined;
M.rewardedAd.preloadPromiseResolve = function(){};
M.rewardedAd.preloadPromiseReject = function(){};
M.rewardedAd.oldSlots.push(M.rewardedAd.slot);
M.rewardedAd.slot = undefined;
M.rewardedAd.state = undefined;
M.preloadFailCount += 1;
});
return M.rewardedAd.preloadPromise;
};
module.prototype.hasCooledDown = function() {
var min_s_between =
M.adCount === 0 && +self.config.ads.min_s_before > 0
? +self.config.ads.min_s_before
: +self.config.ads.min_s_between;
var ret = self.now() - min_s_between * 1000 > M.lastAdCall;
return ret;
};
module.prototype.fireAdCallback = function() {
if (typeof M.closeCallback == "function") {
var retVal = faZepto.extend(
{},
M.defaultReturnValue,
{
"adDidLoad": M.adDidLoad,
"adDidShow": M.adDidShow,
"adCount": M.adCount,
"rewardGranted": M.rewardedAd.rewardGranted
}
);
self.adapters.run("ads", "callback", retVal);
M.closeCallback(retVal);
}
};
module.prototype.floodProtect = function(eventName, delay) {
if (M.floodProtectionMap[eventName]) {
return true;
}
M.floodProtectionMap[eventName] = setTimeout(function() {
M.floodProtectionMap[eventName] = undefined;
}, delay);
return false;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.preloadRewardedAd = function() {
return this.rewardedads.preloadRewardedAd();
};
fg_api.prototype.hasRewardedAd = function() {
return this.rewardedads.hasAd();
};
fg_api.prototype.rewardedAd = function(callback) {
if (this.rewardedads.floodProtect("Rewarded Ad", this.rewardedads.TIMEOUT_FLOOD_PROTECTION)) {
if (typeof callback == "function")
callback(this.rewardedads.defaultReturnValue);
return false;
}
return this.rewardedads.showAd(callback);
};
fg_api.prototype.interstitialModule = function () {
var self = this,
M;
function module() {
// predefs
this.GAM_NETWORK_CODE = "37336410";
this.COOLDOWN_SEC = 120;
this.PRELOAD_DELAY_SEC = 15;
// properties
this.gptInitialized = false;
this.adUnitPath = "";
this.mcmRequired = false;
this.currentSlot = null;
this.oldSlots = [];
this.slotReadyEvent = null;
this.preloadEnabled = true;
this.preloadState = null;
this.closeCallback = null;
this.showAdActive = false;
this.numAdRequests = 0;
this.numAdFills = 0;
this.adDidLoad = false;
this.adDidShow = false;
this.lastShowAdCall = 0;
this.lastAdRequest = 0;
this.abTestEnabled = false;
this.inControlGroup = false;
this.defaultReturnValue = {
"adType": "interstitial",
"adDidLoad": false,
"adDidShow": false,
"adCount": 0
};
}
// enum to keep track of current ad slot state in GPT api
module.prototype.preloadStates = {
"PLANNED": 1,
"ACTIVE": 2,
"FINISHED": 3,
"FAILED_FILL": 4,
"FAILED_SLOT": 5,
"NONE": 6
};
module.prototype.init = function () {
// check if interstitials are supported & allowed
if (M.isEnabled()) {
faZepto.getScript(
"//securepubads.g.doubleclick.net/tag/js/gpt.js",
M.gptLoadedHandler,
function () {
self.log("failed to load google publisher tag library");
}
);
} else {
self.log("interstitial: ads disabled, initialization aborted")
return;
}
// determine ad unit path for ad requests
if (self.config.ads.mcm_network_code &&
detection.is.iframe &&
!self.config.ads.is_own_inventory) {
M.mcmRequired = true;
}
var urlParams = self.getUrlParams();
if (urlParams.fg_env && urlParams.fg_env == "dev") {
M.adUnitPath = "/6355419/Travel/Europe/France/Paris";
} else if (self.config.aid == "A1000-10") {
M.adUnitPath = "/" + M.GAM_NETWORK_CODE +
"/InGameInterstitial//" + self.config.aid + "//d0";
M.abTestEnabled = true;
M.inControlGroup = Math.random() < 0.5;
} else {
M.adUnitPath = "/" + M.GAM_NETWORK_CODE +
(M.mcmRequired ? ("," + self.config.ads.mcm_network_code) : "") +
"/InGameInterstitial//" + self.config.aid + "//d0";
}
};
module.prototype.gptLoadedHandler = function() {
window.googletag = window.googletag || {};
googletag.cmd = googletag.cmd || [];
// initialize gpt event handlers when library is ready
window.googletag.cmd.push(function () {
M.gptInitialized = true;
if (self.config.ads.npa) {
window.googletag
.pubads()
.setPrivacySettings({
nonPersonalizedAds: true
});
}
M.setupListeners();
self.log("interstitial: enabled & initialized");
M.schedulePreload(0);
});
};
module.prototype.setupListeners = function() {
// This event is fired when the creative code is injected into a slot,
// before(!) the creative's resources are fetched.
window.googletag
.pubads()
.addEventListener("slotRenderEnded", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("interstitial: ignored slotRenderEnded event");
return;
}
self.log("interstitial: slot render ended");
if (evt.isEmpty) {
self.log("interstitial: No ad returned.");
M.preloadState = M.preloadStates.FAILED_FILL;
if (M.showAdInProgress())
M.resumeGame();
return;
}
M.adDidLoad = true;
M.numAdFills += 1;
M.preloadState = M.preloadStates.FINISHED;
});
window.googletag
.pubads()
.addEventListener("slotResponseReceived", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("interstitial: ignored slotResponseReceived event");
return;
}
self.log("interstitial: slot responce received", evt);
});
window.googletag
.pubads()
.addEventListener("slotRequested", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("interstitial: ignored slotRequested event");
return;
}
self.log("interstitial: slot requested", evt);
});
// This event is fired when the creative's iframe fires its load event.
window.googletag.pubads().addEventListener("slotOnload", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("interstitial: ignored slotOnload event");
return;
}
self.log("interstitial: slot on load", evt);
});
window.googletag.pubads().addEventListener("slotAdded", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("interstitial: ignored slotAdded event");
return;
}
self.log("interstitial: slot added", evt);
});
window.googletag.pubads().addEventListener("gameManualInterstitialSlotReady", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("interstitial: ignored gameManualInterstitialSlotReady event");
return;
}
self.log("interstitial: slot ready", evt);
M.preloadState = M.preloadStates.FINISHED;
M.slotReadyEvent = evt;
if (M.showAdInProgress())
M.displayCreative();
});
window.googletag.pubads().addEventListener("gameManualInterstitialSlotClosed", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("interstitial: ignored gameManualInterstitialSlotClosed event");
return;
}
self.log("interstitial: slot closed", evt);
if (M.showAdInProgress())
M.resumeGame();
});
};
module.prototype.isEnabled = function () {
if (M.abTestEnabled && M.inControlGroup)
return false;
return (
self.hasFeature("ads") &&
!self.config.ads.off &&
window.famobi_env != "vp" &&
self.config.gameParams.ad_type != "off" &&
self.config.ads.show_interstitial
);
};
module.prototype.showAdInProgress = function () {
return M.showAdActive;
};
module.prototype.clearSlots = function () {
if (M.currentSlot) {
M.oldSlots.push(M.currentSlot);
M.currentSlot = null;
}
window.googletag.cmd.push(function() {
if (M.oldSlots.length > 0)
window.googletag.destroySlots(M.oldSlots);
});
};
module.prototype.hasSlot = function(slot) {
return (M.currentSlot == slot || M.oldSlots.includes(slot));
};
module.prototype.showAd = function(callback, managePauseState = true) {
var cancel = false;
// check early return conditions
if (!M.isEnabled()) {
self.log('interstitial: not enabled, showAd aborted');
cancel = true;
}
if (M.showAdInProgress()) {
self.log('interstitial: an ad is already in progress, showAd aborted');
cancel = true;
}
if (!M.hasCooledDown()) {
self.log('interstitial: cooldown active - showAd aborted');
cancel = true;
}
if (M.preloadState == M.preloadStates.PLANNED) {
self.log('interstitial: preload planned - showAd aborted');
cancel = true;
}
if (cancel) {
// run callback with default parameters to prevent blocking
M.fireCallback(callback);
return false;
}
M.managePauseState = managePauseState;
M.closeCallback = callback;
M.lastShowAdCall = self.now();
M.showAdActive = true;
if (M.managePauseState) {
self.game.pause();
self.spinner.show();
}
if (M.preloadState == M.preloadStates.NONE ||
M.preloadState == null ||
M.preloadState == M.preloadStates.FAILED_FILL) {
self.log('interstitial: no ad preloaded, initiate ad request');
M.requestAd();
} else if (M.preloadState == M.preloadStates.ACTIVE) {
self.log('interstitial: waiting for preload');
} else if (M.preloadState == M.preloadStates.FINISHED) {
self.log('interstitial: preloaded ad found, attempt to display');
M.displayCreative();
} else if (M.preloadState == M.preloadStates.FAILED_SLOT) {
self.log('interstitial: no slot created, showAd aborted');
M.resumeGame();
}
};
module.prototype.resumeGame = function() {
// bye bye sloty
self.log("interstitial: clean up slot");
M.clearSlots();
// resume game
self.log("interstitial: resume game");
if (M.managePauseState) {
self.game.resume();
self.spinner.hide();
}
M.showAdActive = false;
M.preloadState = M.preloadStates.NONE;
M.fireCloseCallback();
// time next preload
if (M.preloadEnabled) {
M.schedulePreload();
}
};
module.prototype.schedulePreload = function(delay) {
if (!M.preloadEnabled)
return;
if (delay === undefined) {
var requestCooldown = M.lastAdRequest + M.COOLDOWN_SEC * 1000;
var showAdCooldown = M.lastShowAdCall + M.PRELOAD_DELAY_SEC * 1000;
delay = Math.max(0, Math.max(requestCooldown, showAdCooldown) - self.now());
}
setTimeout(function() {
self.log("interstitial: timed preload starting")
M.requestAd();
}, delay);
M.preloadState = M.preloadStates.PLANNED;
self.log("interstitial: timed preload starting in", delay, "ms")
};
module.prototype.displayCreative = function() {
// show loaded creative
if (M.slotReadyEvent) {
M.slotReadyEvent.makeGameManualInterstitialVisible();
M.adDidShow = true;
M.slotReadyEvent = null;
self.log("interstitial: is active.");
} else {
self.log("interstitial: no slot ready event, interstitial failed, resume");
M.resumeGame();
}
};
module.prototype.requestAd = function() {
// init ad request related vars
M.adDidLoad = false;
M.adDidShow = false;
M.slotReadyEvent = null;
// clean previous ad slot remainder
M.clearSlots();
window.googletag.cmd.push(function () {
// create GPT out-of-page slot
M.currentSlot = window.googletag.defineOutOfPageSlot(M.adUnitPath, window.googletag.enums.OutOfPageFormat.GAME_MANUAL_INTERSTITIAL);
if (M.currentSlot) {
self.log('interstitial: slot created - waiting to be ready');
// setup slot
M.currentSlot.addService(googletag.pubads());
M.currentSlot.setTargeting("a", "" + self.config.aid)
.setTargeting("game", "" + window.famobi_gameID)
.setTargeting("gametype", "html5")
.setTargeting("webinterstitial", "1")
.setTargeting("uuid", "" + self.config.uuid)
.setTargeting("arc", "" + M.numAdRequests)
.setTargeting("aic", "" + M.numAdFills)
.setTargeting("rt", "adxfcgmi")
.setTargeting("if", detection.is.iframe ? "1" : "0");
if (!window.googletag.pubadsReady) {
window.googletag.enableServices();
self.log("enabled & initialized gpt services");
}
// trigger ad request
M.numAdRequests += 1;
M.preloadState = M.preloadStates.ACTIVE;
M.lastAdRequest = self.now();
window.googletag.display(M.currentSlot);
}
else {
// no ad slot created
self.log('interstitial: slot failed - page or device does not support interstitials');
M.preloadState = M.preloadStates.FAILED_SLOT;
if (M.showAdInProgress)
M.resumeGame();
}
});
};
module.prototype.fireCloseCallback = function() {
M.fireCallback(M.closeCallback)
M.closeCallback = null;
};
module.prototype.fireCallback = function(callback) {
if (typeof callback == "function") {
var retVal = faZepto.extend(
{},
M.defaultReturnValue,
{
"adDidLoad": M.adDidLoad,
"adDidShow": M.adDidShow,
"adCount": M.numAdRequests
}
);
callback.call(null, retVal);
}
};
module.prototype.hasCooledDown = function() {
return ((self.now() - M.COOLDOWN_SEC * 1000) > M.lastAdRequest) ||
(M.preloadState == M.preloadStates.FINISHED);
};
M = new module();
M.init();
return M;
};
fg_api.prototype.bannerModule = function () {
var self = this,
M;
function module() {
this.OUTER_CONTAINER_PREFIX = "fg-banner-outer";
this.INNER_CONTAINER_PREFIX = "fg-banner-inner";
this.SLOT_TYPE_KEY = "bannertype";
this.TYPES = ["top", "bottom", "left", "right"];
this.AD_UNIT_SIZES = {
top: [[320, 50], [320, 100]],
bottom: [[320, 50], [320, 100]],
left: [[120, 600], [160, 600]],
right: [[120, 600], [160, 600]]
};
this.CSS_FADE_IN = true;
this.CSS_FADE_OUT = true;
this.CSS_FADE_DURATION_MS = 600;
this.CSS_TRANS_BACKGROUND = true;
this.CSS_SHADOW = true;
this.WAIT_BEFORE_REFRESH_MS = 40000;
this.GAM_NETWORK_CODE = "37336410";
this.BASE_CONFIG = {
enabled: false,
top: {
enabled: false,
max_ratio: 0.6,
min_width: 300,
overlay: false
},
bottom: {
enabled: false,
max_ratio: 0.6,
min_width: 300,
overlay: false
},
left: {
enabled: false,
min_ratio: 1.3,
min_height: 600,
overlay: false
},
right: {
enabled: false,
min_ratio: 1.3,
min_height: 600,
overlay: false
}
};
this.lastAdCall = 0;
this.adRequestCount = 0;
this.adImpressionCount = 0;
this.adUnit = "";
this.gptInitialized = false;
this.showAdActive = false;
this.requestFailCount = 0;
this.requestBlocked = false;
this.bannerSizeLeft = 0;
this.bannerSizeTop = 0;
this.bannerSizeRight = 0;
this.bannerSizeBottom = 0;
this.support = {};
this.sizes = {};
this.containers = {};
this.slots = {};
this.refreshTimeout = {};
this.refreshAfter = {};
this.showAdIntervalID = 0;
this.adUnitPath = "";
this.mcmRequired = false;
this.refreshEnabled = true;
this.config = {};
this.forceBannerOff = false;
this.forceBannerOn = false;
}
module.prototype.init = function () {
// check if banners are supported & allowed
var urlParams = self.getUrlParams();
if (urlParams.fg_force_banner && urlParams.fg_force_banner == "0") {
this.forceBannerOff = true;
self.log("banner: ads disabled via URL param, initialization aborted")
return;
}
if (urlParams.fg_force_banner && urlParams.fg_force_banner == "1") {
this.forceBannerOn = true;
self.log("banner: ads enabled via URL param")
}
if (M.isEnabled()) {
faZepto.getScript(
"//securepubads.g.doubleclick.net/tag/js/gpt.js",
gptLoadedCallback,
function () {
self.log("failed to load google publisher tag library");
}
);
} else {
self.log("banner: ads disabled, initialization aborted")
return;
}
// determine ad unit path for ad requests
if (self.config.ads.mcm_network_code &&
detection.is.iframe &&
!self.config.is_own_inventory) {
M.mcmRequired = true;
}
if (urlParams.fg_env && urlParams.fg_env == "dev") {
M.adUnitPath = "/6355419/Travel/Europe";
} else {
M.adUnitPath = "/" + M.GAM_NETWORK_CODE +
(M.mcmRequired ? ("," + self.config.ads.mcm_network_code) : "") +
"/OnPage//" + self.config.aid + "//GamePage//Leaderboard";
}
// get banner config from gameparams (seeder)
M.parseBannerConfig();
// init props for all banner types
M.TYPES.forEach(function(type) {
M.support[type] = false;
M.sizes[type] = [];
M.containers[type] = null;
M.slots[type] = null;
M.refreshAfter[type] = null;
M.containers[type] = M.getContainerElement(type) || M.createContainerElement(type);
});
self.onorientationchange(M.viewportResizeHandler);
self.adapters.add("game", "loaded", function () {
if (!M.showAdIntervalID)
M.showAdIntervalID = setInterval(function(){
M.showAds();
}, M.WAIT_BEFORE_REFRESH_MS);
M.showAds();
});
function gptLoadedCallback() {
// Make sure that googletag.cmd exists
// see https://developers.google.com/doubleclick-gpt/common_implementation_mistakes
window.googletag = window.googletag || {};
googletag.cmd = googletag.cmd || [];
// initialize gpt event handlers when library is ready
window.googletag.cmd.push(function () {
M.gptInitialized = true;
if (self.config.ads.npa)
window.googletag
.pubads()
.setPrivacySettings({
nonPersonalizedAds: true
});
window.googletag.pubads().setCentering(false);
setupGPTEventListeners();
});
}
function setupGPTEventListeners() {
// This event is fired when the creative code is injected into a slot,
// before(!) the creative's resources are fetched.
window.googletag
.pubads()
.addEventListener("slotRenderEnded", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("banner: ignored slotRenderEnded event");
return;
}
self.log("banner: slot render ended");
if (evt.isEmpty) {
self.log("banner: No ad returned.");
}
var type = M.getSlotType(evt.slot);
M.refreshAfter[type] = Date.now() + M.WAIT_BEFORE_REFRESH_MS;
});
window.googletag
.pubads()
.addEventListener("slotResponseReceived", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("banner: ignored slotResponseReceived event");
return;
}
self.log("banner: slot responce received", evt);
});
window.googletag
.pubads()
.addEventListener("slotRequested", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("banner: ignored slotRequested event");
return;
}
self.log("banner: slot requested", evt);
});
// This event is fired when the creative's iframe fires its load event.
window.googletag.pubads().addEventListener("slotOnload", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("banner: ignored slotOnload event");
return;
}
self.log("banner: slot on load", evt);
if (M.CSS_FADE_IN) {
M.fadeInSlot(evt.slot);
}
});
window.googletag.pubads().addEventListener("slotAdded", function (evt) {
if (!M.hasSlot(evt.slot)) {
self.log("banner: ignored slotAdded event");
return;
}
self.log("banner: slot added", evt);
});
}
};
module.prototype.fadeInSlot = function(slot) {
if (!slot) {
self.log("banner: cannot fade in undefined slot");
return;
}
var type = M.getSlotType(slot);
var container = M.getContainerElement(type);
var innerContainer = M.getContainerElement(type, "inner");
//self.log("banner: attempt to change container CSS for fade in");
if (type == "top" || type == "bottom") {
if (!M.isOverlay(type)) {
container.style.transform = "translateY(0)";
container.style.display = "flex";
} else {
innerContainer.style.transform = "translateY(0)";
container.style.display = "flex";
}
}
if (type == "left" || type == "right") {
if (!M.isOverlay(type)) {
container.style.transform = "translateX(0)";
container.style.display = "flex";
} else {
innerContainer.style.transform = "translateX(0)";
container.style.display = "flex";
}
}
}
module.prototype.fadeOutSlot = function(slot) {
if (!slot) {
self.log("banner: cannot fade in undefined slot");
return;
}
var type = M.getSlotType(slot);
var container = M.getContainerElement(type);
var innerContainer = M.getContainerElement(type, "inner");
var transform;
//self.log("banner: attempt to change container CSS for fade out");
if (type == "top" || type == "bottom") {
transform = (type == "top") ? "translateY(-100%)" : "translateY(100%)";
if (!M.isOverlay(type)) {
container.style.transform = transform;
} else {
innerContainer.style.transform = transform;
}
}
if (type == "left" || type == "right") {
transform = (type == "left") ? "translateX(-100%)" : "translateX(100%)";
if (!M.isOverlay(type)) {
container.style.transform = transform;
} else {
innerContainer.style.transform = transform;
}
}
};
module.prototype.parseBannerConfig = function() {
// init config, all placements off
M.config = Object.assign({}, M.BASE_CONFIG);
// if exists, merge-in config from game params
if (typeof self.config.gameParams.banner == "object" && self.config.gameParams.banner.enabled) {
self.log("banner: found banner config in game params");
M.config.enabled = true;
var c = self.config.gameParams.banner;
var foundPlacement = false;
M.TYPES.forEach(function(type) {
if (typeof c[type] == "object") {
Object.assign(M.config[type], c[type]);
foundPlacement = true;
self.log("banner: placement update", type);
}
});
if (!foundPlacement) {
self.log("banner: no details given -> enabling default placements");
M.config.bottom.enabled = true;
M.config.right.enabled = true;
}
}
};
module.prototype.isEnabled = function() {
return (
M.forceBannerOn || (
self.hasFeature("ads") &&
(!!self.config.gameParams.banner_enabled || self.config.gameParams.banner && self.config.gameParams.banner.enabled) &&
!self.config.ads.off &&
window.famobi_env != "vp" &&
self.config.gameParams.ad_type != "off" &&
!!self.config.ads.show_banner &&
!M.forceBannerOff &&
self.config.is_own_inventory
)
);
};
module.prototype.getContainerID = function (type, depth) {
return ((depth == "inner") ? M.INNER_CONTAINER_PREFIX : M.OUTER_CONTAINER_PREFIX) + "-" + type;
};
module.prototype.getContainerElement = function(type, depth) {
var containerID = M.getContainerID(type, depth);
var container = document.getElementById(containerID);
//if (container)
// self.log(type + " banner container found:", containerID);
return container;
};
module.prototype.createContainerElement = function(type) {
var containerID = M.getContainerID(type);
var innerContainerID = M.getContainerID(type, "inner");
var containerStyle = "position: fixed; display: flex; z-index: 999; overflow: visible; user-select: none; ";
var innerContainerStyle = "";
var container, innerContainer;
var isFullContainer = !M.isOverlay(type);
if (type == "top" || type == "bottom"){
containerStyle += "width: 100%; flex-direction: row; justify-content: center; ";
innerContainerStyle = "width: min-content; max-height: 100px; ";
if (type == "top") {
if (isFullContainer) {
containerStyle += "height: min-content; ";
containerStyle += "align-items: center; ";
} else {
containerStyle += "height: 0; ";
containerStyle += "align-items: start; ";
}
containerStyle += "top: 0; ";
}
if (type == "bottom") {
if (isFullContainer) {
containerStyle += "height: min-content; ";
containerStyle += "align-items: center; ";
} else {
containerStyle += "height: 0; ";
containerStyle += "align-items: end; ";
}
containerStyle += "bottom: 0; ";
}
}
if (type == "left" || type == "right") {
containerStyle += "height: 100%; align-items: center; ";
innerContainerStyle = "height: min-content; max-width: 160px; ";
if (isFullContainer) {
containerStyle += "width: min-content; ";
} else {
containerStyle += "width: 0; ";
}
if (type == "left") {
if (isFullContainer) {
containerStyle += "justify-content: center; ";
} else {
containerStyle += "justify-content: left; ";
}
containerStyle += "left: 0; ";
}
if (type == "right") {
if (isFullContainer) {
containerStyle += "justify-content: center; ";
} else {
containerStyle += "justify-content: right; ";
}
containerStyle += "right: 0; ";
}
}
if (M.CSS_FADE_IN) {
var fadeCSS = "";
if (type == "bottom")
fadeCSS += "transform: translateY(100%); ";
if (type == "top")
fadeCSS += "transform: translateY(-100%); ";
if (type == "left")
fadeCSS += "transform: translateX(-100%); ";
if (type == "right")
fadeCSS += "transform: translateX(100%); ";
fadeCSS += "transition-property: transform; ";
fadeCSS += "transition-duration: " + M.CSS_FADE_DURATION_MS + "ms; ";
fadeCSS += "transition-timing-function: ease-in-out; ";
if (isFullContainer)
containerStyle += fadeCSS;
else
innerContainerStyle += fadeCSS;
}
if (M.CSS_TRANS_BACKGROUND)
containerStyle += "background: rgba(0,0,0,0.75); ";
if (M.CSS_SHADOW) {
if (isFullContainer) {
containerStyle += "box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.50); ";
} else {
innerContainerStyle += "box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.50); ";
}
}
container = self.createElement("div", {
id: containerID,
style: containerStyle
});
innerContainer = self.createElement("div", {
id: innerContainerID,
style: innerContainerStyle
});
if (!container || !innerContainer)
self.log("banner: " + type + " container creation failed");
else {
container.appendChild(innerContainer);
document.body.insertBefore(container, document.body.firstChild);
}
return container;
};
module.prototype.showAds = function () {
if (!M.isEnabled() || !M.gptInitialized) {
return false;
}
// gather data for viewport/banner compatibility
M.checkViewportSupport();
// setup slots, request ad - gpt event handlers will handle the response
M.TYPES.forEach(function(type) {
if (M.support[type])
window.googletag.cmd.push(() => {
if (M.slots[type]) {
self.log("banner: attempt to refresh slot", type);
if (M.refreshAfter[type] &&
M.refreshAfter[type] <= Date.now() &&
M.refreshEnabled) {
// add-in UAM bidding, if enabled
if (self.apstag && self.apstag.isReadyToFetch()) {
var containerID = M.getContainerID(type, "inner");
var adUnitPath = M.slots[type].getAdUnitPath();
var sizesArray = Array.from(M.sizes[type]);
self.apstag.fetchAndApplyDisplayBids(containerID, adUnitPath, sizesArray)
.then(function(bids) {
self.log("banner: aps bids activated")
}, function() {
self.log("banner: failed to prefetch aps bids, will send std request instead")
})
.finally(function() {
window.googletag.pubads().refresh([M.slots[type]]);
});
} else {
window.googletag.pubads().refresh([M.slots[type]]);
}
} else {
self.log("banner: too early to refresh slot", type);
}
} else {
self.log("banner: attempt to create slot", type);
M.configureSlot(type);
window.googletag.display(M.getContainerID(type, "inner"));
}
});
});
};
module.prototype.configureSlot = function (type) {
// report preload as time of ad request
M.lastAdCall = self.now();
// check if container exists
if (!M.containers[type]) {
self.log(type + " banner container undefined");
return false;
}
// check if slot was already created
if (M.slots[type]) {
self.log(type + " slot already defined");
return false;
}
var containerID = M.getContainerID(type, "inner");
// create slot
M.slots[type] = window.googletag
.defineSlot(M.adUnitPath, M.sizes[type], containerID)
.addService(window.googletag.pubads())
.setTargeting("a", "" + self.config.aid)
.setTargeting("game", "" + window.famobi_gameID)
.setTargeting("gametype", "html5")
.setTargeting("video", "0")
.setTargeting("uuid", "" + self.config.uuid)
.setTargeting("rt", "adxfcb")
.setTargeting("if", detection.is.iframe ? "1" : "0")
.setTargeting(M.SLOT_TYPE_KEY, type);
// enable services after slot setup & targeting to avoid race conditions
// see https://developers.google.com/doubleclick-gpt/common_implementation_mistakes#scenario-5:-mis-ordering-calls-to-gpt
if (!window.googletag.pubadsReady) {
window.googletag.enableServices();
self.log("enabled & initialized gpt services");
}
};
module.prototype.checkViewportSupport = function () {
// store current support flags & sizes for comparison
var oldSupport = Object.assign({}, M.support);
var oldSizes = Object.assign({}, M.sizes);
// reset support flags & sizes
M.TYPES.forEach(function(type) {
M.support[type] = false;
M.sizes[type] = [];
});
var size = self.getWindowSize();
if (size.w == 0 || size.h == 0) {
self.log("banner: invalid sized viewport");
return false;
}
var ratio = size.w / size.h;
// check support for each placement type
M.TYPES.forEach(function(type) {
// check if type is enabled via config
if (!M.config[type] || !M.config[type].enabled) {
return;
}
// check viewport ratio
if (M.config[type].max_ratio != null && ratio > M.config[type].max_ratio ||
M.config[type].min_ratio != null && ratio < M.config[type].min_ratio) {
return;
}
// check viewport width & height
if (M.config[type].min_width != null && size.w < M.config[type].min_width ||
M.config[type].min_height != null && size.h < M.config[type].min_height) {
return;
}
// check & add ad unit sizes
M.AD_UNIT_SIZES[type].forEach(function(adUnitSize) {
if (size.w >= adUnitSize[0] && size.h >= adUnitSize[1])
M.sizes[type].push(adUnitSize);
});
// indicate support via flag
if (M.sizes[type].length > 0) {
M.support[type] = true;
}
});
// compare result with previous support state
var hasChanged = false;
M.TYPES.forEach(function(type) {
if ((oldSupport[type] !== M.support[type]) ||
(oldSizes[type].length !== M.sizes[type].length))
hasChanged = true;
});
if (hasChanged)
self.adapters.run("banner", "placementChanged");
};
module.prototype.viewportResizeHandler = function () {
// update supported formats
M.checkViewportSupport();
// clear current ads if support has been lost
M.clearUnsupported();
};
module.prototype.clearUnsupported = function() {
M.TYPES.forEach(function(type) {
if (!M.support[type] && M.containers[type] && M.slots[type]) {
if (M.CSS_FADE_OUT) {
M.fadeOutSlot(M.slots[type]);
}
setTimeout(function(){
window.googletag.cmd.push(function () {
window.googletag.pubads().clear([M.slots[type]]);
M.containers[type].style.display = "none";
});
}, M.CSS_FADE_OUT ? M.CSS_FADE_DURATION_MS : 0);
}
});
}
module.prototype.hasSlot = function(slot) {
return (M.getSlotType(slot) != null);
};
module.prototype.getSlotType = function(slot) {
var slotType = null;
M.TYPES.forEach(function(type) {
if (M.slots[type] === slot)
slotType = type;
});
return slotType;
};
module.prototype.isOverlay = function(type) {
return !!(M.config && M.config[type] && M.config[type].overlay);
};
module.prototype.getOffset = function(type) {
var maxSize = 0;
if (!M.TYPES.includes(type)) {
self.log.error("banner.getOffset: wrong type parameter given", type);
return maxSize;
}
if (M.support[type] && M.sizes[type].length > 0) {
var compareIndex = (type == "top" || type == "bottom") ? 1 : 0;
M.sizes[type].forEach(function(size) {
maxSize = Math.max(size[compareIndex], maxSize);
});
}
return maxSize;
};
module.prototype.toggleRefresh = function() {
M.refreshEnabled = !M.refreshEnabled;
self.log("banner: refresh", M.refreshEnabled ? "on" : "off");
}
M = new module();
M.init();
return M;
};
/* eslint-disable no-undef */
fg_api.prototype.apstagModule = function () {
var self = this,
M;
function module() {
this.APS_PUBLISHER_ID = "8db57ce2-f227-4041-8769-5657c6de665c";
this.APS_BID_TIMEOUT = 10e3;
this.APS_DISPLAY_AD_SERVER = "googletag";
this.APS_VIDEO_AD_SERVER = "DFP";
this.APS_VIDEO_SIZES = {
portrait: [
[768,1024], [390,640], [320,480]
],
landscape: [
[1024,768], [640,480], [640,390], [640,360], [480,320], [400,300], [400,225]
]
};
this.ACTIVE_DISPLAY_SLOT_SIZES = [
[120, 600], [160, 600], [300, 50], [300, 100], [300, 75], [320, 50], [320, 100]
];
this.ACTIVE_VIDEO_SLOT_SIZES = [
[640, 480], [400, 300], [320, 480]
];
this.DEFAULT_SLOT_ID = "Default_InGame_640x480v";
this.DEFAULT_SLOT_PREFIX = "Default_InGame_";
this.isInitialized = false;
this.lastAdCall = 0;
this.adRequestCount = 0;
this.adImpressionCount = 0;
this.forceOff = false;
}
module.prototype.init = function () {
// check if aps is supported & allowed
var urlParams = self.getUrlParams();
if (urlParams.fg_force_aps && urlParams.fg_force_aps == "0") {
this.forceOff = true;
self.log("apstag: aps disabled via URL param, initialization aborted")
return;
}
if (!M.isEnabled()) {
self.log("apstag: ads disabled, initialization aborted")
return;
}
// add apstag lib to window
// eslint-disable-next-line max-params
!function(a9,a,p,s,t,A,g){if(a[a9])return;function q(c,r){a[a9]._Q.push([c,r])}a[a9]={init:function(){q("i",arguments)},fetchBids:function(){q("f",arguments)},setDisplayBids:function(){},targetingKeys:function(){return[]},_Q:[]};A=p.createElement(s);A.async=!0;A.src=t;g=p.getElementsByTagName(s)[0];g.parentNode.insertBefore(A,g)}("apstag",window,document,"script","//c.amazon-adsystem.com/aax2/apstag.js");
// init apstag library to allow bidding
// eslint-disable-next-line no-undef
apstag.init({
pubID: M.APS_PUBLISHER_ID,
adServer: M.APS_DISPLAY_AD_SERVER,
videoAdServer: M.APS_VIDEO_AD_SERVER,
bidTimeout: M.APS_BID_TIMEOUT
}, function() {
self.log("apstag: library initialized");
M.isInitialized = true;
});
};
module.prototype.getVideoSlotID = function(width, height, isPreroll) {
var hasSize = false;
M.ACTIVE_VIDEO_SLOT_SIZES.forEach(function(size) {
if (size[0] == width && size[1] == height) {
hasSize = true;
}
});
return hasSize ?
(M.DEFAULT_SLOT_PREFIX + width + "x" + height + "v") :
M.DEFAULT_SLOT_ID;
};
module.prototype.fetchVideoBids = function(slotID) {
return new Promise(function(resolve, reject){
if (typeof apstag === "undefined" || !(apstag.fetchBids) || !M.isInitialized) {
self.log("apstag: library not initialized, cannot fetch video bids");
return reject();
}
// determine slot properties
let requestSlotID = typeof slotID !== "undefined" ? slotID : M.DEFAULT_SLOT_ID;
// Request Bids
self.log("apstag: requesting bids for slot", requestSlotID);
apstag.fetchBids({
slots: [{
slotID: requestSlotID,
mediaType: 'video'
}]
}, function(bids) {
// Pass bids into the function that will append the key values onto the VAST tag
if (bids.length > 0) {
self.log("apstag: " + bids.length + " bids returned");
self.log("apstag: ", bids);
return resolve(bids);
}
self.log("apstag: no bids returned");
reject();
});
});
};
module.prototype.fetchAndApplyDisplayBids = function(slotElementID, adUnitPath, sizesArray) {
return new Promise(function(resolve, reject) {
if (typeof apstag === "undefined" || !(apstag.fetchBids) || !M.isInitialized) {
self.log("apstag: library not initialized, cannot fetch display bids");
return reject();
}
if (!slotElementID) {
self.log("apstag: cannot fetch display bids, no slot element id provided");
return reject();
}
// Request Bids
self.log("apstag: requesting bids for display slot", slotElementID,
", with ad unit path", adUnitPath, "and sizes", sizesArray);
apstag.fetchBids({
slots: [{
slotID: slotElementID,
slotName: adUnitPath,
sizes: sizesArray
}],
params: {
adRefresh: "1"
}
}, function(bids) {
// Pass bids into the function that will append the key values onto the VAST tag
if (bids.length > 0) {
self.log("apstag: " + bids.length + " display bids returned");
self.log("apstag: ", bids);
self.log("apstag: updating googletag targeting")
apstag.setDisplayBids();
return resolve(bids);
}
self.log("apstag: no bids returned");
reject();
});
});
};
module.prototype.isEnabled = function() {
return (
self.hasFeature("ads") &&
!self.config.ads.off &&
window.famobi_env != "vp" &&
self.config.gameParams.ad_type != "off" &&
!M.forceOff &&
self.config.is_own_inventory
);
};
module.prototype.isReadyToFetch = function() {
return M.isEnabled() && M.isInitialized;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.notifyModule = function() {
var self = this,
M;
function module() {
// define private vars
this.element = "";
this.closing = false;
this.closeCallbacks = [];
}
module.prototype.init = function() {
self.onorientationchange(function() {
if (M.element) {
M.setScrollAreaHeight();
}
});
};
module.prototype.create = function(options) {
var opts = faZepto.extend(
{
overlayColor: null,
overlayStyle: {},
showCloseBtn: true,
returnCallback: function() {},
title: ""
},
options
);
if (!M.closing) {
M.close(); // close all other windows - it's a 'modal'
}
self.navigation.invisible();
self.game.pause();
var className = "";
if (opts.mode) {
className = opts.mode + "-mode";
}
if (M.element && M.element.parentNode) {
M.element.parentNode.removeChild(M.element);
}
M.element = self.createElement("div", {
class: "fg-notify fg-fade fg-show " + className
});
if (M.overlay && M.overlay.parentNode) {
M.overlay.parentNode.removeChild(M.overlay);
}
M.blurredBg = self.createElement("div", {
class: "fg-notify-blurred-bg",
style: "background-image: url(" + self.config.blurred_thumb + ")"
});
self.rootElement.appendChild(M.blurredBg);
M.overlay = self.createElement("div", { class: "fg-notify-overlay" });
if (opts.overlayColor) {
M.overlay.style.backgroundColor = opts.overlayColor;
}
if (opts.overlayStyle) {
faZepto(M.overlay).css(opts.overlayStyle);
}
self.rootElement.appendChild(M.overlay);
M.body = self.createElement("div", { class: "fg-notify-body" });
M.element.appendChild(M.body);
M.header = self.createElement("div", { class: "fg-notify-header" });
M.body.appendChild(M.header);
//M.gameTeaserHolder = self.createElement('div', {'class': 'fg-notify-gameteaser-holder'});
//M.gameTeaser = self.createElement('img', {'src': self.config.thumb});
//M.gameTeaserHolder.appendChild(M.gameTeaser);
//M.header.appendChild(M.gameTeaserHolder);
if (opts.title !== "") {
M.headline = self.createElement("strong", {
class: "fg-notify-headline"
});
M.headline.innerHTML = opts.title;
M.header.appendChild(M.headline);
}
M.scrollArea = self.createElement("div", {
class: "fg-notify-scrollarea"
});
M.body.appendChild(M.scrollArea);
faZepto(M.scrollArea).on("touchmove", function(event) {
// allow native scrolling in games that capture the 'touchmove' event
event.stopPropagation();
return true;
});
self.rootElement.appendChild(M.element);
faZepto([M.element, M.blurredBg]).css({
opacity: "0",
transition: "opacity 1s"
});
if (opts.showCloseBtn !== false) {
M.showCloseBtn();
}
M.closeCallbacks.push(opts.returnCallback);
M.closeCallbacks.push(function() {
self.wait(500).then(function() {
self.game.resume();
});
self.navigation.visible();
});
};
module.prototype.showCloseBtn = function() {
M.closeBtn = self.createElement("div", {
class: "fg-notify-close icon-cancel"
});
if (!M.element) {
return false;
}
M.closeBtn.innerHTML = "×";
M.header.appendChild(M.closeBtn);
self.handleClick(M.closeBtn, function() {
if (!this.getAttribute("data-disable")) {
M.close();
}
});
self.handleClick(M.overlay, function() {
if (
!M.closeBtn.getAttribute("data-disable") &&
!M.overlay.getAttribute("data-disable")
) {
M.close();
}
});
};
module.prototype.setCloseCallback = function(callback) {
if (M.element) {
M.closeCallbacks.push(callback);
return true;
} else {
callback();
return false;
}
};
module.prototype.activateCloseOverlay = function(state) {
if (!M.overlay) {
return false;
}
if (state) {
M.overlay.removeAttribute("data-disable");
} else {
M.overlay.setAttribute("data-disable", "true");
}
};
module.prototype.setContent = function(contentElement) {
if (contentElement) {
M.scrollArea.appendChild(contentElement);
}
M.setScrollAreaHeight();
self.spinner.show();
faZepto([M.element, M.blurredBg]).css({
opacity: "1"
});
// enable links when visible
self.wait(1e3).then(function() {
self.spinner.hide();
M.setScrollAreaHeight();
faZepto(M.element)
.find("[data-xhref]")
.each(function() {
this.setAttribute("href", this.getAttribute("data-xhref"));
});
});
};
module.prototype.setScrollAreaHeight = function() {
var $scrollArea = faZepto(M.scrollArea);
// Reset old values
$scrollArea.css("height", "");
$scrollArea.css("overflow-y", "");
var scrollAreaHeight = $scrollArea.height();
var $header = faZepto(M.header);
var padding = Number(
faZepto(M.body)
.css("padding")
.replace("px", "")
);
var headerHeight =
$header.height() +
Number($header.css("margin-bottom").replace("px", ""));
var windowHeight = faZepto(window).height() - padding * 5; // 4 = top & bottom padding + top & bottom margin, + top margin for icon
var fixedScrollAreaHeight = windowHeight - headerHeight;
if (scrollAreaHeight > fixedScrollAreaHeight) {
$scrollArea.css("height", fixedScrollAreaHeight + "px");
$scrollArea.css("overflow-y", "scroll");
}
};
module.prototype.setDimensions = function(width, height) {
if (!width || width === "") width = 480;
if (!height || height === "") height = 500;
M.element.style.maxHeight = parseInt(height, 10) + 60 + "px";
M.element.style.maxWidth = parseInt(width, 10) + 20 + "px";
M.element.style.display = "";
};
module.prototype.close = function() {
M.closing = true;
if (M.element) {
M.element.style.display = "none";
if (M.element.parentNode) {
M.element.parentNode.removeChild(M.element);
}
} else {
return false;
}
if (M.overlay) {
M.overlay.style.display = "none";
if (M.overlay.parentNode) {
M.overlay.parentNode.removeChild(M.overlay);
}
} else {
return false;
}
if (M.blurredBg) {
M.blurredBg.style.display = "none";
if (M.blurredBg.parentNode) {
M.blurredBg.parentNode.removeChild(M.blurredBg);
}
}
faZepto.each(M.closeCallbacks, function(key, callback) {
if (typeof callback === "function") {
callback();
}
});
M.closeCallbacks = [];
M.closing = false;
};
M = new module();
M.init();
return M;
};
/* eslint-disable no-unused-vars */
fg_api.prototype.adaptersModule = function() {
var self = this,
M;
function module() {
// define private vars
this.adapters = {
ads: {
show: this.createAdapter(),
rewarded: this.createAdapter(),
callback: this.createAdapter(),
vastUrl: this.createAdapter()
},
adEvent: {
loaded: this.createAdapter(),
displayed: this.createAdapter(),
errored: this.createAdapter(),
userClosed: this.createAdapter(),
completed: this.createAdapter()
},
banner: {
placementChanged: this.createAdapter({queueCalls: true, queueLength: 1, runOnce: false})
},
analytics: {
trackEvent: this.createAdapter(),
trackScreen: this.createAdapter(),
trackStats: this.createAdapter()
},
api: {
created: this.createAdapter({queueCalls: true, runOnce: true})
},
game: {
loaded: this.createAdapter({queueCalls: true, runOnce: true}),
gameOver: this.createAdapter(),
levelUp: this.createAdapter(),
preloadProgress: this.createAdapter(),
preloadComplete: this.createAdapter({queueCalls: true, runOnce: true}),
ready: this.createAdapter({queueCalls: true, runOnce: true})
},
player: {
ready: this.createAdapter({queueCalls: true, queueLength: 1, runOnce: false})
},
highscore: {
show: this.createAdapter(),
submit: this.createAdapter()
},
screenshot: {
submit: this.createAdapter()
},
request: {
startGame: this.createAdapter({queueCalls: true, runOnce: true}),
restartGame: this.createAdapter(),
pauseGameplay: this.createAdapter(),
resumeGameplay: this.createAdapter(),
enableAudio: this.createAdapter(),
disableAudio: this.createAdapter(),
enableMusic: this.createAdapter(),
disableMusic: this.createAdapter(),
changeVolume: this.createAdapter()
},
consent: {
platformLoaded: this.createAdapter({queueCalls: true, runOnce: true})
},
tracking: {
trackEvent: this.createAdapter()
},
viewport: {
orientationChanged: this.createAdapter({queueCalls: true, queueLength: 1, runOnce: false}),
offsetChanged: this.createAdapter({queueCalls: true, queueLength: 1, runOnce: false})
}
};
this.adapter_templates = {
ads: {
show: [function(callback, force) {
/* when an interstitial ad is requested */
}],
rewarded: [function(callback) {
/* when a rewarded ad is requested */
}],
callback: [function(options) {
/* fired when ad modal is closed */
}],
vastUrl: [function() {
/* fired when ad vast tag is retrieved */
}]
},
adEvent: {
loaded: [function(ad) {
/**/
}],
displayed: [function() {
/**/
}],
errored: [function(adErrorEvent) {
/**/
}],
userClosed: [function(adcount) {
/**/
}],
completed: [function(adcount) {
/**/
}]
},
banner: {
placementChanged: [function() {
/* change of banner position and/or format */
}]
},
analytics: {
trackEvent: [function(event, params) {
/**/
}],
trackScreen: [function(screen, pageTitle) {
/**/
}],
trackStats: [function(key, value) {
/**/
}]
},
api: {
created: [function(apiInstance) {
/**/
}]
},
game: {
loaded: [function() {
/**/
}],
gameOver: [function() {
/**/
}],
levelUp: [function() {
/**/
}],
preloadProgress: [function() {
/**/
}],
preloadComplete: [function() {
/**/
}],
ready: [function() {
/**/
}]
},
player: {
/*
when the core-gameplay starts and player input affects the current level / round outcome
(after ingame tutorials, countdowns, etc)
*/
ready: [function() {
}]
},
highscore: {
show: [function(level) {
/**/
}],
submit: [function(level, score) {
/**/
}]
},
screenshot: {
submit: [function(screenshot_url, options) {
/**/
}]
},
request: {
/* attention: these request adapters are only used in specific environments (e.g. Famobi apps) */
startGame: [function() {
/* triggered once after loading all assets, indicates when the game should start */
}],
restartGame: [function() {
/* indicates the current level, round or general gameplay should restart from the beginning */
}],
pauseGameplay: [function() {
/* indicates a pause functionality/overlay should be activated when called in gameplay state */
}],
resumeGameplay: [function() {
/* indicates the game should resume when in a paused gameplay state */
}],
enableAudio: [function() {
/* indicates that audio(sfx) should be enabled */
}],
disableAudio: [function() {
/* indicates that audio(sfx) should be disabled */
}],
enableMusic: [function() {
/* indicates that music should be enabled */
}],
disableMusic: [function() {
/* indicates that music should be disabled */
}],
changeVolume: [function(volume) {
/* indicates that the main volume should be set to a provided value */
}]
},
consent: {
platformLoaded:[function() {
/* triggered once after a consent management platform is activated */
}]
},
tracking: {
trackEvent: [function(eventPath, params) {
/* triggered immediately after each trackEvent call */
}]
},
viewport: {
orientationChanged: [function(orientation) {
/* triggered when a change in viewport size indicates a switch to landscape/portrait */
}],
offsetChanged: [function(offsets) {
/* triggered when the API-required offsets change, e.g. because banner-ads need space to display */
}]
}
};
}
var adaptersPrototype = module.prototype;
adaptersPrototype.createAdapter = function(options) {
return {
callbacks: [],
queueCalls: !!(options && options.queueCalls),
queue: [],
queueLength: (options && typeof options.queueLength == "number") ? options.queueLength : undefined,
runOnce: !!(options && options.runOnce),
numRuns: 0
};
};
adaptersPrototype.init = function() {
var section = "",
subsection = "";
if (typeof window.famobi_adapters !== "undefined") {
for (section in window.famobi_adapters) {
for (subsection in window.famobi_adapters[section]) {
this.add(
section,
subsection,
window.famobi_adapters[section][subsection]
);
}
}
}
};
adaptersPrototype.list = function() {
//self.log("available adapters: ", this.adapters);
//self.log("adapter templates: ", this.adapter_templates);
return this.adapters;
};
adaptersPrototype.add = function(section, subsection, callback) {
if (!(section in this.adapters && subsection in this.adapters[section])) {
self.log("adapters.add: invalid (sub-)section");
return this;
}
if (typeof callback !== 'function') {
self.log("adapters.add: invalid callback");
return this;
}
var adapter = this.adapters[section][subsection];
if (typeof adapter != 'object' || !Array.isArray(adapter.callbacks)) {
self.log("adapters.add: broken adapter object for", section, subsection);
return this;
}
self.log("adapters.add: push callback for", section, subsection);
adapter.callbacks.push(callback);
if (adapter.queueCalls && adapter.queue.length > 0) {
adapter.queue.forEach(function(args) {
try {
callback.apply(this, args);
} catch(err) {
console.warn("adapters.run: callback failed for", section + "." + subsection, "\n", err);
}
}, this);
}
return this;
};
adaptersPrototype.has = function(section, subsection) {
return (section in this.adapters) &&
(subsection in this.adapters[section]) &&
(typeof this.adapters[section][subsection] == "object") &&
Array.isArray(this.adapters[section][subsection].callbacks) &&
(this.adapters[section][subsection].callbacks.length > 0);
};
adaptersPrototype.run = function(section, subsection) {
self.log("adapters.run:", section, subsection);
var args = arguments ? Array.prototype.slice.call(arguments, 2) : [];
if (!(section in this.adapters) ||
!(subsection in this.adapters[section]) ||
!(typeof this.adapters[section][subsection] == "object")) {
return false;
}
var adapter = this.adapters[section][subsection];
if (adapter.runOnce && adapter.numRuns > 0) {
console.warn("adapters.run: one-time adapter called more than once for", section + "." + subsection, "\n");
return false;
}
adapter.numRuns += 1;
if (adapter.queueCalls) {
adapter.queue.push(args);
if (typeof adapter.queueLength == "number" &&
adapter.queue.length > adapter.queueLength) {
adapter.queue.shift();
}
}
if (adapter.callbacks.length > 0) {
adapter.callbacks.forEach(function(callback) {
try {
callback.apply(this, args);
} catch(err) {
console.warn("adapters.run: callback failed for", section + "." + subsection, "\n", err);
}
}, this);
return true;
}
return false;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.requestsModule = function() {
var self = this,
M;
function module() {
// define private vars
this.adapterSection = "requests";
this.legitActionIdentifiers = [
"startGame",
"restartGame",
"pauseGameplay",
"resumeGameplay",
"enableAudio",
"enableMusic",
"disableAudio",
"disableMusic",
"changeVolume"
];
}
var requestsPrototype = module.prototype;
requestsPrototype.init = function() {
};
requestsPrototype.isAction = function(actionIdentifier) {
return typeof actionIdentifier === "string" &&
(M.legitActionIdentifiers.indexOf(actionIdentifier) > -1)
};
requestsPrototype.onRequest = function(actionIdentifier, callback) {
if (!self.adapters) {
console.warn(
"onRequest(): adapters module required"
);
return;
}
if (!M.isAction(actionIdentifier)) {
console.warn(
"onRequest(): required param 'action' has to be one of \"" +
M.legitActionIdentifiers.join('", "') + '"'
);
return;
}
if (typeof callback !== "function") {
console.warn(
"onRequest(): required param 'callback' has to be of type 'function'"
);
return;
}
self.adapters.add("request", actionIdentifier, callback);
};
requestsPrototype.requestAction = function(actionIdentifier) {
if (!self.adapters) {
console.warn(
"onRequest(): adapters module required"
);
return;
}
if (!M.isAction(actionIdentifier)) {
console.warn(
"requestAction(): required param 'action' has to be one of \"" +
M.legitActionIdentifiers.join('", "') + '"'
);
return;
}
self.adapters.run.apply(self.adapters, ["request"].concat(Array.from(arguments)))
};
M = new module();
M.init();
return M;
};
/*
convenience functions for requests
*/
fg_api.prototype.onRequest = function(action, callback) {
if (!this.requests) {
console.warn(
"onRequest(): requests module required"
);
return;
}
this.requests.onRequest(action, callback);
};
fg_api.prototype.requestAction = function() {
if (!this.requests) {
console.warn(
"onRequest(): requests module required"
);
return;
}
this.requests.requestAction.apply(this, arguments);
};
fg_api.prototype.consentModule = function() {
var self = this,
M;
function module() {
// define private vars
this.cookieproScriptID = 'e63a91ad-15ec-4e2d-ae18-2a0b6143ecd8';
var urlParams = self.getUrlParams();
this.cookieproPreview = urlParams.otpreview && (urlParams.otpreview == true);
if (self.debug && !this.cookieproPreview)
this.cookieproScriptID += '-test';
this.cookieproScriptURL = 'https://cookie-cdn.cookiepro.com/scripttemplates/otSDKStub.js';
this.cmpLoaded = false;
this.hidePlatformUIRequested = false;
this.statusIDs = [
"termsOfServicePresented",
"termsOfServiceAccepted",
"privacyPolicyPresented",
"privacyPolicyAccepted"
];
this.statusObject = {};
}
module.prototype.init = function() {
// init consent status items as false
M.statusIDs.forEach(function(statusID) {
M.statusObject[statusID] = false;
});
// require consent via TCFv2 CPM in case ads are enabled
if (!self.hasFeature("ads") || self.config.ads.provider == "none")
return;
switch (self.config.cmp) {
case 'cookiepro':
// activate CookiePro Cookies Consent Notice for famobi.com
M.initCookiePro();
break;
case 'none':
break;
case 'default':
default:
// cmp not set: activate CookiePro for non-iframed traffic
if (!detection.is.iframe || self.config.is_own_inventory) {
M.initCookiePro();
}
break;
}
};
module.prototype.initCookiePro = function() {
self.log('consent: loading CookiePro script');
window.OptanonWrapper = window.OptanonWrapper || function() {
self.log('consent: CookiePro loaded');
M.cmpLoaded = true;
if (self.adapters) {
self.adapters.add("adEvent", "loaded", M.hidePlatformUI);
self.adapters.add("game", "loaded", M.hidePlatformUI);
self.adapters.run("consent", "platformLoaded");
}
};
window.addEventListener("OneTrustPCLoaded", function(event) {
self.log("consent: OT Preference Center Loaded")
});
window.addEventListener("OTConsentApplied", function(event) {
self.log("consent: OT User updated consent")
});
window.addEventListener("OneTrustGroupsUpdated", function(event) {
self.log("consent: OT Selected groups are now active")
});
var firstJS = document.getElementsByTagName('script')[0];
var fgJS = document.createElement('script');
fgJS.setAttribute('type', 'text/javascript');
fgJS.setAttribute('charset', 'UTF-8');
fgJS.setAttribute('data-domain-script', M.cookieproScriptID);
fgJS.setAttribute('data-dLayer-ignore', 'true');
fgJS.src = M.cookieproScriptURL.replace('[script_id]', M.cookieproScriptID);
firstJS.parentNode.insertBefore(fgJS, firstJS);
};
module.prototype.hidePlatformUI = function() {
if (M.hidePlatformUIRequested)
return;
// attempt to hide cookiepro settings button
M.hidePlatformUIRequested = true;
var settingsButton = faZepto("#ot-sdk-btn-floating.ot-floating-button");
settingsButton.css({
display: "none"
});
};
module.prototype.isPlatformLoaded = function() {
return M.cmpLoaded;
};
module.prototype.setStatus = function(status, value = true) {
var statusUpdated = false;
if (typeof status == "string" && M.statusIDs.includes(status)) {
// set single status item
M.statusObject[status] = value;
statusUpdated = true;
}
else if (typeof status == "object") {
// update status object
for (var [statusID, statusValue] of Object.entries(status)) {
if (typeof statusID == "string" && M.statusIDs.includes(statusID)) {
M.statusObject[statusID] = statusValue;
statusUpdated = true;
}
}
}
if (statusUpdated) {
self.log("consent: status updated");
}
};
module.prototype.getStatus = function(statusID) {
if (typeof statusID == "string") {
return M.statusObject[statusID];
} else {
return Object.assign({}, M.statusObject);
}
};
M = new module();
M.init();
return M;
};
fg_api.prototype.getConsentStatus = function(statusID) {
return this.consent.getStatus(statusID);
};
/* eslint-disable no-unused-vars */
/* eslint-disable max-params */
fg_api.prototype.click2playModule = function() {
var self = this,
M;
function module() {
this.MAX_WAIT_FOR_LOAD_MS = 3000;
this.isShowing = false;
this.overlayElements = {};
this.status = {};
this.options = {};
}
module.prototype.init = function() {
self.log("Famobi click2play Module Initializing");
};
module.prototype.createOverlay = function() {
M.overlayElements.playBtnContainer = self.createElement("div", {
class:
"fg-click2play" +
(!M.options.showTeaser ? " fg-click2play-continue" : "") +
(detection.is.smartphone ? " smartphone" : ""),
style: "opacity: 0;transition: opacity 1s;"
});
M.overlayElements.gameIcon = self.createElement("div", {
class: "fg-gameicon",
title: M.options.title
});
M.overlayElements.branding = self.createElement("div", {
class: "fg-branding"
});
if (!M.status.gameIconLoaded) {
if (typeof self.config.thumb !== "undefined") {
// eslint-disable-next-line no-unused-vars
M.status.gameIconLoaded = new Promise(function(resolve, reject){
var img = document.createElement("img");
img.onload = function() {
resolve();
};
img.onerror = resolve;
img.src = self.config.thumb;
M.overlayElements.gameIconImage = img;
});
} else {
M.status.gameIconLoaded = Promise.resolve();
}
}
M.status.gameIconLoaded.then(function(){
M.overlayElements.gameIcon.innerHTML =
'<img src="' + self.config.thumb + '" alt>';
});
if (M.options.showTeaser) {
if (!M.status.backgroundLoaded) {
if (typeof self.config.blurred_thumb !== "undefined")
M.status.backgroundLoaded = new Promise(function(resolve, reject){
var img = document.createElement("img");
img.onload = resolve;
img.onerror = resolve;
img.src = self.config.blurred_thumb;
M.overlayElements.gameIconImage = img;
});
else
M.status.backgroundLoaded = Promise.resolve();
}
M.status.backgroundLoaded.then(function(){
M.overlayElements.branding.style.background = '#000 url("' + self.config.blurred_thumb + '") no-repeat center center';
M.overlayElements.branding.style.backgroundSize = "cover";
});
} else {
M.overlayElements.branding.style.background = "rgba(0,0,0,0.75)";
}
M.overlayElements.playBtnStage = self.createElement("div", {
class: "fg-click2play-stage"
});
M.overlayElements.playBtn = self.createElement("div", {
class: "btn-play",
title: ""
});
M.overlayElements.playBtn.innerHTML =
'<div class="fg-click2play-loading"><span class="fg-click2play-loading-bounce1"></span><span class="fg-click2play-loading-bounce2"></span><span class="fg-click2play-loading-bounce3"></span></div>';
M.overlayElements.privacyInfo = self.createElement("div", {
class: "privacy-info"
});
M.overlayElements.privacyInfo.innerHTML = self.translate("api.privacy_info") +
self.translate("api.privacy_link");
M.overlayElements.stageHeader = self.createElement("div", {
class: "fg-click2play-stage-header"
});
M.overlayElements.gameDetails = self.createElement("div", {
class: "fg-gameDetails"
});
M.overlayElements.stageFooter = self.createElement("div", {
class: "fg-click2play-stage-footer"
});
M.overlayElements.playBtnContainer.appendChild(M.overlayElements.playBtnStage);
M.overlayElements.playBtnStage.appendChild(M.overlayElements.stageHeader);
M.overlayElements.playBtnStage.appendChild(M.overlayElements.gameDetails);
M.overlayElements.gameDetails.appendChild(M.overlayElements.gameIcon);
M.overlayElements.playBtnContainer.appendChild(M.overlayElements.branding);
M.overlayElements.gameDetails.appendChild(M.overlayElements.playBtn);
M.overlayElements.playBtnStage.appendChild(M.overlayElements.stageFooter);
// add privacy info if no CMP enabled or not yet available
if (M.options.showPolicy && !(self.consent && self.consent.isPlatformLoaded())) {
M.overlayElements.stageFooter.appendChild(M.overlayElements.privacyInfo);
// hide privacy info once CMP is loaded
if (self.adapters) {
self.adapters.add("consent", "platformLoaded", function(){
if (!M.overlayElements.stageFooter)
return;
faZepto(M.overlayElements.stageFooter).css({
opacity: "0",
transition: "opacity 0.5s"
});
setTimeout(function() {
if (M.overlayElements.stageFooter)
M.overlayElements.stageFooter.style.visibility = "hidden";
}, 500);
})
}
}
var statusArray = [
M.status.gameIconLoaded || Promise.resolve(),
M.status.backgroundLoaded || Promise.resolve()
];
return Promise.all(statusArray);
};
module.prototype.removeOverlayElements = function() {
faZepto(M.overlayElements.playBtnContainer).remove();
M.overlayElements = {};
};
module.prototype.documentReady = function() {
if (!M.status.documentLoaded) {
M.status.documentLoaded = new Promise(function(resolve, reject) {
if (document.readyState == 'interactive' || document.readyState == 'complete') {
resolve();
return;
}
document.addEventListener('readystatechange', function() {
if (document.readyState == 'interactive' || document.readyState == 'complete')
resolve();
}, false);
});
}
return M.status.documentLoaded;
};
module.prototype.showOverlay = function(callback,
showTeaser = true,
showPolicy = true,
title
) {
if (M.isShowing) {
self.log("click2play: overlay already showing, additional call aborted");
if (typeof callback == "function")
callback.call(null);
return false;
}
M.options.callback = (typeof callback === "function") ? callback : null;
M.options.showTeaser = showTeaser;
M.options.showPolicy = showPolicy;
M.options.title = title;
if (title == undefined)
switch (window.famobi_gameID) {
case "embed-game":
case "flash-game":
break;
case "test-game":
M.options.title = "Famobi Testgame";
break;
default:
M.options.title = self.config.name;
}
var overlayReady = M.createOverlay();
Promise.race([
self.wait(M.MAX_WAIT_FOR_LOAD_MS), Promise.all([overlayReady, M.documentReady()])
])
.then(function(){
self.rootElement.appendChild(M.overlayElements.playBtnContainer);
M.isShowing = true;
// bugfix: wait a little after appending container so the following css transition will work
return self.wait(33);
})
.then(function() {
if (self.spinner)
self.spinner.hide();
if(self.navigation)
self.navigation.invisible();
// allow user to close overlay & continue via button
faZepto(M.overlayElements.playBtnContainer).css({
opacity: "1"
});
self.handleClick(M.overlayElements.playBtn, M.fireCallback);
faZepto(M.overlayElements.playBtn).css({
cursor: "pointer"
});
});
};
module.prototype.activateLoadingIndicator = function() {
if (M.overlayElements.playBtn)
faZepto(M.overlayElements.playBtn).addClass("loading");
};
module.prototype.closeOverlay = function() {
self.log("click2play: close overlay");
if (!M.isShowing) {
self.log("click2play: close overlay attempt failed, no overlay found");
}
M.removeOverlayElements();
M.isShowing = false;
M.options = {};
};
module.prototype.fireCallback = function() {
M.activateLoadingIndicator();
if (M.options.showPolicy) {
self.localStorage.setItem("privacy_policy_accepted", "yes");
if (self.consent) {
self.consent.setStatus({
"termsOfServicePresented": true,
"termsOfServiceAccepted": true,
"privacyPolicyPresented": true,
"privacyPolicyAccepted": true
})
}
}
if (typeof M.options.callback == "function") {
self.log("click2play: attempt to fire callback");
M.options.callback.call(null);
}
};
M = new module();
M.init();
return M;
};
/* eslint-disable no-mixed-spaces-and-tabs */
function fg_api(config, queue, debug) {
if (window.famobi_config) {
config = Object.assign({}, config || {}, window.famobi_config);
} else {
config = config || {};
}
queue = queue || [];
var i = 0,
j = queue.length,
self = this;
self.config = config;
self.debug = !!debug;
/**
* create log function with proper line number
*/
(function createLogger() {
self.log = function() {};
self.error = function() {};
if (self.debug && window.console) {
if (Function.prototype.bind) {
self.log = Function.prototype.bind.call(
window.console.log,
window.console
);
self.error = Function.prototype.bind.call(
window.console.error,
window.console
);
} else {
self.log = function() {
Function.prototype.apply.call(
window.console.log,
window.console,
arguments
);
};
self.error = function() {
Function.prototype.apply.call(
window.console.error,
window.console,
arguments
);
};
}
}
})();
faZepto(function() {
self.init();
while (i < j) {
self.push(queue[i++]);
}
});
}
faZepto.fn.preventClick = function() {
this.each(function() {
faZepto(this).on(
"click touchstart touchmove touchcancel touchend",
function(e) {
e.stopPropagation();
return false;
}
);
});
return this;
};
fg_api.prototype.hasFeature = function(feature) {
return (feature in this.config.features) && !!this.config.features[feature];
};
fg_api.prototype.getFeatureProperties = function(feature) {
return this.hasFeature(feature) && (typeof this.config.features[feature] == "object") ? this.config.features[feature] : {};
};
fg_api.prototype.createElement = function(type, attributes) {
var element = document.createElement(type);
for (var key in attributes) {
if (attributes.hasOwnProperty(key)) {
element.setAttribute(key, attributes[key]);
}
}
return element;
};
fg_api.prototype.eventTrap = function(e) {
e.preventDefault();
e.cancelBubble = true;
if (e.stopImmediatePropagation) {
e.stopImmediatePropagation();
} else if (e.stopPropagation) {
e.stopPropagation();
}
};
fg_api.prototype.handleClick = function(element, callback) {
var eventHandler = function(e) {
setTimeout(function() {
callback.call(null, e);
});
e.cancelBubble = true;
if (e.stopImmediatePropagation) {
e.stopImmediatePropagation();
} else if (e.stopPropagation) {
e.stopPropagation();
}
return false;
};
if (typeof callback === "function") {
// http://stackoverflow.com/questions/13396297/windows-phone-8-touch-support
//
// Performing operations that require explicit user interaction on touchstart events is deprecated and will be removed in M54, around October 2016. See https://www.chromestatus.com/features/5649871251963904 for more details.
if (window.navigator.msPointerEnabled) {
element.addEventListener("MSPointerDown", eventHandler, false);
} else if (window.PointerEvent) {
element.addEventListener("pointerup", eventHandler, false);
element.addEventListener("pointermove", this.eventTrap, true);
element.addEventListener("pointerdown", this.eventTrap, true);
element.addEventListener("touchend", this.eventTrap, true);
element.addEventListener("touchmove", this.eventTrap, true);
element.addEventListener("touchstart", this.eventTrap, true);
element.addEventListener("click", this.eventTrap, true);
} else if (detection.is.touch) {
element.addEventListener("touchend", eventHandler, false);
element.addEventListener("touchmove", this.eventTrap, true);
element.addEventListener("touchstart", this.eventTrap, true);
element.addEventListener("click", this.eventTrap, true);
} else {
element.addEventListener("click", eventHandler, false);
}
element.style.cursor = "pointer";
}
return eventHandler;
};
fg_api.prototype.removeClick = function(element, eventHandler) {
if (typeof eventHandler === "function") {
if (window.navigator.msPointerEnabled) {
element.removeEventListener("MSPointerDown", eventHandler, false);
} else if (window.PointerEvent) {
element.removeEventListener("pointerup", eventHandler, false);
element.removeEventListener("pointermove", this.eventTrap, true);
element.removeEventListener("pointerdown", this.eventTrap, true);
} else if (detection.is.touch) {
element.removeEventListener("touchend", eventHandler, false);
element.removeEventListener("touchmove", this.eventTrap, true);
element.removeEventListener("touchstart", this.eventTrap, true);
} else {
element.removeEventListener("click", eventHandler, false);
}
}
return element;
};
fg_api.prototype.getUrlParams = function(a, b, c) {
(a = /[?&]?([^=]+)=([^&]*)/g),
(b =
document.location && document.location.search
? document.location.search.split("+").join(" ")
: "");
// eslint-disable-next-line no-cond-assign
for (var d = {}; (c = a.exec(b));)
d[decodeURIComponent(c[1])] = decodeURIComponent(c[2]);
return d;
};
fg_api.prototype.str = function(chrs) {
var str = "";
function chr(n) {
return String.fromCharCode(n);
}
for (var i = 0; i < chrs.length; i++) {
str += chr(Number(chrs[i]));
}
return str;
};
fg_api.prototype.guid = function() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return (
s4() +
s4() +
"-" +
s4() +
"-" +
s4() +
"-" +
s4() +
"-" +
s4() +
s4() +
s4()
);
};
/**
* create stubs
*/
if (!window.console) {
window.console = {
log: function() {},
debug: function() {},
info: function() {},
warn: function() {},
error: function() {}
};
}
fg_api.prototype.sizeOf = function(data) {
var length = 0;
var prop;
if (!data) {
return length;
}
if (typeof data.length != "undefined") {
return data.length;
}
if (Object.keys) {
// available since ECMAScript 5 and in some browser 10x faster
length = Object.keys(data).length;
} else {
for (prop in data) {
if (data.hasOwnProperty(prop)) {
length++;
}
}
}
return length;
};
if (typeof String.prototype.startsWith != "function") {
String.prototype.startsWith = function(ext) {
return this.indexOf(ext) === 0;
};
}
if (typeof String.prototype.endsWith != "function") {
String.prototype.endsWith = function(ext) {
return this.indexOf(ext) == this.length - ext.length;
};
}
fg_api.prototype.rand = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
fg_api.prototype.now = function() {
return 1 * new Date();
};
fg_api.prototype.shuffleArray = function(array) {
var i = array.length, j, temp;
while (i > 0) {
j = Math.floor(Math.random() * i);
i -= 1;
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
fg_api.prototype.round = function(n, decimals) {
var pow = Math.pow(10, decimals);
return Math.round(n * pow) / pow;
};
fg_api.prototype.find = function(obj, key) {
var index = "";
if (typeof obj === "object") {
for (index in obj) {
if (obj[index] === key) {
return index;
}
}
} else if (typeof obj !== "undefined") {
if (typeof obj.indexOf === "function") {
return obj.indexOf(key);
}
}
return -1;
};
fg_api.prototype.wait = function(n) {
return new Promise(function(resolve) {
setTimeout(resolve, n);
});
};
fg_api.prototype.vibrate = function(n) {
if (typeof n === "undefined") {
n = 20;
}
if (navigator.vibrate) {
return navigator.vibrate(n);
}
return false;
};
// eslint-disable-next-line max-params
fg_api.prototype.countdown = function(
element,
fn,
dataAttributeName,
formatFn
) {
var self = this;
if (typeof fn !== "function") {
fn = function() {};
}
if (typeof dataAttributeName !== "string") {
dataAttributeName = "data-cn";
}
if (typeof formatFn !== "function") {
formatFn = self.seconds2time;
}
faZepto(element).each(function() {
var $this = faZepto(this);
var interval = setInterval(function() {
var timeleft = $this.attr(dataAttributeName) - 1;
$this.attr(dataAttributeName, timeleft);
$this.text(formatFn.apply(this, [timeleft]));
if (!timeleft) {
fn();
return clearInterval(interval);
}
}, 1e3);
});
};
fg_api.prototype.seconds2time = function(n) {
var hours = Math.floor(n / 3600);
var minutes = Math.floor((n - hours * 3600) / 60);
var seconds = Math.floor(n - hours * 3600 - minutes * 60);
var time = "";
if (hours > 0) {
hours = hours < 10 ? "0" + hours : String(hours);
} else {
hours = "00";
}
time += hours + ":";
if (minutes > 0) {
minutes = minutes < 10 ? "0" + minutes : String(minutes);
} else {
minutes = "00";
}
time += minutes + ":";
if (seconds > 0) {
time += seconds < 10 ? "0" + seconds : String(seconds);
} else {
time += "00";
}
return time;
};
if (typeof Number.prototype.toLocaleString === "undefined") {
Number.prototype.toLocaleString = function() {
return "" + this.valueOf();
};
}
Object.entries = Object.entries
? Object.entries
: function(obj) {
var allowedTypes = [
"[object String]",
"[object Object]",
"[object Array]",
"[object Function]"
];
var objType = Object.prototype.toString.call(obj);
if (obj === null || typeof obj === "undefined") {
throw new TypeError(
"Cannot convert undefined or null to object"
);
} else if (!~allowedTypes.indexOf(objType)) {
return [];
} else {
// if ES6 is supported
if (Object.keys) {
return Object.keys(obj).map(function(key) {
return [key, obj[key]];
});
}
var result = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
result.push([prop, obj[prop]]);
}
}
return objType === "[object Array]"
? result
: result.sort(function(a, b) {
return a[1] - b[1];
});
}
};
Object.values = Object.values
? Object.values
: function(obj) {
var allowedTypes = [
"[object String]",
"[object Object]",
"[object Array]",
"[object Function]"
];
var objType = Object.prototype.toString.call(obj);
if (obj === null || typeof obj === "undefined") {
throw new TypeError(
"Cannot convert undefined or null to object"
);
} else if (!~allowedTypes.indexOf(objType)) {
return [];
} else {
// if ES6 is supported
if (Object.keys) {
return Object.keys(obj).map(function(key) {
return obj[key];
});
}
var result = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
result.push(obj[prop]);
}
}
return result;
}
};
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function() {
"use strict";
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !{ toString: null }.propertyIsEnumerable(
"toString"
),
dontEnums = [
"toString",
"toLocaleString",
"valueOf",
"hasOwnProperty",
"isPrototypeOf",
"propertyIsEnumerable",
"constructor"
],
dontEnumsLength = dontEnums.length;
return function(obj) {
if (
typeof obj !== "object" &&
(typeof obj !== "function" || obj === null)
) {
throw new TypeError("Object.keys called on non-object");
}
var result = [],
prop,
i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
})();
}
fg_api.prototype.getMoreGamesButtonImage = function(forceAbsolute) {
var mgb = this.__("more_games_image") || "";
if (this.banner && this.banner.isEnabled())
mgb = "/html5games/branding/default/More_Games600x253_transparent.png";
if (
forceAbsolute ||
(window.location.hostname.indexOf("cdn.famobi.com") === -1 &&
window.location.hostname.indexOf("dev.famobi.com") === -1)
) {
mgb = this.__("more_games_image_prefix") + mgb;
}
return mgb;
};
fg_api.prototype.getBrandingButtonImage = function(forceAbsolute) {
return this.getMoreGamesButtonImage(forceAbsolute);
};
fg_api.prototype.getAbsolutePath = function(relativePath) {
var absolutePath =
document.location.protocol + "//" + document.location.pathname;
// this method is only used for compatibility with Loaders in Cordova Apps,
// otherwise absolute URIs with https://games.cdn.famobi.com are used
if (document.location.protocol !== "file:") {
return relativePath;
}
if (relativePath.startsWith("/")) {
relativePath = relativePath.substr(1);
}
return (
absolutePath.substr(0, absolutePath.lastIndexOf("/") + 1) + relativePath
);
};
fg_api.prototype.socketModule = function () {
var self = this,
M;
function module() {
this.socket = undefined;
this._onConnectCallback = undefined;
}
module.prototype.init = function () {
(function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src =
"//cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js";
fjs.parentNode.insertBefore(js, fjs);
})(document, "script", "socket-io");
};
module.prototype.connect = function (pUrl, pPlayer, pConfig, pSessionId) {
console.log("connecting to socket...");
let config = {
...pConfig,
hasBots: false,
botDifficulty: 1,
mission: {},
assetId: pConfig.assetId + famobi_gameID,
};
M.socket = io(pUrl, {
query: {
sessionId: pSessionId,
isGameInstance: true,
player: JSON.stringify(pPlayer),
config: JSON.stringify(config),
},
});
M.socket.on("connect", () => {
console.log(
"... connection established!",
pUrl,
pSessionId ? "Connecting normally" : "Connecting to the lobby",
pPlayer
);
if (M._onConnectCallback) M._onConnectCallback();
});
};
module.prototype.onConnect = function (pCallback) {
M._onConnectCallback = pCallback;
};
module.prototype.emit = function (pEvent, pData) {
if (M.socket) M.socket.emit(pEvent, pData);
};
module.prototype.on = function (pEvent, pCallback) {
if (M.socket) M.socket.on(pEvent, pCallback);
};
M = new module();
M.init();
return M;
};
fg_api.prototype.storageModule = function(type) {
var self = this,
M;
function module() {
// define private vars
}
module.prototype.init = function(storageType) {
this.receivingData = false;
this.localStorage = {};
this.sessionStorage = {};
this.storage = {}; // one of the above
this.length = 0;
if (storageType == "localStorage" || storageType == "sessionStorage") {
M.setStorageType(storageType);
M.createStorage(storageType);
}
};
module.prototype.setStorageType = function(storageType) {
M.storageType = storageType;
};
module.prototype.getStorageType = function() {
return M.storageType;
};
module.prototype.createStorage = function(storageType) {
if (testStorage(storageType)) {
M.storage = createProxyStorage(storageType);
} else {
M.storage = createFallbackStorage(storageType);
}
};
function testStorage(storageType) {
var storage;
try {
storage = window[storageType];
storage.setItem("test", 1);
storage.removeItem("test");
return true;
} catch (e) {
return false;
}
}
function getNamespacedKey(key, ns) {
if (typeof ns === "undefined") {
ns = window.famobi_gameID;
}
if (ns.length) {
key = ns + ":" + key;
}
return key;
}
// Create a storage proxy (same api like local-/sessionStorage) with double the data!
function createProxyStorage(storageType) {
return {
data: {},
getItem: function(key, ns) {
key = getNamespacedKey(key, ns);
return window[storageType].getItem(key);
},
getProxyItem: function(key, ns) {
key = getNamespacedKey(key, ns);
return this.data[key];
},
setItem: function(key, value, ns) {
key = getNamespacedKey(key, ns);
this.data[key] = value;
this.updateLength();
window[storageType].setItem(key, value);
},
removeItem: function(key, ns) {
key = getNamespacedKey(key, ns);
try {
delete this.data[key];
} catch (e) {}
this.updateLength();
window[storageType].removeItem(key);
},
clear: function() {
for (var key in window[storageType]) {
if (key.indexOf(window.famobi_gameID) === 0)
this.removeItem(key, "");
}
},
key: function(i) {
var keys = [];
for (var key in window[storageType]) {
if (key.indexOf(window.famobi_gameID) === 0) keys.push(key);
}
return typeof keys[i] === "undefined" ? null : keys[i];
},
updateLength: function() {
M.length = self.sizeOf(this.data);
},
getKeys: function() {
var keys = [];
for (var key in window[storageType]) {
if (key.indexOf(window.famobi_gameID) === 0) keys.push(key);
}
return keys;
}
};
}
// Create a storage stub (same api like local-/sessionStorage)
function createFallbackStorage() {
return {
data: {},
getItem: function(key, ns) {
key = getNamespacedKey(key, ns);
return this.data[key];
},
setItem: function(key, value, ns) {
key = getNamespacedKey(key, ns);
this.data[key] = value;
this.updateLength();
},
removeItem: function(key, ns) {
key = getNamespacedKey(key, ns);
try {
delete this.data[key];
} catch (e) {}
this.updateLength();
},
clear: function() {
for (var key in this.data) {
if (key.indexOf(window.famobi_gameID) === 0)
this.removeItem(key, "");
}
},
key: function(i) {
var keys = [];
for (var key in this.data) {
if (key.indexOf(window.famobi_gameID) === 0) keys.push(key);
}
return typeof keys[i] === "undefined" ? null : keys[i];
},
updateLength: function() {
M.length = self.sizeOf(this.data);
},
getKeys: function() {
var keys = [];
for (var key in this.data) {
keys.push(key);
}
return keys;
}
};
}
module.prototype.getStorage = function() {
return M.storage;
};
module.prototype.getItem = function(key, ns) {
var value = M.getStorage().getItem(key, ns);
return value;
};
module.prototype.setItem = function(key, value, ns) {
return M.getStorage().setItem(key, value, ns);
};
module.prototype.removeItem = function(key, ns) {
if (window.top != window.self) {
window.top.postMessage(
{
scope: "famobi_sdk",
method: "removeItem",
package_id: window.famobi_gameID,
aid: self.config.aid,
data: {
key: getNamespacedKey(key, ns)
}
},
"*"
);
}
return M.getStorage().removeItem(key, ns);
};
module.prototype.clear = function() {
return M.getStorage().clear();
};
module.prototype.key = function(i) {
return M.getStorage().key(i);
};
module.prototype.getKeys = function() {
return M.getStorage().getKeys();
};
M = new module();
M.init(type);
return M;
};
fg_api.prototype.highscoresModule = function() {
var self = this,
M;
function module() {
// define private vars
this.max = null;
this.livescore = null;
}
module.prototype.init = function() {};
module.prototype.getMaxScore = function() {
return this.max;
};
module.prototype.setMaxScore = function(score) {
this.max = Math.max(this.max, score);
};
module.prototype.setLiveScore = function(score) {
this.livescore = score;
};
// eslint-disable-next-line no-unused-vars
module.prototype.submitLiveScore = function(score) {
score = Number(score);
return self;
};
module.prototype.submit = function(level, score, callback) {
level =
typeof level !== "undefined" && (level.length || level > 0)
? level
: "0";
score = Number(score);
callback = typeof callback !== "function" ? function() {} : callback;
if (!self.hasFeature("highscores")) {
self.showAd(callback);
return self;
}
function listScores(opts) {
self.notify.create(opts);
// Get you data and remove last list entry
var youData = opts.scores.pop() || [];
youData.name = youData.name || "Guest";
youData.ranks = youData.ranks ? youData.ranks.toLocaleString() : 1;
var infoDiv = self.createElement("div", {
class: "fg-leaderboard"
});
var lastRoundWinner = self.createElement("div", {
class: "fg-leaderboard-lastroundwinner"
});
var currentScore = self.createElement("div", {
class: "fg-leaderboard-currentscore"
});
var headline = self.createElement("div", {
class: "fg-leaderboard-headline"
});
var countDown = self.createElement("div", {
class: "fg-leaderboard-countdown"
});
var countDownHolder = self.createElement("div", {
class: "fg-leaderboard-countdown-holder"
});
var editNickHolder = self.createElement("div", {
class: "fg-leaderboard-editnick"
});
var leaderboardList = self.createElement("table");
var leaderboardListEntries = "";
var leaderboardListEntry = null;
var leaderBoardYouEntry = self.createElement("div", {
class: "fg-leaderboard-you hide"
});
var youClass = "";
var youText = "";
var youEditLink = "";
var rankClass = "";
var numEntry = 1;
opts.winner.name = opts.winner.name || "Guest";
opts.winner.score = opts.winner.score || 0;
if (opts.winner.score) {
lastRoundWinner.innerHTML =
"<h2>Winner yesterday</h2><strong>" +
opts.winner.name +
" <small>" +
opts.winner.score.toLocaleString() +
'</small><span class="profileImageHolder"></span></strong>';
faZepto(lastRoundWinner)
.find(".profileImageHolder")
.html(M.getProfileBarCode(opts.winner.hash));
}
headline.innerHTML = "<h2>Leaderboard today</h2>";
editNickHolder.innerHTML =
'<h2>Change your nick:</h2><input type="text"> <a href="javascript:;" class="saveNick">Save</a> <a href="javascript:;" class="cancelEditNick">Cancel</a>';
leaderBoardYouEntry.innerHTML =
'<div class="rank"></div><div class="profileImage"><div class="profileImageHolder"></div></div><div class="player"><em></em> <a href="javascript:;" class="editNick">Edit</a></div><div class="score"></div>';
faZepto(leaderBoardYouEntry).addClass("rank_" + youData.rank);
faZepto(leaderBoardYouEntry)
.find(".editNick")
.attr("data-nick", youData.name);
faZepto(leaderBoardYouEntry)
.find(".rank")
.text("#" + youData.rank);
faZepto(leaderBoardYouEntry)
.find(".profileImage .profileImageHolder")
.html(M.getProfileBarCode(youData.hash));
faZepto(leaderBoardYouEntry)
.find(".player em")
.text(
youData.name + (youData.name !== "Guest" ? "" : " (You)")
);
faZepto(leaderBoardYouEntry)
.find(".score")
.text(
typeof youData.score === "number"
? youData.score === 0
? "-"
: youData.score.toLocaleString()
: youData.score
);
countDown.innerHTML =
youData.ranks +
" Players • <span data-cn='" +
opts.ttl +
"'>" +
self.seconds2time(opts.ttl) +
"</span> left";
self.countdown(faZepto(countDown).find("span"), function() {
self.notify.close();
self.wait(1e3).then(function() {
M.submit(level, 0);
});
});
var highscoreText = "Your score: ";
if (opts.added >= 0) {
highscoreText = "New high score: ";
faZepto(currentScore).addClass("newHighscore");
}
if (score !== 0) {
currentScore.innerHTML =
highscoreText +
(typeof score === "number"
? score.toLocaleString()
: score);
}
opts.scores.forEach(function(entry) {
youClass = "";
youText = "";
youEditLink = "";
rankClass = "rank_" + numEntry;
entry.name = entry.name || "Guest";
if (typeof entry.me !== "undefined") {
youClass = " you";
youText = entry.name !== "Guest" ? "" : " (You)";
youEditLink =
' <a href="javascript:;" class="editNick">Edit</a>';
}
leaderboardListEntry = faZepto(
'<tr><td class="rank"></td><td class="profileImage"><div class="profileImageHolder"></div></td><td class="player"><em></em>' +
youEditLink +
'</td><td class="score"></td></tr>'
);
leaderboardListEntry
.find(".editNick")
.attr("data-nick", entry.name);
leaderboardListEntry
.find(".rank")
.text("#" + entry.rank || "-/-");
leaderboardListEntry
.find(".profileImage .profileImageHolder")
.html(M.getProfileBarCode(entry.hash));
leaderboardListEntry
.find(".player em")
.text(entry.name + youText);
leaderboardListEntry
.find(".score")
.text(
typeof entry.score === "number"
? entry.score === 0
? "-"
: entry.score.toLocaleString()
: entry.score.toString()
);
leaderboardListEntries +=
'<tr class="' +
rankClass +
youClass +
'">' +
leaderboardListEntry.html() +
"</tr>";
numEntry++;
});
leaderboardList.innerHTML = leaderboardListEntries;
if (lastRoundWinner.innerHTML !== "") {
infoDiv.appendChild(lastRoundWinner);
}
infoDiv.appendChild(headline);
countDownHolder.appendChild(countDown);
infoDiv.appendChild(countDownHolder);
infoDiv.appendChild(currentScore);
infoDiv.appendChild(editNickHolder);
infoDiv.appendChild(leaderBoardYouEntry);
infoDiv.appendChild(leaderboardList);
self.notify.setContent(infoDiv);
faZepto(infoDiv)
.find("a.editNick")
.each(function() {
self.handleClick(this, function() {
var nick = faZepto(this).attr("data-nick");
var $input = faZepto(".fg-leaderboard-editnick input");
var $notify = faZepto(".fg-notify");
$notify.addClass("editNick");
$input.val(nick);
$input.get(0).select();
});
});
faZepto(infoDiv)
.find("a.cancelEditNick")
.each(function() {
self.handleClick(this, function() {
var $notify = faZepto(".fg-notify");
$notify.removeClass("editNick");
self.notify.setScrollAreaHeight();
});
});
faZepto(infoDiv)
.find("a.saveNick")
.each(function() {
self.handleClick(this, function() {
var nick = faZepto(
".fg-leaderboard-editnick input"
).val();
if (nick == null) {
return;
}
html5games_api.updateProfile({
nick: nick || "Anonymous"
});
self.notify.close();
self.wait(1e3).then(function() {
M.submit(level, 0);
});
});
});
// Check if "you" line is in visible area
function checkYouPos() {
var $scrollArea = faZepto(".fg-notify-scrollarea");
if (!$scrollArea.length) {
return;
}
var $youLine = faZepto(".fg-leaderboard table tr.you");
var scrollAreaFrom = $scrollArea.offset().top;
var scrollAreaTo = scrollAreaFrom + $scrollArea.height();
if ($youLine.length > 0) {
var youLineFrom = $youLine.offset().top;
var youLineTo = youLineFrom + $youLine.height();
if (
youLineTo < scrollAreaFrom ||
youLineFrom > scrollAreaTo
) {
faZepto(leaderBoardYouEntry).removeClass("hide");
} else {
faZepto(leaderBoardYouEntry).addClass("hide");
}
} else {
faZepto(leaderBoardYouEntry).removeClass("hide");
}
}
faZepto(".fg-notify-scrollarea").on("scroll", checkYouPos);
self.onorientationchange(checkYouPos);
checkYouPos();
}
self.showAd(function() {
callback();
// Run Adapter if possible
if (self.adapters.run("highscore", "submit", level, score)) {
return self;
}
// Use HTML5Games.com Leaderboards
if (typeof html5games_api !== "undefined") {
// Only send total scores, not level scores
if (
level === "TOTAL" &&
(self.config.aid === "A-MONKEY" ||
self.config.aid === "A-MONKEY-DEV" ||
self.config.aid === "A-NLYWA")
) {
M.setMaxScore(Math.max(M.getMaxScore(), score));
Promise.race([
self.wait(3e3),
html5games_api.submitScore({
score: score
})
])
.then(function(leaderboard) {
if (!leaderboard) {
return;
}
// check if it was a new high score
// -1 = no entry saved
// 0 = entry overwritten with higher score
// 1 = new entry
if (leaderboard.added < 0) {
return;
}
leaderboard.ttl = Math.max(
0,
Number(leaderboard.ttl)
);
if (leaderboard.scores.length) {
listScores(leaderboard);
}
})
.catch(function(reason) {
self.log(reason);
self.spinner.hide();
});
return self;
}
}
});
return self;
};
module.prototype.show = function(level) {
if (self.hasFeature("highscores")) {
// Run Adapter if possible
if (self.adapters.run("highscore", "show", level)) {
return self;
}
}
return self;
};
module.prototype.getProfileBarCode = function(hash) {
var html = "";
if (hash) {
while (hash.length >= 6) {
var col = hash.substr(0, 6);
hash = hash.substr(6);
html += '<span style="background-color:#' + col + ';"></span>';
}
}
return html;
};
module.prototype.get = function() {
return self.sessionStorage.getItem("famobi:score");
};
module.prototype.del = function() {
self.sessionStorage.delItem("famobi:score");
};
module.prototype.submitHighscoreCallback = function() {
M.del();
faZepto(self.rootElement).trigger("fg_api.submitHighscore");
};
M = new module();
M.init();
return M;
};
fg_api.prototype.submitHighscore = function(level, score) {
var self = this;
return new Promise(function(resolve) {
if (self.hasFeature("highscores")) {
return self.highscores.submit(level, score, resolve);
}
resolve();
});
};
fg_api.prototype.showHighscore = function() {
this.highscores.show();
};
fg_api.prototype.getHighscore = function() {
return this.highscores.get();
};
fg_api.prototype.submitHighscoreCallback = function() {
this.highscores.submitHighscoreCallback();
};
fg_api.prototype.setLiveScore = function() {
//this.highscores.setLiveScore(score);
};
fg_api.prototype.screenshotModule = function() {
// http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata
var self = this,
M;
function module() {
this.clipClicked = false;
this.options = {
width: 480,
height: 640
};
this.savingTryoutsNum = 5;
this.savingTryoutsInterval = 3000;
this.savingLocked = false;
this.savingInterval = null;
this.releaseSavingTimeout = null;
this.releaseTimeout = 20000;
}
function getCameraIcon() {
return '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="30px" height="30px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve"><g id="CAMERA_1_" enable-background="new "><g id="CAMERA"><g><path d="M32,22c-6.627,0-12,5.372-12,12c0,6.627,5.373,12,12,12s12-5.373,12-12S38.627,22,32,22z M61,12H48.243l-5.095-5.094l-0.002,0.003C42.602,6.35,41.843,6,41,6H23c-0.976,0-1.835,0.474-2.383,1.196L15.813,12H3c-1.657,0-3,1.343-3,3v40c0,1.657,1.343,3,3,3h58c1.657,0,3-1.343,3-3V15C64,13.343,62.657,12,61,12z M32,52c-9.941,0-18-8.059-18-18c0-9.941,8.059-18,18-18c9.941,0,18,8.059,18,18C50,43.941,41.941,52,32,52z"/></g></g></g></svg>';
}
function initClip() {
var fgFotoshootOverlay = self.createElement("div", {
id: "fg-fotoshoot-overlay"
});
if (
self.config.gameParams.screenshot &&
self.config.gameParams.screenshot.camera
) {
fgFotoshootOverlay.style.top = "auto"; //reset css
fgFotoshootOverlay.style.right = "auto"; //reset css
var cameraConfig = self.config.gameParams.screenshot.camera;
for (var idx in cameraConfig.position) {
if (cameraConfig.position[idx]) {
var direction = cameraConfig.position[idx];
switch (direction) {
case "top":
case "bottom":
fgFotoshootOverlay.style[direction] =
cameraConfig.y + "%";
break;
case "right":
case "left":
fgFotoshootOverlay.style[direction] =
cameraConfig.x + "%";
break;
}
}
}
}
fgFotoshootOverlay.innerHTML = getCameraIcon();
self.rootElement.appendChild(fgFotoshootOverlay);
self.handleClick(fgFotoshootOverlay, takeScreenshot);
}
function getScreenshotParam(name) {
if (self.config.gameParams.screenshot[name]) {
return self.config.gameParams.screenshot[name];
}
}
module.prototype.init = function() {
// is feature disabled
if (!self.hasFeature("screenshot")) {
return;
}
// hasn't special screenshot settings configured
// or screenshot feature is disabled (again???)
// or no screenshot areas defined
if (
!self.config.gameParams.screenshot ||
!self.config.gameParams.screenshot.active ||
!self.sizeOf(self.config.gameParams.screenshot.areas)
) {
return false;
}
self.iframe.subscribePostMessageListener(
"screenshot",
"handleScreenshotSave",
handleScreenshotSave
);
initClip();
};
function discardScreenshotUpload() {
self.modal.close();
}
function releaseUploadLock() {
M.savingLocked = false;
}
function lockUpload() {
M.savingLocked = true;
}
function uploadScreenshot(imageSrc) {
if (M.savingLocked) {
return false;
}
M.fgSaveScreenshot.classList.add("fg-screenshot-btn-loading");
lockUpload();
faZepto.ajax({
type: "POST",
url: self.config.urlRoot + "/services/upload/images",
data: {
reference_id: self.config.uuid,
pingback: "services/upload",
file: imageSrc,
type: "screenshot"
},
dataType: "json",
success: function(response) {
handleScreenshotSave({
url: response.data.public,
txid: response.data.reference.id
});
}
});
return self;
}
function handleScreenshotSave(data) {
var countTryouts = 0;
var image;
if (!data.url || !data.txid) {
return false; //Unknown error
}
// store transaction id from server
M.txid = data.txid;
image = new Image();
image.src = data.url;
image.onload = function() {
imageLoaded(true);
};
image.onerror = function() {
countTryouts++;
if (countTryouts >= M.savingTryoutsNum) {
imageLoaded(false);
}
};
function imageLoaded(imageHasLoaded) {
clearInterval(M.savingInterval);
clearTimeout(M.releaseSavingTimeout);
releaseUploadLock();
if (imageHasLoaded) {
self.modal.close();
M.fgSaveScreenshot.classList.add(
"fg-screenshot-btn-loading-complete"
);
self.showAd(function() {
// Run Adapter if possible
self.adapters.run("screenshot", "submit", data.url, {
width: M.options.width,
height: M.options.height
});
});
} else {
self.modal.shake();
M.fgSaveScreenshot.classList.add(
"fg-screenshot-btn-loading-fail"
);
setTimeout(function() {
M.fgSaveScreenshot.classList.remove(
"fg-screenshot-btn-loading-fail"
);
M.fgSaveScreenshot.classList.remove(
"fg-screenshot-btn-loading"
);
}, 1500);
}
}
}
function getCanvas(canvasID) {
return canvasID
? document.getElementById(canvasID)
: document.getElementsByTagName("canvas")[0];
}
function createImageFromCanvas(canvas, area) {
var image = new Image();
image.src = canvas.toDataURL("image/jpeg");
var targetHeight = 0,
targetWidth = 0;
// calculate based on percentage configured in screenshot params
var slicing = {
width: (image.width / 100) * area.width,
height: (image.height / 100) * area.height,
x: (image.width / 100) * area.x,
y: (image.height / 100) * area.y
};
slicing.aspectRatio = slicing.width / slicing.height;
var aspectRatioCanvas = M.options.width / M.options.height;
// rotate target canvas
if (Math.floor(slicing.aspectRatio) !== Math.floor(aspectRatioCanvas)) {
var tmp = M.options.height;
M.options.height = M.options.width;
M.options.width = tmp;
aspectRatioCanvas = M.options.width / M.options.height;
}
function byHeight() {
targetHeight = M.options.height;
targetWidth = M.options.height * slicing.aspectRatio;
}
function byWidth() {
targetWidth = M.options.width;
targetHeight = M.options.width / slicing.aspectRatio;
}
if (slicing.aspectRatio > 1) {
byHeight();
} else {
byWidth();
}
if (targetWidth > M.options.width) {
byWidth();
}
if (targetHeight > M.options.height) {
byHeight();
}
// find center postion of image
var positionX = (M.options.width - targetWidth) / 2;
var positionY = (M.options.height - targetHeight) / 2;
return {
element: image,
slicing: slicing,
positionX: parseInt(positionX),
positionY: parseInt(positionY),
targetWidth: parseInt(targetWidth),
targetHeight: parseInt(targetHeight),
createTemporaryCanvas: function() {
return self.createElement("canvas", {
width: M.options.width,
height: M.options.height
});
}
};
}
function getCanvasContext(canvas) {
return canvas.getContext("2d");
}
function cropImage(canvas, area) {
var image = createImageFromCanvas(canvas, area);
var tempCanvas = image.createTemporaryCanvas();
var ctx = getCanvasContext(tempCanvas);
ctx.drawImage(
image.element,
image.slicing.x,
image.slicing.y,
image.slicing.width,
image.slicing.height,
image.positionX,
image.positionY,
image.targetWidth,
image.targetHeight
);
var imageSrc = canvas.toDataURL("image/jpeg", 0.7);
image = null;
tempCanvas = null;
ctx = null;
return imageSrc;
}
function displayScreenshotOverlay(imageSrc) {
self.modal.create({
showCloseBtn: false,
transparent: true
});
// screenshot container
var fgScreenshot = self.createElement("div", {
class: "fg-screenshot"
});
// upload screenshot image (link)
M.fgSaveScreenshot = self.createElement("a", {
class: "fg-screenshot-btn-upload"
});
M.fgSaveScreenshot.innerHTML =
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><polygon id="check-mark-icon" points="398.218,92.985 199.729,291.475 113.754,205.476 50,269.242 199.733,419.015 462,156.726 "/></svg>';
self.handleClick(M.fgSaveScreenshot, function() {
uploadScreenshot(imageSrc);
});
fgScreenshot.appendChild(M.fgSaveScreenshot);
// discard screenshot image (link)
var fgDiscardScreenshot = self.createElement("a", {
class: "fg-screenshot-btn-discard"
});
fgDiscardScreenshot.innerHTML =
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><polygon id="x-mark-icon" points="438.393,374.595 319.757,255.977 438.378,137.348 374.595,73.607 255.995,192.225 137.375,73.622 73.607,137.352 192.246,255.983 73.622,374.625 137.352,438.393 256.002,319.734 374.652,438.378 "/></svg>';
self.handleClick(fgDiscardScreenshot, discardScreenshotUpload);
fgScreenshot.appendChild(fgDiscardScreenshot);
var fgScreenshotImage = self.createElement("img", { src: imageSrc });
fgScreenshot.appendChild(fgScreenshotImage);
self.modal.setContent(faZepto(fgScreenshot).get(0));
self.modal.setDimensions(M.options.width, M.options.height);
self.modal.setCloseCallback(function() {
self.clipClicked = false;
});
}
function takeScreenshot(area) {
if (self.clipClicked) {
return false;
}
self.clipClicked = true;
// reset transaction id
M.txid = null;
if (getScreenshotParam("areas")) {
if (area && getScreenshotParam("areas")[area]) {
area = getScreenshotParam("areas")[area];
} else if (getScreenshotParam("areas")["default"]) {
area = getScreenshotParam("areas")["default"];
} else {
area = null;
}
}
if (!area) {
throw Error("No areas defined");
}
var originalCanvas = getCanvas(M.canvasID);
var imageSrc = cropImage(originalCanvas, area);
displayScreenshotOverlay(imageSrc);
}
M = new module();
M.init();
return M;
};
fg_api.prototype.navigationModule = function() {
var self = this,
M;
function module() {
this.eventHandler = function() {};
}
module.prototype.init = function() {
self.fgNavigation = document.createElement("nav");
self.fgNavigation.style.position = "relative";
self.fgNavigation.setAttribute("id", "fg-navigation");
faZepto(self.headElement).append(self.config.style);
if (window.top !== window.self) {
// hide navigation inside frames
return self;
}
self.fgOverlay.innerHTML = self.config.headerHtml;
self.fgOverlay.appendChild(self.fgNavigation);
self.fgOverlay_visible = false;
self.fgHeader = document.getElementById("fg-header");
faZepto("#fg-clip, #fg-logo").each(function() {
self.handleClick(this, toggleOverlay);
});
if (detection.is.android || detection.is.ios) {
faZepto(self.fgOverlay).addClass("isMobile");
}
function toggleOverlay(e) {
if (self.fgOverlay_visible) {
M.hideAll();
} else {
M.show();
}
e.stopPropagation();
return false;
}
// Init Left-Hand-Navigation
if (self.hasFeature("menu")) {
M.setHtml(self.config.menuHtml);
}
return self;
};
module.prototype.bindEvents = function() {
faZepto("[data-switch-lang]").each(function() {
var $this = faZepto(this),
lang = faZepto(this).attr("data-switch-lang");
$this.removeClass("fg-lang-selected");
if (lang === self.gametranslation.curLangString) {
// Move selected language to first position
$this.closest("ul").prepend($this);
$this.addClass("fg-lang-selected");
}
self.handleClick(this, function() {
if ($this.hasClass("fg-lang-selected") === true) {
M.toggleLanguages();
} else {
if (lang.length) {
M.switchLanguage(lang);
}
}
});
});
faZepto("[data-famobi-href]")
.css("cursor", "pointer")
.each(function() {
var callback = function() {
var link = faZepto(this).attr("data-famobi-href");
M.hideAll();
switch (link) {
case "moreGames":
return self.moreGamesLink();
case "back":
return self.backLink();
default:
if (this.href) {
window.open(this.href, "");
return false;
}
}
};
self.handleClick(this, callback.bind(this));
});
faZepto("[data-famobi-fullscreen]").each(function() {
self.handleClick(this, M.switchFullscreen);
});
faZepto("[data-famobi-screenshot]").each(function() {
self.handleClick(this, M.takeScreenshot);
});
};
module.prototype.toggleLanguages = function() {
var $overlayNode = faZepto(self.fgOverlay);
if ($overlayNode.hasClass("fa-lang-shown")) {
$overlayNode.removeClass("fa-lang-shown");
} else {
$overlayNode.addClass("fa-lang-shown");
}
};
module.prototype.switchLanguage = function(lang) {
var params = self.getUrlParams(),
qs = "";
M.hideAll();
params.locale = lang;
qs = faZepto.param(params);
document.location.replace(
document.location.pathname +
"?" +
qs +
(document.location.hash ? document.location.hash : "")
);
};
module.prototype.switchFullscreen = function() {
M.hideAll();
self.fullscreen.toggle();
return true;
};
module.prototype.takeScreenshot = function() {
self.screenshot.shoot();
};
module.prototype.show = function() {
if (self.fgOverlay_visible) {
return self;
}
var $fullscreenIcon = faZepto("#fg-overlay .fa-menu-button-fullscreen");
M.hideAll();
M.eventHandler = self.handleClick(faZepto("html").get(0), M.hideAll);
faZepto("html").get(0).style.cursor = "pointer";
if (
!document.fullscreenElement &&
!document.mozFullScreenElement &&
!document.webkitFullscreenElement &&
!document.msFullscreenElement
) {
$fullscreenIcon
.removeClass("fa-fullscreen-enabled")
.addClass("fa-fullscreen-disabled");
} else {
$fullscreenIcon
.removeClass("fa-fullscreen-disabled")
.addClass("fa-fullscreen-enabled");
}
self.fgOverlay_visible = true;
faZepto(self.fgOverlay).addClass("navigation-view");
self.fgNavigation.style.display = "";
return self;
};
module.prototype.hide = function() {
return M.hideAll();
};
// hide all views (navigation, iframe, maybe more) call before you want to display a new "view"
module.prototype.hideAll = function() {
if (!self.fgOverlay_visible) {
return self;
}
if (M.eventHandler) {
self.removeClick(faZepto("html").get(0), M.eventHandler);
}
var $fgOverlay = faZepto(self.fgOverlay);
$fgOverlay.removeClass("iframe-view navigation-view fa-lang-shown");
self.fgOverlay_visible = false;
return self;
};
module.prototype.invisible = function() {
self.fgOverlay.style.display = "none";
};
module.prototype.visible = function() {
self.fgOverlay.style.display = "";
};
module.prototype.getMoreGamesLink = function() {
return self.debug ? self.__("more_games_url") : "javascript:void(0);";
};
module.prototype._moreGamesLink = function(popup) {
// disable for testing
if (!self.debug) {
return false;
}
var moreGamesLink = M.getMoreGamesLink();
if (
!moreGamesLink ||
moreGamesLink == "http://" ||
moreGamesLink == "javascript:"
) {
// jshint ignore:line
return false;
}
// disable more games link when overlays are visible
// (accidential click events triggered by engines like Construct2)
if (
faZepto("#fg-root .fg-ad-container").height() > 0 ||
faZepto("#fg-root .fg-click2play").height() > 0
) {
return false;
}
// disable link when gremlins are active
if (typeof gremlins !== "undefined") {
return false;
}
// disable link when banner ads active (prevent overlap while wip)
if (self.banner && self.banner.isEnabled()) {
return false;
}
// open link in new window
if (typeof popup == "undefined") {
popup = false;
}
if (!popup || !window.open(moreGamesLink, "")) {
try {
window.top.location.href = moreGamesLink;
} catch (ex) {
window.location.href = moreGamesLink;
}
}
return true;
};
module.prototype.moreGamesLink = function(popup) {
return M._moreGamesLink(popup);
};
module.prototype.setHtml = function(html) {
self.fgNavigation.innerHTML = html;
M.bindEvents();
self.gametranslation.translateHtml(faZepto(self.fgNavigation));
};
module.prototype.getAlsoLikedApps = function() {};
M = new module();
M.init();
return M;
};
fg_api.prototype.backLink = function() {
var self = this;
// Fallback to previous page
if (history.length > 2) {
window.history.go(-2);
} else {
if (window.opener) {
try {
// iOS8 is missing window.close support, thanks AAPL
window.close();
} catch (ex) {
// SecurityError
}
}
// Fallback to more games url
self.moreGamesLink(false);
}
return false;
};
fg_api.prototype.moreGamesLink = function(popup) {
return this.navigation.moreGamesLink(popup);
};
fg_api.prototype.openBrandingLink = function(popup) {
return this.navigation.moreGamesLink(popup);
};
fg_api.prototype.getShortLink = function() {
return this.config.short_url;
};
fg_api.prototype.getAppLink = function() {
return (
"https://play.famobi.com/" +
window.famobi_gameID +
".app/" +
this.config.aid
);
};
fg_api.prototype.spinnerModule = function() {
var self = this,
M;
function module() {
// define private vars
this.spinner = "";
this.timeout = 15e3;
this.fadeoutTime = 500;
this.maxTimeout = null;
this.stateTimeout = null;
}
var spinnerPrototype = module.prototype;
spinnerPrototype.init = function() {
M.spinner = self.createElement("div", { class: "fg-spinner" });
//M.spinner.innerHTML = '<div class="fg-dot1"></div><div class="fg-dot2"></div><div class="fg-dot3"></div><div class="fg-dot4"></div><div class="fg-dot5"></div><div class="fg-dot6"></div><div class="fg-dot7"></div>';
M.spinner.innerHTML =
'<div id="cssload-pgloading"><div class="cssload-loadingwrap"><ul class="cssload-bokeh"><li></li><li></li><li></li><li></li></ul></div></div>';
self.rootElement.appendChild(M.spinner);
faZepto(M.spinner).css({
"display": "none",
"visibility": "visible"
});
M.spinnerOutline = self.createElement("div", {
class: "fg-spinner-outline"
});
M.spinnerOutline.innerHTML = "<div></div>";
self.rootElement.appendChild(M.spinnerOutline);
var fadeoutTimeCSS = (Math.round(M.fadeoutTime / 10) / 100) + "s";
faZepto(M.spinnerOutline).css({
"position": "absolute",
"display": "none",
"visibility": "hidden",
"top": "0",
"left": "0",
"right": "0",
"bottom": "0",
"background": "rgba(0,0,0,0.8)",
"transition-property": "opacity",
"transition-duration": fadeoutTimeCSS,
"transition-delay": "0s"
});
return this;
};
spinnerPrototype.show = function(timeout) {
M.spinnerState = "new";
M.spinner.style.display = "block";
M.spinnerOutline.style.display = "block";
self.wait(33).then(function(){
M.spinner.style.visibility = "visible";
M.spinnerOutline.style.visibility = "visible";
M.spinner.style.left = "50%";
M.spinner.style.opacity = "1.0";
M.spinnerOutline.style.opacity = "1.0";
// custom timeout
if (timeout) {
M.timeout = timeout;
} else {
// show spinner max 15sec
M.timeout = 15e3;
}
M.stateTimeout = setTimeout(function() {
if (M.spinnerState == "tryhide") {
M.spinnerState = "closeable";
M.hide();
} else {
M.spinnerState = "closeable";
}
}, 250);
M.maxTimeout = setTimeout(function() {
M.hide();
}, M.timeout);
})
return this;
};
spinnerPrototype.hide = function() {
if (M.spinnerState && M.spinnerState == "closeable") {
self.log('set spinner opacity to 0 @', Date.now());
M.spinner.style.opacity = "0";
M.spinnerOutline.style.opacity = "0";
setTimeout(function() {
self.log('set spinner display none @', Date.now());
M.spinner.style.display = "none";
M.spinnerOutline.style.display = "none";
M.spinner.style.visibility = "hidden";
M.spinnerOutline.style.visibility = "hidden";
}, M.fadeoutTime);
clearTimeout(M.maxTimeout);
clearTimeout(M.stateTimeout);
} else {
M.spinnerState = "tryhide";
}
return this;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.showSpinner = function(timeMillis) {
var self = this;
self.spinner.show(timeMillis);
};
fg_api.prototype.hideSpinner = function() {
var self = this;
self.spinner.hide();
};
fg_api.prototype.modalModule = function() {
var self = this,
M;
function module() {
// define private vars
this.element = "";
this.closing = false;
this.closeCallbacks = [];
}
module.prototype.init = function() {
self.iframe
.subscribePostMessageListener(
"modal",
"showModalCloseBtn",
function() {
M.showCloseBtn();
}
)
.subscribePostMessageListener("modal", "setModalHeader", function(
data
) {
M.setHeader(data.title);
})
.subscribePostMessageListener("modal", "close", function() {
M.close();
})
.subscribePostMessageListener(
"modal",
"setModalCloseBtnTimer",
function(data) {
self.spinner.hide();
M.setCloseBtnTimer(data.sec, data.options);
}
);
};
module.prototype.create = function(options) {
var opts = faZepto.extend(
{
overlayColor: null,
overlayStyle: {},
showCloseBtn: true,
title: ""
},
options
);
if (!M.closing) {
M.close(); // close all other window - it's a MODAL
}
self.navigation.invisible();
self.game.pause();
var className = "";
if (opts.mode) {
className = opts.mode + "-mode";
}
if (M.element && M.element.parentNode) {
M.element.parentNode.removeChild(M.element);
}
M.element = self.createElement("div", {
class: "fg-modal fg-fade fg-show " + className
});
if (M.overlay && M.overlay.parentNode) {
M.overlay.parentNode.removeChild(M.overlay);
}
M.overlay = self.createElement("div", { class: "fg-modal-overlay" });
if (opts.overlayColor) {
M.overlay.style.backgroundColor = opts.overlayColor;
}
if (opts.overlayStyle) {
faZepto(M.overlay).css(opts.overlayStyle);
}
self.rootElement.appendChild(M.overlay);
M.header = self.createElement("header", {});
M.element.appendChild(M.header);
M.body = self.createElement("div", { class: "fg-modal-body" });
M.element.appendChild(M.body);
self.rootElement.appendChild(M.element);
if (opts.showCloseBtn !== false) {
M.showCloseBtn();
}
if (opts.transparent) {
M.body.classList.add("fg-modal-transparent");
}
if (opts.title) {
M.setHeader(opts.title);
}
M.closeCallbacks.push(function() {
self.game.resume();
self.navigation.visible();
});
};
module.prototype.showCloseBtn = function() {
M.closeBtn = self.createElement("div", {
class: "fg-modal-close icon-cancel"
});
if (!M.element) {
return false;
}
M.element.appendChild(M.closeBtn);
self.handleClick(M.closeBtn, function() {
if (!this.getAttribute("data-disable")) M.close();
});
self.handleClick(M.overlay, function() {
if (
!M.closeBtn.getAttribute("data-disable") &&
!M.overlay.getAttribute("data-disable")
)
M.close();
});
};
module.prototype.setCloseCallback = function(callback) {
if (M.element && M.element.style.display !== "none") {
M.closeCallbacks.push(callback);
return true;
} else {
callback();
return false;
}
};
module.prototype.updateCloseBtn = function(disable) {
var currentSec = M.closeBtnTimer ? M.closeBtnTimer.current : 0;
if (disable) {
M.fallbackTimeout = setTimeout(M.updateCloseBtn, 5000);
} else if (M.fallbackTimeout) {
clearTimeout(M.fallbackTimeout);
}
if (!M.closeBtn) {
return;
}
if (currentSec > 0 || disable) {
M.closeBtn.innerHTML =
'<span class="counter">' + currentSec + "</span>" || "";
M.closeBtn.setAttribute("data-disable", "true");
} else {
M.closeBtn.innerHTML = "";
M.closeBtn.removeAttribute("data-disable");
}
};
module.prototype.setCloseBtnTimer = function(sec, options) {
if (!options) {
options = {};
}
M.clearCloseBtnTimer();
M.closeBtnTimer = {
autoclose:
typeof options.autoclose == "undefined"
? true
: options.autoclose,
sec: sec,
current: (options.faketime || sec) + 1,
timeout: 0,
options: options
};
M.closeBtnTicker();
};
module.prototype.clearCloseBtnTimer = function() {
if (M.closeBtnTimer && M.closeBtnTimer.timeout) {
clearTimeout(M.closeBtnTimer.timeout);
}
};
module.prototype.closeBtnTicker = function() {
var options = M.closeBtnTimer.options;
M.closeBtnTimer.current = Math.max(--M.closeBtnTimer.current, 0);
if (M.closeBtnTimer.current === 0 && M.closeBtnTimer.autoclose) {
M.close();
} else {
M.updateCloseBtn();
}
var faketime = parseInt(options.faketime || M.closeBtnTimer.sec, 10);
M.closeBtnTimer.timeout = setTimeout(
M.closeBtnTicker,
parseInt((M.closeBtnTimer.sec / faketime) * 1000, 10)
);
};
module.prototype.activateCloseBtn = function(state) {
if (!M.closeBtn) {
return false;
}
M.closeBtn.style.display = state ? "block" : "none";
if (state) {
M.closeBtn.removeAttribute("data-disable");
} else {
M.closeBtn.setAttribute("data-disable", "true");
}
};
module.prototype.activateCloseOverlay = function(state) {
if (!M.overlay) {
return false;
}
if (state) {
M.overlay.removeAttribute("data-disable");
} else {
M.overlay.setAttribute("data-disable", "true");
}
};
module.prototype.setContent = function(contentElement) {
if (contentElement) {
M.body.appendChild(contentElement);
}
};
module.prototype.setHeader = function(headline) {
headline = headline || "";
if (!M.header) {
return;
}
M.header.innerHTML = headline.length ? headline + "" : "";
M.header.style.display = headline.length ? "block" : "none";
};
module.prototype.setDimensions = function(width, height) {
if (!width || width === "") width = 480;
if (!height || height === "") height = 500;
M.element.style.maxHeight = parseInt(height, 10) + 60 + "px";
M.element.style.maxWidth = parseInt(width, 10) + 20 + "px";
M.element.style.display = "";
};
module.prototype.close = function() {
M.closing = true;
M.clearCloseBtnTimer();
if (M.element) {
M.element.style.display = "none";
} else {
return false;
}
if (M.overlay) {
M.overlay.style.display = "none";
} else {
return false;
}
faZepto.each(M.closeCallbacks, function(key, callback) {
if (typeof callback === "function") {
callback();
}
});
M.closeCallbacks = [];
M.closing = false;
};
module.prototype.closeAd = function() {
M.closing = true;
M.clearCloseBtnTimer();
faZepto.each(M.closeCallbacks, function(key, callback) {
if (typeof callback === "function") {
callback();
}
});
M.closeCallbacks = [];
M.closing = false;
};
module.prototype.shake = function(callback) {
M.element.classList.add("fg-modal-shake");
setTimeout(function() {
M.element.classList.remove("fg-modal-shake");
if (typeof callback === "function") {
callback();
}
}, 2000);
};
module.prototype.shakeAndClose = function() {
M.shake(M.close);
};
M = new module();
M.init();
return M;
};
fg_api.prototype.iframeModule = function() {
var self = this,
postMessageListeners = {},
M;
function module() {
// define private vars
}
var iframePrototype = module.prototype;
iframePrototype.init = function() {
listenForPostMessage();
};
iframePrototype.subscribePostMessageListener = function(
moduleName,
actionName,
callback
) {
if (!postMessageListeners[moduleName]) {
postMessageListeners[moduleName] = {};
}
postMessageListeners[moduleName][actionName] = callback;
// method chaining
return iframePrototype;
};
function hasPostMessageListener(message) {
return (
message.module &&
postMessageListeners[message.module] &&
message.action &&
postMessageListeners[message.module][message.action]
);
}
function notifyPostMessageListener(message) {
if (hasPostMessageListener(message)) {
return postMessageListeners[message.module][message.action](
message.data || {}
);
}
// self.error('Post message listener [' + (message.module || 'undefined') + '] with action [' + (message.action || 'undefined') + '] not found');
return false;
}
function onPostMessageReceive(e) {
var messageObject = e.data;
notifyPostMessageListener(messageObject);
}
function listenForPostMessage() {
// Use postMessage API for "secure" cross-domain message-passing
window.addEventListener("message", onPostMessageReceive, false);
}
iframePrototype.create = function() {
self.iframeContainer = self.createElement("div", {
id: "fg-iframe-container"
});
self.iframeElement = self.createElement("iframe", {
id: "fg-iframe",
class: "fg-iframe",
name: "fg-iframe",
src: "",
style: "background: transparent none;"
});
self.iframeContainer.appendChild(self.iframeElement);
return self;
};
iframePrototype.updateSize = function() {
if (self.iframeElement) {
self.iframeElement.style.height = "0px";
self.iframeElement.style.height = "100%";
}
return self;
};
/**
* Set the iframe's src="" attribute
*/
iframePrototype.load = function(src) {
self.comIframe = self.createElement("iframe", {
id: "fg-com-iframe",
name: "fg-com-iframe",
src: src
});
self.fgOverlay.appendChild(self.comIframe);
};
/**
* Displays the iframe with the specified width/height dimensions
*/
iframePrototype.show = function(url, options) {
var opts = faZepto.extend(
{
width: "",
height: ""
},
options
);
if (!self.iframeContainer) {
//create iframe if not exist
M.create();
}
self.navigation.hideAll();
self.modal.create(options);
if (url.length) {
if (url.indexOf("/") === 0) {
url = self.config.urlRoot + url;
}
self.iframeElement.setAttribute("src", url);
self.spinner.show(2e3);
self.iframeElement.onload = function() {
self.spinner.hide();
};
} else {
self.log("url not set");
}
if (opts.mode && opts.mode == "seamless") {
self.iframeElement.setAttribute("seamless", "seamless");
opts.height = "none";
}
if (opts.mode && opts.mode == "ad")
self.iframeElement.setAttribute("scrolling", "no");
else self.iframeElement.setAttribute("scrolling", "yes");
self.modal.setCloseCallback(function() {
if (self.iframeElement) {
self.iframeElement.setAttribute("src", "");
}
});
self.modal.setContent(self.iframeContainer); //insert iframe into modal
self.modal.setDimensions(opts.width, opts.height);
return self;
};
iframePrototype.hide = function() {
faZepto(self.fgOverlay).css({
"max-width": "",
"max-height": ""
});
return self;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.orientationModule = function() {
var self = this,
M;
function module() {
// define private vars
}
var orientationPrototype = module.prototype;
orientationPrototype.init = function() {
if (window.famobi_env === "vp") {
return self;
}
M.update(self.config.gameParams.orientation);
return self;
};
orientationPrototype.update = function(orientation) {
// show rotation screen?
if (
typeof orientation != "undefined" &&
self.hasFeature('rotation') &&
!detection.is.pc &&
!detection.is.tablet &&
window.screen &&
window.screen.height !== window.screen.width
) {
self.rootElement.className =
self.rootElement.className + " fg-orientation-" + orientation;
if (typeof M.fgLandscapeOverlay == "undefined") {
M.fgLandscapeOverlay = document.createElement("div");
M.fgLandscapeOverlay.setAttribute("id", "fg-landscape-overlay");
M.fgLandscapeImage = document.createElement("img");
M.fgLandscapeImage.setAttribute(
"src",
"/html5games/gameapi/v1/images/RotateToLandscape.png"
);
M.fgLandscapeImage.setAttribute("class", "fg-orientation-icon");
M.fgLandscapeImage.setAttribute("alt", "switch to landscape");
M.fgLandscapeOverlay.appendChild(M.fgLandscapeImage);
self.rootElement.appendChild(M.fgLandscapeOverlay);
}
if (typeof M.fgPortraitOverlay == "undefined") {
M.fgPortraitOverlay = document.createElement("div");
M.fgPortraitOverlay.setAttribute("id", "fg-portrait-overlay");
M.fgPortraitImage = document.createElement("img");
M.fgPortraitImage.setAttribute(
"src",
"/html5games/gameapi/v1/images/RotateToPortrait.png"
);
M.fgPortraitImage.setAttribute("class", "fg-orientation-icon");
M.fgPortraitImage.setAttribute("alt", "switch to portrait");
M.fgPortraitOverlay.appendChild(M.fgPortraitImage);
self.rootElement.appendChild(M.fgPortraitOverlay);
}
}
return self;
};
orientationPrototype.lock = function() {
var lockOrientation =
"orientation-lock" in self.config.gameParams
? self.config.gameParams["orientation-lock"]
: self.config.gameParams.orientation;
if ("orientation" in screen) {
// API supported, yeah!
if (!detection.is.smartphone) {
// exit here, if desktop, notebook or tablet device is detected. orientation is only valid for smartphones, tablets could use a responsive version of the game in a different orientation mode or just scale accordingly.
return true;
}
try {
switch (lockOrientation) {
case "portrait":
case "landscape":
screen.orientation.lock(lockOrientation + "-primary");
}
} catch (e) {
self.log(e);
}
} else {
// API not supported :(
}
};
orientationPrototype.unlock = function() {
if ("orientation" in screen) {
screen.orientation.unlock();
}
};
M = new module();
M.init().onorientationchange(function() {
//self.log('famobi.onorientationchange: ', self.getOrientation(), window.innerWidth, window.innerHeight);
});
return M;
};
fg_api.prototype.getOrientation = function() {
var orientation = "";
if (window.innerHeight != window.innerWidth) {
orientation = window.matchMedia("(orientation: portrait)").matches
? "portrait"
: "landscape";
}
return orientation;
};
fg_api.prototype.onOrientationChange = fg_api.prototype.onorientationchange = function(
callback
) {
if (typeof callback !== "function") {
this.error("famobi.onorientationchange: no valid callback provided.");
return null;
}
return faZepto(window).resize(callback);
};
if (typeof window !== "undefined" && !window.famobi_tracking) {
!function(a, b) {
var tracking = {
endpointUrl: 'https://data.html5games.com/',
game: '',
uidStorageId: 'trackingUid',
uid: null,
initializedUser: false,
debug: false,
version: 0,
queue: [],
currentPromise: Promise.resolve(),
runDry: false
};
var EVENTS = {
'LEVEL_START' : 'event/level/start',
'LEVEL_END' : 'event/level/end',
'LEVEL_UPDATE' : 'event/level/update',
'PING' : 'event/ping',
'AD' : 'event/ad'
}
var EVENT_PARAMS = {
'level': 'number', // The current level number
'score': 'number', // Scores
'stars': 'number', // Earned stars
'movesAvailable': 'number', // Total number of available moves
'movesLeft': 'number', // Moves left when the user finishes the level
'success': 'boolean', // User has successfully solved the level
'revives': 'number', // Number of ressurrections
'powerups': 'object', // Powerups used in the level
'jumpStarters': 'object', // Initial starting power ups used
'data': 'object' // Custom json object
}
function log() {
if (tracking.debug)
console.log.apply(this, arguments);
}
function initUser(preferredUid) {
var storage = window.hasOwnProperty('famobi') ? window.famobi.localStorage : window.localStorage;
var storedUid = storage.getItem(tracking.uidStorageId);
if (storedUid !== null && typeof storedUid !== 'undefined' &&
storedUid !== 'null' && storedUid !== 'undefined') {
log('tracking init - user id retrieved from storage', storedUid);
const params = {
'locale': (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
};
trackEvent("event/user/start", params);
return Promise.resolve(storedUid);
} else {
if (tracking.runDry) {
return Promise.resolve();
}
log('tracking init - no uid found in storage, requesting new user');
return new Promise(function(resolve, reject) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
log('tracking init - response', this.response);
var data = JSON.parse(this.response).data;
var splitTests = data.splitTests;
storage.setItem(tracking.uidStorageId, data.uid);
log('tracking initialized - new user id received', data.uid);
resolve(data.uid);
}
};
xhttp.onerror = function() {
log("xhttp error");
};
xhttp.addEventListener('error', function(e) {
log('tracking init - failed', e);
reject();
});
xhttp.open('POST', tracking.endpointUrl + 'event/user', true);
xhttp.setRequestHeader('Content-type', 'application/json');
xhttp.setRequestHeader('X-Version', tracking.version);
xhttp.setRequestHeader('X-Game', tracking.game);
xhttp.setRequestHeader('X-AID', window.famobi.config.aid);
window.famobi.getUrlParams()["original_ref"] && xhttp.setRequestHeader('X-Referrer', window.famobi.getUrlParams()["original_ref"]);
if (preferredUid && (typeof preferredUid == 'string' && preferredUid.length > 0 || typeof preferredUid == 'number' && preferredUid > 0)) {
xhttp.setRequestHeader('X-User', preferredUid);
} else {
xhttp.setRequestHeader('X-User', getRandomUUID());
}
var data = {
'locale': (navigator.languages && navigator.languages.length)
? navigator.languages[0]
: navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
};
if((window.famobi.config.aid || "").length) {
data.aid = window.famobi.config.aid;
}
const campaign = window.famobi.getUrlParams()['campaign'];
if (typeof campaign != "undefined"){
data.tag = campaign;
}
try{
xhttp.send(JSON.stringify(data));
} catch(e) {
log(e);
}
});
}
}
function init(game, preferredUid, clientVersion, debug, trackAds, runDry) {
if (debug) {
tracking.debug = true;
log('tracking init called');
}
if(!window.famobi.hasFeature("tracking") || runDry === true) {
tracking.runDry = true;
}
if (Number.isInteger(clientVersion)) {
tracking.version = clientVersion;
} else {
log('tracking init - clientVersion rejected, has to be integer');
}
if (tracking.initializedUser) {
log('tracking init cancelled - already initialized');
return;
}
if (typeof game === 'string' && game.length > 0) {
tracking.game = game;
} else {
log('tracking init - game rejected, has to be valid string');
return;
}
if (trackAds !== false && window.hasOwnProperty('famobi') && window.famobi.hasOwnProperty('adapters')) {
window.famobi.adapters.add('ads', 'callback', trackingAdCallback);
}
initUser(preferredUid).then(function(id) {
tracking.uid = id;
tracking.initializedUser = true;
processQueue();
});
}
function trackingAdCallback(result) {
log('adCallback event ', result);
if (result.adType != "rewarded" || result.rewardGranted == true) {
var _data = {
'adType': result.adType,
'fill': result.adDidLoad,
'blocked': window.google == undefined
};
trackEvent('AD', _data);
}
}
function trackEvent(event, data) {
var eventPath = (event in EVENTS) ? EVENTS[event] : event;
if (typeof eventPath !== 'string' || typeof data !== 'object' || data === null) {
log('tracking event cancelled - wrong/missing parameters', 'eventPath', eventPath, 'data', data);
return;
}
if (famobi.hasOwnProperty("adapters")) {
famobi.adapters.run("tracking", "trackEvent", eventPath, data);
}
log('queuing event', eventPath, 'with data', data);
tracking.queue.push({'eventPath': eventPath, 'data': data});
if (tracking.initializedUser)
processQueue();
}
function sendRequest(eventPath, data) {
log('tracking event', eventPath, 'with data', data);
if (tracking.runDry) {
return Promise.resolve();
}
return new Promise(function(resolve, reject) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
resolve();
}
};
xhttp.onerror = function() {
log("xhttp error");
};
xhttp.addEventListener('error', function(e) {
log('tracking send request failed -', e);
reject();
});
setTimeout(reject, 10000);
xhttp.open('POST', tracking.endpointUrl + eventPath, true);
xhttp.setRequestHeader('Content-type', 'application/json');
xhttp.setRequestHeader('X-Game', tracking.game);
xhttp.setRequestHeader('X-Version', tracking.version);
xhttp.setRequestHeader('X-User', tracking.uid);
xhttp.setRequestHeader('X-AID', window.famobi.config.aid);
try{
xhttp.send(JSON.stringify(data));
}catch(e) {
log(e);
}
});
}
function processQueue() {
tracking.queue.forEach(function(queuedEvent) {
tracking.currentPromise = tracking.currentPromise.then(function() {
return sendRequest(queuedEvent.eventPath, queuedEvent.data)
}, function() {
return sendRequest(queuedEvent.eventPath, queuedEvent.data)
});
});
tracking.queue = [];
}
function getRandomUUID() {
var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
b[a] = {
'EVENTS': EVENTS,
'trackEvent': trackEvent,
'init': init
}
}('famobi_tracking', window);
}
fg_api.prototype.trackingModule = function() {
var self = this,
M;
function module() {
this.promise = null;
this.isHidden = false;
this.famobi_gameIDs = {
"supported": [
"3d-basketball",
"3d-bowling",
"3d-chess",
"3d-darts",
"3d-free-kick",
"3d-free-kick-world-cup-18",
"7-words",
"8-ball-billiards-classic",
"8-ball-online",
"adventure-drivers",
"archery-world-tour",
"billiard-blitz-challenge",
"blaze-kick",
"blocks-puzzle-zoo",
"boat-battles",
"brain-trainer",
"bubble-tower-3d",
"bubble-woods",
"bus-parking-3d",
"butterfly-shimai",
"candy-bubble",
"cannon-balls-3d",
"chess-classic",
"city-dunk",
"color-pixel-art-classic",
"color-shape",
"color-tunnel",
"colorpop",
"crazy-caves",
"crazy-hen-level",
"crowd-run-3d",
"cubito",
"curve-ball-3d",
"dance-battle",
"diamond-rush",
"diamond-rush-2",
"dices-2048-3d",
"dominoes-classic",
"drift-cup-racing",
"drift-dudes",
"duo-cards",
"e-scooter",
"element-blocks",
"emoji-flow",
"emoji-match",
"endless-truck",
"euro-penalty-2016",
"euro-penalty-cup",
"euro-penalty-cup-2021",
"find-500-differences",
"food-rush",
"foot-chinko",
"frankenstein-go",
"freecell-solitaire-classic",
"fruit-ninja",
"fuzzies",
"garden-bloom",
"garden-match-3d",
"giant-2048",
"giant-attack",
"good-shelves",
"gold-mine",
"gold-miner-tom",
"gun-spin",
"hoop-royale",
"jetpack-joyride",
"jigsaw-puzzle-deluxe",
"jungle-run",
"knife-rain",
"lovetester3",
"love-tester",
"mahjong-3d",
"mahjong-classic",
"mahjong-world",
"mandala-coloring-book",
"maze",
"merge-jewels",
"monkey-bounce",
"neon-swing",
"neon-tower",
"neon-swing",
"om-nom-bubbles",
"om-nom-connect-classic",
"om-nom-run",
"onet-connect-classic",
"onet-gallery-3d",
"onet-world",
"parking-rush",
"parking-panic",
"peet-a-lock",
"peet-around",
"pengu-slide",
"perfect-piano",
"pets-rush",
"pirates-the-match-3",
"pop-it-3d",
"pop-it-duel",
"pull-pins",
"ramp",
"save-the-princess",
"slice-rush",
"slope",
"smarty-bubbles",
"smarty-bubbles-2",
"soccer-bubbles",
"soccertastic",
"soccertastic-world-cup-18",
"solitaire-classic",
"solitaire-klondike",
"square-stacker",
"stack-smash",
"stair-race-3d",
"sudoku-classic",
"super-thrower",
"sushi-roll",
"table-tennis-world-tour",
"tap-tap-dunk",
"tile-journey",
"tnt-bomb",
"totemia-cursed-marbles",
"tower-crash-3d",
"tower-smash",
"tower-smash-level",
"traffic-tom",
"train-2048",
"truck-trials",
"uncle-ahmed",
"word-bird",
"word-detector",
"word-search-classic",
"words-of-wonders",
"world-cup-penalty-2018",
"zoo-boom"
],
"blocked": [
],
mapping: {
"bubble-tower-3d": "bubbles-tower-3d",
"lovetester3": "lovetester",
"tower-crash-3d": "tower-crash",
"cannon-balls-3d": "cannon-balls",
"blocks-puzzle-zoo": "blocks-puzzle"
}
};
if(self.getUrlParams().fg_env === "staging") {
famobi.log(this.famobi_gameIDs.mapping);
}
//this.famobi_gameIDs = {"supported":["smarty-bubbles-2", "zoo-boom"], "blocked":[]};
}
module.prototype.init = function() {
window.famobi_dataLayer =
window.famobi_dataLayer || window.dataLayer || [];
// Google tag: Trigger init event with additional params for analytics dimensions
window.famobi_dataLayer.push(
"event", "api_init", {
"package_id": window.famobi_gameID,
"affiliate_id": self.config.aid,
"referrer_origin": self.config.referrer_origin || "unknown",
"iframe_detected": detection.is.iframe ? "true" : "false",
"dfp_available": self.config.ads.dfp_available ? "true" : "false",
"referrer_matched": self.config.referrer_matched ? "true" : "false",
"first_ancestor_origin": self.config.first_ancestor_origin || "unknown",
"last_ancestor_origin": self.config.last_ancestor_origin || "unknown"
}
);
M.initializeFamobiTracking();
};
module.prototype.initializeFamobiTracking = function() {
if (M.promise) {
return M.promise;
}
M.promise = new Promise(function(resolve, reject) {
if(["A-MONKEYGAMES-DEV"].includes(self.config.aid)) {
reject("Famobi Tracking is not supported for this affiliate id");
return;
}
if (self.hasFeature("standalone") || M.famobi_gameIDs.blocked.includes(window.famobi_gameID)) {
reject("Famobi Tracking is not supported");
return;
}
function _onVisibilityChanged() {
if (document.hidden || document.mozHidden || document.webkitHidden || document.msHidden)
M.isHidden = true;
else
M.isHidden = false;
}
document.addEventListener("visibilitychange", _onVisibilityChanged, false);
document.addEventListener("mozvisibilitychange", _onVisibilityChanged, false);
document.addEventListener("webkitvisibilitychange", _onVisibilityChanged, false);
document.addEventListener("msvisibilitychange", _onVisibilityChanged, false);
if(typeof window.famobi_tracking !== "undefined") {
var debug = false,
runDry = false,
urlParams = self.getUrlParams();
if(!self.hasFeature("tracking") || !M.famobi_gameIDs.supported.includes(window.famobi_gameID)) {
runDry = true;
}
if(urlParams.fg_env && (urlParams.fg_env == "dev" || urlParams.fg_env == "staging")) {
debug = true;
}
try {
window.famobi_tracking.init((M.famobi_gameIDs.mapping[window.famobi_gameID] || window.famobi_gameID), null, 0, debug, true, runDry);
} catch (ex) {
famobi.log(ex);
}
var pingInterval = setInterval(function() {
try {
setTimeout(function() {
if(!M.isHidden) {
window.famobi_tracking.trackEvent(window.famobi_tracking.EVENTS.PING, {});
} else {
if(debug) {
famobi.log("hidden: famobi_tracking.EVENTS.PING skipped!");
}
}
}, (Math.floor(Math.random() * 60) * 1000));
} catch (ex) {
famobi.log(ex);
}
}, 6E4);
resolve();
} else {
reject("Famobi Tracking not ready");
}
});
return M.promise;
};
module.prototype.data = function(dataObject) {
window.famobi_dataLayer.push(dataObject);
};
module.prototype.trackEvent = function() {
return;
};
module.prototype.trackPassiveEvent = function() {
return M.trackEvent();
};
M = new module();
M.init();
return M;
};
!(function(a, b) {
var famobi_analytics = {
stats: {}, // params for achivements etc. - custom key-value pairs
events: [], // list of logged events, for debugging purposes
currentScreen: "",
pageTitle: "",
// STATS
trackStats: function(key, value, amount) {
return new Promise(function(resolve, reject) {
var res = {};
var values = {};
if (typeof key === "string") {
values[key] = value;
}
var statsValidator = function() {
// eslint-disable-next-line no-unused-vars
for (var k in values) {
var testKey =
typeof key === "string" &&
key.length &&
key.length <= 42 &&
key.match(/^[a-z_0-9]+$/);
if (!testKey) {
// eslint-disable-next-line no-console
console.warn(
"trackStats(): key '" +
key +
"' contains not only lowercase letters, numbers and underscore ([a-z_0-9]), maximum length: 42 characters"
);
return false;
}
}
return true;
};
var isValid = statsValidator();
if (!isValid) {
reject(
"trackStats(): invalid params " +
JSON.stringify(key, value)
);
return false;
}
var updateKey = function(key, value) {
if (typeof key === "string" && key.length) {
if (
key in famobi_analytics.stats &&
(typeof value === "undefined" || value === null)
) {
delete famobi_analytics.stats[key];
} else {
if (typeof value !== "undefined" && value) {
famobi_analytics.stats[key] = value;
}
}
return true;
} else {
throw "trackStats(): key is not a string or an Object";
}
};
if (key && typeof key === "object") {
for (var k in key) {
value = key[k];
updateKey(k, value);
}
res = key;
} else {
updateKey(key, value);
res[key] = value;
}
if (famobi.hasOwnProperty("adapters")) {
famobi.adapters.run("analytics", "trackStats", key, value, amount);
}
resolve(res);
});
},
getStats: function() {
// for debugging purposes
return new Promise(function(resolve) {
resolve(famobi_analytics.stats);
});
},
// EVENTS
trackEvent: function(event, params) {
return new Promise(function(resolve, reject) {
if (typeof famobi_analytics[event] === "undefined") {
reject("trackEvent(): unknown event '" + event + "'");
return false;
}
params = params || {};
if (typeof params !== "object" && params !== null) {
reject(
"trackEvent(): second parameter needs to be an object"
);
return false;
}
var paramsValidator = function() {
var availableParams = {
levelName: "",
reason: [
"timeout",
"dead",
"wrong_answer",
"quit",
"draw"
],
levelScore: -0.0,
liveScore: -0.0,
totalScore: -0.0,
bgmVolume: 0.0,
sfxVolume: 0.0
};
var requiredParams = {
EVENT_LEVELFAIL: ["levelName", "reason"],
EVENT_LEVELRESTART: ["levelName"],
EVENT_LEVELSTART: ["levelName"],
EVENT_LEVELSUCCESS: ["levelName"],
EVENT_LEVELSCORE: ["levelName", "levelScore"],
EVENT_LIVESCORE: ["liveScore"],
EVENT_TOTALSCORE: ["totalScore"],
EVENT_VOLUMECHANGE: ["bgmVolume", "sfxVolume"],
EVENT_CUSTOM: []
};
if (
typeof requiredParams[event] !== "undefined" &&
Object.keys(params).length === 0
) {
// eslint-disable-next-line no-console
console.warn(
"trackEvent(): '" +
event +
"' requires at least one parameter"
);
return false;
}
if (typeof requiredParams[event] === "undefined") {
return true;
}
var k = 0;
var name = "";
var param = null;
for (k; k < requiredParams[event].length; k++) {
name = requiredParams[event][k];
param = availableParams[name];
if (typeof param === "string") {
if (typeof params[name] !== "string") {
// eslint-disable-next-line no-console
console.warn(
"trackEvent(): required param '" +
name +
"' has to be of type string"
);
return false;
}
}
if (typeof param === "number") {
if (typeof params[name] !== "number") {
// eslint-disable-next-line no-console
console.warn(
"trackEvent(): required param '" +
name +
"' has to be of type number"
);
return false;
}
}
if (typeof param === "object") {
if (param.indexOf(params[name]) === -1) {
// eslint-disable-next-line no-console
console.warn(
"trackEvent(): required param '" +
name +
"' has to be one of \"" +
param.join('", "') +
'"'
);
return false;
}
}
}
typeof famobi.gameanalytics !== "undefined" && famobi.gameanalytics.trackEvent(event, params);
if(typeof famobi.mixpanel !== "undefined") {
params.event = event;
famobi.mixpanel.trackEvent("famobi_analytics", params);
}
return true;
};
var isValid = paramsValidator();
if (!isValid) {
return reject(
"trackEvent(): invalid params " + JSON.stringify(params)
);
}
//famobi_analytics.events.push({event: event, params: params});
if (famobi.hasOwnProperty("adapters")) {
famobi.adapters.run(
"analytics",
"trackEvent",
event,
params
);
}
if (famobi_analytics.TRIGGER_AD.indexOf(event) > -1) {
if (
"reason" in params &&
(params["reason"] === "quit" ||
params["reason"] === "draw")
) {
return resolve(event, params);
}
return famobi.showAd(function() {
resolve(event, params);
});
}
if (famobi_analytics.TRIGGER_CUSTOM.indexOf(event) > -1) {
if(window.famobi.hasFeature("forced_mode") && ["A-MONKEYGAMES-DEV"].includes(window.famobi.config.aid) && ["archery-world-tour", "candy-bubble", "bubble-woods", "diamond-rush", "kumba-kool", "om-nom-bubbles", "smarty-bubbles", "smarty-bubbles-2", "jungle-run", "e-scooter"].includes(window.famobi_gameID) && "eventName" in params && params.eventName == "LEVELEND") {
return reject(event, params);
}
return resolve(event, params);
}
if (famobi_analytics.TRIGGER_LEVELSCORE.indexOf(event) > -1) {
return famobi
.submitHighscore(
params["levelName"],
params["levelScore"]
)
.then(function() {
resolve(event, params);
});
}
if (famobi_analytics.TRIGGER_TOTALSCORE.indexOf(event) > -1) {
return famobi
.submitHighscore("TOTAL", params["totalScore"])
.then(function() {
resolve(event, params);
});
}
if (famobi_analytics.TRIGGER_LIVESCORE.indexOf(event) > -1) {
famobi.setLiveScore(params["liveScore"]);
return resolve(event, params);
}
return resolve(event, params);
});
},
getEvents: function() {
// for debugging purposes
return new Promise(function(resolve) {
resolve(famobi_analytics.events);
});
},
EVENT_CUSTOM: "EVENT_CUSTOM",
EVENT_LEVELFAIL: "EVENT_LEVELFAIL",
EVENT_LEVELRESTART: "EVENT_LEVELRESTART",
EVENT_LEVELSTART: "EVENT_LEVELSTART",
EVENT_LEVELSUCCESS: "EVENT_LEVELSUCCESS",
EVENT_LIVESCORE: "EVENT_LIVESCORE",
EVENT_LEVELSCORE: "EVENT_LEVELSCORE",
EVENT_TOTALSCORE: "EVENT_TOTALSCORE",
EVENT_TUTORIALCOMPLETED: "EVENT_TUTORIALCOMPLETED",
EVENT_TUTORIALSKIPPED: "EVENT_TUTORIALSKIPPED",
EVENT_VOLUMECHANGE: "EVENT_VOLUMECHANGE",
EVENT_PAUSE: "EVENT_PAUSE",
EVENT_RESUME: "EVENT_RESUME",
// SCREEN
trackScreen: function(screen, pageTitle) {
return new Promise(function(resolve, reject) {
var requiredPageTitleScreens = ["SCREEN_OTHER"];
if (typeof famobi_analytics[screen] === "undefined") {
reject("trackScreen(): unknown screen '" + screen + "'");
return false;
}
if (
!pageTitle &&
screen.indexOf(requiredPageTitleScreens) > -1
) {
reject(
"trackScreen(): screen '" +
screen +
"' requires param 'pageTitle'"
);
return false;
}
if (pageTitle && typeof pageTitle !== "string") {
reject(
"trackScreen(): required param 'pageTitle' has to be a non-empty string"
);
return false;
}
famobi_analytics.currentScreen = screen;
famobi_analytics.pageTitle = pageTitle;
if (famobi.hasOwnProperty("adapters")) {
famobi.adapters.run(
"analytics",
"trackScreen",
screen,
pageTitle
);
}
resolve(screen, pageTitle);
});
},
getScreen: function() {
return famobi_analytics.currentScreen;
},
getPageTitle: function() {
return famobi_analytics.pageTitle;
},
SCREEN_OTHER: "SCREEN_OTHER", // custom, use pageTitle to differentiate
SCREEN_BONUS: "SCREEN_BONUS", // bonus screen, e.g. extra chance
SCREEN_CHARACTER: "SCREEN_CHARACTER", // Select character
SCREEN_CREDITS: "SCREEN_CREDITS", // credits screen, if used
SCREEN_GAMERESULT: "SCREEN_GAMERESULT", // result screen with total score (game over)
SCREEN_HELP: "SCREEN_HELP", // help screen
SCREEN_HOME: "SCREEN_HOME", // home screen (start screen)
SCREEN_LEVEL: "SCREEN_LEVEL", // level screen while playing
SCREEN_LEVELINTRO: "SCREEN_LEVELINTRO", // level has not yet begun (optional)
SCREEN_LEVELLOADING: "SCREEN_LEVELLOADING", // level is loading (optional)
SCREEN_LEVELRESULT: "SCREEN_LEVELRESULT", // result screen with level score
SCREEN_LEVELSELECT: "SCREEN_LEVELSELECT", // level select screen
SCREEN_PAUSE: "SCREEN_PAUSE", // pause screen
SCREEN_SETTINGS: "SCREEN_SETTINGS", // settings screen (advanced game settings)
SCREEN_SHOP: "SCREEN_SHOP", // when the game features an ingame shop, use pageTitle to differentiate between items
SCREEN_SPLASH: "SCREEN_SPLASH", // splash screen, if used
SCREEN_TUTORIAL: "SCREEN_TUTORIAL", // tutorial screen(s), use pageTitle to differentiate between multiple tutorial screens
TRIGGER_AD: ["EVENT_LEVELSUCCESS", "EVENT_LEVELFAIL"],
TRIGGER_LEVELSCORE: ["EVENT_LEVELSCORE"],
TRIGGER_LIVESCORE: ["EVENT_LIVESCORE"],
TRIGGER_TOTALSCORE: ["EVENT_TOTALSCORE"],
TRIGGER_CUSTOM: ["EVENT_CUSTOM"]
};
// export famobi_analytics object to global object
b[a] = famobi_analytics;
})("famobi_analytics", window);
fg_api.prototype.gameanalyticsModule = function() {
var self = this,
M;
function module() {
this.promise = null;
this.builds = [
"A-IKI23"
];
this.url = "//download.gameanalytics.com/js/GameAnalytics-4.4.5.min.js";
this.fg_test = ["1", "true"].includes(famobi.getUrlParams()["fg_test"]);
this.log = self.getUrlParams().fg_env === "staging" || ["1", "true"].includes(famobi.getUrlParams()["fg_test"]);
this.setEnabledInfoLog = self.getUrlParams().fg_env === "staging" || this.fg_test;
this.setEnabledEventSubmission = true;
self.config.gameParams.gameanalytics = self.config.gameParams.gameanalytics || {};
this.game_key = self.config.gameParams.gameanalytics.game_key;
this.secret_key = self.config.gameParams.gameanalytics.secret_key;
this.skipFamobiAnalytics = self.config.gameParams.gameanalytics.skip_famobi_analytics || false;
this.force = !!self.config.gameParams.gameanalytics.force;
let build = self.config.gameParams.gameanalytics.build;
this.build = typeof build === "string" && build.length ? build : "famobi-web 1.0.0";
if(this.builds.includes(self.config.aid)) {
this.build += " [" + self.config.aid + "]";
}
};
module.prototype.init = function() {
if(M.game_key && M.secret_key) {
M.log && console.log("[GameAnalytics] GA keys found!");
if(!M.fg_test) {
M.initialize().catch(e => {
M.log && console.log(e);
});
}
}
};
module.prototype.trackEvent = function(event, params) {
window.gameanalytics = window.gameanalytics || {};
if(typeof window.gameanalytics.GameAnalytics === "undefined") {
return;
}
params = params || {};
params.eventName = params.eventName || "";
if(M.skipFamobiAnalytics && !params.eventName.toLowerCase().startsWith("ga:")) {
return;
}
switch(event) {
case "EVENT_LEVELFAIL":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_LEVELFAIL:" + params.reason});
break;
case "EVENT_LEVELRESTART":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_LEVELRESTART"});
break;
case "EVENT_LEVELSTART":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_LEVELSTART"});
break;
case "EVENT_LEVELSUCCESS":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_LEVELSUCCESS"});
break;
case "EVENT_LEVELSCORE":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_LEVELSCORE", value: params.levelScore});
break;
case "EVENT_LIVESCORE":
// nope: function call happens way too often
break;
case "EVENT_TOTALSCORE":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_TOTALSCORE", value: params.totalScore});
break;
case "EVENT_VOLUMECHANGE":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_VOLUMECHANGE"});
break;
case "EVENT_CUSTOM":
// bridge (EVENT_CUSTOM to GameAnalytics Event)
if(params.eventName.toLowerCase().startsWith("ga:") && typeof gameanalytics !== "undefined") {
switch(params.eventName.toLowerCase().split(":")[1]) {
case "business":
gameanalytics.GameAnalytics.addBusinessEvent(params.cartType, params.itemType, params.itemId, params.amount, params.currency);
break;
case "resource":
gameanalytics.GameAnalytics.addResourceEvent(params.flowType, params.resourceCurrency, params.amount, params.itemType, params.itemId);
break;
case "progression":
gameanalytics.GameAnalytics.addProgressionEvent(params.progressionStatus, params.progression01, params.progression02, params.progression03, params.value);
break;
case "error":
gameanalytics.GameAnalytics.addErrorEvent(params.severity, params.message);
break;
case "design":
gameanalytics.GameAnalytics.addDesignEvent(params.eventId, params.value);
break;
case "ads":
break;
case "impression":
break;
default:
M.log && console.log("unknown GA event type");
}
return;
}
if(params.eventName === "LEVELEND") {
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:LEVELEND:" + params.result, value: params.score});
}
break;
case "EVENT_TUTORIALCOMPLETED":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_TUTORIALCOMPLETED"});
break;
case "EVENT_TUTORIALSKIPPED":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_TUTORIALSKIPPED"});
break;
case "EVENT_PAUSE":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_PAUSE"});
break;
case "EVENT_RESUME":
window.famobi_analytics.trackEvent("EVENT_CUSTOM", {eventName: "ga:design", eventId: "TrackEvent:EVENT_RESUME"});
break;
default:
// do nothing
}
};
module.prototype.initialize = function(params) {
if (M.promise) {
return M.promise;
}
params = params || {};
params.game_analytics = params.game_analytics || {};
self.config = self.config || {};
self.config.game_analytics = self.config.game_analytics || {};
M.promise = new Promise((resolve, reject) => {
if (!self.hasFeature("gameanalytics") && !M.force) {
return reject("[GameAnalytics] GA is not supported (feature 'gameanalytics' is disabled)");
}
if(M.fg_test) {
M.game_key = self.config.game_analytics.game_key || M.game_key;
M.secret_key = self.config.game_analytics.secret_key || M.secret_key;
M.build = self.config.game_analytics.build || M.build;
}
if(!(typeof M.game_key === "string" && M.game_key.length && typeof M.secret_key === "string" && M.secret_key.length)) {
return reject("[GameAnalytics] GA is not supported (missing or invalid keys)");
}
M.build = typeof params.build === "string" && params.build .length ? params.build : M.build;
const setEnabledInfoLog = typeof params.setEnabledInfoLog === "boolean" ? params.setEnabledInfoLog : M.setEnabledInfoLog;
const setEnabledEventSubmission = typeof params.setEnabledEventSubmission === "boolean" ? params.setEnabledEventSubmission : M.setEnabledEventSubmission;
// available items
const resource_currencies = params.game_analytics.resource_currencies || self.config.game_analytics.resource_currencies || null;
const resource_item_types = params.game_analytics.resource_item_types || self.config.game_analytics.resource_item_types || null;
const custom_01 = params.game_analytics.custom_01 || self.config.game_analytics.custom_01 || null;
const custom_02 = params.game_analytics.custom_02 || self.config.game_analytics.custom_02 || null;
const custom_03 = params.game_analytics.custom_03 || self.config.game_analytics.custom_03 || null;
const onScriptLoaded = () => {
if(typeof GameAnalytics !== "undefined") {
M.log && console.log(
"[GameAnalytics] Initializing...",
{
game_key: M.game_key,
build: M.build,
force: M.force,
setEnabledInfoLog,
setEnabledEventSubmission,
skipFamobiAnalytics: M.skipFamobiAnalytics,
resource_currencies,
resource_item_types,
custom_01,
custom_02,
custom_03
}
);
GameAnalytics("setEnabledInfoLog", setEnabledInfoLog);
GameAnalytics("setEnabledEventSubmission", setEnabledEventSubmission);
GameAnalytics("configureBuild", M.build);
resource_currencies && GameAnalytics("configureAvailableResourceCurrencies", resource_currencies);
resource_item_types && GameAnalytics("configureAvailableResourceItemTypes", resource_item_types);
custom_01 && GameAnalytics("configureAvailableCustomDimensions01", custom_01);
custom_02 && GameAnalytics("configureAvailableCustomDimensions02", custom_02);
custom_03 && GameAnalytics("configureAvailableCustomDimensions03", custom_03);
GameAnalytics("initialize", M.game_key, M.secret_key);
resolve();
}
reject("[GameAnalytics] GA is not ready");
};
faZepto.getScript(M.url, onScriptLoaded, onScriptLoaded);
});
return M.promise;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.initialize = function(params) {
return this.gameanalytics.initialize(params);
};
fg_api.prototype.trackEvent = function(event, params) {
return this.gameanalytics.trackEvent(event, params);
};
fg_api.prototype.mixpanelModule = function() {
var self = this,
M;
function module() {
this.log = self.getUrlParams().fg_env === "staging";
this.promise = null;
this.projectToken = "27541b18470cb5310e6db5799e4ed2bf";
this.debug = true;
this.track_pageview = true;
this.persistence = "localStorage";
this.force = false;
this.supportedGames = [
"zoo-boom"
];
};
module.prototype.init = function() {
M.initialize().catch(e => {
M.log && console.log(e);
});
};
module.prototype.trackEvent = function(event, params) {
if(typeof mixpanel === "undefined") {
return;
}
params = params || {};
params.eventName = params.eventName || "";
if(params.event === "EVENT_LIVESCORE" || (params.event === "EVENT_CUSTOM" && params.eventName.toLowerCase().startsWith("ga:"))) {
return;
}
params['game-id'] = window.famobi_gameID;
M.log && console.log("mixpanel.track(%s, %s)", event, JSON.stringify(params));
mixpanel.track(event, params);
};
module.prototype.initialize = function(params) {
if (M.promise) {
return M.promise;
}
M.promise = new Promise((resolve, reject) => {
if (!self.hasFeature("mixpanel") && !M.force) {
return reject("[mixpanel] Mixpanel is not supported (feature 'mixpanel' is disabled)");
}
if (!M.supportedGames.includes(window.famobi_gameID)) {
return reject("[mixpanel] Game is not supported");
}
(function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(e,f,c){function g(a,d){var b=d.split(".");2==b.length&&(a=a[b[0]],d=b[1]);a[d]=function(){a.push([d].concat(Array.prototype.slice.call(arguments,0)))}}var a=b;"undefined"!==typeof c?a=b[c]=[]:c="mixpanel";a.people=a.people||[];a.toString=function(a){var d="mixpanel";"mixpanel"!==c&&(d+="."+c);a||(d+=" (stub)");return d};a.people.toString=function(){return a.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split(" ");
for(h=0;h<i.length;h++)g(a,i[h]);var j="set set_once union unset remove delete".split(" ");a.get_group=function(){function b(c){d[c]=function(){call2_args=arguments;call2=[c].concat(Array.prototype.slice.call(call2_args,0));a.push([e,call2])}}for(var d={},e=["get_group"].concat(Array.prototype.slice.call(arguments,0)),c=0;c<j.length;c++)b(j[c]);return d};b._i.push([e,f,c])};b.__SV=1.2;e=f.createElement("script");e.type="text/javascript";e.async=!0;e.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===f.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";g=f.getElementsByTagName("script")[0];g.parentNode.insertBefore(e,g)}})(document,window.mixpanel||[]);
if(typeof window.mixpanel !== "undefined") {
mixpanel.init(M.projectToken, {
debug: M.debug,
track_pageview: M.track_pageview,
persistence: M.persistence
});
resolve();
} else {
reject("[mixpanel] Mixpanel is not ready");
}
});
return M.promise;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.initialize = function(params) {
return this.mixpanel.initialize(params);
};
fg_api.prototype.trackEvent = function(event, params) {
return this.mixpanel.trackEvent(event, params);
};
if (typeof window !== "undefined" && typeof fenster === "undefined" && typeof window.fenster === "undefined") {
!(function(a, b) {
const fenster = (
function() {
let isDebug = false;
try{
const searchParams = new URL(window.location.href).searchParams;
isDebug = ["1", "true"].includes(searchParams.get("debug"));
} catch(e) {
}
isDebug && console.log("fenster...")
let innerWidth = window.innerWidth;
let innerHeight = window.innerHeight;
let interval = null;
let fnResize = null;
function subscribeToOffsetUpdates(_fnResize) {
fnResize = _fnResize;
};
function init() {
isDebug && console.log("init 'fenster'...");
window.famobi.adapters.add("viewport", "offsetChanged", offsets => {
isDebug && console.log("[offsets] onOffsetChange");
update();
});
update();
};
function update() {
if(typeof window.famobi === "undefined" || typeof window.famobi.getOffsets !== "function") {
return;
}
let top = window.famobi.getOffsets().top || 0;
let right = window.famobi.getOffsets().right || 0;
let bottom = window.famobi.getOffsets().bottom || 0;
let left = window.famobi.getOffsets().left || 0;
isDebug && console.log(
"[offsets] top: %s, right: %s, bottom: %s, left: %s",
top,
right,
bottom,
left
);
innerWidth = window.innerWidth - right;
innerHeight = window.innerHeight - bottom;
isDebug && console.log("[offsets] innerWidth: %s, innerHeight: %s",
innerWidth,
innerHeight
);
if(typeof fnResize === "function") {
fnResize();
}
};
function test(right = 0, bottom = 0) {
const offsets = {
top: 0,
right,
bottom,
left: 0
};
window.famobi.getOffsets = () => {
return offsets;
}
window.famobi.adapters.run("viewport", "offsetChanged", offsets);
};
addEventListener("resize", (event) => {
update();
});
interval = setInterval(() => {
isDebug && console.log("[fenster] checking for onOffsetChange")
if (typeof window.famobi !== "undefined" &&
typeof window.famobi.adapters !== "undefined" &&
typeof window.famobi.adapters.list === "function" &&
typeof window.famobi.adapters.list()["viewport"] !== "undefined") {
clearInterval(interval);
init();
}
}, 250);
return {
get innerHeight() {
return innerHeight;
},
get innerWidth() {
return innerWidth;
},
update: update,
subscribeToOffsetUpdates: subscribeToOffsetUpdates,
test: test
};
}
)();
b[a] = fenster;
})("fenster", window);
}
fg_api.prototype.gameStarted = function() {
var self = this;
self.log("Received gameStarted signal");
};
fg_api.prototype.gamePaused = function() {
var self = this;
self.log("Received gamePaused signal");
};
fg_api.prototype.gameResumed = function() {
var self = this;
self.log("Received gameResumed signal");
};
fg_api.prototype.gameOver = function() {
var self = this;
self.ads.showAd(function() {
// Run Adapter if possible
self.adapters.run("game", "gameOver");
});
self.log("Received gameOver signal");
};
fg_api.prototype.levelUp = function() {
var self = this;
self.ads.showAd(function() {
// Run Adapter if possible
self.adapters.run("game", "levelUp");
});
self.log("Received levelUp signal");
};
fg_api.prototype.gameReady = function() {
var self = this;
// Run Adapter if possible
self.adapters.run("game", "ready");
self.log("Received gameReady signal");
};
fg_api.prototype.playerReady = function() {
var self = this;
// Run Adapter if possible
self.adapters.run("player", "ready");
self.log("Received playerReady signal");
};
fg_api.prototype.geoModule = function() {
var self = this,
M;
function module() {
// define private vars
this.promise = null;
this.geolocationUrl =
"https://pro.ip-api.com/json/?key=0meDkSsHhF3MQK0&fields=2";
this.geodata = {
countryCode: ""
};
this.ISOCountryGroups = {
eea: [
"at",
"be",
"bg",
"cy",
"cz",
"de",
"dk",
"ee",
"es",
"fi",
"fr",
"gb",
"gr",
"hr",
"hu",
"ie",
"is",
"it",
"li",
"lt",
"lu",
"lv",
"mt",
"nl",
"no",
"pl",
"pt",
"ro",
"se",
"si",
"sk"
]
};
}
module.prototype.init = function() {
M.promise = new Promise(function(resolve, reject) {
if (self.hasFeature("standalone")) {
reject();
return;
}
setTimeout(reject, 10e3);
self.rest.get(M.geolocationUrl).then(function(result) {
if (!result || !result.countryCode) {
reject();
return;
}
faZepto.extend(M.geodata, result);
resolve(M.geodata);
}, reject);
});
};
module.prototype.getCountryCode = function() {
return new Promise(function(resolve, reject) {
M.promise.then(function(geodata) {
resolve(geodata.countryCode);
}, reject);
});
};
module.prototype.isEEA = function() {
return new Promise(function(resolve, reject) {
M.promise.then(function(geodata) {
resolve(
M.ISOCountryGroups.eea.indexOf(
geodata.countryCode.toLowerCase()
) > -1
);
}, reject);
});
};
M = new module();
M.init();
return M;
};
fg_api.prototype.lsgModule = function() {
var self = this,
M;
function module() {}
module.prototype.init = function() {
this.lsg_version = "lsg_v17";
this.is_active = (window.famobi_env !== "vp");
this.is_sampling_all_rules = true;
this.rules = [];
this.rule = null; // price rule
this.locale = null; // CountryCode
this.promise = null;
// rules with a "unified price rule" counterpart in ad manager
this.all_rules = {
a0000: 0.0,
a0010: 0.1,
a0020: 0.2,
a0040: 0.4,
a0080: 0.8,
a0100: 1,
a0120: 1.2,
a0140: 1.4,
a0160: 1.6,
a0180: 1.8,
b0200: 2,
b0250: 2.5,
b0300: 3,
b0350: 3.5,
b0400: 4,
b0450: 4.5,
b0500: 5,
b0550: 5.5,
b0600: 6,
b0700: 7,
b0800: 8,
b0900: 9,
b1000: 10,
b1200: 12
};
// locales that use custom price rules - deactivate lsg/waterfall for these
this.cpr_locales = [
"at",
"jp",
"nl",
"br",
"gb",
"tr"
];
};
module.prototype.ready = function() {
if (!M.promise) {
M.promise = new Promise(function(resolve, reject) {
Promise.resolve(M.getLocale())
.then(function(locale) {
// abort if locale has cpr
//if (M.cpr_locales.indexOf(locale.toLowerCase()) > -1) {
M.isActive(false);
return Promise.reject("Locale " + locale + " has custom price rules.");
//} else
// return Promise.resolve();
})
.then(function() {
// get data for randomized pricerule selection
return M.pickRandomRule().then(resolve, reject);
})
.catch(function(err) {
self.log("LSG deactivated", err ? ("reason:" + err) : "");
reject(err);
});
});
}
return M.promise;
};
module.prototype.isActive = function(setter) {
if (typeof setter !== "undefined") {
M.is_active = setter;
return setter;
}
return new Promise(function(resolve, reject) {
if (M.is_active) {
resolve();
} else {
reject();
}
});
};
module.prototype.isSamplingAllRules = function(setter) {
if (typeof setter !== "undefined") {
M.is_sampling_all_rules = !!setter;
}
return !!M.is_sampling_all_rules;
};
module.prototype.getRules = function() {
return new Promise(function(resolve, reject) {
if (self.sizeOf(M.rules)) {
return resolve(M.rules);
}
if (!M.isActive()) {
return reject();
}
M.rules = [];
faZepto.each(M.all_rules, function(key, value) {
M.rules.push([key, value]);
});
resolve(M.rules);
});
};
module.prototype.pickRandomRule = function() {
return new Promise(function(resolve, reject) {
M.getRules().then(function() {
if (!self.sizeOf(M.rules)) {
M.rule = "";
resolve(M.rule);
return;
}
var randomRule =
M.rules[self.rand(0, self.sizeOf(M.rules) - 1)];
if (!randomRule) {
reject();
return;
}
M.rule = {
name: randomRule[0],
value: randomRule[1],
ctr: randomRule[2]
};
resolve(M.rule);
}, reject);
});
};
module.prototype.remix = function() {
return M.pickRandomRule();
};
module.prototype.getRule = function() {
if (!M.rule) {
return "";
}
return M.rule;
};
module.prototype.exportRules = function() {
if (!M.rules) {
return [];
}
return Array.from(M.rules);
};
module.prototype.getLocale = function() {
if (null !== M.locale) {
return M.locale;
}
return new Promise(function(resolve) {
self.geo.getCountryCode().then(
function(countryCode) {
M.locale = countryCode.toUpperCase();
resolve(M.locale);
},
function() {
M.locale = self.gametranslation.getNavigatorLanguage();
M.locale = M.locale.toUpperCase();
resolve(M.locale);
}
);
});
};
M = new module();
M.init();
return M;
};
fg_api.prototype.gametranslationModule = function() {
var self = this,
M;
function module() {
// define private vars
}
module.prototype.init = function() {
M.curLangString = M.getUserLang();
// Always fall back to 'en' when the user locale is not supported or translated
if (M.getSupportedLanguages().indexOf(M.curLangString) === -1) {
M.curLangString = "en";
}
M.translationData = M.getGameTranslations();
M.translateHtml(faZepto("body"));
};
module.prototype.getSupportedLanguages = function() {
return self.config.languages || [];
};
module.prototype.getGameTranslations = function() {
var i18n = self.config.game_i18n,
lang = M.curLangString;
if (i18n.current) {
return i18n.current;
}
faZepto.each(i18n, function(language, translations) {
faZepto.each(translations, function(key, value) {
if (value == null) {
i18n[language][key] = "";
} else if (typeof i18n[language][key] === "string") {
i18n[language][key] = value.replace(/\{lang\}/g, language);
}
});
});
i18n.current = faZepto.extend(
{},
i18n["default"],
i18n[self.config.aid + ".default"],
i18n[lang],
i18n[self.config.aid + "." + lang]
);
return (self.config.game_i18n.current = i18n.current);
};
module.prototype.translateString = function(key) {
return M.translationData.hasOwnProperty(key)
? M.translationData[key]
: null;
};
module.prototype.getNavigatorLocale = function() {
var language = "";
if (navigator.languages && self.sizeOf(navigator.languages)) {
language = navigator.languages[0];
} else if (navigator.language) {
language = navigator.language;
} else if (navigator.userLanguage) {
language = navigator.userLanguage;
} else if (navigator.browserLanguage) {
language = navigator.browserLanguage;
}
return language;
};
module.prototype.getNavigatorLanguage = function() {
return M.getNavigatorLocale().substr(0, 2);
};
module.prototype.getUserLang = function() {
var urlParams = self.getUrlParams(),
lang = M.getNavigatorLanguage();
if (urlParams.locale && urlParams.locale.length == 2) {
return urlParams.locale;
}
switch (lang) {
case "ch":
case "at":
return "de";
default:
return lang;
}
};
module.prototype.translateHtml = function($selector) {
$selector.find("[data-i18n]").each(function() {
var textkey = this.getAttribute("data-i18n");
this.innerHTML = M.translateString(textkey);
});
return $selector;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.__ = function(key) {
return this.gametranslation.translateString(key);
};
// Alias for __()
fg_api.prototype.translate = function(key) {
return this.__(key);
};
fg_api.prototype.translateHtml = function() {
return this.gametranslation.translateHtml.apply(this, arguments);
};
fg_api.prototype.getCurrentLanguage = function() {
return this.gametranslation.curLangString;
};
fg_api.prototype.gameModule = function() {
var self = this,
M;
function module() {
// define private vars
this.waitingCounter = 0;
this.preloadProgress = 0;
}
var gamePrototype = module.prototype;
gamePrototype.prepare = function() {
M.linkCanonical()
.changeOpacity()
.changeMetaViewport();
faZepto(self.rootElement).on("faGame:loaded", M.changeMetaViewport);
faZepto(self.rootElement).on("faGame:loaded", M.hideCanvasBodyOverflow);
return new Promise(function(resolve) {
(function next() {
if (
!window.famobi_pregameJS ||
!window.famobi_pregameJS.length
) {
resolve(M);
return;
}
var currentScript = window.famobi_pregameJS.shift();
if (currentScript instanceof Promise) {
currentScript.then(next, next);
} else if (typeof currentScript === "function") {
Promise.resolve(currentScript.call(self)).then(next, next);
} else {
var scriptEl = document.createElement("script");
scriptEl.onload = next;
scriptEl.onerror = next;
scriptEl.src = currentScript;
self.bodyElement.appendChild(scriptEl);
}
})();
});
};
gamePrototype.setWaiting = function(newVal) {
newVal
? M.waitingCounter++
: M.waitingCounter > 0
? M.waitingCounter--
: (M.waitingCounter = 0);
return M;
};
gamePrototype.isWaiting = function() {
return M.waitingCounter > 0;
};
gamePrototype.canResume = function() {
return M.waitingCounter === 1;
};
gamePrototype.init = function() {
self.spinner.show();
(function next() {
// is the game waiting for an Ad to finish loading/displaying (DFP Video)?
if (M.isWaiting()) {
return;
}
if (!window.famobi_gameJS.length) {
faZepto(self.rootElement).trigger("faGame:loaded");
self.spinner.hide();
// Run Adapter if possible
self.adapters.run("game", "loaded");
return;
}
var currentScript = window.famobi_gameJS.shift();
if (typeof currentScript === "function") {
currentScript.call(self);
next();
} else {
var scriptEl = document.createElement("script");
scriptEl.onload = next;
scriptEl.onerror = next;
scriptEl.src = currentScript;
self.bodyElement.appendChild(scriptEl);
}
})();
};
gamePrototype.pause = function() {
//self.log('game.pause');
if (M.isWaiting()) {
//self.log('game is already waiting, do not pause');
M.setWaiting(true);
return false;
}
M.setWaiting(true);
try {
if (typeof window.famobi_onPauseRequested == "function") {
window.famobi_onPauseRequested();
return true;
}
// Phaser
if (window.game && typeof window.game.paused !== "undefined") {
window.game.paused = true;
return true;
}
// Construct 2
if (typeof window.cr_setSuspended !== "undefined") {
cr_setSuspended(true);
//faZepto('<iframe id="fg-clickthrough-frame" src="about:blank" style="width: 100%; height: 100%; display: block; position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 999"></iframe>').appendTo(self.rootElement);
return true;
}
// CreateJS <3
if (typeof window.createjs !== "undefined") {
//window.createjs.Sound.setMute(true);
}
} catch (e) {
self.log("Pausing game failed: " + e);
}
return false;
};
gamePrototype.resume = function() {
//self.log('game.resume');
//self.log('isWaiting?', M.isWaiting());
if (!M.isWaiting()) {
//self.log('game is not waiting, do not resume');
return false;
}
if (!M.canResume()) {
//self.log('game is still waiting, do not resume');
M.setWaiting(false);
return false;
}
M.setWaiting(false);
try {
if (typeof window.famobi_onResumeRequested == "function") {
window.famobi_onResumeRequested();
return true;
}
// Phaser
if (window.game && typeof window.game.paused !== "undefined") {
window.game.paused = false;
return true;
}
// Construct 2
if (typeof window.cr_setSuspended !== "undefined") {
cr_setSuspended(false);
//faZepto('iframe#fg-clickthrough-frame').remove();
return true;
}
// CreateJS <3
if (typeof window.createjs !== "undefined") {
//window.createjs.Sound.setMute(false);
}
} catch (e) {
self.log("Resuming game failed: " + e);
}
return false;
};
gamePrototype.linkCanonical = function() {
var canonicalUrl = self.getShortLink();
var link = faZepto(
'<link rel="canonical" href="' + canonicalUrl + '">'
);
link.appendTo(self.headElement);
return M;
};
gamePrototype.changeOpacity = function() {
var opac = self.bodyElement.style.opacity + "";
if (opac !== "" && parseInt(opac) < 1) {
self.bodyElement.style.opacity = "1.0";
}
return M;
};
gamePrototype.changeMetaViewport = function() {
// change meta viewport content if its attribute 'data-original' exists
var $metaviewport = document.querySelector("meta[name=viewport]"),
ua = navigator.userAgent,
metaViewPortSetting = $metaviewport
? $metaviewport.getAttribute("data-original")
: undefined;
if ($metaviewport && metaViewPortSetting) {
if (ua.match(/iPhone|iPod|Tizen/i))
metaViewPortSetting =
"width=device-width, user-scalable=0, minimum-scale=1.0, initial-scale=0.5, maximum-scale=0.5, minimal-ui";
else if (ua.match(/iPad/i))
metaViewPortSetting =
"width=device-width, user-scalable=0, minimum-scale=1.0, initial-scale=1.0, maximum-scale=1.0, minimal-ui";
else if (ua.match(/Android/i))
metaViewPortSetting =
"width=device-width, initial-scale=1, maximum-scale=1.01";
$metaviewport.setAttribute("content", metaViewPortSetting);
}
};
gamePrototype.showCanvas = function() {
var canvas = document.querySelectorAll("canvas");
var i = 0;
if (canvas) {
for (i; i < canvas.length; ++i) {
canvas[i].style.display =
canvas[i].getAttribute("fa-orig-display") || "";
}
}
};
gamePrototype.hideCanvas = function() {
var canvas = document.querySelectorAll("canvas");
var i = 0;
if (canvas) {
for (i; i < canvas.length; ++i) {
canvas[i].setAttribute(
"fa-orig-display",
canvas[i].style.display
);
canvas[i].style.display = "none";
}
}
};
gamePrototype.hideCanvasBodyOverflow = function() {
var canvas = document.querySelector("canvas");
if (canvas) {
self.bodyElement.style.overflow = "hidden";
}
};
gamePrototype.setPreloadProgress = function(percent) {
if (typeof percent !== 'number') {
console.warn(
"setPreloadProgress(): required param 'percent' has to be of type number"
);
return;
}
var progress = Math.min(100, Math.max(M.preloadProgress, percent));
if (progress > M.preloadProgress) {
M.preloadProgress = progress;
self.adapters.run("game", "preloadProgress", progress);
if (progress == 100) {
self.adapters.run("game", "preloadComplete");
}
}
};
M = new module();
return M;
};
/*
add convenience functions to main api namespace
*/
fg_api.prototype.setPreloadProgress = function() {
this.game.setPreloadProgress.apply(this, arguments);
};
fg_api.prototype.audioModule = function(type) {
var self = this,
M;
function module() {
// define private vars
this.volume = 1;
}
module.prototype.init = function() {
};
module.prototype.setVolume = function(volume) {
if (typeof volume !== "number") {
self.log("setVolume(): required param 'volume' has to be of type number");
return false;
}
if (volume < 0 || volume > 1) {
self.log("setVolume(): param 'volume' out of bounds (0.0, 1.0)");
}
var targetVolume = Math.min(1, Math.max(0, volume));
if (targetVolume !== M.volume) {
M.volume = targetVolume;
self.requestAction("changeVolume", targetVolume)
}
};
module.prototype.getVolume = function() {
return M.volume;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.setVolume = function(volume) {
if (!this.audio) {
self.log(
"setVolume(): audio module required"
);
return;
}
this.audio.setVolume(volume);
};
fg_api.prototype.getVolume = function() {
if (!this.audio) {
self.log(
"getVolume(): audio module required"
);
return 1;
}
return this.audio.getVolume();
};
fg_api.prototype.fullscreenModule = function() {
var self = this,
M;
function module() {
// define private vars
this.isSupported = false;
}
module.prototype.init = function() {
var elem = document.documentElement;
try {
if (!elem) {
throw "documentElement not supported";
}
if (
!(
document.fullscreenEnabled ||
document.webkitFullscreenEnabled ||
document.mozFullScreenEnabled ||
document.msFullscreenEnabled
)
) {
throw "Fullscreen mode not supported";
}
if (elem.requestFullscreen) {
this.requestFullscreen = "requestFullscreen";
} else if (elem.requestFullScreen) {
this.requestFullscreen = "requestFullScreen";
} else if (elem.webkitRequestFullScreen) {
this.requestFullscreen = "webkitRequestFullscreen";
} else if (elem.webkitRequestFullScreen) {
this.requestFullscreen = "webkitRequestFullScreen";
} else if (elem.mozRequestFullScreen) {
this.requestFullscreen = "mozRequestFullScreen";
} else if (elem.msRequestFullscreen) {
this.requestFullscreen = "msRequestFullscreen";
} else {
throw "Fullscreen API not supported";
}
this.isSupported = !!this.requestFullscreen;
} catch (ex) {
this.isSupported = false;
}
if (!self.config.aid.startsWith("A-MONKEY")) {
// skip the following tests in monkey-games.app
if (
detection.is.ios ||
detection.is.pc ||
!self.hasFeature("fullscreen") ||
/^MacIntel|Win32|Win64$/.test(navigator.platform)
) {
this.isSupported = false;
}
if (!this.isSupported) {
faZepto("[data-famobi-fullscreen]").remove();
}
}
};
module.prototype.isSupported = function() {
return this.isSupported;
};
module.prototype.start = function() {
var elem = document.documentElement;
if (self.fullscreen.isSupported) {
elem[this.requestFullscreen]();
} else {
return false;
}
return true;
};
module.prototype.stop = function() {
self.orientation.unlock();
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
return true;
};
module.prototype.toggle = function() {
if (
!document.fullscreenElement &&
!document.mozFullScreenElement &&
!document.webkitFullscreenElement &&
!document.msFullscreenElement
) {
M.start();
setTimeout(function() {
self.orientation.lock();
}, 1e3);
return true;
} else {
return M.stop();
}
};
M = new module();
M.init();
return M;
};
fg_api.prototype.flashModule = function() {
var self = this,
M;
function module() {
// define private vars
this.offsetWidth = 0; // px
this.offsetHeight = 0; // px
// swfobject
this.swfUrl = window.famobi_gameID + ".swf";
this.replaceElemId = "myContent";
this.width = parseInt(window.innerWidth) - this.offsetWidth;
this.height = parseInt(window.innerHeight) - this.offsetHeight;
this.swfVersion = "9.0.0";
this.xiSwfUrl = "expressInstall.swf";
this.flashvars = {
fg_aid: window.famobi.config.aid,
fg_uid: window.famobi.config.uuid,
fg_game: window.famobi_gameID
};
this.params = {
allowscriptaccess: "always"
};
this.attributes = {};
this.callbackFn = function() {};
}
var flashPrototype = module.prototype;
flashPrototype.init = function() {
var fgFlash = null, // flash replacing container
fgGetFlashLink = null, // get flash link
arr = ["flashvars", "params", "attributes"],
fgGetFlash = null; // get flash image
if (!self.config.gameParams.flash) return false;
//self.log("Set, ...");
M.replaceElemId =
self.config.gameParams.flash.replaceElemId || M.replaceElemId;
M.swfUrl = self.config.gameParams.flash.swfUrl || M.swfUrl;
M.width = self.config.gameParams.flash.width || M.width;
M.height = self.config.gameParams.flash.height || M.height;
M.swfVersion = self.config.gameParams.flash.swfVersion || M.swfVersion;
M.xiSwfUrl = self.config.gameParams.flash.xiSwfUrl || M.xiSwfUrl;
// create div container for swfobject to replace
fgFlash = document.createElement("div");
fgFlash.setAttribute("id", M.replaceElemId);
fgFlash.setAttribute("style", "display: none");
self.bodyElement.appendChild(fgFlash);
// disable ads
self.config.ads.off = true;
// callback
if (self.config.gameParams.flash.callbackFn) {
M.callbackFn = self.config.gameParams.flash.callbackFn;
} else {
M.callbackFn = function() {
if (swfobject.getFlashPlayerVersion().major === 0) {
fgFlash.style.display = "block";
fgGetFlashLink = self.createElement("a", {
href: "http://www.adobe.com/go/getflashplayer",
target: "_blank"
});
fgGetFlash = self.createElement("img", {
src: "/flashgames/swfobject/getFlash.png",
alt: "Get Adobe Flash player",
title: "Get Adobe Flash player"
});
fgGetFlashLink.appendChild(fgGetFlash);
fgFlash.appendChild(fgGetFlashLink);
self.modal.create({ title: "Get Adobe Flash player" });
self.modal.setContent(fgFlash);
}
};
}
// merge flashvars, params and attributes
for (var key in arr) {
if (!self.config.gameParams.flash[arr[key]]) break;
for (var attrName in self.config.gameParams.flash[arr[key]]) {
M[arr[key]][attrName] =
self.config.gameParams.flash[arr[key]][attrName];
}
}
//self.log("Go!");
window.famobi_gameJS = window.famobi_gameJS || [];
window.famobi_gameJS.unshift(
"/flashgames/swfobject/swfobject.js",
function() {
swfobject.embedSWF(
M.swfUrl,
M.replaceElemId,
M.width,
M.height,
M.swfVersion,
M.xiSwfUrl,
M.flashvars,
M.params,
M.attributes,
M.callbackFn
);
}
);
return self;
};
//create new instace of Module
M = new module();
//initialize Module
M.init();
return M;
};
fg_api.prototype.restModule = function() {
var M;
function module() {}
module.prototype.init = function() {};
module.prototype.get = function(url, headers) {
return new Promise(function(resolve, reject) {
faZepto.ajax({
url: url,
headers: headers,
success: function(result) {
resolve(result);
},
error: function(err) {
reject(err);
}
});
});
};
module.prototype.getJSON = function(url, headers) {
return new Promise(function(resolve, reject) {
faZepto.ajax({
url: url,
headers: headers,
contentType: "application/json; charset=UTF-8",
success: function(result) {
resolve(result);
},
error: function(err) {
reject(err);
}
});
});
};
module.prototype.post = function(url, data, headers) {
headers = headers || {};
return new Promise(function(resolve, reject) {
faZepto.ajax({
url: url,
type: "POST",
contentType: "application/json; charset=UTF-8",
headers: headers,
data: JSON.stringify(data),
success: function(result) {
resolve(result);
},
error: function(err) {
reject(err);
}
});
});
};
M = new module();
M.init();
return M;
};
fg_api.prototype.debugModule = function() {
var self = this,
M;
function module() {}
module.prototype.init = function() {
self.adapters.add("analytics", "trackStats", function(key, value) {
self.log(
"%c trackStats ",
"background: #333333; color: white; display: block;"
);
if (typeof key === "string") {
if(typeof value === "object") {
self.log(key + ":");
self.log(value);
} else {
self.log(key + ": " + value);
}
} else {
self.log(key);
}
});
self.adapters.add("analytics", "trackEvent", function(event, params) {
// if(event == "EVENT_LIVESCORE") return;
self.log(
"%c " + event + " %c (trackEvent)",
"background: #0092c3; color: white; display: block;",
""
);
self.log(params);
});
self.adapters.add("analytics", "trackScreen", function(
screen,
pageTitle
) {
self.log(
"%c " +
screen +
" %c (trackScreen)" +
(pageTitle ? " - pageTitle: " + pageTitle : ""),
"background: #f08119; color: white; display: block;",
""
);
});
};
M = new module();
M.init();
return M;
};
fg_api.prototype.videoModule = function() {
var self = this,
M;
function module() {
this.element = null;
this.elementId = "fa-video";
this.videoUrl = self.config.urlRoot + "/services/video";
}
module.prototype.init = function() {
M.element = document.getElementById(M.elementId);
M.player = videojs(M.elementId);
self.onorientationchange(M.resizeHandler);
M.resizeHandler();
M.player.src([
{
type: "video/mp4",
src:
"https://video.cdn.famobi.com/marketing/videos/" +
self.config.video.sources.mp4
}
]);
M.player.dock({
title: ""
});
M.player.brand({
image: "FamobiFLogo.svg",
title: "Proudly brought to you by Famobi.com",
destination: "https://famobi.com",
destinationTarget: "_blank"
});
M.player.watermark({
image: "FamobiFWhiteLogo.svg",
position: "top-right",
fadeTime: 1000,
url: "https://famobi.com"
});
// Remove controls from the player on iPad to stop native controls from stealing
// our click
var contentPlayer = document.getElementById("fa-video");
if (
(navigator.userAgent.match(/iPad/i) ||
navigator.userAgent.match(/Android/i)) &&
contentPlayer.hasAttribute("controls")
) {
contentPlayer.removeAttribute("controls");
}
// Initialize the ad container when the video player is clicked, but only the
// first time it's clicked.
var startEvent = "click";
if (
navigator.userAgent.match(/iPhone/i) ||
navigator.userAgent.match(/iPad/i) ||
navigator.userAgent.match(/Android/i)
) {
startEvent = "touchend";
}
M.player.one(startEvent, function() {
M.player.ima.initializeAdDisplayContainer();
M.player.ima.requestAds();
M.player.play();
M.trackEvent("play");
});
M.trackEvent("show");
return self;
};
module.prototype.resizeHandler = function() {
var size = self.getWindowSize();
M.player.width(size.h / (16 / 9));
};
module.prototype.trackEvent = function(eventName) {
var validEvents = ["play", "show"];
if (validEvents.indexOf(eventName) === -1) {
self.log(
"trackEvent(): eventName must be one of ",
validEvents.join(", ")
);
return false;
}
eventName = "video." + (eventName || "show");
// track video event
var postData = {
aid: self.config.aid,
event: eventName
};
return faZepto.post(
M.videoUrl + "/videos/" + self.config.video.id + "/track",
postData
);
};
M = new module();
M.init();
return M;
};
fg_api.prototype.videoadsModule = function() {
var self = this,
M;
function module() {
this.closeCallback = function() {};
// flag if the last ad request was filled
this.adDidLoad = false;
// time in millis when the last ad was shown
this.lastAdCall = +self.now();
}
module.prototype.init = function() {
self.config.ads = faZepto.extend({}, self.config.ads);
if (!M.isEnabled()) {
M.provider = "none";
} else {
M.provider = self.config.ads.provider;
}
M.adcount = 0;
M.floodProtectionMap = {};
switch (M.provider) {
default:
faZepto.getScript(
"https://imasdk.googleapis.com/js/sdkloader/ima3.js",
sdkLoadedCallback,
function() {
sdkLoadedCallback();
}
);
M.dfp_ad_unit_code = "/37336410/InVideo//" + self.config.aid;
break;
}
function sdkLoadedCallback() {
if (typeof google != "undefined" && google.ima) {
google.ima.settings.setLocale(
self.gametranslation.getNavigatorLanguage()
);
google.ima.settings.setVpaidMode(
google.ima.ImaSdkSettings.VpaidMode.ENABLED
);
var options = {
id: "fa-video",
showCountdown: false,
adTagUrl: M.getAdTagUrl()
};
// This must be called before player.play() below.
self.video.player.ima(options);
}
}
};
module.prototype.getAdTagUrl = function() {
var myadTagUrl = "";
var descriptionUrl = encodeURIComponent(
self.config.ads.description_url
);
var language = self.gametranslation.getNavigatorLanguage();
M.dfp_custom_params = {
a: "" + self.config.aid,
gametype: "video",
video: "1",
invideo: "1",
videoid: self.config.video.id
};
// @see https://support.google.com/dfp_premium/answer/1068325?hl=de
myadTagUrl =
"https://securepubads.g.doubleclick.net/gampad/ads?npa=1&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&url=[referrer_url]&correlator=[timestamp]&ciu_szs=";
if (M.dfp_ad_unit_code != "") {
myadTagUrl = myadTagUrl + "&iu=" + M.dfp_ad_unit_code;
}
if (M.adWidth >= 728) {
myadTagUrl = myadTagUrl + "&sz=728x480";
} else if (
M.adWidth >= 640 ||
(M.dfp_custom_params.video && M.dfp_custom_params.video === "1")
) {
myadTagUrl = myadTagUrl + "&sz=640x480";
} else if (M.adWidth >= 336) {
myadTagUrl = myadTagUrl + "&sz=336x280";
} else {
myadTagUrl = myadTagUrl + "&sz=300x250";
}
if (descriptionUrl != "") {
myadTagUrl = myadTagUrl + "&description_url=" + descriptionUrl;
}
if (M.dfp_custom_params) {
myadTagUrl =
myadTagUrl +
"&cust_params=" +
encodeURIComponent(faZepto.param(M.dfp_custom_params));
}
if (language != "") {
myadTagUrl = myadTagUrl + "&hl=" + language;
}
return myadTagUrl;
};
module.prototype.hasCooledDown = function() {
var min_s_between =
M.adcount === 0 && +self.config.ads.min_s_before > 0
? +self.config.ads.min_s_before
: +self.config.ads.min_s_between;
var ret = self.now() - min_s_between * 1000 > M.lastAdCall;
return ret;
};
module.prototype.isAdvertisingActive = function(opts) {
if (!opts.iframeAllowed && window.top !== window.self) {
self.log("ads disabled in <iframe>");
return false;
}
return true;
};
module.prototype.isNthAdvertising = function(n) {
return +M.adcount % n === 0;
};
module.prototype.lastAdCallWasNsecondsAgo = function(n) {
return self.now() - n * 1000 >= M.lastAdCall;
};
module.prototype.fireAdCallback = function() {
if (typeof M.closeCallback == "function") {
M.closeCallback();
}
M.closeCallback = function() {};
};
module.prototype.isEnabled = function() {
return self.hasFeature("videoads") && !self.config.ads.off;
};
module.prototype.floodProtect = function(eventName, delay) {
if (M.floodProtectionMap[eventName]) {
return true;
}
M.floodProtectionMap[eventName] = setTimeout(function() {
M.floodProtectionMap[eventName] = undefined;
}, delay);
return false;
};
M = new module();
M.init();
return M;
};
fg_api.prototype.viewportModule = function () {
var self = this,
M;
function module() {
// define private vars
}
module.prototype.init = function () {
self.adapters.add("banner", "placementChanged", M.handleBannerPlacementChange);
return self;
};
module.prototype.getOffset = function(offsetType) {
var offset = 0;
if (self.banner && self.banner.isEnabled())
offset += self.banner.getOffset(offsetType);
return offset;
};
module.prototype.getOffsets = function() {
return {
top: M.getOffset("top"),
bottom: M.getOffset("bottom"),
left: M.getOffset("left"),
right: M.getOffset("right")
};
};
module.prototype.handleBannerPlacementChange = function() {
var offsets = M.getOffsets();
self.adapters.run("viewport", "offsetChanged", offsets);
};
M = new module();
M.init();
return M;
};
fg_api.prototype.getWindowSize = function () {
return {
w: window.innerWidth,
h: window.innerHeight
};
};
fg_api.prototype.getOffsets = function() {
return this.viewport.getOffsets();
};
fg_api.prototype.onOffsetChange = function(callback) {
if (typeof callback !== "function") {
this.error("famobi.onOffsetChange: no valid callback function provided.");
return null;
}
this.adapters.add("viewport", "offsetChanged", callback);
};
fg_api.prototype.init = function () {
var self = this;
self.rootElement = document.getElementById("fg-root");
self.bodyElement = document.getElementsByTagName("body")[0];
self.headElement = document.getElementsByTagName("head")[0];
if (!self.rootElement) {
self.rootElement = self.createElement("div", {
id: "fg-root",
class: "fg-root",
hidden: "hidden",
style: "color: #999;font-weight:normal;"
});
document.body.insertBefore(self.rootElement, document.body.firstChild);
}
self.fgOverlay = self.createElement("div", { id: "fg-overlay" });
if (self.config.gameParams.overlay_position)
self.fgOverlay.className =
"overlay-" +
self.config.gameParams.overlay_position +
" clip-" +
self.config.gameParams.overlay_position;
if (
self.config.gameParams.overlay_distance &&
self.config.gameParams.overlay_distance !== ""
) {
if (
self.config.gameParams.overlay_position &&
self.config.gameParams.overlay_position == "bottom"
)
self.fgOverlay.style.bottom = isNaN(
self.config.gameParams.overlay_distance
)
? self.config.gameParams.overlay_distance
: self.config.gameParams.overlay_distance + "px";
else
self.fgOverlay.style.top = isNaN(self.config.gameParams.overlay_distance)
? self.config.gameParams.overlay_distance
: self.config.gameParams.overlay_distance + "px";
}
self.rootElement.appendChild(self.fgOverlay);
self.config.name = faZepto.parseJSON(self.config.name);
self.config.package_id = faZepto.parseJSON(self.config.package_id);
// referrer & parent-frame check
// match the passed referrer param with domains of the current portal
self.config.referrer_origin = "";
self.config.referrer_matched = false;
self.config.first_ancestor_origin = "";
self.config.first_ancestor_matched = false;
self.config.last_ancestor_origin = "";
self.config.last_ancestor_matched = false;
self.config.is_own_inventory = false;
var urlParams = self.getUrlParams();
var referrerURL = urlParams.original_ref
? urlParams.original_ref
: document.referrer;
var portalDomains = self.config.ads.domains;
var parsedRefURL, parsedPortalURL, parsedAncestorOrigin;
var parsedPortalURLs = [];
// try parsing the referrer's URL for easier comparison
try {
parsedRefURL = new URL(referrerURL);
self.config.referrer_origin = parsedRefURL.origin;
} catch (error) {
self.log("cannot parse referrer URL", referrerURL);
}
// try parsing portal URLs first for easy comparability
if (Array.isArray(portalDomains) && portalDomains.length > 0) {
for (var domain of portalDomains) {
// skip empty items
if (domain.length < 1) continue;
// prefix domain with protocol (if missing) for parsing
var d = domain.toLowerCase();
if (!d.startsWith("http://") && !d.startsWith("https://"))
d = "https://" + d;
// parse and stash portal URLs
try {
parsedPortalURL = new URL(d);
if (parsedPortalURL.hostname) parsedPortalURLs.push(parsedPortalURL);
} catch (error) {
console.log("cannot parse portal URL", d);
continue;
}
}
}
// compare hostnames of parsed URL and portal domains
// - checked vice-versa so additional subdomains won't prevent recognition
// - subdomain www is ignored
function doesURLMatchPortalDomains(parsedURL) {
var hostname = parsedURL.hostname
.split(".")
.filter(function (substring) {
return substring !== "www";
})
.join(".");
for (parsedPortalURL of parsedPortalURLs) {
if (
(hostname && hostname.indexOf(parsedPortalURL.hostname) >= 0) ||
(parsedPortalURL.hostname &&
parsedPortalURL.hostname.indexOf(hostname) >= 0)
) {
self.log(hostname, "matches", parsedPortalURL.hostname);
return true;
}
}
return false;
}
// try matching parsed domains with referrer
if (
parsedRefURL &&
parsedRefURL.hostname &&
parsedPortalURLs.length > 0 &&
doesURLMatchPortalDomains(parsedRefURL)
) {
self.config.referrer_matched = true;
}
// try matching parent frame origins via ancestorOrigin (webkit only)
if (location.ancestorOrigins && location.ancestorOrigins.length > 0) {
try {
parsedAncestorOrigin = new URL(location.ancestorOrigins.item(0));
if (parsedAncestorOrigin) {
self.config.first_ancestor_origin = parsedAncestorOrigin.origin;
if (doesURLMatchPortalDomains(parsedAncestorOrigin)) {
self.config.first_ancestor_matched = true;
}
}
} catch (error) {
self.log("cannot parse first ancestor origin", error);
}
try {
parsedAncestorOrigin = new URL(
location.ancestorOrigins.item(location.ancestorOrigins.length - 1)
);
if (parsedAncestorOrigin) {
self.config.last_ancestor_origin = parsedAncestorOrigin.origin;
if (doesURLMatchPortalDomains(parsedAncestorOrigin)) {
self.config.last_ancestor_matched = true;
}
}
} catch (error) {
self.log("cannot parse last ancestor origin", error);
}
}
self.log(
"affiliate domain matching:",
self.config.referrer_matched ? "found at least one domain" : "no domain found"
);
// check if top domain is owned and operated by famobi
if ((detection.is.iframe &&
self.config.last_ancestor_origin &&
(self.config.last_ancestor_origin.endsWith("/famobi.com") ||
self.config.last_ancestor_origin.endsWith(".famobi.com"))) ||
(!detection.is.iframe &&
(location.hostname == "famobi.com" ||
location.hostname.endsWith(".famobi.com")))
) {
self.config.is_own_inventory = true;
}
self.config.blurred_thumb =
self.config.blurred_thumb ||
"https://img.cdn.famobi.com/portal/html5games/images/tmp/blurred/RacingMonsterTrucksTeaser.jpg";
document.title = self.config.name;
function require(module) {
return (
self[module + "Module"] &&
self[module + "Module"].call(
self,
Array.prototype.slice.call(arguments, 1)
)
);
}
self.adapters = require("adapters");
self.requests = require("requests");
self.consent = require("consent");
self.game = require("game");
self.localStorage = require("storage", "localStorage");
self.sessionStorage = require("storage", "sessionStorage");
self.gametranslation = require("gametranslation");
self.rest = require("rest");
self.geo = require("geo");
self.lsg = require("lsg");
self.viewport = require("viewport");
switch (self.config.aid) {
case "A-MONKEYGAMES":
case "A-MONKEYGAMES-DEV":
self.socket = require("socket");
break;
default:
if (
self.getUrlParams()["fg_env"] == "staging" ||
self.config.gameParams.socket_enabled
) {
self.socket = require("socket");
}
}
function onloadCallback() {
self.rootElement.removeAttribute("hidden");
// keep order
// navigation first, because event handlers and language switches otherwise don't work
self.navigation = require("navigation");
// spinner first, used by ads
self.spinner = require("spinner").show();
self.tracking = require("tracking");
self.gameanalytics = require("gameanalytics");
self.mixpanel = require("mixpanel");
self.iframe = require("iframe");
self.modal = require("modal");
self.notify = require("notify");
self.highscores = require("highscores");
self.screenshot = require("screenshot");
self.click2play = require("click2play");
self.ads = require("ads");
self.rewardedads = require("rewardedads");
self.interstitial = require("interstitial");
self.banner = require("banner");
self.apstag = require("apstag");
self.audio = require("audio");
self.fullscreen = require("fullscreen");
self.orientation = require("orientation");
self.flash = require("flash");
self.debugger = require("debug");
if (window.famobi_env === "vp") {
self.video = require("video");
self.videoads = require("videoads");
}
self.game.init();
if (detection.is.pc && window.console) {
// eslint-disable-next-line no-console
console.log(
"%c ||| Brought to you |||",
"background-color: #0092c3; background-image: -webkit-linear-gradient(top, #0092c3, #eee); background-image: linear-gradient(to bottom, #0092c3, #eee); padding: 5px 10px; color: #333"
);
// eslint-disable-next-line no-console
console.log(
"%c ||| by Famobi |||",
"background-color: #f08119; background-image: -webkit-linear-gradient(top, #f08119, #eee); background-image: linear-gradient(to bottom, #f08119, #eee); padding: 5px 10px; color: #111"
);
// eslint-disable-next-line no-console
console.log(
"%c ||| HTML5Games.com |||",
"background-color: #333; background-image: -webkit-linear-gradient(top, #333, #eee); background-image: linear-gradient(to bottom, #333, #eee); padding: 5px 10px; color: #fff"
);
}
}
// Favicon
if (!faZepto('link[rel="icon"]').length) {
self.headElement.appendChild(
faZepto(
'<link rel="icon" type="image/png" sizes="32x32" href="' +
self.config.thumb +
'">'
).get(0)
);
self.headElement.appendChild(
faZepto(
'<link rel="icon" type="image/png" sizes="64x64" href="' +
self.config.thumb +
'">'
).get(0)
);
self.headElement.appendChild(
faZepto(
'<link rel="icon" type="image/png" sizes="96x96" href="' +
self.config.thumb +
'">'
).get(0)
);
self.headElement.appendChild(
faZepto(
'<link rel="icon" type="image/png" sizes="192x192" href="' +
self.config.thumb +
'">'
).get(0)
);
}
// Load Styles
function loadStylesheet() {
return new Promise(function (resolve) {
self.wait(1e3).then(resolve);
var newStylesheet = document.createElement("link");
newStylesheet.setAttribute("rel", "stylesheet");
newStylesheet.setAttribute("type", "text/css");
newStylesheet.setAttribute(
"href",
self.config.assetsPath + "/css/play.css"
);
newStylesheet.onload = resolve;
newStylesheet.onerror = resolve;
self.headElement.appendChild(newStylesheet);
});
}
function loadMoreGamesButton() {
return new Promise(function (resolve) {
// Detect if more-games-button can be loaded, otherwise fall back to a transparent png
var moreGamesBtn = self.getMoreGamesButtonImage();
var moreGamesImg = new Image();
moreGamesImg.onload = resolve;
moreGamesImg.onerror = function () {
if (self.config.game_i18n.current) {
self.config.game_i18n.current.more_games_image =
"/html5games/branding/default/More_Games600x253_transparent.png";
}
resolve();
};
moreGamesImg.src = moreGamesBtn;
});
}
Promise.all([self.game.prepare(), loadStylesheet(), loadMoreGamesButton()])
.then(onloadCallback)
.catch(onloadCallback);
return self;
};