PageSourceSearch

https://w.likebtn.com/js/w/widget.js

js likebtn.com collected 2026-10-02 03:41:09 UTC 256,200 bytes, 5,710 lines download raw bytes

1if (typeof(LikeBtn)=="undefined" || !LikeBtn) {
2
3    // load CSS
4            (function(d) {
5            var likebtn_css = d.createElement('link'); likebtn_css.type = 'text/css'; likebtn_css.rel = 'stylesheet';
6            likebtn_css.href = '//w.likebtn.com/css/w/widget.css?v=41';
7            (d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(likebtn_css);
8        })(document);
9    
10    var LikeBtn = function (window_obj) {
11        var obj = {};
12        // supported locales
13        obj.locales = ['en','ru','af','ar','hy','be','bn','bg','bs','ca','zh_CN','zh_HK','cs','fa','fi','fr','da','nl','de','el','he','hu','id','it','ja','kk','ko','lv','lt','ne','no','pl','pt','pt_BR','ro','sr','sk','sl','es','sv','th','tr','uk','vi'];
14        obj.styles = ['custom','white','lightgray','gray','black','padded','drop','line','github','transparent','youtube','habr','heartcross','plusminus','google','greenred','large','elegant','disk','squarespace','slideshare','baidu','uwhite','ublack','uorange','ublue','ugreen','direct','homeshop','nero','sku','review','likebtn','roundthumb','ok','mid','mini','bootstrap','angular','tick','stack','vertplus'];
15        obj.styles_per_css = '16';
16        obj.css_path = '/css/w/';
17        /*
18        obj.styles_css = [
19            '/css/w/style2.css?v=41',
20            '/css/w/style3.css?v=41',
21        ];
22        */
23        // debug mode
24        obj.debug = 0;
25        // is pv counter sent
26        obj.pv_sent = false;
27        // if LikeBtn has been runned or not
28        obj.runned = 0;
29        // interval for checking DOM state
30        obj.interval;
31        // site plan - determined from item
32        obj.plan = 0;
33        // test cookie name
34        obj.cookie_test_name = 'likebtn_test';
35        // cookie name
36        obj.cookie_vote_name = 'likebtn_vote';
37        // group_identifier cookie name
38        obj.cookie_group_identifier = 'likebtn_group_identifier';
39        // cookie lifetime
40        //obj.cookie_lifetime = 31449600; // 1 year
41        // cookie with counts
42        obj.cookie_count_lifetime = '300';
43        // count cookie name
44        obj.cookie_count_name = 'likebtn_count';
45        // locale cookie lifetime
46        obj.cookie_locale_lifetime = 2592000; // month
47        // information about current client
48        obj.client = {};
49        // automatic language detection
50        //obj.lang_auto = 'auto';
51        // default application language
52        obj.default_lang = 'en';
53        // settings percent replacer
54        //obj.settings_percent_replacer = '!';
55        // locale cookie name
56        obj.cookie_locale_name = 'likebtn_locale';
57        // backend used to determine browser http headers
58        //obj.http_headers_backend = '//ajaxhttpheaders2.appspot.com';        // browser locale detection has been launched and is running
59        obj.browser_locale_detection_running = false;
60        // real client browser locale - 2 first carachters
61        obj.browser_locale;
62        // time for animating counter counting in ms
63        obj.count_time = 1000;
64        // counting step in ms
65        obj.count_tstep = 70.0;
66        // Voting effect duration
67        obj.ef_time = 500;
68        // maximum number of buttons per page
69        obj.max_buttons_per_page = {
70            0: 1,            1: 10,            2: 25,            3: 1000000,            4: 1000000                    };
71        obj.https_check_disabled = ['wix.likebtn.com','devwix.likebtn.com','www.weebly.com'];
72        // addthis script has been loaded
73        obj.addthis_loaded = false;
74        obj.aip = false;
75        // bumber of share buttons
76        obj.share_buttons_count = 8;
77        // delay before popup can be closed by outside click
78        obj.popup_close_delay = 2000;
79        // popup padding for calculating popup width
80        obj.popup_padding = 8;
81        // popup min width
82        obj.popup_min_w = 148;
83        obj.identifier_maxl = 970;
84        // normalized identifiers cache
85        obj.norm_identifiers = {};
86                // Size of a bunch of items
87        obj.bunch_size = 100;
88        // Total buttons loaded via bunches
89        obj.bunch_btns = 0;
90        // List of items indexes ready to be loaded
91        obj.bunch = [];
92        // local website delimiter
93        obj.local_delimiter = '!';
94        // default order of the elements in the popup
95        obj.deafault_popup_content_order = ['popup_share', 'popup_donate', 'popup_html'];
96        // addthis buttons
97        obj.addthis_buttons = {
98            'all': ['facebook', 'twitter', 'preferred_1', 'preferred_2', 'preferred_3', 'preferred_4', 'preferred_5', 'compact'],
99            'ru': ['vk', 'odnoklassniki_ru', 'twitter', 'facebook', 'preferred_1', 'preferred_2', 'preferred_3', 'compact']
100        };
101        // mapping AddThis codes to other system
102        obj.addthis_mapping = {
103            'odnoklassniki_ru': 'odnoklassniki'
104        };
105        obj.addthis_preferred = [
106            'print', 'email', 'google_gmail', 'facebook', 'twitter', 'linkedin', 'pinterest', 'whatsapp', 'telegram', 'tumblr', 'livejournal', 'viber', 'trello', 
107        ];
108        // available events
109        obj.event_types = {
110            "loaded": "likebtn.loaded",
111            "click": "likebtn.click",
112            "like": "likebtn.like",
113            "unlike": "likebtn.unlike",
114            "dislike": "likebtn.dislike",
115            "undislike": "likebtn.undislike",
116            "popupopen": "likebtn.popupopen",
117            "popupclose": "likebtn.popupclose",
118            "voted": "likebtn.voted"
119        };
120        // settings for each button
121        obj.settings = {
122           values: [],
123           schema: {
124               "lang": { type: "lang", def: "en" },
125               "identifier": { type: "string", escape: "no", def: "" },
126               "site_id": { type: "string", escape: "no", def: "" },
127               "group_identifier": { type: "string", def: "" },
128               "local_domain": { type: "string", def: "" },
129               "domain_from_parent": { type: "bool", def: 1 },
130               "subdirectory": { type: "string", def: "" },
131               "rtl": { type: "bool", def: 0 },
132               "ef_voting": { type: "string", def: "" },
133               "show_like_label": { type: "bool", def: 1 },
134               "show_dislike_label": { type: "bool", def: 0 },
135               "popup_dislike": { type: "bool", def: 0 },
136               "like_enabled": { type: "bool", def: 1 },
137               "dislike_enabled": { type: "bool", def: 1 },
138               "icon_like_show": { type: "bool", def: 1 },
139               "icon_dislike_show": { type: "bool", def: 1 },
140               "lazy_load": { type: "bool", def: 0 },
141               "counter_clickable": { type: "bool", def: 0 },
142               "counter_type": { type: "string", def: "number" },
143               "counter_show": { type: "bool", def: "1" },
144               "counter_padding": { type: "string", def: "" },
145               // "init_l_from": { type: "string", def: "" },
146               // "init_l_to": { type: "string", def: "" },
147               "counter_zero_show": { type: "bool", def: 0 },
148               "counter_frmt": { type: "string", def: "" },
149               "counter_count": { type: "bool", def: 0 },
150               "voting_enabled": { type: "bool", def: 1 },
151               "voting_cancelable": { type: "bool", def: 1 },
152               "voting_both": { type: "bool", def: 0 },
153               "voting_frequency": { type: "string", def: 0 },
154               "theme": { type: "string", def: "white" },
155
156               "btn_size": { type: "string", def: "22" },
157               "icon_l": { type: "string", def: "thmb5-u" },
158               "icon_d": { type: "string", def: "thmb5-d" },
159               "icon_l_url": { type: "string", def: "" },
160               "icon_d_url": { type: "string", def: "" },
161               "icon_l_url_v": { type: "string", def: "" },
162               "icon_d_url_v": { type: "string", def: "" },
163               "icon_size": { type: "string", def: "" },
164               "vert": { type: "bool", def: 0 },
165               "icon_l_c": { type: "string", def: "333333" },
166               "icon_d_c": { type: "string", def: "333333" },
167               "icon_l_c_v": { type: "string", def: "#fbae05" },
168               "icon_d_c_v": { type: "string", def: "#fbae05" },
169               "label_c": { type: "string", def: "333333" },
170               "label_c_v": { type: "string", def: "#3b3b3b" },
171               "counter_l_c": { type: "string", def: "555555" },
172               "counter_d_c": { type: "string", def: "555555" },
173               "bg_c": { type: "string", def: "fafafa" },
174               "bg_c_v": { type: "string", def: "fafafa" },
175               "brdr_c": { type: "string", def: "c6c6c6" },
176               "f_size": { type: "string", def: "12"},
177               "f_family": { type: "string", def: "Arial" },
178               "f_style": { type: "string", def: "r" },
179               "label_fs": { type: "string", def: "b" },
180               "counter_fs": { type: "string", def: "r" },
181               "share_enabled": { type: "bool", def: 1 },
182               "share_size": { type: "string", def: "medium" },
183               "item_url": { type: "url", def: "" },
184               "item_title": { type: "string", escape: "html", def: "" },
185               "item_description": { type: "string", escape: "html", def: "" },
186               "item_image": { type: "url", def: "" },
187               "item_date": { type: "string", def: "" },
188               "addthis_pubid": { type: "string", def: "ra-511b51aa3d843ec4" },
189               "addthis_service_codes": { type: "string", def: "" },
190               "loader_show": { type: "bool", def: 0 },
191               "loader_image": { type: "string", def: "" },
192               "tooltip_enabled": { type: "bool", def: 1 },
193               "tooltip_like_show_always": { type: "bool", def: 0 },
194               "tooltip_dislike_show_always": { type: "bool", def: 0 },
195               "white_label": { type: "bool", def: 0 },
196               "popup_disabled": { type: "bool", def: 0 },
197               "popup_position": { type: "string", def: "top" },
198               "popup_style": { type: "string", def: "light" },
199               "popup_width": { type: "string", def: "176" },
200               "popup_hide_on_outside_click": { type: "bool", def: 1 },
201               "popup_on_load": { type: "bool", def: 0 },
202               "popup_html": { type: "string", escape: "no", def: "" },
203               "popup_donate": { type: "string", escape: "no", def: "" },
204               "popup_content_order": { type: "string", escape: "html", def: "" },
205               "event_handler": { type: "string", def: "" },
206               "rich_snippet": { type: "bool", def: 0 },
207               "debug": { type: "bool", def: 0 },
208               "info_message": { type: "bool", def: 1 },
209               "i18n_like": { type: "string", escape: "html", def: "" },
210               "i18n_dislike": { type: "string", escape: "html", def: "" },
211               "i18n_after_like": { type: "string", escape: "html", def: "" },
212               "i18n_after_dislike": { type: "string", escape: "html", def: "" },
213               "i18n_like_tooltip": { type: "string", escape: "html", def: "" },
214               "i18n_dislike_tooltip": { type: "string", escape: "html", def: "" },
215               "i18n_unlike_tooltip": { type: "string", escape: "html", def: "" },
216               "i18n_undislike_tooltip": { type: "string", escape: "html", def: "" },
217               "i18n_share_text": { type: "string", escape: "html", def: "" },
218               "i18n_popup_close": { type: "string", escape: "html", def: "" },
219               "i18n_popup_text": { type: "string", escape: "html", def: "" },
220               "i18n_popup_donate": { type: "string", escape: "html", def: "" },
221
222               // hidden
223               "engine": { type: "string", def: "" },
224               "engine_v": { type: "string", def: ""  },
225               "plugin_v": { type: "string", def: "" },
226               "prx": { type: "string", def: "" },
227               "vt": { type: "string", def: "" }, // vote type
228
229               // non-modifiable
230               "host": { type: "string", nonmodifiable: 0, def: window.location.hostname },
231               "url": { type: "string", nonmodifiable: 1, def: window.location.href }
232           }
233        };
234        // default values
235        obj.settings.values = [];
236        // translations stored in this script
237        obj.translations = {
238                            "en": {
239                    "i18n_like": "Like",
240                    "i18n_dislike": "Dislike",
241                    "i18n_after_like": "Like",
242                    "i18n_after_dislike": "Dislike",
243                    "i18n_like_tooltip": "I like this",
244                    "i18n_dislike_tooltip": "I dislike this",
245                    "i18n_unlike_tooltip": "Unlike",
246                    "i18n_undislike_tooltip": "Undislike",
247                    "i18n_share_text": "Would you like to share?",
248                    "i18n_popup_close": "Close",
249                    "i18n_popup_text": "Glad you liked it!",
250                    "i18n_popup_donate": "Show gratitude in the form of a donation"
251                },                            "ru": {
252                    "i18n_like": "Нравится",
253                    "i18n_dislike": "Не нравится",
254                    "i18n_after_like": "Нравится",
255                    "i18n_after_dislike": "Не нравится",
256                    "i18n_like_tooltip": "Мне это нравится",
257                    "i18n_dislike_tooltip": "Мне это не нравится",
258                    "i18n_unlike_tooltip": "Больше не нравится",
259                    "i18n_undislike_tooltip": "Отменить",
260                    "i18n_share_text": "Хотите поделиться?",
261                    "i18n_popup_close": "Закрыть",
262                    "i18n_popup_text": "Рады, что вам понравилось!",
263                    "i18n_popup_donate": "Отблагодарить рублём"
264                },                            "af": {
265                    "i18n_like": "شسی",
266                    "i18n_dislike": "یشس",
267                    "i18n_after_like": "شسی",
268                    "i18n_after_dislike": "یشس",
269                    "i18n_like_tooltip": "یشسیسش",
270                    "i18n_dislike_tooltip": "سشیشس",
271                    "i18n_unlike_tooltip": "سشی",
272                    "i18n_undislike_tooltip": "یشس",
273                    "i18n_share_text": "شسیشس",
274                    "i18n_popup_close": "شسیسشی",
275                    "i18n_popup_text": "سشی",
276                    "i18n_popup_donate": "سشی"
277                },                            "ar": {
278                    "i18n_like": "أعجبني",
279                    "i18n_dislike": "لم يعجبني",
280                    "i18n_after_like": "أعجبني",
281                    "i18n_after_dislike": "لم يعجبني",
282                    "i18n_like_tooltip": "أعجبني هذا",
283                    "i18n_dislike_tooltip": "لم يعجبني هذا",
284                    "i18n_unlike_tooltip": "إلغاء إعجابي",
285                    "i18n_undislike_tooltip": "إلغاء عدم إعجابي",
286                    "i18n_share_text": "هل تود نشر هذا؟",
287                    "i18n_popup_close": "إغلاق",
288                    "i18n_popup_text": "سعيد لأنك أحببته !",
289                    "i18n_popup_donate": "اظهار الامتنان على شكل هبة"
290                },                            "hy": {
291                    "i18n_like": "Հավանել",
292                    "i18n_dislike": "Չհավանել",
293                    "i18n_after_like": "Հավանել",
294                    "i18n_after_dislike": "Չհավանել",
295                    "i18n_like_tooltip": "Ես հավանում եմ սա",
296                    "i18n_dislike_tooltip": "Ես չեմ հավանում սա",
297                    "i18n_unlike_tooltip": "վերացնել",
298                    "i18n_undislike_tooltip": "վերացնել",
299                    "i18n_share_text": "Ցանկանում եք կիսել?",
300                    "i18n_popup_close": "Փակել",
301                    "i18n_popup_text": "Ուրախ եմ որ Ձեզ դուր եկավ այն.",
302                    "i18n_popup_donate": "նվիրաբերել"
303                },                            "be": {
304                    "i18n_like": "Спадабаецца",
305                    "i18n_dislike": "Не спадабаецца",
306                    "i18n_after_like": "Спадабаецца",
307                    "i18n_after_dislike": "Не спадабаецца",
308                    "i18n_like_tooltip": "Мне гэта спадабаецца",
309                    "i18n_dislike_tooltip": "Мне гэта не спадабаецца",
310                    "i18n_unlike_tooltip": "Больш не да спадобы",
311                    "i18n_undislike_tooltip": "Адмяніць",
312                    "i18n_share_text": "Жадаеце падзяліцца?",
313                    "i18n_popup_close": "Закрыць",
314                    "i18n_popup_text": "Вельмі рады, што вам спадабалася!",
315                    "i18n_popup_donate": "Падзячыць грашыма"
316                },                            "bn": {
317                    "i18n_like": "লাইক",
318                    "i18n_dislike": "ডিসলাইক",
319                    "i18n_after_like": "লাইক",
320                    "i18n_after_dislike": "ডিসলাইক",
321                    "i18n_like_tooltip": "লাইক করছি",
322                    "i18n_dislike_tooltip": "লাইক করছি না",
323                    "i18n_unlike_tooltip": "আনলাইক",
324                    "i18n_undislike_tooltip": "আনডিসলাইক",
325                    "i18n_share_text": "শেয়ার করতে চাও",
326                    "i18n_popup_close": "বন্ধ",
327                    "i18n_popup_text": "ধন্যবাদ",
328                    "i18n_popup_donate": "মুক্ত হস্তে দান"
329                },                            "bg": {
330                    "i18n_like": "Харесвам",
331                    "i18n_dislike": "Нехаресвам",
332                    "i18n_after_like": "Харесвам",
333                    "i18n_after_dislike": "Нехаресвам",
334                    "i18n_like_tooltip": "Харесвам това",
335                    "i18n_dislike_tooltip": "Нехаресвам това",
336                    "i18n_unlike_tooltip": "Нехаресвам",
337                    "i18n_undislike_tooltip": "Харесвам",
338                    "i18n_share_text": "Искате ли да споделите?",
339                    "i18n_popup_close": "Затвори",
340                    "i18n_popup_text": "Благодарим Ви, че харесахте!",
341                    "i18n_popup_donate": "Покажете своята благодарност, като направите дарение"
342                },                            "bs": {
343                    "i18n_like": "Sviđa mi se",
344                    "i18n_dislike": "Ne sviđa mi se",
345                    "i18n_after_like": "Sviđa mi se",
346                    "i18n_after_dislike": "Ne sviđa mi se",
347                    "i18n_like_tooltip": "Sviđa mi se",
348                    "i18n_dislike_tooltip": "Ne sviđa mi se",
349                    "i18n_unlike_tooltip": "Ne sviđa mi se",
350                    "i18n_undislike_tooltip": "Ne sviđa mi se",
351                    "i18n_share_text": "Želite podijeliti?",
352                    "i18n_popup_close": "Zatvori",
353                    "i18n_popup_text": "Drago nam je da Vam se sviđa!",
354                    "i18n_popup_donate": "Donirajte i podržite"
355                },                            "ca": {
356                    "i18n_like": "M'agrada",
357                    "i18n_dislike": "No m'agrada",
358                    "i18n_after_like": "M'agrada",
359                    "i18n_after_dislike": "No m'agrada",
360                    "i18n_like_tooltip": "Això m'agrada",
361                    "i18n_dislike_tooltip": "Això no m'agrada",
362                    "i18n_unlike_tooltip": "Ja no m'agrada",
363                    "i18n_undislike_tooltip": "Ja no em desagrada",
364                    "i18n_share_text": "T'agradaria compartir-ho?",
365                    "i18n_popup_close": "Tencar",
366                    "i18n_popup_text": "M'alegro que t'agradi!",
367                    "i18n_popup_donate": "Demostra gratitud en forma de donació"
368                },                            "zh_CN": {
369                    "i18n_like": "é¡¶",
370                    "i18n_dislike": "踩",
371                    "i18n_after_like": "é¡¶",
372                    "i18n_after_dislike": "踩",
373                    "i18n_like_tooltip": "顶一下",
374                    "i18n_dislike_tooltip": "踩一下",
375                    "i18n_unlike_tooltip": "不顶了",
376                    "i18n_undislike_tooltip": "不踩了",
377                    "i18n_share_text": "分享吗?",
378                    "i18n_popup_close": "关闭",
379                    "i18n_popup_text": "谢谢夸奖",
380                    "i18n_popup_donate": "捐助支持"
381                },                            "zh_HK": {
382                    "i18n_like": "喜歡",
383                    "i18n_dislike": "不喜歡",
384                    "i18n_after_like": "喜歡",
385                    "i18n_after_dislike": "不喜歡",
386                    "i18n_like_tooltip": "我喜歡",
387                    "i18n_dislike_tooltip": "我不喜歡",
388                    "i18n_unlike_tooltip": "收回喜歡",
389                    "i18n_undislike_tooltip": "收回不喜歡",
390                    "i18n_share_text": "分享?",
391                    "i18n_popup_close": "關閉",
392                    "i18n_popup_text": "希望你喜歡!",
393                    "i18n_popup_donate": "我們會很感謝您的慷慨解囊"
394                },                            "cs": {
395                    "i18n_like": "Líbí",
396                    "i18n_dislike": "Nelíbí",
397                    "i18n_after_like": "Líbí",
398                    "i18n_after_dislike": "Nelíbí",
399                    "i18n_like_tooltip": "Líbí se mi to",
400                    "i18n_dislike_tooltip": "Nelíbí se mi to",
401                    "i18n_unlike_tooltip": "Vzít tento hlas zpět",
402                    "i18n_undislike_tooltip": "Vzít tento hlas zpět",
403                    "i18n_share_text": "Chcete využít možnosti sdílení?",
404                    "i18n_popup_close": "Zavřít",
405                    "i18n_popup_text": "Jsme rádi, že se vám to líbilo!",
406                    "i18n_popup_donate": "Projevte nám svoje díky i formou daru"
407                },                            "fa": {
408                    "i18n_like": "می‌پسندم",
409                    "i18n_dislike": "نمی‌پسندم",
410                    "i18n_after_like": "می‌پسندم",
411                    "i18n_after_dislike": "نمی‌پسندم",
412                    "i18n_like_tooltip": "من می‌پسندم",
413                    "i18n_dislike_tooltip": "من نمی‌پسندم",
414                    "i18n_unlike_tooltip": "لغو پسندیدن",
415                    "i18n_undislike_tooltip": "لغو مخالفت",
416                    "i18n_share_text": "در کجا مایلید به اشتراک بگذارید؟!",
417                    "i18n_popup_close": "بستن",
418                    "i18n_popup_text": "خوشحالم که این را می‌پسندید!",
419                    "i18n_popup_donate": "نمایش قدردانی در قالب کمک مالی"
420                },                            "fi": {
421                    "i18n_like": "Tykkään",
422                    "i18n_dislike": "En tykkää",
423                    "i18n_after_like": "Tykkään",
424                    "i18n_after_dislike": "En tykkää",
425                    "i18n_like_tooltip": "Pidän tästä",
426                    "i18n_dislike_tooltip": "En pidä tästä",
427                    "i18n_unlike_tooltip": "En tykkää",
428                    "i18n_undislike_tooltip": "Poista valintani",
429                    "i18n_share_text": "Haluaisitko jakaa?",
430                    "i18n_popup_close": "Sulje",
431                    "i18n_popup_text": "Kiva kun pidät tästä!",
432                    "i18n_popup_donate": "Osoita kiitollisuutta lahjoituksen muodossa"
433                },                            "fr": {
434                    "i18n_like": "J'aime",
435                    "i18n_dislike": "Je n'aime pas",
436                    "i18n_after_like": "J'aime",
437                    "i18n_after_dislike": "Je n'aime pas",
438                    "i18n_like_tooltip": "J'aime ça",
439                    "i18n_dislike_tooltip": "Je n'aime pas ça",
440                    "i18n_unlike_tooltip": "Je n'aime plus",
441                    "i18n_undislike_tooltip": "Retirer Je n'aime pas",
442                    "i18n_share_text": "Souhaitez-vous partager?",
443                    "i18n_popup_close": "Fermer",
444                    "i18n_popup_text": "Heureux que vous ayez aimé!",
445                    "i18n_popup_donate": "Montrez votre gratitude avec un don"
446                },                            "da": {
447                    "i18n_like": "Synes godt om",
448                    "i18n_dislike": "Synes ikke om",
449                    "i18n_after_like": "Synes godt om",
450                    "i18n_after_dislike": "Synes ikke om",
451                    "i18n_like_tooltip": "Jeg kan lide dette",
452                    "i18n_dislike_tooltip": "Jeg kan ikke lide dette",
453                    "i18n_unlike_tooltip": "Fjern synes godt om",
454                    "i18n_undislike_tooltip": "Fjern synes ikke om",
455                    "i18n_share_text": "Vil du dele dette?",
456                    "i18n_popup_close": "Luk",
457                    "i18n_popup_text": "Tak fordi du synes om dette!",
458                    "i18n_popup_donate": "Jeg ønsker at bidrage med en donation"
459                },                            "nl": {
460                    "i18n_like": "Leuk",
461                    "i18n_dislike": "Niet leuk",
462                    "i18n_after_like": "Leuk",
463                    "i18n_after_dislike": "Niet leuk",
464                    "i18n_like_tooltip": "Ik vind dit leuk",
465                    "i18n_dislike_tooltip": "Ik vind dit niet leuk",
466                    "i18n_unlike_tooltip": "Niet meer leuk",
467                    "i18n_undislike_tooltip": "Ik vind dit leuk",
468                    "i18n_share_text": "Wil je dit delen?",
469                    "i18n_popup_close": "Sluit",
470                    "i18n_popup_text": "We zijn blij dat je het leuk vond!",
471                    "i18n_popup_donate": "Donatie"
472                },                            "de": {
473                    "i18n_like": "Mag ich",
474                    "i18n_dislike": "Mag ich nicht",
475                    "i18n_after_like": "Mag ich",
476                    "i18n_after_dislike": "Mag ich nicht",
477                    "i18n_like_tooltip": "Gefällt mir",
478                    "i18n_dislike_tooltip": "Gefällt mir nicht",
479                    "i18n_unlike_tooltip": "Gefällt mir nicht mehr",
480                    "i18n_undislike_tooltip": "Gefällt mir wieder",
481                    "i18n_share_text": "Möchtest du es mit anderen teilen?",
482                    "i18n_popup_close": "Schließen",
483                    "i18n_popup_text": "Schön, dass es dir gefällt!",
484                    "i18n_popup_donate": "Spenden"
485                },                            "el": {
486                    "i18n_like": "Μου αρέσει",
487                    "i18n_dislike": "Πες μας γιατί",
488                    "i18n_after_like": "Μου αρέσει",
489                    "i18n_after_dislike": "Πες μας γιατί",
490                    "i18n_like_tooltip": "Μου αρέσει",
491                    "i18n_dislike_tooltip": "Πες μας γιατί",
492                    "i18n_unlike_tooltip": "Μετάνιωσα",
493                    "i18n_undislike_tooltip": "Μετάνιωσα",
494                    "i18n_share_text": "Θες να το μοιραστείς;",
495                    "i18n_popup_close": "Κλείσιμο",
496                    "i18n_popup_text": "Χαίρομαι που σου άρεσε!",
497                    "i18n_popup_donate": "Ευχαριστούμε!"
498                },                            "he": {
499                    "i18n_like": "אהבתי",
500                    "i18n_dislike": "לא אהבתי",
501                    "i18n_after_like": "אהבתי",
502                    "i18n_after_dislike": "לא אהבתי",
503                    "i18n_like_tooltip": "אוהבת",
504                    "i18n_dislike_tooltip": "לא אוהבת",
505                    "i18n_unlike_tooltip": "לא אהבתי",
506                    "i18n_undislike_tooltip": "אהבתי",
507                    "i18n_share_text": "לשתף?",
508                    "i18n_popup_close": "לסגור",
509                    "i18n_popup_text": "שמחים שאהבת!",
510                    "i18n_popup_donate": "תודה"
511                },                            "hu": {
512                    "i18n_like": "Tetszik",
513                    "i18n_dislike": "Nem tetszik",
514                    "i18n_after_like": "Tetszik",
515                    "i18n_after_dislike": "Nem tetszik",
516                    "i18n_like_tooltip": "Kedvelem ezt",
517                    "i18n_dislike_tooltip": "Nem kedvelem ezt",
518                    "i18n_unlike_tooltip": "Mégsem tetszik",
519                    "i18n_undislike_tooltip": "Mégis tetszik",
520                    "i18n_share_text": "Szeretné megosztani?",
521                    "i18n_popup_close": "Bezár",
522                    "i18n_popup_text": "Örülünk, hogy tetszett!",
523                    "i18n_popup_donate": "Támogass"
524                },                            "id": {
525                    "i18n_like": "Suka",
526                    "i18n_dislike": "Tidak Suka",
527                    "i18n_after_like": "Suka",
528                    "i18n_after_dislike": "Tidak Suka",
529                    "i18n_like_tooltip": "Aku suka ini",
530                    "i18n_dislike_tooltip": "Aku tidak suka ini",
531                    "i18n_unlike_tooltip": "Batal menyukai",
532                    "i18n_undislike_tooltip": "Batal tidak menyukai",
533                    "i18n_share_text": "Anda mau membagikan?",
534                    "i18n_popup_close": "Tutup",
535                    "i18n_popup_text": "Terima kasih karena mau menyukai!",
536                    "i18n_popup_donate": "Tunjukkan keramahan melalui bentuk menyumbang"
537                },                            "it": {
538                    "i18n_like": "Mi piace",
539                    "i18n_dislike": "Non mi piace",
540                    "i18n_after_like": "Mi piace",
541                    "i18n_after_dislike": "Non mi piace",
542                    "i18n_like_tooltip": "Mi piace questo",
543                    "i18n_dislike_tooltip": "Non mi piace questo",
544                    "i18n_unlike_tooltip": "Non mi piace più",
545                    "i18n_undislike_tooltip": "Mi piace",
546                    "i18n_share_text": "Vorresti condividere?",
547                    "i18n_popup_close": "Chiudi",
548                    "i18n_popup_text": "Spero ti sia piaciuto!",
549                    "i18n_popup_donate": "Mostra gratitudine sotto forma di una donazione"
550                },                            "ja": {
551                    "i18n_like": "よく気づきました",
552                    "i18n_dislike": "参考にならない",
553                    "i18n_after_like": "よく気づきました",
554                    "i18n_after_dislike": "参考にならない",
555                    "i18n_like_tooltip": "これは気に入りました",
556                    "i18n_dislike_tooltip": "これは好きではありません",
557                    "i18n_unlike_tooltip": "好きではない",
558                    "i18n_undislike_tooltip": "嫌いではない",
559                    "i18n_share_text": "シェアしたいですか。",
560                    "i18n_popup_close": "閉じる",
561                    "i18n_popup_text": "お気に入りありがとうございます。",
562                    "i18n_popup_donate": "寄付する"
563                },                            "kk": {
564                    "i18n_like": "Ұнайды",
565                    "i18n_dislike": "Ұнамайды",
566                    "i18n_after_like": "Ұнайды",
567                    "i18n_after_dislike": "Ұнамайды",
568                    "i18n_like_tooltip": "Маған ұнайды",
569                    "i18n_dislike_tooltip": "Маған ұнамайды",
570                    "i18n_unlike_tooltip": "Маған ұнады",
571                    "i18n_undislike_tooltip": "Маған ұнамады",
572                    "i18n_share_text": "Бөлісу",
573                    "i18n_popup_close": "Жабу",
574                    "i18n_popup_text": "Достарыңызбен бөлісіңіз!",
575                    "i18n_popup_donate": "Алғыс айту"
576                },                            "ko": {
577                    "i18n_like": "좋아요",
578                    "i18n_dislike": "싫어요",
579                    "i18n_after_like": "좋아요",
580                    "i18n_after_dislike": "싫어요",
581                    "i18n_like_tooltip": "나 이거 좋아요",
582                    "i18n_dislike_tooltip": "나 이거 싫어요",
583                    "i18n_unlike_tooltip": "좋아요 취소",
584                    "i18n_undislike_tooltip": "싫어요 취소",
585                    "i18n_share_text": "공유하겠습니까?",
586                    "i18n_popup_close": "닫기",
587                    "i18n_popup_text": "'좋아요'해주셔서 감사합니다.",
588                    "i18n_popup_donate": "기부로 감사 전하기"
589                },                            "lv": {
590                    "i18n_like": "Patīk",
591                    "i18n_dislike": "Nepatīk",
592                    "i18n_after_like": "Patīk",
593                    "i18n_after_dislike": "Nepatīk",
594                    "i18n_like_tooltip": "Man patīk",
595                    "i18n_dislike_tooltip": "Man nepatīk",
596                    "i18n_unlike_tooltip": "Pārdomāju",
597                    "i18n_undislike_tooltip": "Pārdomāju",
598                    "i18n_share_text": "Vai vēlies dalīties?",
599                    "i18n_popup_close": "Aizvērt",
600                    "i18n_popup_text": "Prieks, ka patika!",
601                    "i18n_popup_donate": "Ziedo naudu"
602                },                            "lt": {
603                    "i18n_like": "Patinka",
604                    "i18n_dislike": "Nepatiko",
605                    "i18n_after_like": "Patinka",
606                    "i18n_after_dislike": "Nepatiko",
607                    "i18n_like_tooltip": "Man patiko",
608                    "i18n_dislike_tooltip": "Man nepatiko",
609                    "i18n_unlike_tooltip": "Nustoti mėgti",
610                    "i18n_undislike_tooltip": "Nustoti nemėgti",
611                    "i18n_share_text": "Ar nori pasidalinti",
612                    "i18n_popup_close": "Uždaryti",
613                    "i18n_popup_text": "Dėkojame už balsą!",
614                    "i18n_popup_donate": "Padėkokite autoriui dovanėle"
615                },                            "ne": {
616                    "i18n_like": "लाइक गर्नुहोस",
617                    "i18n_dislike": "अनलाइक गर्नुहोस",
618                    "i18n_after_like": "लाइक गर्नुहोस",
619                    "i18n_after_dislike": "अनलाइक गर्नुहोस",
620                    "i18n_like_tooltip": "मन पर्यो",
621                    "i18n_dislike_tooltip": "मन परेन",
622                    "i18n_unlike_tooltip": "मन परेन",
623                    "i18n_undislike_tooltip": "मन पर्यो",
624                    "i18n_share_text": "यसलाई शेयर गर्नहोस्",
625                    "i18n_popup_close": "बन्द",
626                    "i18n_popup_text": "लाइक गर्नु भएकोमा यहालाई धन्यबाद",
627                    "i18n_popup_donate": "दान गर्नु भएकोमा यहालाई धन्यबाद !"
628                },                            "no": {
629                    "i18n_like": "Liker",
630                    "i18n_dislike": "Misliker",
631                    "i18n_after_like": "Liker",
632                    "i18n_after_dislike": "Misliker",
633                    "i18n_like_tooltip": "Jeg liker denne",
634                    "i18n_dislike_tooltip": "Jeg liker ikke denne",
635                    "i18n_unlike_tooltip": "Angre Liker",
636                    "i18n_undislike_tooltip": "Angre Liker ikke",
637                    "i18n_share_text": "Ønsker du å dele",
638                    "i18n_popup_close": "Lukk",
639                    "i18n_popup_text": "Glad du likte det",
640                    "i18n_popup_donate": "Vis takknemlighet ved å gi donasjon"
641                },                            "pl": {
642                    "i18n_like": "Lubię",
643                    "i18n_dislike": "Nie lubię",
644                    "i18n_after_like": "Lubię",
645                    "i18n_after_dislike": "Nie lubię",
646                    "i18n_like_tooltip": "Lubię to",
647                    "i18n_dislike_tooltip": "Nie lubię tego",
648                    "i18n_unlike_tooltip": "Usuń polubienie",
649                    "i18n_undislike_tooltip": "Usuń nie lubię",
650                    "i18n_share_text": "Chcesz się podzielić?",
651                    "i18n_popup_close": "Zamknij",
652                    "i18n_popup_text": "Dziękujemy, że polubiłeś!",
653                    "i18n_popup_donate": "Okaż hojność przekazując darowiznę"
654                },                            "pt": {
655                    "i18n_like": "Gostar",
656                    "i18n_dislike": "Não Gostar",
657                    "i18n_after_like": "Gostar",
658                    "i18n_after_dislike": "Não Gostar",
659                    "i18n_like_tooltip": "Gostei",
660                    "i18n_dislike_tooltip": "Não Gostei",
661                    "i18n_unlike_tooltip": "Não gostar",
662                    "i18n_undislike_tooltip": "Tirar não gosto",
663                    "i18n_share_text": "Queres partilhar?",
664                    "i18n_popup_close": "Fechar",
665                    "i18n_popup_text": "Ainda bem que gostou!",
666                    "i18n_popup_donate": "Mostre a sua gratidão, fazendo um donativo"
667                },                            "pt_BR": {
668                    "i18n_like": "Gostei",
669                    "i18n_dislike": "Não Gostei",
670                    "i18n_after_like": "Gostei",
671                    "i18n_after_dislike": "Não Gostei",
672                    "i18n_like_tooltip": "Eu gosto disso",
673                    "i18n_dislike_tooltip": "Eu não gosto disso",
674                    "i18n_unlike_tooltip": "Desfazer",
675                    "i18n_undislike_tooltip": "Desfazer",
676                    "i18n_share_text": "Você gostaria de compartilhar?",
677                    "i18n_popup_close": "Fechar",
678                    "i18n_popup_text": "Que bom que você gostou!",
679                    "i18n_popup_donate": "Mostre sua gratidão em forma de doação"
680                },                            "ro": {
681                    "i18n_like": "Îmi place",
682                    "i18n_dislike": "Nu-mi place",
683                    "i18n_after_like": "Îmi place",
684                    "i18n_after_dislike": "Nu-mi place",
685                    "i18n_like_tooltip": "Îmi place asta",
686                    "i18n_dislike_tooltip": "Nu-mi place asta",
687                    "i18n_unlike_tooltip": "Nu-mi place",
688                    "i18n_undislike_tooltip": "Nu-mi mai place",
689                    "i18n_share_text": "Vrei să distribui?",
690                    "i18n_popup_close": "Închide",
691                    "i18n_popup_text": "Bucuros că va plăcut!",
692                    "i18n_popup_donate": "Exprimaţi-Vă generozitatea printr-o donaţie"
693                },                            "sr": {
694                    "i18n_like": "Dopada mi se",
695                    "i18n_dislike": "Ne dopada mi se",
696                    "i18n_after_like": "Dopada mi se",
697                    "i18n_after_dislike": "Ne dopada mi se",
698                    "i18n_like_tooltip": "Ovo mi se dopada",
699                    "i18n_dislike_tooltip": "Ovo mi se ne dopadaа",
700                    "i18n_unlike_tooltip": "Poništi",
701                    "i18n_undislike_tooltip": "Poništi",
702                    "i18n_share_text": "Podeli sa drugima?",
703                    "i18n_popup_close": "Zatvori",
704                    "i18n_popup_text": "Drago nam je!",
705                    "i18n_popup_donate": "Donacije"
706                },                            "sk": {
707                    "i18n_like": "Páči sa",
708                    "i18n_dislike": "Nepáči sa",
709                    "i18n_after_like": "Páči sa",
710                    "i18n_after_dislike": "Nepáči sa",
711                    "i18n_like_tooltip": "Páči sa mi to",
712                    "i18n_dislike_tooltip": "Nepáči sa mi to",
713                    "i18n_unlike_tooltip": "Odobrať Páči sa mi to",
714                    "i18n_undislike_tooltip": "Odobrať Páči sa mi to",
715                    "i18n_share_text": "Chcete využiť možnosť zdieľania?",
716                    "i18n_popup_close": "Zavrieť",
717                    "i18n_popup_text": "Sme radí, že sa Vám to páčilo!",
718                    "i18n_popup_donate": "Prejavte nám svoje poďakovanie aj formou daru"
719                },                            "sl": {
720                    "i18n_like": "Všeč",
721                    "i18n_dislike": "Ni mi všeč",
722                    "i18n_after_like": "Všeč",
723                    "i18n_after_dislike": "Ni mi všeč",
724                    "i18n_like_tooltip": "Všeč mi je",
725                    "i18n_dislike_tooltip": "Ni mi všeč to",
726                    "i18n_unlike_tooltip": "Si si premislil",
727                    "i18n_undislike_tooltip": "Ni mi bilo všeč",
728                    "i18n_share_text": "Bi želel deliti to?",
729                    "i18n_popup_close": "Zapri",
730                    "i18n_popup_text": "Lepo, da ti je všeč",
731                    "i18n_popup_donate": "Doniranje omogočeno"
732                },                            "es": {
733                    "i18n_like": "Me gusta",
734                    "i18n_dislike": "No me gusta",
735                    "i18n_after_like": "Me gusta",
736                    "i18n_after_dislike": "No me gusta",
737                    "i18n_like_tooltip": "Me gusta esto",
738                    "i18n_dislike_tooltip": "No me gusta esto",
739                    "i18n_unlike_tooltip": "Quitar me gusta",
740                    "i18n_undislike_tooltip": "Quitar no me gusta",
741                    "i18n_share_text": "¿Te gustaría compartir?",
742                    "i18n_popup_close": "Cerrar",
743                    "i18n_popup_text": "¡Nos alegra que te guste!",
744                    "i18n_popup_donate": "Demuestre su gratitud en la forma de un donativo"
745                },                            "sv": {
746                    "i18n_like": "Gilla",
747                    "i18n_dislike": "Ogilla",
748                    "i18n_after_like": "Gilla",
749                    "i18n_after_dislike": "Ogilla",
750                    "i18n_like_tooltip": "Det här gillar jag",
751                    "i18n_dislike_tooltip": "Det här gillar jag inte",
752                    "i18n_unlike_tooltip": "Tackar",
753                    "i18n_undislike_tooltip": "Det här var ju inte så kul, men tack",
754                    "i18n_share_text": "Vill du dela med dig?",
755                    "i18n_popup_close": "Stäng",
756                    "i18n_popup_text": "Vi är glada att du gillade det!",
757                    "i18n_popup_donate": "Donera"
758                },                            "th": {
759                    "i18n_like": "ชอบ",
760                    "i18n_dislike": "ไม่ชอบ",
761                    "i18n_after_like": "ชอบ",
762                    "i18n_after_dislike": "ไม่ชอบ",
763                    "i18n_like_tooltip": "ฉันชอบสิ่งนี้",
764                    "i18n_dislike_tooltip": "ฉันไม่ชอบสิ่งนี้",
765                    "i18n_unlike_tooltip": "แตกต่าง",
766                    "i18n_undislike_tooltip": "ไม่ชอบ",
767                    "i18n_share_text": "คุณต้องการที่จะแชร์?",
768                    "i18n_popup_close": "ปิด",
769                    "i18n_popup_text": "ดีใจที่คุณชอบมัน!",
770                    "i18n_popup_donate": "แสดงความกตัญญูในรูปแบบของการบริจาค"
771                },                            "tr": {
772                    "i18n_like": "Beğen",
773                    "i18n_dislike": "Beğenmedim",
774                    "i18n_after_like": "Beğen",
775                    "i18n_after_dislike": "Beğenmedim",
776                    "i18n_like_tooltip": "Beğendim",
777                    "i18n_dislike_tooltip": "Beğenmedim",
778                    "i18n_unlike_tooltip": "Beğenmekten Vazgeç",
779                    "i18n_undislike_tooltip": "Beğen",
780                    "i18n_share_text": "Paylaşmak ister misiniz?",
781                    "i18n_popup_close": "Kapat",
782                    "i18n_popup_text": "Beğendiğine sevindim!",
783                    "i18n_popup_donate": "Bağış yaparak memnuniyetinizi gösterebilirsiniz"
784                },                            "uk": {
785                    "i18n_like": "Подобається",
786                    "i18n_dislike": "Не подобається",
787                    "i18n_after_like": "Подобається",
788                    "i18n_after_dislike": "Не подобається",
789                    "i18n_like_tooltip": "Мені подобається",
790                    "i18n_dislike_tooltip": "Мені не подобається",
791                    "i18n_unlike_tooltip": "Не подобається",
792                    "i18n_undislike_tooltip": "Мені подобається",
793                    "i18n_share_text": "Хочете поділитися?",
794                    "i18n_popup_close": "Закрити",
795                    "i18n_popup_text": "Раді, що вам сподобалося!",
796                    "i18n_popup_donate": "Віддячити"
797                },                            "vi": {
798                    "i18n_like": "Thích",
799                    "i18n_dislike": "Không thích",
800                    "i18n_after_like": "Thích",
801                    "i18n_after_dislike": "Không thích",
802                    "i18n_like_tooltip": "Đã hâm mộ",
803                    "i18n_dislike_tooltip": "Bạn không thích điều này",
804                    "i18n_unlike_tooltip": "Bỏ thích",
805                    "i18n_undislike_tooltip": "Bỏ không thích",
806                    "i18n_share_text": "Bạn có muốn chia sẻ?",
807                    "i18n_popup_close": "Đóng",
808                    "i18n_popup_text": "Cảm ơn vì bạn đã thích nó!",
809                    "i18n_popup_donate": "Tặng"
810                }                    };
811        // settings which are being not sent to server
812        // it's indexes match obj.settings.values indexes and represent each button on page
813        // in order they appear on a page
814        // - locale - contains locale, supported by widget
815        // - identifier_hash
816        // - loaded
817        // - wrapper
818        obj.dyn_settings = {
819           values: []
820        };
821        // plans
822        obj.plans = {
823            TRIAL: 9,            FREE: 0,            PLUS: 1,            PRO: 2,            VIP: 3,            ULTRA: 4                    };
824        // domains for which domain_from_parent is forced (usually CDNs)
825                // Stack of loaded assets
826        obj.loaded_assets = [];
827        // Stack of event listeners
828        obj.event_listeners = [];
829        // Loader default
830        obj.loader_img = 'data:image/gif;base64,R0lGODlhEAALAPQAAP///wAAANra2tDQ0Orq6gYGBgAAAC4uLoKCgmBgYLq6uiIiIkpKSoqKimRkZL6+viYmJgQEBE5OTubm5tjY2PT09Dg4ONzc3PLy8ra2tqCgoMrKyu7u7gAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCwAAACwAAAAAEAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJCwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJCwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHTuBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V55zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAAABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7AAAAAAAAAAAA';
831
832
833        // set settings value
834        obj.settings.set = function (index, property, value) {
835            //obj.assert(obj.settings.schema[property] != null, "Wrong property name: "+property);
836            if (obj.settings.schema[property] == null) {
837                obj.log("Unknown property name: property: "+property+", index: "+index);
838                return false;
839            }
840            var schema = obj.settings.schema[property];
841            var prepared_value;
842
843            obj.assert( !schema.nonmodifiable, "Attempt to modify unmodifiable property: "+property);
844
845            switch (schema.type) {
846                case "bool":
847                    prepared_value = obj.toBool(value);
848                    break;
849                case "url":
850                    prepared_value = value + "";
851                    obj.log(
852                        (prepared_value.substr(0, 7) == 'http://' || prepared_value.substr(0, 8) == 'https://'
853                        || prepared_value.substr(0, 2) == '//'),
854                        "Wrong URL format: "+value
855                    );
856                    break;
857                case "string":
858                    prepared_value = value + "";
859                    break;
860                case "lang":
861                    // check if value contains supported language
862                    //var supported_lang = false;
863                    //if (value == obj.lang_auto) {
864                    //    supported_lang = true;
865                    //} else {
866                    //    supported_lang = obj.isLocaleSupported(value);
867                    //}
868                    // if wrong lnag code passed use default lang
869                    //if (!supported_lang) {
870                    //    obj.log("Unsupported language: "+value);
871                    //    value = obj.default_lang;
872                    //}
873                    prepared_value = value + "";
874                    break;
875            }
876            if (obj.isDefined(schema.escape)) {
877                switch (schema.escape) {
878                    case "html":
879                        prepared_value = obj.escapeHTML(prepared_value);
880                        prepared_value = obj.replaceAll(/"/, '"', prepared_value);
881                        break;
882                    case "no":
883                        // Do nothing
884                }
885            } else {
886                // cut double quotes out
887                if (prepared_value) {
888                    prepared_value = obj.replaceAll(/"/, '', prepared_value+'');
889                }
890            }
891            // validate theme
892            if ((property == "theme" || property == "style") && !obj.inArray(prepared_value, obj.styles)) {
893                prepared_value = obj.getDefaultValue('theme');
894            }
895            // Normalize identifier
896            if (property == 'identifier') {
897                prepared_value = obj.normalizeIdentifier(prepared_value);
898            }
899
900            /*if (typeof(obj.settings.values[index]) == "undefined") {
901                obj.settings.values[index] = obj.settings.default_values;
902            }*/
903            obj.settings.values[index][property] = prepared_value;
904
905            // set debug if needed
906            if (property == "debug" && prepared_value) {
907                obj.debug = 1;
908            }
909
910            return obj.settings;
911        };
912
913        // get settings value
914        obj.settings.get = function (index, property) {
915            obj.assert(typeof(obj.settings.values[index]) != "undefined", "Wrapper not found: "+index);
916            obj.assert(typeof(obj.settings.values[index][property]) != "undefined",
917                        "Property not found: property: "+property+", wrapper: "+index);
918            var value = obj.settings.values[index][property];
919            obj.assert(value != null, "Undefined property name '" + property + "'.");
920            return value;
921        }
922
923        // Convert host to ASCII
924        obj.settings.setDefaultHost = function () {
925            obj.settings.schema['host']['def'] = obj.punycode.ToUnicode(obj.settings.schema['host']['def']);
926        }
927
928        // set dynamic settings value
929        obj.dyn_settings.set = function (index, property, value) {
930            if (!obj.isDefined(obj.dyn_settings.values[index])) {
931                obj.dyn_settings.values[index] = {};
932            }
933            obj.dyn_settings.values[index][property] = value;
934            return obj.dyn_settings;
935        };
936
937        // get settings value
938        obj.dyn_settings.get = function (index, property) {
939            //obj.assert(typeof(obj.dyn_settings.values[index]) != "undefined", "[dyn_settings] Wrapper not found: "+index);
940            //obj.assert(typeof(obj.dyn_settings.values[index][property]) != "undefined",
941            //            "[dyn_settings] Property not found: property: "+property+", wrapper: "+index);
942            var value;
943            if (obj.isDefined(obj.dyn_settings.values[index]) &&
944                obj.isDefined(obj.dyn_settings.values[index][property]))
945            {
946                value = obj.dyn_settings.values[index][property];
947            }
948
949            return value;
950        }
951
952        // assertions
953        obj.assertionError = function (assertion_message) {
954            this.message = assertion_message;
955        };
956
957        obj.assertionError.prototype.toString = function () {
958            return "LikeBtn: Assertion Error: " + (this.message || "[no message]");
959        };
960
961        obj.assert = function (condition, assertion_message) {
962            if (!condition) {
963                obj.log("LikeBtn assertion failed: " + assertion_message);
964                throw new obj.assertionError(assertion_message);
965            }
966        };
967
968        // Convert anything to bool
969        obj.toBool = function (value) {
970            if (((!isNaN(parseInt(value)) && parseInt(value)) || value == "true") && value != "false") {
971                return 1;
972            } else {
973                return 0;
974            }
975        }
976
977        // Convert anything to bool
978        obj.validateSettings = function (index) {
979            var errors = [];
980            // voting_both and voting_frequency can not be used together
981            if (obj.getParameter(index, 'voting_frequency') && obj.getParameter(index, 'voting_both')) {
982                errors.push('voting_both and voting_frequency can not be used together');
983            }
984            return errors;
985        }
986
987        // Get list of default settings
988        obj.getDefaultSettings = function () {
989            var settings = {};
990            for (parameter in obj.settings.schema) {
991                settings[parameter] = obj.settings.schema[parameter]['def'];
992            }
993            return settings;
994        }
995
996        // Get parameter default value
997        obj.getDefaultValue = function (parameter) {
998            if (typeof(obj.settings.schema[parameter]) != 'undefined') {
999                return obj.settings.schema[parameter]['def'];
1000            } else {
1001                return null;
1002            }
1003        }
1004
1005        // check if value contain supported language
1006        obj.isLocaleSupported = function (locale) {
1007            var supported = false;
1008            for (var i=0; i<obj.locales.length; i++){
1009                if (obj.locales[i] == locale) {
1010                    supported = true;
1011                }
1012            }
1013            return supported;
1014        };
1015
1016        // init
1017        obj.init = function (internal_launch) {
1018
1019            // IE6 and older are not supported
1020            if (document.body && typeof(document.body.style.maxHeight) === "undefined") {
1021                return;
1022            }
1023
1024            // Set host in default settings
1025            obj.settings.setDefaultHost();
1026
1027            if ((typeof(internal_launch) == "undefined" || !internal_launch || !obj.runned) && !obj.interval) {
1028                // wait till DOM is ready
1029                obj.interval = setInterval(function() {
1030
1031                    obj.initWrappers();
1032                    
1033                    // Load collected bunch of items
1034                    obj.loadBunch();
1035
1036                    if (document.readyState === "complete") {
1037                        clearInterval(obj.interval);
1038                        obj.interval = 0;
1039                    }
1040                }, 100);
1041            }
1042
1043            // track body click event
1044            if (internal_launch && document.body) {
1045                obj.addEventListener(document.body, 'click', obj.onBodyClick);
1046            }
1047        }
1048
1049        // init wrappers
1050        obj.initWrappers = function () {
1051
1052            var index;
1053
1054            // collect buttons till DOM is ready
1055            obj.runned = 1;
1056
1057            // get all wrappers
1058            var wrappers = obj.q('.likebtn-wrapper');
1059
1060            // Page views conter
1061            if (wrappers.length && !obj.pv_sent) {
1062                obj.pv();
1063                obj.pv_sent = true;
1064            }
1065
1066            // process only those wrappers, whose settings were not read
1067            for (for_index=0; for_index<wrappers.length; for_index++) {
1068
1069                // get btn wrapper
1070                var wrapper = wrappers[for_index];
1071
1072                // miss loaded/loading button
1073                if (obj.hasClass(wrapper, 'lb-loaded') || (typeof(wrapper.likebtn_loading) !== "undefined" && wrapper.likebtn_loading)) {
1074                    continue;
1075                }
1076
1077                // wrapper has been initialized
1078                wrapper.likebtn_loading = true;
1079                wrapper.className += " lb-loaded";
1080
1081                index = obj.dyn_settings.values.length;
1082
1083                // miss loaded wrappers
1084                if (obj.dyn_settings.get(index, "loaded")) {
1085                    continue;
1086                }
1087
1088                // process settings
1089                obj.settings.values.push(obj.getDefaultSettings());
1090
1091                for (var property in obj.settings.schema) {
1092                    value = wrapper.getAttribute('data-'+property);
1093                    if (value) {
1094                        obj.settings.set(index, property, value);
1095                    }
1096                }
1097
1098                // Set 'url'
1099                if (!obj.needDomainFromParent(index)) {
1100                    // Current window URL
1101                    obj.settings.values[index].url = window.location.href;
1102                } else {
1103                    // Parent window URL
1104                    if (document.referrer) {
1105                        obj.settings.values[index].url = document.referrer;
1106                    } else {
1107                        obj.settings.values[index].url = window.location.href;
1108                    }
1109                }
1110
1111                // remember identifier
1112                //obj.dyn_settings.set(index, "orig_identifier", obj.getParameter(index, 'identifier'));
1113                // set identifier if empty
1114                if (!obj.getParameter(index, 'identifier')) {
1115                    obj.settings.set(index, 'identifier', obj.normalizeUrlIdentifier(obj.getParameter(index, 'url')));
1116                }
1117
1118                // Reset CSS
1119                //wrapper.style.lineHeight = '';
1120
1121                
1122                // backward compatibility
1123                value = wrapper.getAttribute('data-color_scheme') || wrapper.getAttribute('data-style');
1124                if (value) {
1125                    obj.settings.set(index, 'theme', value);
1126                }
1127                if (wrapper.getAttribute('data-substract_dislikes')) {
1128                    obj.settings.set(index, 'counter_type', 'subtract_dislikes');
1129                }
1130                if (obj.getParameter(index, 'counter_type') == 'substract_dislikes') {
1131                    obj.settings.set(index, 'counter_type', 'subtract_dislikes');
1132                }
1133                if (wrapper.getAttribute('data-display_only') && obj.toBool(wrapper.getAttribute('data-display_only')) == 1) {
1134                    obj.settings.set(index, 'voting_enabled', '0');
1135                }
1136                if (wrapper.getAttribute('data-show_copyright') && obj.toBool(wrapper.getAttribute('data-show_copyright')) == 0) {
1137                    obj.settings.set(index, 'white_label', '1');
1138                }
1139                if (wrapper.getAttribute('data-unlike_allowed') && obj.toBool(wrapper.getAttribute('data-unlike_allowed')) == 0) {
1140                    obj.settings.set(index, 'voting_cancelable', '0');
1141                }
1142                if (wrapper.getAttribute('data-revote_period')) {
1143                    obj.settings.set(index, 'voting_frequency', wrapper.getAttribute('data-revote_period'));
1144                }
1145                if (wrapper.getAttribute('data-popup_enabled') && obj.toBool(wrapper.getAttribute('data-popup_enabled')) == 0) {
1146                    obj.settings.set(index, 'popup_disabled', '1');
1147                }
1148                if (wrapper.getAttribute('data-bg_c') && !wrapper.getAttribute('data-bg_c_v')) {
1149                    obj.settings.set(index, 'bg_c_v', wrapper.getAttribute('data-bg_c'));
1150                }
1151                // Set host
1152                var get_host = obj.getHost({}, index); 
1153                if (get_host && typeof(get_host.error_message) == "undefined" && typeof(get_host.h) != "undefined") {
1154                     obj.settings.set(index, 'host', get_host.h);
1155                }
1156
1157                obj.log("Settings loaded (index: "+index+")", obj.settings.values[index]);
1158
1159                // remember wrapper
1160                obj.dyn_settings.set(index, "wrapper", wrapper);
1161
1162                // for counter
1163                obj.dyn_settings.set(index, "counted", false);
1164
1165                // remember identifier_hash
1166                //obj.dyn_settings.set(index, "identifier_hash", obj.hashCode(obj.getParameter(index, 'identifier')));
1167                // remember identifier_hash
1168                obj.dyn_settings.set(index, "identifier_hash", obj.hashCodeMd5(obj.getParameter(index, 'identifier')));
1169
1170                // Ids Hash not to load the button 
1171                obj.dyn_settings.set(index, "ids_hash", obj.getIdsHash(
1172                    obj.getParameter(index, 'identifier'),
1173                    obj.getParameter(index, 'group_identifier'),
1174                    obj.getParameter(index, 'site_id')
1175                ));
1176
1177                // Validate settings
1178                var settings_errors = obj.validateSettings(index);
1179                if (settings_errors.length) {
1180                    obj.infoMessage(index, wrapper, settings_errors.join('. '));
1181                    obj.setLoaded(index, wrapper);
1182                    continue;
1183                }
1184
1185                // load buttons style css
1186                obj.loadStyle(obj.getParameter(index, 'theme'));
1187
1188                // Load affect style
1189                if (obj.getParameter(index, 'ef_voting')) {
1190                    obj.loadAsset('/css/w/effect.css?v=41', 'css');
1191                }
1192
1193                // load button
1194                var lang = obj.getParameter(index, "lang");
1195
1196                if (/*lang == obj.lang_auto ||*/ !obj.isLocaleSupported(lang)) {
1197                    // get browser locale from cookie
1198                    /*obj.browser_locale = obj.getCookie(obj.cookie_locale_name);
1199                    if (!obj.browser_locale) {
1200                        // detect and remember locale
1201                        if (!obj.browser_locale_detection_running) {
1202                            // detect locale and load button after detection is finished
1203                            obj.browser_locale_detection_running = true;
1204                            obj.dyn_settings.set(index, "locale", '');
1205                            obj.detectLocaleAndLoad();
1206                        }
1207                    } else {
1208                        // if locale has been already detected
1209                        if (obj.isLocaleSupported(obj.browser_locale)) {
1210                            obj.dyn_settings.set(index, "locale", obj.browser_locale);
1211                        } else {
1212                            obj.dyn_settings.set(index, "locale", obj.default_lang);
1213                        }
1214                        obj.load(index);
1215                    }*/
1216                    obj.dyn_settings.set(index, "locale", obj.default_lang);
1217                } else {
1218                    // if button do not need browser locale detection load it now
1219                    obj.dyn_settings.set(index, "locale", lang);
1220                }
1221                obj.load(index);
1222            }
1223        };
1224
1225        // Count page views
1226        obj.pv = function()
1227        {
1228            //var pv_img = new Image();
1229            //pv_img.src = "https://ssl.google-analytics.com/__utm.gif?utmac=UA-37384414-2&utmhn="+encodeURIComponent(obj.settings.schema['host']['def']);
1230
1231            var pv_img = new Image();
1232            pv_img.src = "//pv.likebtn.com?nc=.php&t="+Date.now()+"&h="+encodeURIComponent(obj.settings.schema['host']['def']);
1233        }
1234
1235        // detect client browser locale and launch loading of those buttons having lang=auto
1236        /*obj.detectLocaleAndLoad = function () {
1237            obj.JSONP.get( obj.http_headers_backend, {}, function(headers) {
1238                obj.log('Browser Accept-Language', headers);
1239
1240                if (obj.isDefined(headers) && obj.isDefined(headers['Accept-Language'])) {
1241                    obj.browser_locale = headers['Accept-Language'].substr(0, 2);
1242                } else {
1243                    // set default lang as browser locale
1244                    obj.browser_locale = obj.default_lang;
1245                }
1246                obj.browser_locale_detection_running = false;
1247
1248                // remember browser locale in cookie
1249                var cookie_locale_date = new Date();
1250                cookie_locale_date.setSeconds(cookie_locale_date.getSeconds() + parseInt(obj.cookie_locale_lifetime));
1251                obj.setCookie(
1252                    obj.cookie_locale_name,
1253                    obj.browser_locale,
1254                    {expires:cookie_locale_date, path:"/"}
1255                );
1256
1257                // get lang corresponding browser locale
1258                var lang = obj.browser_locale;
1259                if (!obj.isLocaleSupported(lang)) {
1260                    lang = obj.default_lang;
1261                }
1262
1263                // now load those buttons, which have lang=auto
1264                for (var index in obj.settings.values) {
1265                    // find buttons without 'locale' dynamic setting and load them
1266                    if (!obj.isDefined(obj.dyn_settings.values[index])
1267                        || !obj.isDefined(obj.dyn_settings.values[index]['locale'])
1268                        || !obj.dyn_settings.values[index]['locale'])
1269                    {
1270                        obj.dyn_settings.set(index, "locale", lang);
1271                        obj.load(index);
1272                    }
1273                }
1274                // Load items bunch if init wrappers has finished
1275                if (!obj.interval) {
1276                    obj.loadBunch();
1277                }
1278            },
1279            'callback', function() {
1280                // use default lang on error
1281                for (var index in obj.settings.values) {
1282                    // find buttons without 'locale' dynamic setting and load them
1283                    if (!obj.isDefined(obj.dyn_settings.values[index])
1284                        || !obj.isDefined(obj.dyn_settings.values[index]['locale'])
1285                        || !obj.dyn_settings.values[index]['locale'])
1286                    {
1287                        obj.dyn_settings.set(index, "locale", obj.default_lang);
1288                        obj.load(index);
1289                    }
1290                }
1291                // Load items bunch if init wrappers has finished
1292                if (!obj.interval) {
1293                    obj.loadBunch();
1294                }
1295            });
1296        }*/
1297
1298        // load button HTML
1299        // This function collects buttons indexed ready to be loaded and loads them by bunches
1300        obj.load = function (index) {
1301            // Lazy load
1302            if (obj.getParameter(index, "lazy_load") || obj.getParameter(index, "counter_count")/*&& !obj.isVisible(index)*/) {
1303                // window scroll event
1304                obj.addEventListener(window, 'scroll', obj.onWindowScroll);
1305                //return false;
1306            }
1307
1308            // Check if already added to bunch
1309            if (obj.inArray(index, obj.bunch)) {
1310                return false;
1311            }
1312            
1313            // check if button is being loaded
1314            /*if (obj.dyn_settings.get(index, "loading")) {
1315                return false;
1316            }*/
1317
1318            // mark button as being loaded
1319            //obj.dyn_settings.set(index, "loading", true);
1320
1321            // show loader
1322            if (obj.getParameter(index, "loader_show")) {
1323                 var wrapper = obj.dyn_settings.get(index, "wrapper");
1324                 var loader_image = obj.getParameter(index, "loader_image");
1325                 if (!loader_image) {
1326                    loader_image = obj.loader_img;
1327                 }
1328                 wrapper.innerHTML = '<img src="'+loader_image+'" />';
1329            }
1330
1331            // Show button instead of loading
1332            if (!obj.getParameter(index, 'loader_show')) {
1333                // If button with such ids already loaded - just show it
1334                var ids_hash = obj.getIdsHash(
1335                    obj.getParameter(index, 'identifier'),
1336                    obj.getParameter(index, 'group_identifier'),
1337                    obj.getParameter(index, 'site_id')
1338                );
1339                for (compare_index in obj.settings.values) {
1340                    if (compare_index == index) {
1341                        continue;
1342                    }
1343                    if (obj.dyn_settings.get(compare_index, 'ids_hash') == ids_hash && obj.dyn_settings.get(compare_index, 'data')) {
1344                        obj.buttonShow(index, obj.dyn_settings.get(index, "wrapper"), obj.dyn_settings.get(compare_index, "data"));
1345                        return;
1346                    }
1347                }
1348            }
1349
1350            // Add button to bunch                
1351            obj.bunch_btns++;
1352            obj.bunch.push(index);
1353
1354            // Bunch is full - load bunch
1355            if (obj.bunch.length >= obj.bunch_size) {
1356                obj.loadBunch();
1357            }
1358        }
1359
1360        // Load collected bunch of itmes
1361        obj.loadBunch = function() {
1362
1363            // Exit if bunch is empty
1364            if (!obj.bunch.length) {
1365                return false;
1366            }
1367
1368            var url = '//wi.likebtn.com/w/i/';
1369
1370            // inject vars into URL
1371            //obj.assert(typeof(obj.settings.values[index]) != "undefined", "Settings not found on LikeBtn load: "+index);
1372
1373            // pass only those options which are needed on server side
1374            var settings_values = obj.getRequestSettingsItems(obj.bunch);
1375
1376            // error occured receiving settings
1377            if (obj.isDefined(settings_values['error_message'])) {
1378                var wrapper = obj.dyn_settings.get(index, "wrapper");
1379                obj.infoMessage(index, wrapper, settings_values['error_message']);
1380                obj.setLoaded(index, wrapper);
1381                return;
1382            }
1383
1384            // http://en.wikipedia.org/wiki/Percent-encoding#Types%5Fof%5FURI%5Fcharacters
1385            // http://blog.wolffmyren.com/2008/03/27/base64-valid-character-set/
1386            url = url + '?s=' + obj.encodeSettings(settings_values);
1387
1388            obj.log("Load HTML: "+url);
1389
1390            // Reset bunch
1391            obj.bunch = [];
1392
1393            // get html using JSONP
1394            obj.JSONP.get(url, {}, function(data) {
1395
1396                // remember site plan
1397                if (obj.isDefined(data.p) && data.p > obj.plan) {
1398                    obj.plan = data.p;
1399                }
1400
1401                // No items found
1402                if (!data.is) {
1403                    return false;
1404                }
1405
1406                for (item_index in data.is) {
1407                    if (isNaN(parseInt(item_index))) {
1408                        continue;
1409                    }
1410                    var item = data.is[item_index];
1411
1412                    // Determine index by md5 hash
1413                    var index = obj.getIndexByIdentifierHash(item.ha, true);
1414                    var wrapper = obj.dyn_settings.get(index, "wrapper");
1415
1416                    if (!wrapper) {
1417                        obj.log("Item wrapper not found: " + item.h);
1418                        continue;
1419                    }
1420
1421                    // Site disabled
1422                    /*if (data.di) {
1423                        wrapper.setAttribute('data-site_disabled', '1');
1424                    }
1425
1426                    // Wrong site id
1427                    if (data.e) {
1428                        wrapper.setAttribute('data-likebtn_error', data.e);
1429                    }*/
1430                    var item_data = {
1431                        di: data.di,
1432                        e: data.e,
1433                        ha: item.ha,
1434                        l: item.l,
1435                        d: item.d
1436                    }
1437                    if (typeof(data.sc) != "undefined") {
1438                        item_data.sc = data.sc;
1439                    }
1440                    obj.dyn_settings.set(index, "data", item_data);
1441                    
1442                    if (!obj.getParameter(index, "lazy_load") || obj.isVisible(index)) {
1443                        obj.buttonShow(index, wrapper, item_data);
1444                    }
1445                };
1446            });
1447        };
1448
1449        // vote
1450        obj.vote = function(type, index, event) {
1451
1452            obj.triggerEvent(obj.event_types.click, index);
1453                        // voting disabled
1454            if (!obj.getParameter(index, "voting_enabled")) {
1455                return;
1456            }
1457
1458            // In case Like button is placed inside a link
1459            if (event) {
1460                obj.stopPropagation(event);
1461                // Check if it was a click on button
1462                if (typeof(event.preventDefault) !== "undefined" && typeof(event.target) !== "undefined" &&
1463                    (obj.hasClass(event.target, 'likebtn-icon') || obj.hasClass(event.target, 'likebtn-label') || obj.hasClass(event.target, 'lb-count')))
1464                {
1465                    event.preventDefault();
1466                }
1467            }
1468            // close all popups
1469            obj.closeAllPopups(index);
1470
1471            // if share tooltip is visible - do nothing
1472            if (type == 1) {
1473                var share_active = obj.q('#lb-like-'+index+'.lb-share-active');
1474            } else {
1475                var share_active = obj.q('#lb-dislike-'+index+'.lb-share-active');
1476            }
1477            if (typeof(share_active[0]) != "undefined" && !obj.getParameter(index, 'popup_on_load')) {
1478                return;
1479            }
1480
1481            // button group has already voted
1482            if (obj.isGroupVoted(index)) {
1483                return;
1484            }
1485
1486            // if unliking and unliking is not allowed - do nothing
1487            check_voted = obj.q('#lb-like-'+index+'.lb-voted, '+'#lb-dislike-'+index+'.lb-voted');
1488
1489            if (check_voted[0] && !obj.getParameter(index, "voting_cancelable")) {
1490                return;
1491            }
1492
1493            // pass only those options which are needed on the server side
1494            var settings_values = obj.getRequestSettings(index);
1495
1496            settings_values["url"] = obj.getParameter(index, "url");
1497
1498            
1499            var url = '//wv.likebtn.com/w/v/1/2';
1500            // inject vars into URL
1501            obj.assert(typeof(obj.settings.values[index]) != "undefined", "Settings not for LikeBtn: "+index);
1502            obj.log('Sending Vote request', obj.settings.values[index]);
1503
1504            //var client = obj.getClient();
1505            //obj.log('Client', client);
1506
1507            url = url.replace("/1/2", "/"+parseInt(type)+"/"+parseInt(index));
1508            //url = url + '?s=' + encodeURIComponent(obj.Base64.encode((obj.JSON.encode(settings_values))));
1509            url = url + '?s=' + encodeURIComponent(obj.JSON.encode(settings_values));
1510            url = url + '&ivt=' + obj.getItemVoteType(index);
1511            url = url + '&vb=' + obj.getParameter(index, "voting_both");
1512            url = url + '&vf=' + obj.getParameter(index, "voting_frequency");
1513            //url = url + '&client=' + encodeURIComponent(obj.Base64.encode((obj.JSON.encode(client))));
1514            //url = url + '&c=' + encodeURIComponent(obj.Base64.encode((obj.JSON.encode(client))));
1515            url = url + '&t=' + (new Date()).getTime() + '&nc=.php';
1516
1517            // append engine and plugin info
1518            var engine = obj.getParameter(index, "engine");
1519                          
1520            if (!engine) {
1521                engine = obj.guessEngine();
1522            }
1523            if (engine) {
1524                url = url + '&engine=' + engine;
1525            }
1526            if (obj.getParameter(index, "engine_v")) {
1527                url = url + '&engine_v=' + obj.getParameter(index, "engine_v");
1528            }
1529            if (obj.getParameter(index, "plugin_v")) {
1530                url = url + '&plugin_v=' + obj.getParameter(index, "plugin_v");
1531            }
1532
1533            // Proxy
1534            var prx = obj.getParameter(index, 'prx');
1535            if (prx) {
1536                if (prx.indexOf("?") > -1) {
1537                    prx += '&';
1538                } else {
1539                    prx += '?';
1540                }
1541                url = prx + 'likebtn_q=' + encodeURIComponent(obj.Base64.encode(url));
1542            }
1543
1544            obj.log("Vote: "+url);
1545
1546            // send request using JSONP
1547            obj.JSONP.get(url, {}, function(data) {
1548
1549                obj.triggerEvent(obj.event_types.voted, index, data);
1550
1551                obj.log("Vote result", data);
1552
1553                // Check errors
1554                // All errors except some of them are ignored
1555                if (typeof(data.err) !== "undefined" && data.err == 'site_id error') {
1556                    obj.infoMessage(index, obj.dyn_settings.get(index, "wrapper"), 'Current domain does not belong to the website with specified site_id. Please add domain "'+obj.getParameter(index, 'host')+'" to the website on <a href="https://likebtn.com/en/customer.php/websites" title="Like Button">Websites</a> page.');
1557                    return;
1558                }
1559
1560                if (typeof(data.result) == "undefined" || !data.result || typeof(data.data.type) == "undefined") {
1561                    return;
1562                }
1563
1564                var identifier_hash = obj.getItemIdentifierHash(index);
1565
1566                // set count cookie
1567                obj.setCountsData(data.data.index, identifier_hash);
1568
1569                // set/update vote cookie
1570                obj.setVotesData(data.data.index, data.data.type, identifier_hash);
1571            });
1572
1573            // show share or not
1574            var show_share = false;
1575
1576            // show/hide, increase/decrease votes
1577            var click_el;
1578            var click_count_el;
1579            var other_el;
1580            var other_count_el;
1581            // contains opposite count element if it is clicked
1582            var other_clicked_count_el;
1583            var a_el;
1584            var share_el;
1585            if (type == 1) {
1586                // click on Like
1587                click_el = obj.q('#lb-like-'+index);
1588                click_count_el = obj.q('#lb-like-'+index+' .lb-count');
1589                click_label_el = obj.q('#lb-like-'+index+' .likebtn-label');
1590
1591                // other element
1592                other_el = obj.q('#lb-dislike-'+index);
1593                other_count_el = obj.q('#lb-dislike-'+index+' .lb-count');
1594                other_clicked_count_el = obj.q('#lb-dislike-'+index+'.lb-voted .lb-count');
1595                other_clicked_label_el = obj.q('#lb-dislike-'+index+'.lb-voted .likebtn-label');
1596
1597                show_share = true;
1598                a_el = obj.q('#lb-like-'+index+' .lb-a');
1599                share_el = obj.q('#lb-like-'+index+' .lb-share-tt');
1600            } else {
1601                // click on Dislike
1602                click_el = obj.q('#lb-dislike-'+index);
1603                click_count_el = obj.q('#lb-dislike-'+index+' .lb-count');
1604                click_label_el = obj.q('#lb-dislike-'+index+' .likebtn-label');
1605
1606                // other element
1607                other_el = obj.q('#lb-like-'+index);
1608                other_count_el = obj.q('#lb-like-'+index+' .lb-count');
1609                other_clicked_count_el = obj.q('#lb-like-'+index+'.lb-voted .lb-count');
1610                other_clicked_label_el = obj.q('#lb-like-'+index+'.lb-voted .likebtn-label');
1611
1612                if (obj.getParameter(index, "popup_dislike")) {
1613                    a_el = obj.q('#lb-dislike-'+index+' .lb-a');
1614                    share_el = obj.q('#lb-dislike-'+index+' .lb-share-tt');
1615                    show_share = true;
1616                }
1617            }
1618
1619            // check button state
1620            var event_type = "";
1621            if (typeof(click_el[0]) != "undefined") {
1622                if ( (" " + click_el[0].className + " ").replace(/[\n\t]/g, " ").indexOf(" lb-voted ") > -1 ) {
1623                    // Unlike or Undislike
1624                    // remove .lb-voted
1625                    if (typeof(click_el[0]) != "undefined") {
1626                        click_el[0].className = click_el[0].className.replace(/lb\-voted/,'');
1627                    } else {
1628                        obj.log('Clicked element not found on Vote');
1629                    }
1630                    // decrease count
1631                    if (typeof(click_count_el[0]) != "undefined") {
1632                        //var cur_count = parseInt(click_count_el[0].innerHTML);
1633                        var cur_count = parseInt(click_count_el[0].getAttribute('data-count'));
1634
1635                        if (!isNaN(cur_count) && cur_count) {
1636                            var new_count = cur_count-1;
1637                            obj.updateCountsAfterClick(index, type, new_count, click_count_el[0], other_count_el[0]);
1638                        }
1639                    } else {
1640                        obj.log('Click element count not found on Vote');
1641                    }
1642                    show_share = false;
1643                    // process group identifier option
1644                    obj.processGroupIdentifier(index, 0);
1645
1646                    // remember event type
1647                    if (type == 1) {
1648                        event_type = obj.event_types.unlike;
1649                        // update labels
1650                        if (obj.isDefined(click_label_el[0])) {
1651                            click_label_el[0].innerHTML = obj.getLabel(index, "i18n_like");
1652                        }
1653                    } else {
1654                        event_type = obj.event_types.undislike;
1655                        // update labels
1656                        if (obj.isDefined(click_label_el[0])) {
1657                            click_label_el[0].innerHTML = obj.getLabel(index, "i18n_dislike");
1658                        }
1659                    }
1660
1661                } else {
1662                    // Like or Dislike
1663                    // add .lb-voted
1664                    if (typeof(click_el[0]) != "undefined") {
1665                        obj.removeClass(click_el[0], "lb-voted-now");
1666                        click_el[0].className += " lb-voted";
1667                        // for effects
1668                        click_el[0].className += " lb-voted-now";                        
1669                    } else {
1670                        obj.log('Clicked element not found on Vote');
1671                    }
1672                    // increase count
1673                    if (typeof(click_count_el[0]) != "undefined") {
1674                        var cur_count = parseInt(click_count_el[0].getAttribute('data-count'));
1675                        if (isNaN(cur_count)) {
1676                            cur_count = 0;
1677                        }
1678                        var new_count = cur_count+1;
1679                        obj.updateCountsAfterClick(index, type, new_count, click_count_el[0], other_count_el[0]);
1680                    } else {
1681                        obj.log('Click element count not found on Vote');
1682                    }
1683
1684                    // Remove vote from other button
1685                    if (!obj.getParameter(index, "voting_both")) {
1686                        // remove .lb-voted class from other button
1687                        if (typeof(other_el[0]) != "undefined") {
1688                            other_el[0].className = other_el[0].className.replace(/lb\-voted/,'');
1689                        } else {
1690                            obj.log('Other element not found on Vote');
1691                        }
1692                        // decrease count
1693                        if (typeof(other_clicked_count_el[0]) != "undefined") {
1694                            var cur_count = parseInt(other_clicked_count_el[0].getAttribute('data-count'));
1695                            if (!isNaN(cur_count) && cur_count) {
1696                                var new_count = cur_count-1;
1697                                //other_clicked_count_el[0].innerHTML = cur_count-1;
1698                                var opposite_type;
1699                                if (type == 1) {
1700                                    opposite_type = '-1';
1701                                } else {
1702                                    opposite_type = '1';
1703                                }
1704                                obj.updateCountsAfterClick(index, opposite_type, new_count, other_count_el[0], click_count_el[0]);
1705                            }
1706                        }
1707                    }
1708                    // hide opposite share if visible
1709                    obj.popupHide(null, index);
1710                    // process group identifier option
1711                    obj.processGroupIdentifier(index, 1);
1712
1713                    // remember event type
1714                    if (type == 1) {
1715                        event_type = obj.event_types.like;
1716                        // update labels
1717                        if (obj.isDefined(click_label_el[0])) {
1718                            // Use like text if after_like not set
1719                            if (obj.getParameter(index, "i18n_like") && !obj.getParameter(index, "i18n_after_like")) {
1720                                click_label_el[0].innerHTML = obj.getLabel(index, "i18n_like");
1721                            } else {
1722                                click_label_el[0].innerHTML = obj.getLabel(index, "i18n_after_like");
1723                            }
1724                        }
1725                        if (obj.isDefined(other_clicked_label_el[0]) && !obj.getParameter(index, "voting_both")) {
1726                            other_clicked_label_el[0].innerHTML = obj.getLabel(index, "i18n_dislike");
1727                        }
1728                    } else {
1729                        event_type = obj.event_types.dislike;
1730                        // update labels
1731                        if (obj.isDefined(click_label_el[0])) {
1732                            // Use dislike text if after_dislike not set
1733                            if (obj.getParameter(index, "i18n_dislike") && !obj.getParameter(index, "i18n_after_dislike")) {
1734                                click_label_el[0].innerHTML = obj.getLabel(index, "i18n_dislike");
1735                            } else {
1736                                click_label_el[0].innerHTML = obj.getLabel(index, "i18n_after_dislike");
1737                            }
1738                        }
1739                        if (obj.isDefined(other_clicked_label_el[0]) && !obj.getParameter(index, "voting_both")) {
1740                            other_clicked_label_el[0].innerHTML = obj.getLabel(index, "i18n_like");
1741                        }
1742                    }
1743                }
1744                // show/hide counters
1745                obj.showCounter(click_count_el[0], index);
1746                obj.showCounter(other_clicked_count_el[0], index);
1747
1748                var wrapper = obj.dyn_settings.get(index, "wrapper");
1749
1750                if (obj.getParameter(index, "theme") == 'custom') {
1751                    obj.showCustomVoting(wrapper); 
1752                }
1753
1754                if (obj.checkPlan(obj.plans.VIP)) {
1755                    var popup_disabled = obj.getParameter(index, "popup_disabled");
1756                } else {
1757                    var popup_disabled = obj.getDefaultValue('popup_disabled');
1758                }
1759
1760                // Show popup
1761                if (show_share && !popup_disabled  && typeof(click_el[0]) != "undefined") {
1762                    // show popup
1763                    obj.popupShow(index, type);
1764                } else {
1765                    // hide popup
1766                    obj.popupHide(null, index);
1767                }
1768
1769                // add lb-display-only if unlike not allowed
1770                if (!obj.getParameter(index, "voting_cancelable")) {
1771                    if (obj.isDefined(wrapper)) {
1772                        wrapper.className += " lb-display-only";
1773                    }
1774                }
1775
1776                // set count cookie
1777                obj.setCountsData(index);
1778
1779                // set/update vote cookie
1780                obj.setVotesData(index, type);
1781
1782                // trigger an event
1783                obj.triggerEvent(event_type, index);
1784
1785                // Redisplay buttons with the same identifier
1786                var cur_identifier = obj.getParameter(index, "identifier");
1787                for (var i in obj.settings.values) {
1788                    // find buttons without 'locale' dynamic setting and load them
1789                    if (i != index && obj.getParameter(i, 'identifier') == cur_identifier &&
1790                        obj.dyn_settings.get(i, "wrapper") != obj.dyn_settings.get(index, "wrapper")
1791                    ) {
1792                        obj.refresh(i);
1793                    }
1794                }
1795
1796            } // click_el is defined
1797        }
1798
1799        // Refresh button
1800        obj.refresh = function(index) {
1801            obj.apply(obj.dyn_settings.get(index, "wrapper"), obj.settings.values[index]);
1802        }
1803
1804        // Show loaded button by index
1805        obj.buttonShow = function(index, wrapper, data) {
1806
1807            if (!obj.isDefined(wrapper)) {
1808                wrapper = obj.dyn_settings.get(index, "wrapper");
1809            } 
1810            if (!wrapper) {
1811                return false;
1812            }
1813
1814            if (!obj.isDefined(data)) {
1815                data = obj.dyn_settings.get(index, "data");
1816            }
1817            if (!data) {
1818                return false;
1819            }
1820
1821            // add color scheme class
1822            wrapper.className += " lb-style-"+obj.getParameter(index, "theme");
1823
1824            // add popup position class
1825            wrapper.className += " lb-popup-position-"+obj.getParameter(index, "popup_position");
1826
1827            // add tooltip position class
1828            if (!obj.getParameter(index, "tooltip_enabled")) {
1829                wrapper.className += " lb-tooltip-disabled";
1830            }
1831            // add tooltip always show flag
1832            if (obj.getParameter(index, "tooltip_like_show_always")) {
1833                wrapper.className += " lb-tooltip-like-show-always";
1834            }
1835            if (obj.getParameter(index, "tooltip_dislike_show_always")) {
1836                wrapper.className += " lb-tooltip-dislike-show-always";
1837            }
1838
1839            // add counter_type class
1840            if (obj.getParameter(index, "counter_type") == 'single_number') {
1841                wrapper.className += " lb-counter-type-single-number";
1842            }
1843            // RTL
1844            if (obj.getParameter(index, "rtl")) {
1845                wrapper.className += " lb-rtl";
1846            }
1847
1848            // add popup style class
1849            wrapper.className += " lb-popup-style-"+obj.getParameter(index, "popup_style");
1850
1851            // Error messages
1852            if (data.di == '1') {
1853                obj.infoMessage(index, wrapper, 'Your website has been disabled. Contact <a href="https://likebtn.com" title="Like Button">LikeBtn.com</a>');
1854                return;
1855            } else if (index >= obj.max_buttons_per_page[obj.plan] && obj.bunch_btns > obj.max_buttons_per_page[obj.plan] && obj.getParameter(index, "engine") != 'weebly') {
1856                obj.infoMessage(index, wrapper, obj.getPlanName(obj.plan) + ' tariff plan allows to show maximum ' +  obj.max_buttons_per_page[obj.plan] + ' button(s) per page. Upgrade your website plan on <a href="https://likebtn.com/#plans_pricing" title="Like Button">LikeBtn.com</a>');
1857                return;
1858            } else if (data.e) {
1859                if (data.e == 'site_id error') {
1860                    if (obj.getParameter(index, "engine") == 'shopify') {
1861                        obj.infoMessage(index, wrapper, 'It looks like you have changed the primary domain name of your Shopify website. Just log in <a href="https://likebtn.com/en/shopify/store.php/configure" title="Like Button Rating" target="_blank">here</a> and buttons will be automatically configured for the new domain name (you may need to clear your browser cache afterwards)');
1862                    } else {
1863                        obj.infoMessage(index, wrapper, 'Current domain does not belong to the website with specified site_id. Please add domain "'+obj.getParameter(index, 'host')+'" to the website on <a href="https://likebtn.com/en/customer.php/websites" title="Like Button">Websites</a> page.');
1864                    }
1865                } else {
1866                    obj.infoMessage(index, wrapper, data.e);
1867                }
1868                return;
1869            /*} else if (!obj.inArray(obj.getParameter(index, 'host'), obj.https_check_disabled) && !obj.checkPlan(obj.plans.PLUS) && (typeof(data.sc) == "undefined" || data.sc == '1') && 'https:' == document.location.protocol) {
1870                obj.infoMessage(index, wrapper, 'Your plan does not allow to load Like button using HTTPS. Upgrade your website plan on <a href="https://likebtn.com/#plans_pricing" title="Like Button">LikeBtn.com</a>');
1871                return;*/
1872            } else {
1873                wrapper.innerHTML = obj.getHtml(data, index);
1874
1875                // Rich Snippet
1876                if (obj.getParameter(index, 'rich_snippet')) {
1877                    wrapper.setAttribute("itemscope", "");
1878                    //wrapper.setAttribute("itemtype", "http://schema.org/Article");
1879                    wrapper.setAttribute("itemtype", "http://schema.org/Product");
1880                }
1881                // add lb-unlike-not-allowed class if needed
1882                if (!obj.getParameter(index, "voting_cancelable")) {
1883                    wrapper.className += " lb-unlike-not-allowed";
1884                }
1885                // add lb-display-only class if needed
1886                if (!obj.getParameter(index, "voting_enabled")) {
1887                    wrapper.className += " lb-display-only";
1888                }
1889                if (obj.getParameter(index, "vert")) {
1890                    wrapper.className += " lb-vert";
1891                }
1892            }
1893
1894            // get counts from cookies
1895            var item_counts = obj.getItemCountFromCookie(index);
1896
1897            if ((obj.isDefined(item_counts) && item_counts) || obj.getParameter(index, 'counter_zero_show')) {
1898
1899                // calculate counts
1900                if (obj.isDefined(item_counts['1'])) {
1901                    var like_count_el = obj.getItemCountEl(index, 1);
1902                    if (obj.isDefined(like_count_el)) {
1903                        item_counts['1'] = parseInt(item_counts['1']);
1904                        if (isNaN(item_counts['1'])) {
1905                            item_counts['1'] = 0;
1906                        }
1907                        obj.showCounter(like_count_el, index);
1908                    }
1909                } else {
1910                    item_counts['1'] = 0;
1911                }
1912                if (obj.isDefined(item_counts['-1'])) {
1913                    var dislike_count_el = obj.getItemCountEl(index, '-1');
1914                    if (obj.isDefined(dislike_count_el)) {
1915                        item_counts['-1'] = parseInt(item_counts['-1']);
1916                        if (isNaN(item_counts['-1'])) {
1917                            item_counts['-1'] = 0;
1918                        }
1919                        obj.showCounter(dislike_count_el, index);
1920                    }
1921                } else {
1922                    item_counts['-1'] = 0;
1923                }
1924
1925                // show counters
1926                var counts = obj.getCountsPrepared(index, {'1':item_counts['1'], '-1':item_counts['-1']});
1927
1928                if (obj.isDefined(like_count_el)) {
1929                    like_count_el.innerHTML = counts['1'];
1930                    like_count_el.setAttribute('data-count', item_counts['1']);
1931                    obj.showCounter(like_count_el, index);
1932                }
1933                if (obj.isDefined(dislike_count_el)) {
1934                    dislike_count_el.innerHTML = counts['-1'];
1935                    dislike_count_el.setAttribute('data-count', item_counts['-1']);
1936                    obj.showCounter(dislike_count_el, index);
1937                }
1938            }
1939
1940            // highlight button if Client voted for an Item
1941            var item_vote_type = obj.getItemVoteType(index);
1942
1943            if (item_vote_type) {
1944                var l = data.l;
1945                var d = data.d;
1946
1947                if (item_counts) {
1948                    if (item_counts['1']) {
1949                        l = item_counts['1'];
1950                    }
1951                    if (item_counts['-1']) {
1952                        d = item_counts['-1'];
1953                    }
1954                }
1955                l = parseInt(l);
1956                d = parseInt(d);
1957                if (isNaN(l)) {
1958                    l = 0;
1959                }
1960                if (isNaN(d)) {
1961                    d = 0;
1962                }
1963
1964                var el_list = [];
1965                if (item_vote_type == '-1' && d > 0) {
1966                    el_list.push( obj.q('#lb-dislike-'+index) );
1967                } else if (item_vote_type == '1' && l > 0) {
1968                    el_list.push( obj.q('#lb-like-'+index) );
1969                } else if (item_vote_type == '2') {
1970                    if (d > 0) {
1971                        el_list.push( obj.q('#lb-dislike-'+index) );
1972                    }
1973                    if (l > 0) {
1974                        el_list.push( obj.q('#lb-like-'+index) );
1975                    }
1976                }
1977                // add lb-voted class
1978                for (el_index in el_list) {
1979                    var el = el_list[el_index];
1980                    if (typeof(el[0]) != "undefined") {
1981                        el[0].className += " lb-voted";
1982                        // for effects
1983                        //el[0].className += " lb-voted-now";
1984
1985                        // Show label
1986                        var label = null;
1987                        if (obj.hasClass(el[0], 'lb-like')) {
1988                            label = obj.q('#lb-like-'+index+' .likebtn-label');
1989                        } else {
1990                            label = obj.q('#lb-dislike-'+index+' .likebtn-label');
1991                        }
1992                        if (obj.isDefined(label[0])) {
1993                            if (obj.hasClass(el[0], 'lb-like')) {
1994                                // Use like text if after_like not set
1995                                if (obj.getParameter(index, "i18n_like") && !obj.getParameter(index, "i18n_after_like")) {
1996                                    label[0].innerHTML = obj.getLabel(index, "i18n_like");
1997                                } else {
1998                                    label[0].innerHTML = obj.getLabel(index, "i18n_after_like");
1999                                }
2000                            } else {
2001                                // Use dislike text if after_dislike not set
2002                                if (obj.getParameter(index, "i18n_dislike") && !obj.getParameter(index, "i18n_after_dislike")) {
2003                                    label[0].innerHTML = obj.getLabel(index, "i18n_dislike");
2004                                } else {
2005                                    label[0].innerHTML = obj.getLabel(index, "i18n_after_dislike");
2006                                }
2007                            }
2008                        }
2009                    }
2010                }
2011                // process group identifier option
2012                //obj.processGroupIdentifier(index, 1);
2013            }
2014
2015            // Custom theme
2016            if (obj.getParameter(index, "theme") == 'custom') {
2017                obj.customTheme(index, wrapper);
2018            }
2019
2020            // Apply group_identifier to the button if needed
2021            obj.applyGroupIdentifier(index);
2022
2023            // set popup position for "right"
2024            obj.setPopupAndTooltipsPosition(index);
2025
2026            // show popup if needed
2027            if (obj.getParameter(index, "popup_on_load")) {
2028                obj.popupShow(index);
2029            }
2030
2031            obj.setLoaded(index, wrapper);
2032
2033            // trigger an event
2034            obj.triggerEvent(obj.event_types.loaded, index);
2035
2036            if (obj.getParameter(index, "counter_count")
2037                && !obj.dyn_settings.get(index, "counted") 
2038                && obj.isVisible(index)
2039            ) {
2040                obj.counterCount(index);
2041            }
2042        }
2043
2044        obj.counterCount = function(index) {
2045            
2046            obj.dyn_settings.set(index, "counted", true);
2047
2048            wrapper = obj.dyn_settings.get(index, "wrapper");
2049            if (!wrapper) {
2050                return false;
2051            }
2052            
2053            var likes = 0;
2054            var dislikes = 0;
2055
2056            var el_l = obj.q('#lb-like-'+index+' .lb-count');
2057            var el_d = obj.q('#lb-dislike-'+index+' .lb-count');
2058            var like_count_el;
2059            var item_counts = obj.getItemCountFromCookie(index);
2060            if (typeof(el_l[0]) !== "undefined") {
2061                like_count_el = el_l[0];
2062
2063                likes = parseInt(item_counts['1']);
2064                if (isNaN(likes)) {
2065                    likes = like_count_el.getAttribute('data-count')
2066                }
2067            }
2068            var dislike_count_el;
2069            if (typeof(el_d[0]) !== "undefined") {
2070                dislike_count_el = el_d[0];
2071
2072                dislikes = parseInt(item_counts['-1']);
2073                if (isNaN(dislikes)) {
2074                    dislikes = dislike_count_el.getAttribute('data-count')
2075                }
2076            }
2077
2078            window.setTimeout(function() {obj.counterTick(index, like_count_el, dislike_count_el, 0, 0, likes, dislikes)}, obj.count_tstep);
2079        }
2080
2081        obj.counterTick = function(index, like_count_el, dislike_count_el, cur_l, cur_d, likes, dislikes) { 
2082
2083            var done = 0;
2084            var step_l = likes * obj.count_tstep / obj.count_time;
2085            var step_d = dislikes * obj.count_tstep / obj.count_time;
2086
2087            cur_l = Math.ceil(cur_l + step_l);
2088            if (cur_l >= likes) {
2089                cur_l = likes;
2090                done++;
2091            }
2092            cur_d = Math.ceil(cur_d + step_d);
2093            if (cur_d >= dislikes) {
2094                cur_d = dislikes;
2095                done++;
2096            }
2097
2098            var counts = obj.getCountsPrepared(index, {'1':cur_l, '-1':cur_d});
2099            if (obj.isDefined(like_count_el)) {
2100                like_count_el.innerHTML = counts['1'];
2101            }
2102            if (obj.isDefined(dislike_count_el)) {
2103                dislike_count_el.innerHTML = counts['-1'];
2104            }
2105
2106            if (done != 2) {
2107                window.setTimeout(function() {obj.counterTick(index, like_count_el, dislike_count_el, cur_l, cur_d, likes, dislikes)}, obj.count_tstep);
2108            }
2109        }
2110
2111        // Get label text
2112        obj.getLabel = function(index, option, default_text) {
2113            var label = '';
2114
2115            if (!obj.isDefined(default_text)) {
2116                default_text = '';
2117            }
2118
2119            if (obj.getParameter(index, option)) {
2120                label = obj.getParameter(index, option);
2121            } else {
2122                if (typeof(obj.translations[obj.dyn_settings.get(index, "locale")]) != "undefined") {
2123                    label = obj.translations[obj.dyn_settings.get(index, "locale")][option];
2124                } else {
2125                    label = default_text;
2126                }
2127            }
2128            return label;
2129        }
2130
2131        // Update counts after client clicked
2132        obj.updateCountsAfterClick = function (index, type, new_count, click_count_el, other_count_el) {
2133            var counts;
2134            if (type == 1) {
2135                counts = obj.getCountsPrepared(index, {'1':new_count, '-1':obj.getItemCount(index, '-1')});
2136                click_count_el.innerHTML = counts['1'];
2137                if (obj.isDefined(other_count_el)) {
2138                    other_count_el.innerHTML = counts['-1'];
2139                }
2140            } else {
2141                counts = obj.getCountsPrepared(index, {'1':obj.getItemCount(index, '1'), '-1':new_count});
2142                click_count_el.innerHTML = counts['-1'];
2143                if (obj.isDefined(other_count_el)) {
2144                    other_count_el.innerHTML = counts['1'];
2145                }
2146            }
2147
2148            click_count_el.setAttribute('data-count', new_count);
2149        }
2150
2151        // Remember counts data
2152        obj.setCountsData = function(index, identifier_hash) {
2153            var count_like    = obj.getItemCount(index, 1);
2154            var count_dislike = obj.getItemCount(index, '-1');
2155            var cookie_count = {
2156                '1': count_like,
2157                '-1': count_dislike
2158            };
2159
2160            if (!identifier_hash) {
2161                identifier_hash = obj.getItemIdentifierHash(index);
2162            }
2163
2164            var cookie_count_date = new Date();
2165            cookie_count_date.setSeconds(cookie_count_date.getSeconds() + parseInt(obj.cookie_count_lifetime));
2166
2167            obj.setData(
2168                obj.cookie_count_name+""+identifier_hash,
2169                obj.JSON.encode(cookie_count),
2170                {expires:cookie_count_date, path:"/"}
2171            );
2172        }
2173
2174        // Remember votes data
2175        obj.setVotesData = function(index, type, identifier_hash) {
2176            if (!identifier_hash) {
2177                identifier_hash = obj.getItemIdentifierHash(index);
2178            }
2179            // 0 - no clicked buttons
2180            // 1 - like
2181            // -1 -dislike
2182            // 2 - both clicked
2183            if (type == 0) {
2184                // none of the buttons clicked
2185                obj.removeData(obj.cookie_vote_name+""+identifier_hash);
2186            } else {
2187                cookie_votes = parseInt(type);
2188
2189                var cookie_date = new Date();
2190                var voting_frequency = obj.getParameter(index, "voting_frequency");
2191                var cookie_eternal = false;
2192                voting_frequency = parseInt(voting_frequency);
2193                if (voting_frequency && !isNaN(voting_frequency)) {
2194                    cookie_date.setSeconds(cookie_date.getSeconds() + voting_frequency);
2195                } else {
2196                    cookie_date.setYear(cookie_date.getFullYear() + 1);
2197                    cookie_eternal = true;
2198                }
2199
2200                obj.setData(
2201                    obj.cookie_vote_name+""+identifier_hash,
2202                    cookie_votes,
2203                    {expires:cookie_date, path:"/"},
2204                    cookie_eternal
2205                );
2206            }
2207        }
2208
2209        // Prepare settings for sending (vote)
2210        obj.getRequestSettings = function (index) {
2211            var host = obj.getParameter(index, "host");
2212
2213            // pass only those options which are needed on server side
2214            var settings_values = {
2215                "h": "",
2216                "s": "",
2217                "i": ""
2218            }
2219            if (!obj.isDefined(obj.settings.values[index])) {
2220                return settings_values;
2221            }
2222
2223            settings_values = obj.getHost(settings_values, index);           
2224
2225            settings_values["h"] = obj.normalizeHost(settings_values["h"]);
2226            settings_values["s"] = obj.getParameter(index, "site_id");
2227            settings_values["i"] = obj.settings.values[index]["identifier"];
2228
2229            return settings_values;
2230        }
2231
2232        // Prepare settings for sending (item)
2233        obj.getRequestSettingsItems = function (items) {
2234            // Use host/site settings from the first item
2235            var index = items[0];
2236            var item_hash = '';
2237
2238            // pass only those options which are needed on server side
2239            var settings_values = {
2240                "h": "",
2241                "s": "",
2242                "i": []
2243            }
2244            if (!obj.isDefined(obj.settings.values[index])) {
2245                return settings_values;
2246            }
2247
2248            settings_values = obj.getHost(settings_values, index);           
2249
2250            settings_values["h"] = obj.normalizeHost(settings_values["h"]);
2251            settings_values["s"] = obj.getParameter(index, "site_id");
2252            for (var i = 0; i < items.length; i++) {
2253                item_hash = obj.hashCodeMd5(obj.settings.values[items[i]]["identifier"]);
2254                settings_values["i"].push(item_hash);
2255            };
2256
2257            return settings_values;
2258        }
2259
2260        // Determine host
2261        obj.getHost = function (settings_values, index) {
2262            var host = obj.getParameter(index, "host");
2263            var url = window.location.href;
2264            var local_domain = obj.trim(obj.getParameter(index, "local_domain"));
2265            var is_local_domain = false;
2266
2267            // Backward compatibility
2268            if (obj.isDefined(local_domain) && local_domain) {
2269                if (obj.isDomainLocal(local_domain)) {
2270                    local_domain = obj.punycode.ToUnicode(local_domain);
2271                    // check if current host in browser matches local_domain
2272                    var current_domain = obj.punycode.ToUnicode(window.location.hostname);
2273                    var local_domain_host = obj.extractHostFromLocalDomain(local_domain);
2274                    if (local_domain_host == current_domain) {
2275                        host = local_domain;
2276                        is_local_domain = true;
2277                    } else {
2278                        settings_values['error_message'] = 'Domain "' + local_domain_host + '" specified in local_domain parameter does not match current page domain "' + current_domain + '", parameter is ignored (see <a href="//likebtn.com/en/faq#local_domain" title="Like Button FAQ">LikeBtn.com FAQ</a>)';
2279                        return settings_values;
2280                    }
2281                } else {
2282                    settings_values['error_message'] = 'Passed local_domain parameter "' + local_domain + '" has wrong format, parameter is ignored (see <a href="//likebtn.com/en/faq#local_domain" title="Like Button FAQ">LikeBtn.com FAQ</a>)';
2283                    return settings_values;
2284                }
2285            } else if (obj.needDomainFromParent(index)) {
2286                // In iframe
2287                // get parent (referrer) domain
2288                var url = document.referrer;
2289                if (url) {
2290                    var referrer_host = obj.getDomainFromUrl(url);
2291                    if (referrer_host) {
2292                        host = referrer_host;
2293                    }
2294                }
2295                // For Chrome only
2296                if (!url && typeof(window.location.ancestorOrigins) != "undefined" && window.location.ancestorOrigins.length) {
2297                    host = obj.getDomainFromUrl(window.location.ancestorOrigins[window.location.ancestorOrigins.length-1]);
2298                }
2299            }
2300
2301            if (host.indexOf('.googleusercontent.com') != -1) {
2302                // Hack for Google Sites
2303                // Google Sites has iframe in iframe
2304                // 882957552-atari-embeds.googleusercontent.com
2305                host = 'sites.google.com';
2306            }
2307            
2308            // Check subdirectory
2309            if (!is_local_domain) {
2310                var subdirectory = obj.normalizeSubdirectory(obj.getParameter(index, "subdirectory"));
2311                if (subdirectory) {
2312                    var cur_subdirectory = obj.normalizeSubdirectory(obj.getPathFromUrl(url));
2313
2314                    if (!cur_subdirectory.match(new RegExp('^'+obj.regexpQuote(subdirectory)))) {
2315                        settings_values['error_message'] = 'Current subdirectory "' + cur_subdirectory + '" does not match the specified subdirectory: "' + subdirectory + '"';
2316                        return settings_values;
2317                    } else {
2318                        // Concatenate host and subdirectory
2319                        host = host + subdirectory;
2320                    }
2321                }
2322            }
2323
2324            settings_values['h'] = host;
2325
2326            return settings_values;
2327        }
2328
2329        // Encode settings for passing in URL
2330        obj.encodeSettings = function (settings_values) {
2331            var settings = encodeURIComponent(obj.JSON.encode(settings_values));
2332            //settings = obj.replaceAll(/%/, obj.settings_percent_replacer, settings);
2333            return settings;
2334        }
2335
2336        // If there is a parent - use parent domain
2337        obj.needDomainFromParent = function (index) {
2338
2339            //var forced_domain_from_parent = true;
2340            //var host = obj.getParameter(index, "host");
2341
2342            /*for (i in obj.forced_domain_from_parent) {
2343                if (host.indexOf(obj.forced_domain_from_parent[i])) {
2344                    forced_domain_from_parent = true;
2345                    break;
2346                }
2347            }*/
2348
2349            //if ((obj.getParameter(index, "domain_from_parent") || forced_domain_from_parent) && window.location != window.parent.location) {
2350            if (obj.getParameter(index, "domain_from_parent") && window.location != window.parent.location) {
2351                return true;
2352            } else {
2353                return false;
2354            }
2355        }
2356
2357        // get item html
2358        obj.getHtml = function (data, index) {
2359            var lb_html = '';
2360            var settings = null;
2361            var translation = {};
2362
2363            if (!obj.isDefined(data)) {
2364                return lb_html;
2365            }
2366
2367            // get settings
2368            if (obj.isDefined(obj.settings.values[index])) {
2369                settings = obj.settings.values[index];
2370            }
2371
2372            // get translation
2373            translation = obj.translations[obj.dyn_settings.get(index, "locale")];
2374
2375            if (!settings || !translation) {
2376                return lb_html;
2377            }
2378
2379            // counts
2380            var counts = obj.getCountsPrepared(index, {'1':data.l, '-1':data.d});
2381
2382            // like counter
2383            var counter_like_show = true;
2384            if ( (!counts['1'] && obj.getParameter(index, 'counter_type') != 'percent' && !obj.getParameter(index, 'counter_zero_show')) || !obj.getParameter(index, 'counter_show')) {
2385                counter_like_show = false;
2386            }
2387            var counter_like_html = '<span class="lb-count'+(!counter_like_show ? ' lb-hidden' : '')+'" data-count="'+data.l+'">'+counts['1']+'</span>';
2388
2389            // dislike counter
2390            var counter_dislike_show = true;
2391
2392            if ( (!counts['-1'] && obj.getParameter(index, 'counter_type') != 'percent' && !obj.getParameter(index, 'counter_zero_show')) || !obj.getParameter(index, 'counter_show') || obj.getParameter(index, 'counter_type') == 'subtract_dislikes') {
2393                counter_dislike_show = false;
2394            }
2395            var counter_dislike_html = '<span class="lb-count'+(!counter_dislike_show ? ' lb-hidden' : '')+'" data-count="'+data.d+'">'+counts['-1']+'</span>';
2396
2397            // like
2398            if (settings.like_enabled || !settings.dislike_enabled) {
2399                lb_html += '<span class="likebtn-button lb-like'+(settings.counter_clickable ? ' lb-counter-clickable' : '')+(settings.ef_voting ? ' lb-ef-'+settings.ef_voting : '')+'" id="lb-like-'+index+'" '+(settings.counter_clickable ? 'onclick="LikeBtn.vote(1, '+index+', event);"' : '')+'>';
2400                lb_html += '<span '+((!settings.counter_clickable /*&& settings.voting_enabled*/) ? 'onclick="LikeBtn.vote(1, '+index+', event);"' : '')+' class="lb-a" data-lb_index="'+index+'">';
2401                lb_html += '<i class="lb-tt lb-tooltip-tt"><i class="lb-tt-lt"></i><i class="lb-tt-rt"></i><i class="lb-tt-m">'+(settings.i18n_like_tooltip ? settings.i18n_like_tooltip : translation.i18n_like_tooltip)+'</i><i class="lb-tt-mu">'+(settings.i18n_unlike_tooltip ? settings.i18n_unlike_tooltip : translation.i18n_unlike_tooltip)+'</i><i class="lb-tt-m2"></i><i class="lb-tt-lb"></i><i class="lb-tt-rb"></i><i class="lb-tt-a"></i></i>';
2402                if (settings.icon_like_show || !settings.show_like_label) {
2403                    lb_html += '<span class="likebtn-icon lb-like-icon">&nbsp;</span>';
2404                }
2405                if (settings.show_like_label) {
2406                    lb_html += '<span class="likebtn-label lb-like-label">'+(settings.i18n_like ? settings.i18n_like : translation.i18n_like)+'</span>';
2407                }
2408                lb_html += '</span>'+counter_like_html+'</span>';
2409            }
2410
2411            // dislike
2412            if (settings.dislike_enabled) {
2413                lb_html += '<span class="likebtn-button lb-dislike '+(settings.counter_clickable ? ' lb-counter-clickable' : '')+(settings.ef_voting ? ' lb-ef-'+settings.ef_voting : '')+'" id="lb-dislike-'+index+'" '+(settings.counter_clickable ? 'onclick="LikeBtn.vote(-1, '+index+', event);"' : '')+'>';
2414                lb_html += '<span '+((!settings.counter_clickable /*&& settings.voting_enabled*/) ? 'onclick="LikeBtn.vote(-1, '+index+', event);"' : '')+' class="lb-a" data-lb_index="'+index+'">';
2415                lb_html += '<i class="lb-tt lb-tooltip-tt"><i class="lb-tt-lt"></i><i class="lb-tt-rt"></i><i class="lb-tt-m">'+(settings.i18n_dislike_tooltip ? settings.i18n_dislike_tooltip : translation.i18n_dislike_tooltip)+'</i><i class="lb-tt-mu">'+(settings.i18n_undislike_tooltip ? settings.i18n_undislike_tooltip : translation.i18n_undislike_tooltip)+'</i><i class="lb-tt-m2"></i><i class="lb-tt-lb"></i><i class="lb-tt-rb"></i><i class="lb-tt-a"></i></i>';
2416                if (settings.icon_dislike_show || !settings.show_dislike_label) {
2417                    lb_html += '<span class="likebtn-icon lb-dislike-icon">&nbsp;</span>';
2418                }
2419                if (settings.show_dislike_label) {
2420                    lb_html += '<span class="likebtn-label lb-dislike-label">'+(settings.i18n_dislike ? settings.i18n_dislike : translation.i18n_dislike)+'</span>';
2421                }
2422                lb_html += '</span>'+counter_dislike_html+'</span>';
2423            }
2424            // Rich Snippet
2425            if (obj.getParameter(index, 'rich_snippet')) {
2426                var rc_values = obj.getRichSnippetValues(data);
2427                var item_date = obj.getParameter(index, 'item_date');
2428                if (!item_date) {
2429                    item_date = '2026-10-01T00:00:00+00:00';
2430                }
2431                var item_name = obj.getParameter(index, 'item_title');
2432                if (!item_name) {
2433                    item_name = document.title;
2434                }
2435                if (rc_values.count) {
2436                  lb_html += 
2437                      '<meta itemprop="name" content="'+item_name+'" />'+
2438                      '<meta itemprop="headline" content="'+obj.getParameter(index, 'item_title')+'" />'+
2439                      '<meta itemprop="description" content="'+obj.getParameter(index, 'item_description')+'" />'+
2440                      '<meta itemprop="image" content="'+obj.getParameter(index, 'item_image')+'" />'+
2441                      '<meta itemprop="datePublished" content="'+item_date+'" />'+
2442                      '<meta itemprop="url" content="'+obj.getParameter(index, 'item_url')+'" />'+
2443                      '<span itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">'+
2444                          '<meta itemprop="worstRating" content="1" />'+
2445                          '<meta itemprop="bestRating" content="5" />'+
2446                          '<meta itemprop="ratingValue" content="'+rc_values.value+'" />'+
2447                          '<meta itemprop="ratingCount" content="'+rc_values.count+'" />'+
2448                      '</span>';
2449                }
2450            }
2451
2452            return lb_html;
2453        }
2454
2455        // Mark button as loaded
2456        obj.setLoaded = function (index, wrapper) {
2457            wrapper.likebtn_loading = false;
2458            obj.dyn_settings.set(index, "loaded", true);
2459        }
2460        // get rich snippet aggregate rating values
2461        obj.getRichSnippetValues = function (data) {
2462            var likes = parseInt(data.l);
2463            if (isNaN(likes)) {
2464                likes = 0;
2465            }
2466            var dislikes = parseInt(data.d);
2467            if (isNaN(dislikes)) {
2468                dislikes = 0;
2469            }
2470            var count = likes+dislikes;
2471            var value = 0;
2472            if (count > 0) {
2473                value = Math.round((((likes*5+dislikes) / count ) * 10 ) / 10);
2474            }
2475            return {
2476                count: count,
2477                value: value
2478            }
2479        }
2480
2481        // Apply custom theme
2482        obj.customTheme = function(index, wrapper) {
2483            var btn_size = parseInt(obj.getParameter(index, 'btn_size'));
2484            var bg_c = obj.getParameter(index, 'bg_c');
2485            var brdr_c = obj.getParameter(index, 'brdr_c');
2486
2487            if (btn_size || bg_c || brdr_c) {
2488                var lb_like = wrapper.getElementsByClassName('lb-like')[0];
2489                var lb_dislike = wrapper.getElementsByClassName('lb-dislike')[0];
2490            }
2491            if (btn_size) {
2492                if (btn_size > 1000) {
2493                    btn_size = 1000;
2494                }
2495                wrapper.style.lineHeight = btn_size+"px";
2496            }
2497            if (lb_like) {
2498                if (btn_size) {
2499                    lb_like.style.height = btn_size+"px";
2500                    //lb_like.style.lineHeight = btn_size+"px";
2501                }
2502                if (bg_c) {
2503                    lb_like.style.backgroundColor = bg_c;
2504                }
2505                if (brdr_c) {
2506                    lb_like.style.borderColor = brdr_c;
2507                }
2508            }
2509            if (lb_dislike) {
2510                if (btn_size) {
2511                    lb_dislike.style.height = btn_size+"px";
2512                    //lb_dislike.style.lineHeight = btn_size+"px";
2513                }
2514                if (bg_c) {
2515                    lb_dislike.style.backgroundColor = bg_c;
2516                }
2517                if (brdr_c) {
2518                    lb_dislike.style.borderColor = brdr_c;
2519                }
2520            }
2521        
2522            /*
2523            Don't remove. Needed for loading fonts on prod.
2524                                                             */
2525
2526            var icon_l = obj.getParameter(index, 'icon_l');
2527            var icon_l_url = obj.getParameter(index, 'icon_l_url');
2528            var icon_l_url_v = obj.getParameter(index, 'icon_l_url_v');
2529            var like_icon = wrapper.getElementsByClassName('lb-like-icon')[0];
2530            var icon_l_c = obj.getParameter(index, 'icon_l_c');
2531            if (like_icon) {
2532                if (icon_l_url) {
2533                    if (!icon_l_url_v) {
2534                        icon_l_url_v = icon_l_url;
2535                    }
2536                    obj.removeClass(like_icon, "lb-fi");
2537                    like_icon.outerHTML = '<img src="'+icon_l_url+'" class="'+like_icon.className+'"/><img src="'+icon_l_url_v+'" class="'+like_icon.className+' lb-icon-v"/>';
2538                } else if (icon_l) {
2539                    // Load font
2540                    obj.loadAsset('/css/w/icons.css?v=41', 'css');
2541                    like_icon.outerHTML = '<span class="lb-fi-'+icon_l+' '+like_icon.className+' lb-fi"></span>';
2542
2543                    like_icon = wrapper.getElementsByClassName('lb-like-icon')[0];
2544
2545                    // Icon Color
2546                    if (icon_l_c) {
2547                        like_icon.style.color = icon_l_c;
2548                    }
2549
2550                    // Icon Size
2551                    var icon_size = obj.getParameter(index, 'icon_size');
2552                    if (icon_size) {
2553                        like_icon.style.fontSize = icon_size+'px';
2554                        if (btn_size) {
2555                            like_icon.style.height = btn_size+'px';
2556                        }
2557                    }
2558                }
2559            }
2560
2561            var icon_d = obj.getParameter(index, 'icon_d');
2562            var icon_d_url = obj.getParameter(index, 'icon_d_url');
2563            var icon_d_url_v = obj.getParameter(index, 'icon_d_url_v');
2564            var dislike_icon = wrapper.getElementsByClassName('lb-dislike-icon')[0];
2565            var icon_d_c = obj.getParameter(index, 'icon_d_c');
2566            if (dislike_icon) {
2567                if (icon_d_url) {
2568                    if (!icon_d_url_v) {
2569                        icon_d_url_v = icon_d_url;
2570                    }
2571                    obj.removeClass(dislike_icon, "lb-fi");
2572                    dislike_icon.outerHTML = '<img src="'+icon_d_url+'" class="'+dislike_icon.className+'"/><img src="'+icon_d_url_v+'" class="'+dislike_icon.className+' lb-icon-v"/>';
2573                } else if (icon_d) {
2574                    // Load font
2575                    obj.loadAsset('/css/w/icons.css?v=41', 'css');
2576                    dislike_icon.outerHTML = '<span class="lb-fi-'+icon_d+' '+dislike_icon.className+' lb-fi"></span>';
2577
2578                    dislike_icon = wrapper.getElementsByClassName('lb-dislike-icon')[0];
2579
2580                    // Icon Color
2581                    if (icon_d_c) {
2582                        dislike_icon.style.color = icon_d_c;
2583                    }
2584
2585                    // Icon Size
2586                    var icon_size = obj.getParameter(index, 'icon_size');
2587                    if (icon_size) {
2588                        dislike_icon.style.fontSize = icon_size+'px';
2589                        if (btn_size) {
2590                            dislike_icon.style.height = btn_size+'px';
2591                        }
2592                    }
2593                }
2594            }
2595
2596            // Font
2597            var f_size = parseInt(obj.getParameter(index, 'f_size'));
2598            var f_family = obj.getParameter(index, 'f_family');
2599            var label_fs = obj.getParameter(index, 'label_fs');
2600            var counter_fs = obj.getParameter(index, 'counter_fs');
2601            var label_c = obj.getParameter(index, 'label_c');
2602            var counter_l_c = obj.getParameter(index, 'counter_l_c');
2603            var counter_d_c = obj.getParameter(index, 'counter_d_c');
2604            //var f_brtns_v = obj.getParameter(index, 'f_brtns_v');
2605
2606            var like_label = wrapper.getElementsByClassName('lb-like-label')[0];
2607            var like_count = obj.q1("#lb-like-"+index+" .lb-count");
2608
2609            var dislike_label = wrapper.getElementsByClassName('lb-dislike-label')[0];
2610            var dislike_count = obj.q1("#lb-dislike-"+index+" .lb-count");
2611
2612            if (like_label) {
2613                if (f_size) {
2614                    like_label.style.fontSize = f_size+'px';
2615                }
2616                if (f_family) {
2617                    like_label.style.fontFamily = f_family;
2618                }
2619                if (label_fs) {
2620                    obj.fontStyle(like_label, label_fs);
2621                }
2622                if (label_c) {
2623                    like_label.style.color = label_c;
2624                }
2625            }
2626            if (like_count) {
2627                if (f_size) {
2628                    like_count.style.fontSize = f_size+'px';
2629                }
2630                if (f_family) {
2631                    like_count.style.fontFamily = f_family;
2632                }
2633                if (counter_fs) {
2634                    obj.fontStyle(like_count, counter_fs);
2635                }
2636                if (counter_l_c) {
2637                    like_count.style.color = counter_l_c;
2638                }
2639            }
2640
2641            if (dislike_label) {
2642                if (f_size) {
2643                    dislike_label.style.fontSize = f_size+'px';
2644                }
2645                if (f_family) {
2646                    dislike_label.style.fontFamily = f_family;
2647                }
2648                if (label_fs) {
2649                    obj.fontStyle(dislike_label, label_fs);
2650                }
2651                if (label_c) {
2652                    dislike_label.style.color = label_c;
2653                }
2654            }
2655            if (dislike_count) {
2656                if (f_size) {
2657                    dislike_count.style.fontSize = f_size+'px';
2658                }
2659                if (f_family) {
2660                    dislike_count.style.fontFamily = f_family;
2661                }
2662                if (counter_fs) {
2663                    obj.fontStyle(dislike_count, counter_fs);
2664                }
2665                if (counter_d_c) {
2666                    dislike_count.style.color = counter_d_c;
2667                }
2668            }
2669
2670            // Show voting
2671            obj.showCustomVoting(wrapper);
2672
2673            // After Voting
2674            var icon_l_c_v = obj.getParameter(index, 'icon_l_c_v');
2675            var icon_d_c_v = obj.getParameter(index, 'icon_d_c_v');
2676            var label_c_v = obj.getParameter(index, 'label_c_v');
2677            var bg_c_v = obj.getParameter(index, 'bg_c_v');
2678
2679            if (icon_l_c_v || icon_d_c || label_c_v || icon_l_c || icon_d_c || bg_c_v) {
2680                var lb_a = wrapper.getElementsByClassName('lb-a');
2681                for (i in lb_a) {
2682                    if (isNaN(parseInt(i))) {
2683                        continue;
2684                    }
2685                    lb_a[i].onmouseover = function(e) { obj.onMouseOver(e); };
2686
2687                    lb_a[i].onmouseout = function(e) {
2688                        var el = e.target;
2689                        if (!obj.hasClass(el, 'lb-a')) {
2690                            el = el.parentElement;
2691                        }
2692
2693                        // If button is voted - do nothing
2694                        if (obj.hasClass(el.parentElement, 'lb-voted')) {
2695                            return;
2696                        }
2697
2698                        obj.removeCustomVoting(el);
2699                    };
2700                }
2701            }
2702        }
2703
2704        // Set custom voted colors
2705        obj.showCustomVoting = function (wrapper) {
2706            var lb_a = wrapper.getElementsByClassName('lb-a');
2707            for (i in lb_a) {
2708                if (isNaN(parseInt(i))) {
2709                    continue;
2710                }
2711                if (obj.hasClass(lb_a[i].parentElement, 'lb-voted')) {
2712                    obj.onMouseOver({target: lb_a[i]});
2713                } else {
2714                    obj.removeCustomVoting(lb_a[i]);
2715                }
2716            }
2717        }
2718
2719        // Remove custom voted colors
2720        obj.removeCustomVoting = function (el) {
2721            if (el.hasAttribute('data-icon_c')) {
2722                var data_icon_c = el.getAttribute('data-icon_c');
2723                var icon_el = el.getElementsByClassName('likebtn-icon')[0];
2724                icon_el.style.color = data_icon_c;
2725                el.removeAttribute('data-icon_c');
2726            }
2727            if (el.hasAttribute('data-label_c')) {
2728                var data_label_c = el.getAttribute('data-label_c');
2729                var label_el = el.getElementsByClassName('likebtn-label')[0];
2730                label_el.style.color = data_label_c;
2731                el.removeAttribute('data-label_c');
2732            }
2733            var btn_el = el.parentElement;
2734            if (btn_el.hasAttribute('data-bg_c')) {
2735                var data_bg_c = btn_el.getAttribute('data-bg_c');
2736                btn_el.style.backgroundColor = data_bg_c;  
2737                btn_el.removeAttribute('data-bg_c');
2738            }
2739        }
2740
2741        // On mouse over
2742        obj.onMouseOver = function (e) {
2743
2744            var el = e.target;
2745            if (!obj.hasClass(el, 'lb-a')) {
2746                el = el.parentElement;
2747            }
2748            var index = parseInt(el.getAttribute('data-lb_index'));
2749
2750            if (!el || isNaN(index)) {
2751                return;
2752            }
2753
2754            var label_c = obj.getParameter(index, 'label_c');
2755            var icon_class = '';
2756            // Determine the type
2757            if (obj.hasClass(el.parentElement, 'lb-like')) {
2758                icon_class = 'icon_l_c';
2759            } else {
2760                icon_class = 'icon_d_c';
2761            }
2762
2763            var icon_c = obj.getParameter(index, icon_class);
2764
2765            // Icon
2766            if (!el.hasAttribute('data-icon_c')) {
2767                var icon_c_v = obj.getParameter(index, icon_class+'_v');
2768                var data_icon_c = el.getAttribute('data-icon_c');
2769                var icon_el = el.getElementsByClassName('likebtn-icon')[0];
2770                if (icon_c_v && icon_el) {
2771                    var cur_c = icon_el.style.color;
2772                    if (icon_c && icon_el) {
2773                        // Save current color
2774                        el.setAttribute('data-icon_c', cur_c);
2775                        // Calculate new color
2776                        icon_el.style.color = icon_c_v;
2777                    }
2778                }
2779            }
2780
2781            // Label
2782            if (!el.hasAttribute('data-label_c')) {
2783                var label_c_v = obj.getParameter(index, 'label_c_v');
2784                var data_label_c = el.getAttribute('data-label_c');
2785                var label_el = el.getElementsByClassName('likebtn-label')[0];
2786                if (label_c_v && label_el) {
2787                    var cur_c = label_el.style.color;
2788                    if (label_c && label_el) {
2789                        // Save current color
2790                        el.setAttribute('data-label_c', cur_c);
2791                        // Calculate new color
2792                        label_el.style.color = label_c_v;
2793                    }
2794                }
2795            }
2796
2797            // Background
2798            btn_el = el.parentElement;
2799            if (!btn_el) {
2800                return;
2801            }
2802            if (!btn_el.hasAttribute('data-bg_c')) {
2803                var bg_c_v = obj.getParameter(index, 'bg_c_v');
2804
2805                var data_bg_c = btn_el.getAttribute('data-bg_c');
2806                var bg_c = obj.getParameter(index, 'bg_c');
2807
2808                if (bg_c_v && btn_el) {
2809                    var cur_c = btn_el.style.backgroundColor;
2810                    if (bg_c) {
2811                        // Save current color
2812                        btn_el.setAttribute('data-bg_c', cur_c);
2813                        btn_el.style.backgroundColor = bg_c_v;
2814                    }
2815                }
2816            }
2817        }
2818
2819        // Set element font style
2820        obj.fontStyle = function (el, fs) {
2821            if (fs == 'r') {
2822                el.style.fontWeight = 'normal';
2823            } else if (fs == 'ri') {
2824                el.style.fontWeight = 'normal';
2825                el.style.fontStyle = 'italic';
2826            } else if (fs == 'b') {
2827                el.style.fontWeight = 'bold';
2828            } else if (fs == 'bi') {
2829                el.style.fontWeight = 'bold';
2830                el.style.fontStyle = 'italic';
2831            }
2832        }
2833
2834        // get parameter shortcut
2835        obj.getParameter = function (index, name) {
2836            return obj.settings.get(index, name);
2837        }
2838
2839        // get item count
2840        obj.getItemCount = function (index, type) {
2841            if (!type) {
2842                return undefined;
2843            }
2844            var count_el = obj.getItemCountEl(index, type);
2845            if (typeof(count_el) != "undefined") {
2846               return count_el.getAttribute('data-count');
2847            }
2848            return undefined;
2849        }
2850
2851        // get item count element
2852        obj.getItemCountEl = function (index, type) {
2853            if (type == 1) {
2854                var count_el = obj.q('#lb-like-'+index+' .lb-count');
2855            } else {
2856                var count_el = obj.q('#lb-dislike-'+index+' .lb-count');
2857            }
2858            if (typeof(count_el[0]) != "undefined") {
2859               return count_el[0];
2860            }
2861            return undefined;
2862        }
2863
2864        // get counts representation
2865        obj.getCountsPrepared = function (index, values) {
2866            var counts = {};
2867
2868            values['1'] = parseInt(values['1']);
2869            if (isNaN(values['1'])) {
2870                values['1'] = 0;
2871            }
2872            values['-1'] = parseInt(values['-1']);
2873            if (isNaN(values['-1'])) {
2874                values['-1'] = 0;
2875            }
2876
2877            var counter_type = obj.getParameter(index, 'counter_type');
2878            if (counter_type == 'percent') {
2879                // percent
2880                var sum = values['1'] + values['-1'];
2881                var like_percent;
2882                var dislike_percent;
2883                if (sum) {
2884                    like_percent    = Math.round( (values['1'] * 100) / sum );
2885                    dislike_percent = 100 - like_percent;
2886                } else {
2887                    like_percent    = 50;
2888                    dislike_percent = 50;
2889                }
2890                counts = {'1':like_percent+'%', '-1':dislike_percent+'%' };
2891            } else if (counter_type == 'subtract_dislikes') {
2892                var diff_value = values['1'] - values['-1'];
2893                //if (diff_value > 0) {
2894                counts = {'1':diff_value, '-1': 0};
2895                //} else {
2896                //    counts = {'1':0, '-1': 0};
2897                //}
2898            } else if (counter_type == 'single_number') {
2899                var diff_value = values['1'] - values['-1'];
2900                if (diff_value > 0) {
2901                    counts = {'1':diff_value, '-1': 0};
2902                } else if (diff_value < 0) {
2903                    counts = {'1':0, '-1': diff_value};
2904                } else {
2905                    counts = {'1':0, '-1': 0};
2906                }
2907            } else {
2908                // number
2909                counts = {'1':values['1'], '-1':values['-1'] };
2910            }
2911
2912            if (counter_type != 'percent') {
2913                var counter_frmt = obj.getParameter(index, 'counter_frmt');
2914 
2915                if (counter_frmt == 'km') {
2916                    counts['1'] = obj.km(counts['1']);
2917                    counts['-1'] = obj.km(counts['-1']);
2918                } else {
2919                    var sep = '';
2920                    if (counter_frmt == 'space') {
2921                        sep = ' ';
2922                    } else if (counter_frmt == 'period') {
2923                        sep = '.';
2924                    } else if (counter_frmt == 'comma') {
2925                        sep = ',';
2926                    } else if (counter_frmt == 'apo') {
2927                        sep = "'";
2928                    }
2929                    counts['1'] = obj.sep(counts['1'], sep);
2930                    counts['-1'] = obj.sep(counts['-1'], sep);
2931                }
2932            }
2933
2934            // apply padding
2935            var padding = obj.getParameter(index, 'counter_padding');
2936            if (padding != '') {
2937                counts['1'] = obj.paddingApply(padding, counts['1']);
2938                counts['-1'] = obj.paddingApply(padding, counts['-1']);
2939            }
2940            return counts;
2941        }
2942
2943        // Separate thousands
2944        obj.sep = function (n, sep) {
2945            if (n < 1000) {
2946                return n;
2947            } else {
2948                return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, sep);
2949            }
2950        }
2951
2952        // To KM
2953        obj.km = function(n) {
2954            if (n < 1000) {
2955                return n;
2956            }
2957            if (n < 999999) {
2958                var v = n / 1000;
2959                v = v.toFixed(1);
2960                if (v - Math.floor(v) == 0) {
2961                    v = Math.floor(v);
2962                }
2963                return v+'K';
2964            }
2965            if (n >= 1000000) {
2966                var v = n / 1000000;
2967                v = v.toFixed(1);
2968                if (v - Math.floor(v) == 0) {
2969                    v = Math.floor(v);
2970                }
2971                return v+'M';
2972            }
2973        }
2974
2975        // apply padding to the value
2976        obj.paddingApply = function (padding, value) {
2977            var v = value + "";
2978            v = v.split("");
2979            var p = padding.split("");
2980
2981            if (p.length > v.length) {
2982                var result = [];
2983                var v_index = 0;
2984                for (var i = 0; i < p.length; i++) {
2985                    v_index = i - (p.length - v.length);
2986                    if (obj.isDefined(v[v_index])) {
2987                        result[i] = v[v_index];
2988                    } else {
2989                        result[i] = p[i];
2990                    }
2991                }
2992                return result.join("");
2993            }
2994            return value;
2995        }
2996
2997        // get vote type for item from cookies
2998        obj.getItemVoteType = function (index) {
2999
3000            // First check cookie
3001            var identifier_hash = obj.getItemIdentifierHash(index);
3002
3003            if (identifier_hash) {
3004                // get vote from cookie
3005                var cookie_votes = obj.getData(obj.cookie_vote_name+""+identifier_hash);
3006
3007                if (!obj.isDefined(cookie_votes)) {
3008                    // backward compatibility
3009                    var cookie_votes_old = obj.getCookieAsObject(obj.cookie_vote_name);
3010                    if (obj.isDefined(cookie_votes_old) && obj.isDefined(cookie_votes_old[identifier_hash])
3011                        && !isNaN(parseInt(cookie_votes_old[identifier_hash]) && parseInt(cookie_votes_old[identifier_hash]))
3012                    ) {
3013                        return parseInt(cookie_votes_old[identifier_hash]);
3014                    }
3015                } else {
3016                    if (parseInt(cookie_votes)) {
3017                        return parseInt(cookie_votes);
3018                    }
3019                }
3020            }
3021
3022            // Check data parameter
3023            var vt = obj.getParameter(index, "vt");
3024            if (vt && !isNaN(parseInt(vt))) {
3025                return parseInt(vt);
3026            }
3027
3028            return '';
3029        }
3030
3031        // get vote type for item from cookies
3032        obj.getItemCountFromCookie = function (index) {
3033
3034            var identifier_hash = obj.getItemIdentifierHash(index);
3035
3036            // get Item container
3037            if (identifier_hash) {
3038                // get count from cookie
3039                var cookie_count = obj.getCookieAsObject(obj.cookie_count_name+""+identifier_hash);
3040
3041                if (obj.isDefined(cookie_count)) {
3042                    return cookie_count;
3043                }
3044            }
3045            return '';
3046        }
3047
3048        // get cookie content as JSON
3049        obj.getCookieAsObject = function (name) {
3050            var cookie_str = obj.getData(name);
3051            return obj.JSON.decode(cookie_str);
3052        }
3053
3054        // get Item identifier
3055        obj.getItemIdentifier = function (index) {
3056            var item_identifier = obj.getParameter(index, "identifier");
3057
3058            if (!item_identifier) {
3059                item_identifier = obj.normalizeUrlIdentifier(obj.getParameter(index, "url"));
3060            }
3061
3062            return obj.normalizeIdentifier(item_identifier);
3063        }
3064
3065        // Fix identifier length
3066        obj.normalizeIdentifier = function (identifier) {
3067            if (identifier && typeof(obj.norm_identifiers[identifier]) !== "undefined") {
3068                return obj.norm_identifiers[identifier];
3069            }
3070            
3071            if (identifier && identifier.length*2 > obj.identifier_maxl && obj.utf8ByteCount(identifier) > obj.identifier_maxl) {
3072                norm_identifier = obj.mbSubstr(identifier, 0, obj.identifier_maxl);
3073            } else {
3074                norm_identifier = identifier;
3075            }
3076
3077            obj.norm_identifiers[identifier] = norm_identifier;
3078
3079            return norm_identifier;
3080        }
3081
3082        obj.mbSubstr = function(str, start, len) {
3083            str = str.substr(start, len);
3084            for (var i = str.length-1; i > 0 ; i--) {
3085                str = str.substr(start, i+1);
3086                if (obj.utf8ByteCount(str) <= len) {
3087                    //console.log('result:'+str);
3088                    return str;
3089                }
3090            }
3091            return str;
3092        }
3093
3094        /**
3095         * codePoint - an integer containing a Unicode code point
3096         * return - the number of bytes required to store the code point in UTF-8
3097         */
3098        obj.utf8Len = function(codePoint) {
3099            if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
3100                return 0;
3101            }
3102            if(codePoint < 0) return 0;;
3103            if(codePoint <= 0x7F) return 1;
3104            if(codePoint <= 0x7FF) return 2;
3105            if(codePoint <= 0xFFFF) return 3;
3106            if(codePoint <= 0x1FFFFF) return 4;
3107            if(codePoint <= 0x3FFFFFF) return 5;
3108            if(codePoint <= 0x7FFFFFFF) return 6;
3109            return 0;
3110        }
3111
3112        obj.isHighSurrogate = function(codeUnit) {
3113            return codeUnit >= 0xD800 && codeUnit <= 0xDBFF;
3114        }
3115
3116        obj.isLowSurrogate = function(codeUnit) {
3117            return codeUnit >= 0xDC00 && codeUnit <= 0xDFFF;
3118        }
3119
3120        /**
3121         * Transforms UTF-16 surrogate pairs to a code point.
3122         * See RFC2781
3123         */
3124        obj.toCodepoint = function(highCodeUnit, lowCodeUnit) {
3125            if (!obj.isHighSurrogate(highCodeUnit)) throw new Error("Illegal argument: "+highCodeUnit);
3126            if (!obj.isLowSurrogate(lowCodeUnit)) throw new Error("Illegal argument: "+lowCodeUnit);
3127            highCodeUnit = (0x3FF & highCodeUnit) << 10;
3128            var u = highCodeUnit | (0x3FF & lowCodeUnit);
3129            return u + 0x10000;
3130        }
3131
3132        /**
3133         * Counts the length in bytes of a string when encoded as UTF-8.
3134         * str - a string
3135         * return - the length as an integer
3136         */
3137        obj.utf8ByteCount = function(str) {
3138            var count = 0;
3139            for (var i=0; i<str.length; i++) {
3140                var ch = str.charCodeAt(i);
3141                try {
3142                    if (obj.isHighSurrogate(ch)) {
3143                        var high = ch;
3144                        var low = str.charCodeAt(++i);
3145                        count += obj.utf8Len(obj.toCodepoint(high, low));
3146                    } else {
3147                        count += obj.utf8Len(ch);
3148                    }
3149                } catch(e) {
3150                    // Do nothing
3151                }
3152            }
3153            return count;
3154        }
3155
3156        // get Item identifier hash
3157        obj.getItemIdentifierHash = function (index) {
3158
3159            var item_identifier = obj.getItemIdentifier(index);
3160            return obj.hashCodeMd5(item_identifier);
3161        }
3162
3163        // get Item identifier hash
3164        // only_unloaded - find only buttons which has not been loaded
3165        /*obj.getIndexByIdentifierHash = function (identifier_hash, only_unloaded) {
3166
3167            for (var index in obj.dyn_settings.values) {
3168                if (obj.dyn_settings.get(index, "identifier_hash") == identifier_hash) {
3169                    if (obj.isDefined(only_unloaded) && only_unloaded) {
3170                        if (obj.isDefined(obj.dyn_settings.get(index, "loaded"))) {
3171                            continue;
3172                        }
3173                    }
3174                    return index;
3175                }
3176            }
3177            return -1;
3178        }*/
3179
3180        // get Item identifier hash MD5
3181        obj.getIndexByIdentifierHash = function (identifier_hash, only_unloaded) {
3182
3183            for (var index in obj.dyn_settings.values) {
3184                if (obj.dyn_settings.get(index, "identifier_hash") == identifier_hash) {
3185                    if (obj.isDefined(only_unloaded) && only_unloaded) {
3186                        if (obj.isDefined(obj.dyn_settings.get(index, "loaded"))) {
3187                            continue;
3188                        }
3189                    }
3190                    return index;
3191                }
3192            }
3193            return -1;
3194        }
3195
3196        // normilizes identifier if it is URL
3197        // parameters are not included
3198        obj.normalizeUrlIdentifier = function (url) {
3199            var parser = document.createElement('a');
3200            parser.href = url;
3201            var normalized_identifier = parser.pathname;
3202
3203            // Convert URL encoded UTF symbols
3204            normalized_identifier = decodeURIComponent(normalized_identifier);
3205
3206            if (!normalized_identifier) {
3207                normalized_identifier = '/';
3208            }
3209
3210            // add slash in the beginning
3211            if (normalized_identifier.charAt(0) != '/') {
3212                normalized_identifier = '/' + normalized_identifier;
3213            }
3214
3215            return obj.normalizeIdentifier(normalized_identifier);
3216        }
3217
3218        // show counter
3219        obj.showCounter = function (el, index) {
3220            
3221            if (typeof(el) != "undefined") {
3222                var counter_type = obj.getParameter(index, 'counter_type');
3223
3224                // for percent counter type counter is displayed always
3225                if (((parseInt(el.innerHTML) == 0 && counter_type != 'percent') || !obj.getParameter(index, "counter_show")) && !obj.getParameter(index, 'counter_zero_show')) {
3226                    el.style.display = 'none';
3227                } else {
3228
3229                    if (el.parentNode && obj.hasClass(el.parentNode, 'lb-dislike') && counter_type == 'subtract_dislikes') {
3230                        // Subtract dislikes and counter_zero_show
3231                        el.style.display = 'none';
3232                    } else {
3233                        el.style.display = 'inline-block';
3234                    }
3235                }
3236            }
3237        }
3238
3239        // process group identifier - set display only for buttons
3240        obj.processGroupIdentifier = function (voted_index, add) {
3241            var group_identifier = obj.getParameter(voted_index, 'group_identifier');
3242            var wrapper;
3243
3244            if (!obj.isDefined(add)) {
3245                add = 1;
3246            }
3247
3248            // exit if button do not have group identifier
3249            if (!obj.isDefined(group_identifier) || !group_identifier) {
3250                 return;
3251            }
3252
3253            // Add/remove group_identifier to/from storage
3254            var item_hash = obj.getItemIdentifierHash(voted_index);
3255            var stored_group_identifier = obj.getData(obj.cookie_group_identifier);
3256            if (!obj.isDefined(stored_group_identifier)) {
3257                stored_group_identifier = {};
3258            }
3259            if (add) {
3260                // Remember group_identifier and button hash
3261                stored_group_identifier[group_identifier] = item_hash;
3262            } else {
3263                // Remove group_identifier from storage
3264                if (obj.isDefined(stored_group_identifier[group_identifier]) && stored_group_identifier[group_identifier] == item_hash) {
3265                    delete stored_group_identifier[group_identifier];
3266                }
3267            }
3268            obj.setData(
3269                obj.cookie_group_identifier,
3270                stored_group_identifier,
3271                {expires:obj.datePlus(), path:"/"},
3272                true
3273            );
3274
3275            // set voting_enabled for other buttons of the group
3276            var new_voting_enabled;
3277            if (add) {
3278                new_voting_enabled = '0';
3279            } else {
3280                new_voting_enabled = '1';
3281            }
3282
3283            for (index = 0; index < obj.settings.values.length; index++) {
3284                if (index != voted_index && obj.getParameter(index, 'group_identifier') == group_identifier) {
3285                    obj.settings.set(index, 'voting_enabled', new_voting_enabled);
3286                    wrapper = obj.dyn_settings.get(index, "wrapper");
3287                    if (obj.isDefined(wrapper)) {
3288                        if (add) {
3289                            // like/dislike
3290                            wrapper.className += " lb-display-only";
3291                        } else {
3292                            // unlike/undislike
3293                            obj.removeClass(wrapper, "lb-display-only");
3294                        }
3295                    }
3296                }
3297            }
3298        }
3299
3300        // Check if button's group is voted (except index button)
3301        obj.isGroupVoted = function(index) {
3302            var group_identifier = obj.getParameter(index, 'group_identifier');
3303
3304            // exit if button do not have group identifier
3305            if (!group_identifier) {
3306                 return false;
3307            }
3308
3309            // Add/remove group_identifier to/from storage
3310            var stored_group_identifier = obj.getData(obj.cookie_group_identifier);
3311            if (stored_group_identifier && stored_group_identifier[group_identifier] && stored_group_identifier[group_identifier] != obj.getItemIdentifierHash(index)) {
3312                return true;
3313            }
3314        }
3315
3316        // check if button has group_identifier in which button has already been voted
3317        obj.applyGroupIdentifier = function (index) {
3318            var group_identifier = obj.getParameter(index, 'group_identifier');
3319            var item_hash = obj.getItemIdentifierHash(index);
3320            var wrapper;
3321
3322            // exit if button does not have group identifier
3323            if (!obj.isDefined(group_identifier) || !group_identifier) {
3324                 return;
3325            }
3326
3327            // Get group_identifier list from storage
3328            stored_group_identifier = obj.getData(obj.cookie_group_identifier);
3329            if (!obj.isDefined(stored_group_identifier)) {
3330                stored_group_identifier = {};
3331            }
3332            if (obj.isDefined(stored_group_identifier[group_identifier]) && stored_group_identifier[group_identifier] != item_hash) {
3333                // set voting_enabled for button
3334                obj.settings.set(index, 'voting_enabled', 0);
3335                wrapper = obj.dyn_settings.get(index, "wrapper");
3336                if (obj.isDefined(wrapper)) {
3337                    wrapper.className += " lb-display-only";
3338                }
3339            }
3340        }
3341
3342        // Add milliseconds to date
3343        obj.datePlus = function (ms) {
3344            if (typeof(ms) === "undefined") {
3345                ms = 365*24*60*60*1000;
3346            }
3347            var date = new Date();
3348            date.setTime(date.getTime() + ms);
3349
3350            return date;
3351        }
3352
3353        // set popup position for "right" for all popups inside button
3354        obj.setPopupAndTooltipsPosition = function (index) {
3355            if (obj.getParameter(index, "popup_position") == 'right') {
3356                el_like = obj.q('#lb-like-'+index);
3357                el_popups = obj.q('#lb-like-'+index+' .lb-tt');
3358                if (obj.isDefined(el_like[0])) {
3359                    for (popup_index in el_popups) {
3360                        el_popups[popup_index].style.left = (parseInt(el_like[0].clientWidth) + 5) + 'px';
3361                    }
3362                }
3363                el_dislike = obj.q('#lb-dislike-'+index);
3364                el_popups = obj.q('#lb-dislike-'+index+' .lb-tt');
3365                if (obj.isDefined(el_dislike[0])) {
3366                    for (popup_index in el_popups) {
3367                        el_popups[popup_index].style.left = (parseInt(el_dislike[0].clientWidth) + 5) + 'px';
3368                    }
3369                }
3370            }
3371        }
3372
3373        // adjust popup on position on the screen
3374        obj.adjustPopupPosition = function(index) {
3375            
3376            el_like = obj.q('#lb-like-'+index);
3377            if (obj.isDefined(el_like[0])) {
3378                obj.adjustPopupPositionPerButton(index, 'like', el_like[0]);
3379            }
3380
3381            el_dislike = obj.q('#lb-dislike-'+index);
3382            if (obj.isDefined(el_dislike[0])) {
3383                obj.adjustPopupPositionPerButton(index, 'dislike', el_dislike[0]);
3384            }
3385        }
3386
3387        obj.adjustPopupPositionPerButton = function(index, like_dislike, el_btn) {
3388            el_popup = obj.q('#lb-'+like_dislike+'-'+index+' .lb-share-tt');
3389            if (obj.isDefined(el_popup[0])) {
3390                fixed = false;
3391                // Fix left
3392                if (obj.getParameter(index, "popup_position") == 'left') {
3393                    left = obj.getElementLeft(el_popup[0]);
3394                    if (left < 0) {
3395                        el_popup[0].style.left = '-'+obj.getElementLeft(el_btn)+'px';
3396                        el_popup[0].style.right = 'auto';
3397
3398                        // and top
3399                        el_popup[0].style.top = parseInt(el_btn.clientHeight)+'px';
3400                        obj.switchPopupArrow(index, like_dislike, false);
3401
3402                        fixed = true;
3403                    } else {
3404                        el_popup[0].style.left = 'auto';
3405                        el_popup[0].style.right = '100%';
3406                        el_popup[0].style.top = 'auto';
3407                        obj.switchPopupArrow(index, like_dislike, true);
3408                    }
3409                }
3410                if (obj.getParameter(index, "popup_position") != 'left' && !fixed) {
3411                    // Fix right
3412                    width = parseInt(el_popup[0].clientWidth);
3413                    left = Math.ceil(obj.getElementLeft(el_popup[0]));
3414                    right = left+width;
3415                    viewport_width = obj.viewportWidth();
3416                    if (right > (viewport_width+2)) {
3417                        el_popup[0].style.left = '-'+(right - viewport_width + 2)+'px';
3418                        if (Math.ceil(obj.getElementLeft(el_popup[0])) < 0) {
3419                            // Move popup to the left border
3420                            el_popup[0].style.left = '-'+left+'px';
3421                        }
3422
3423                        obj.switchPopupArrow(index, like_dislike, false);
3424                    } else {
3425                        el_popup[0].style.left = '-2px';
3426                    }
3427                }
3428            }
3429        }
3430
3431        obj.switchPopupArrow = function(index, like_dislike, visible) {
3432            el_arrow = obj.q('#lb-'+like_dislike+'-'+index+' .lb-tt-a');
3433            if (obj.isDefined(el_arrow[0])) {
3434                if (visible) {
3435                    display = 'block';
3436                } else {
3437                    display = 'none';
3438                }
3439                el_arrow[0].style.display = display;
3440            }
3441        }
3442
3443        // If element goes outside it extends window.innerWidth
3444        // document.documentElement.clientWidth works in iframe
3445        obj.viewportWidth = function() {
3446            return document.documentElement.clientWidth || window.screen.width;
3447        }
3448
3449        // set popup width
3450        obj.setPopupWidth = function (index) {
3451            var popup_width = parseInt(obj.getParameter(index, "popup_width"));
3452            if (isNaN(popup_width)) {
3453                popup_width = obj.getDefaultValue('popup_width');
3454            }
3455            if (popup_width < obj.popup_min_w) {
3456                popup_width = obj.popup_min_w;
3457            }
3458            popup_width = popup_width - obj.popup_padding;
3459
3460            var btns = ['like', 'dislike'];
3461
3462            for (btn in btns) {
3463                var addthis_toolbox = obj.q('#lb-'+btns[btn]+'-'+index+' .addthis_toolbox');
3464                if (obj.isDefined(addthis_toolbox[0]) && obj.hasClass(addthis_toolbox[0], 'addthis_toolbox')) {
3465                    addthis_toolbox[0].style.width = popup_width+'px';
3466                }
3467                var footer = obj.q('#lb-'+btns[btn]+'-'+index+' .lb-share-tt-ft');
3468                if (obj.isDefined(footer[0]) && obj.hasClass(footer[0], 'lb-share-tt-ft')) {
3469                    footer[0].style.minWidth = popup_width+'px';
3470                }
3471            }
3472        }
3473
3474        // hash
3475        // http://erlycoder.com/49/javascript-hash-functions-to-convert-string-into-integer-hash-
3476        /*obj.hashCode = function(str) {
3477            var hash = 0;
3478            if (!obj.isDefined(str) || typeof(str) != "string" || str.length == 0) {
3479                return hash;
3480            }
3481            for (i = 0; i < str.length; i++) {
3482                chr = str.charCodeAt(i);
3483                hash = ((hash<<5)-hash)+chr;
3484                //hash = Math.abs(hash);
3485                hash = hash & hash; // Convert to 32bit integer
3486                //hash = Math.abs(hash);
3487            }
3488            return hash;
3489        }*/
3490
3491        // Get hash using MD5
3492        obj.hashCodeMd5 = function(str) {
3493            var hash = obj.md5.md5(str);
3494            return hash.substr(0, 12);
3495        }
3496
3497        // trim string
3498        obj.trim = function(str) {
3499            str += '';
3500            return str.replace(/^\s+|\s+$/g, '');
3501        }
3502
3503        // in array
3504        obj.inArray = function(needle, haystack) {
3505            var length = haystack.length;
3506            for(var i = 0; i < length; i++) {
3507                if(haystack[i] == needle) return true;
3508            }
3509            return false;
3510        }
3511
3512        // Escape HTML entities
3513        obj.escapeHTML = function(string) {
3514            var pre = document.createElement('pre');
3515            var text = document.createTextNode(string);
3516            pre.appendChild(text);
3517            return pre.innerHTML;
3518        }
3519
3520        // Unescape HTML entities
3521        obj.unescapeHTML = function(string) {
3522            var e = document.createElement('div');
3523            e.innerHTML = string;
3524            return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
3525        }
3526
3527        // check if site plan is equal or higher
3528        obj.checkPlan = function(plan) {
3529            if (obj.plan >= plan) {
3530                return true;
3531            } else {
3532                return false;
3533            }
3534        }
3535
3536        // Get popup donate html
3537        obj.getPopupDonateHtml = function(donate_str, index) {
3538            var html = '';
3539            var donate_obj = null;
3540
3541            donate_str = obj.unescapeHTML(donate_str);
3542            donate_obj = obj.unserializeDonateStr(donate_str);
3543
3544            if (!donate_obj) {
3545                return;
3546            }
3547
3548            // Purpose is the page title by default
3549            var purpose = document.title;
3550            if (donate_obj.purpose) {
3551                purpose = donate_obj.purpose;
3552            } else if (obj.getParameter(index, "item_title")) {
3553                purpose = obj.getParameter(index, "item_title");
3554            }
3555
3556            for (var system in donate_obj.payment_systems) {
3557                html += obj.getPaymentSystemHtml(donate_obj.payment_systems[system], purpose);
3558                html += "&nbsp;";
3559            }
3560
3561            if (html) {
3562                html = '<div class="lb-donate-container">' + html + '</div>';
3563            }
3564
3565            return html;
3566        }
3567
3568        // Get Payment System HTML
3569        obj.getPaymentSystemHtml = function(system, purpose) {
3570            var html = '';
3571            var href = '';
3572            var amount = '';
3573            var amount_integer = parseInt(system.amount_integer);
3574            var amount_fractional = parseInt(system.amount_fractional);
3575
3576            // Prepare amount
3577            if (system.amount_integer || system.amount_fractional) {
3578                if (isNaN(amount_integer)) {
3579                    amount_integer = 0;
3580                }
3581                if (isNaN(amount_fractional)) {
3582                    amount_fractional = 0;
3583                }
3584                amount = amount_integer+'.'+amount_fractional;
3585            }
3586
3587            // Prepare purpose
3588            purpose = obj.replaceAll(/["&]/, '', purpose);
3589
3590            switch (system.system) {
3591                case "PayPal":
3592                    href = 'https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business='+escape(system.account)+'&item_name='+purpose+'&currency_code='+escape(system.currency)+'&amount='+escape(amount);
3593                    break;
3594
3595                case "Bitcoin":
3596                    href = 'bitcoin:'+escape(system.account)+'?label='+purpose;
3597                    break;
3598
3599                case "Google Wallet":
3600                    href = 'mailto:'+escape(system.account)+'?Subject='+purpose;
3601                    break;
3602
3603                case "Yandex.Money":
3604                    // https://money.yandex.ru/embed/quickpay/donate.xml
3605                    href = 'https://money.yandex.ru/quickpay/confirm.xml?quickpay-form=donate&receiver='+escape(system.account)+'&sum='+escape(amount)+'&targets='+purpose+'&payment-type-choice=on&mobile-payment-type-choice=on';
3606                    break;
3607
3608                case "WebMoney":
3609                    href = 'https://advisor.wmtransfer.com/Spasibo.aspx?url='+escape(system.account);
3610                    break;
3611
3612                case "Qiwi":
3613                    href = 'https://visa.qiwi.com/payment/transfer/form.action?extra[%27account%27]='+escape(system.account)+'&amountInteger='+escape(system.amount_integer)+'&amountFraction='+escape(system.amount_fractional)+'&extra[%27comment%27]='+purpose;
3614                    break;
3615
3616                case "SmsCoin":
3617                    var language_full = system.language;
3618                    if (system.language == 'en') {
3619                        language_full = 'english';
3620                        href = 'http://donate.smscoin.com/js/smsdonate/index_en.html';
3621                    } else {
3622                        if (language_full == 'ru') {
3623                            language_full = 'russian';
3624                        }
3625                        href = 'http://donate.smscoin.com/js/smsdonate/index.html';
3626                    }
3627                    href += '?sid='+escape(system.account)+'&language='+escape(language_full);
3628                    break;
3629
3630                case "Zaypay":
3631                    if (system.language) {
3632                        href = 'http://www.zaypay.com//'+escape(system.language)+'/pay/'+escape(system.account)+'/payments/new';
3633                    } else {
3634                        href = 'http://www.zaypay.com/pay/'+escape(system.account);
3635                    }
3636                    break;
3637            }
3638
3639            if (href) {
3640                var system_prepared = obj.replaceAll(/[^A-z0-9]/, '', system.system.toLowerCase());
3641                html += '<a href="'+href+'" target="_blank" class="lb-donate lb-donate-'+system_prepared+'"></a>';
3642                obj.loadAsset('/css/w/popup_donate.css?v=41', 'css');
3643            }
3644
3645            return html;
3646        }
3647
3648        // Unserizalize donate object from string
3649        obj.unserializeDonateStr = function(donate_str) {
3650
3651            var donate_obj = null;
3652            if (donate_str) {
3653                donate_obj = obj.JSON.decode(donate_str);
3654
3655                // Populate fields
3656                if (typeof(donate_obj.purpose) == "undefined") {
3657                    donate_obj.purpose = '';
3658                }
3659                if (typeof(donate_obj.payment_systems) == "undefined") {
3660                    donate_obj.payment_systems = [];
3661                }
3662                for (var system in donate_obj.payment_systems) {
3663                    if (typeof(donate_obj.payment_systems[system].system) == "undefined") {
3664                        donate_obj.payment_systems[system].system = '';
3665                    }
3666                    if (typeof(donate_obj.payment_systems[system].account) == "undefined") {
3667                        donate_obj.payment_systems[system].account = '';
3668                    }
3669                    if (typeof(donate_obj.payment_systems[system].amount_fractional) == "undefined") {
3670                        donate_obj.payment_systems[system].amount_fractional = '';
3671                    }
3672                    if (typeof(donate_obj.payment_systems[system].amount_integer) == "undefined") {
3673                        donate_obj.payment_systems[system].amount_integer = '';
3674                    }
3675                    if (typeof(donate_obj.payment_systems[system].currency) == "undefined") {
3676                        donate_obj.payment_systems[system].currency = '';
3677                    }
3678                    if (typeof(donate_obj.payment_systems[system].language) == "undefined") {
3679                        donate_obj.payment_systems[system].language = '';
3680                    }
3681                }
3682
3683                donate_obj = obj.escapeDonateObj(donate_obj);
3684            }
3685
3686            return donate_obj;
3687        }
3688
3689        // Escape donate object
3690        obj.escapeDonateObj = function(donate_obj, slash_quotes) {
3691            if (typeof(donate_obj) != "undefined") {
3692                // Replace quotes in the purpose
3693                if (typeof(slash_quotes) != "undefined" && slash_quotes) {
3694                    donate_obj.purpose = obj.replaceAll('"', '\\&quot;', donate_obj.purpose);
3695                } else {
3696                    donate_obj.purpose = obj.replaceAll('"', '&quot;', donate_obj.purpose);
3697                }
3698                donate_obj.purpose = obj.replaceAll(/&/, '', donate_obj.purpose);
3699
3700                // Remove quotes from other parameters
3701                // Payment systems may contain functions
3702                for (var system in donate_obj.payment_systems) {
3703                    if (isNaN(parseInt(system))) {
3704                        continue;
3705                    }
3706                    donate_obj.payment_systems[system].system = obj.replaceAll(/["&]/, '', donate_obj.payment_systems[system].system);
3707                    donate_obj.payment_systems[system].account = obj.replaceAll(/["&]/, '', donate_obj.payment_systems[system].account);
3708                    if (typeof(donate_obj.payment_systems[system].amount_fractional) != "undefined") {
3709                        donate_obj.payment_systems[system].amount_fractional = obj.replaceAll(/["&]/, '', donate_obj.payment_systems[system].amount_fractional);
3710                    }
3711                    if (typeof(donate_obj.payment_systems[system].amount_integer) != "undefined") {
3712                        donate_obj.payment_systems[system].amount_integer = obj.replaceAll(/["&]/, '', donate_obj.payment_systems[system].amount_integer);
3713                    }
3714                    if (typeof(donate_obj.payment_systems[system].currency) != "undefined") {
3715                        donate_obj.payment_systems[system].currency = obj.replaceAll(/["&]/, '', donate_obj.payment_systems[system].currency);
3716                    }
3717                    if (typeof(donate_obj.payment_systems[system].language) != "undefined") {
3718                        donate_obj.payment_systems[system].language = obj.replaceAll(/["&]/, '', donate_obj.payment_systems[system].language);
3719                    }
3720                }
3721            }
3722            return donate_obj;
3723        }
3724
3725        // Load asset
3726        obj.loadAsset = function(path, type) {
3727            obj.log("Loading asset: "+path);
3728            var d = window.document;
3729
3730            // Asset has already been loaded
3731            if (obj.inArray(path, obj.loaded_assets)) {
3732                return false;
3733            }
3734
3735            var asset_link = d.createElement('link');
3736            switch (type) {
3737                case "css":
3738                case "text/css":
3739                    asset_link.type = 'text/css';
3740                    asset_link.rel = 'stylesheet';
3741            }
3742
3743            asset_link.href = '//w.likebtn.com'+path+'?v=41';
3744            (d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(asset_link);
3745
3746            obj.loaded_assets.push(path);
3747
3748            return true;
3749        }
3750
3751        // Load style CSS
3752        // First bunch of styles is loaded in widget.css
3753        obj.loadStyle = function(style) {
3754
3755            // determine style index (starts from 1)
3756            var style_index = 1;
3757            for (var i=0; i<obj.styles.length; i++) {
3758                if (obj.styles[i] == style) {
3759                    //style_index = i + 1;
3760                    // there is a custom theme in he first file
3761                    style_index = i;
3762                    break;
3763                }
3764            }
3765            style_index++;
3766            var style_css_index = Math.ceil(style_index / obj.styles_per_css);
3767            /*if (typeof(obj.styles_css[style_css_index-2]) === "undefined") {
3768                obj.log("Could not determine CSS file index for the style: "+style);
3769                return false;
3770            }*/
3771
3772            // The first is already loaded
3773            if (style_css_index > 1) {
3774                var asset_url = obj.css_path+'style'+style_css_index+'.css';
3775                obj.loadAsset(asset_url, 'css');
3776            }
3777            return true;
3778        }
3779        
3780        // check if host is local
3781        obj.isDomainLocal = function(host) {
3782            if (obj.isDefined(host) && host.match(new RegExp("^[^" + obj.local_delimiter + "]+" + obj.local_delimiter + "[^" + obj.local_delimiter + "]+$"))) {
3783                return true;
3784            } else {
3785                return false;
3786            }
3787        }
3788
3789        // Extract host from local_domain parameter
3790        obj.extractHostFromLocalDomain = function(host) {
3791            return host.replace(new RegExp("^([^" + obj.local_delimiter + "]+)" + obj.local_delimiter + "[^" + obj.local_delimiter + "]+$"), "$1");
3792        }
3793
3794        // log
3795        obj.log = function (msg, object) {
3796            if (!obj.debug) {
3797                return;
3798            }
3799            window_obj.console && window_obj.console.log("LikeBtn: " + msg);
3800            if (typeof(object) != "undefined") {
3801                window_obj.console && window_obj.console.log(object);
3802            }
3803        }
3804
3805        // clone object
3806        obj.cloneObject = function (object) {
3807            if (object == null || typeof(object) != 'object') {
3808                return object;
3809            }
3810            var temp = object.constructor(); // changed
3811            for(var key in object) {
3812                temp[key] = obj.cloneObject(object[key]);
3813            }
3814            return temp;
3815        }
3816
3817        // show popup (for Like by default)
3818        obj.popupShow = function (index, type) {
3819
3820            var click_el;
3821            var a_el = [];
3822            var popup_el = [];
3823
3824            click_el_l = obj.q('#lb-like-'+index);
3825            click_el_d = obj.q('#lb-dislike-'+index);
3826
3827            if ((!obj.isDefined(type) || type == 1 || !click_el_d.length) && click_el_l.length) {
3828                // Like
3829                type = 1;
3830                click_el = click_el_l;
3831                a_el = obj.q('#lb-like-'+index+' .lb-a');
3832                popup_el = obj.q('#lb-like-'+index+' .lb-share-tt');
3833            } else {
3834                // Dislike
3835                type = -1;
3836                click_el = click_el_d;
3837                if (obj.getParameter(index, "popup_dislike")) {
3838                    a_el = obj.q('#lb-dislike-'+index+' .lb-a');
3839                    popup_el = obj.q('#lb-dislike-'+index+' .lb-share-tt');
3840                }
3841            }
3842
3843            // do not close popup on body click
3844            obj.dyn_settings.set(index, "no_popup_close", true);
3845
3846            // allow to close by outside click after dealy
3847            window.setTimeout(function() { obj.dyn_settings.set(index, "no_popup_close", false); }, obj.popup_close_delay);
3848
3849            if (popup_el && obj.isDefined(popup_el[0])) {
3850                // share HTML has been already added
3851                // add class
3852                click_el[0].className += " lb-share-active";
3853                obj.setCssProperty(popup_el[0], "display", "block");
3854            } else {
3855                // build popup
3856                if (a_el && obj.isDefined(a_el[0])) {
3857                    var popup_content = '<i class="lb-tt lb-share-tt" style="display: block !important"><i class="lb-tt-lt"></i><i class="lb-tt-rt"></i><i class="lb-tt-m2"></i><i class="lb-tt-m" style="display: block !important">';
3858                    var share_enabled = obj.getDefaultValue('share_enabled');
3859                    if (obj.checkPlan(obj.plans.PLUS)) {
3860                        share_enabled = obj.getParameter(index, "share_enabled");
3861                    }
3862                    var popup_share_html = '';
3863                    if (share_enabled) {
3864                        popup_share_html += '<div class="lb-popup-label lb-popup-label-share">'+obj.getLabel(index, "i18n_share_text", 'Would you like to share?')+'</div>';
3865                        // Share
3866                        var item_url = obj.getParameter(index, "item_url");
3867                        if (!item_url) {
3868                            if (obj.needDomainFromParent(index)) {
3869                                // Use parent URL
3870                                // Not working: referrer contains embedded URL
3871                                if (document.referrer) {
3872                                    item_url = document.referrer;
3873                                } else {
3874                                    item_url = window.location.href;
3875                                }
3876                            } else {
3877                                item_url = window.location.href;
3878                            }
3879                        }
3880                        var share_size = obj.getParameter(index, "share_size");
3881                        var addthis_size = '';
3882                        if (!share_size || share_size == 'small') {
3883                            // Do nothing
3884                            addthis_size = 'addthis_20x20_style a2a_kit_size_16';
3885                        } else if (share_size == 'medium') {
3886                            addthis_size = 'addthis_20x20_style a2a_kit_size_20';
3887                        } else if (share_size == 'large') {
3888                            addthis_size = 'addthis_32x32_style a2a_kit_size_32';
3889                        }
3890
3891                        popup_share_html += '<span class="a2a_kit a2a_default_style addthis_toolbox addthis_default_style '+addthis_size+'" data-a2a-url="'+item_url+'" ';
3892                        var item_title = obj.getParameter(index, "item_title");
3893                        if (item_title) {
3894                            popup_share_html += ' data-a2a-title="'+item_title+'" ';
3895                        }
3896                        var item_description = obj.getParameter(index, "item_description");
3897                        if (item_description) {
3898                            popup_share_html += ' addthis:description="'+item_description+'" ';
3899                        }
3900                        //var item_image = obj.getParameter(index, "item_description");
3901                        popup_share_html += '>';
3902
3903                        var custom_addthis_service_codes = obj.getParameter(index, "addthis_service_codes");
3904                        var addthis_service_codes = [];
3905                        if (obj.checkPlan(obj.plans.PRO) && custom_addthis_service_codes) {
3906                            // show customer defined buttons
3907                            addthis_service_codes = custom_addthis_service_codes.split(',');
3908                        } else {
3909                            // show predefiend buttons
3910                            if (obj.isDefined(obj.addthis_buttons[obj.dyn_settings.get(index, "locale")])) {
3911                                addthis_service_codes = obj.addthis_buttons[obj.dyn_settings.get(index, "locale")];
3912                            } else {
3913                                addthis_service_codes = obj.addthis_buttons['all'];
3914                            }
3915                        }
3916
3917                        var preferred = [...obj.addthis_preferred];
3918                        var services = {};
3919
3920                        for (var addthis_index in addthis_service_codes) {
3921                            if (addthis_index>=obj.share_buttons_count || isNaN(parseInt(addthis_index))) {
3922                                break;
3923                            }
3924                            var service = obj.trim(addthis_service_codes[addthis_index]);
3925                            if (typeof(obj.addthis_mapping[service]) != "undefined") {
3926                                service = obj.addthis_mapping[service];
3927                            }
3928                            if (service == 'compact') {
3929                                service = 'dd';
3930                            } else {
3931                                if (service.match(/^preferred_/)) {
3932                                    for (var preferred_i in preferred) {
3933                                        if (typeof(services[preferred[preferred_i]]) == "undefined") {
3934                                            service = preferred[preferred_i];
3935                                            preferred.splice(preferred_i, 1);
3936                                            break;
3937                                        }
3938                                    }
3939                                }
3940                                services[service] = 1;
3941                                service = 'button_'+service;
3942                            }
3943                            popup_share_html += '<a class="a2a_'+service+'"></a>';
3944                        }
3945                        popup_share_html += '</span>';
3946                    }
3947
3948                    // Popup Donate
3949                    var popup_donate = obj.getDefaultValue('popup_donate');
3950                    var popup_donate_html = '';
3951                    if (obj.checkPlan(obj.plans.VIP)) {
3952                        popup_donate = obj.getParameter(index, "popup_donate");
3953                        popup_donate_html = obj.getPopupDonateHtml(popup_donate, index);
3954                        if (popup_donate && !popup_donate_html) {
3955                            obj.log("Could not parse popup donate JSON:" + popup_donate);
3956                        }
3957                    }
3958
3959                    // Popup HTML
3960                    var popup_html = obj.getDefaultValue('popup_html');
3961                    if (obj.checkPlan(obj.plans.PRO)) {
3962                        popup_html = obj.getParameter(index, "popup_html");
3963                        popup_html = obj.replaceAll(/&quot;/, '"', popup_html);
3964                    }
3965
3966                    // Check the order
3967                    var popup_content_order = obj.getParameter(index, "popup_content_order") + "";
3968                    popup_content_order = obj.replaceAll(' ', '', popup_content_order);
3969                    var resulting_popup_content_order = popup_content_order.split(',');
3970
3971                    // Add missed elements to the custom order
3972                    for (default_popup_element_index in obj.deafault_popup_content_order) {
3973                        if (!obj.inArray(obj.deafault_popup_content_order[default_popup_element_index], resulting_popup_content_order)) {
3974                            resulting_popup_content_order.push(obj.deafault_popup_content_order[default_popup_element_index]);
3975                        }
3976                    }
3977
3978                    for (popup_element_index in resulting_popup_content_order) {
3979                        switch (resulting_popup_content_order[popup_element_index]) {
3980                            case "popup_share":
3981                                if (popup_share_html) {
3982                                    popup_content += popup_share_html;
3983                                }
3984                                break;
3985                            case "popup_donate":
3986                                if (popup_donate_html) {
3987                                    popup_content += '<div class="lb-popup-label lb-popup-label-donate">'+obj.getLabel(index, "i18n_popup_donate", 'Show gratitude in the form of a donation')+'</div>';
3988                                    popup_content += popup_donate_html;
3989                                }
3990                                break;
3991                            case "popup_html":
3992                                if (popup_html) {
3993                                    popup_content += popup_html;
3994                                }
3995                                break;
3996                        }
3997                    }
3998
3999                    // There is no content in the popup
4000                    if (!share_enabled && !popup_html && !popup_donate_html) {
4001                        popup_content += '<span class="lb-share-tt-popup_text">';
4002                        if (obj.getParameter(index, "i18n_popup_text")) {
4003                            popup_content += obj.getParameter(index, "i18n_popup_text");
4004                        } else {
4005                            if (typeof(obj.translations[obj.dyn_settings.get(index, "locale")]) != "undefined") {
4006                                popup_content += obj.translations[obj.dyn_settings.get(index, "locale")]["i18n_popup_text"];
4007                            } else {
4008                                popup_content += 'Glad you liked it!';
4009                            }
4010                        }
4011                        popup_content += '</span>';
4012                    }
4013                    popup_content += '<i class="lb-share-tt-ft"><a class="lb-share-tt-tm" href="//likebtn.com" target="_blank" style="display: inline !important">&copy; LikeBtn.com</a>';
4014                    popup_content += '<i class="lb-share-tt-cl" onclick="LikeBtn.popupHide(event, '+index+'); return false;">';
4015
4016                    if (obj.getParameter(index, "i18n_popup_close")) {
4017                        popup_content += obj.getParameter(index, "i18n_popup_close");
4018                    } else {
4019                        if (typeof(obj.translations[obj.dyn_settings.get(index, "locale")]) != "undefined") {
4020                            popup_content += obj.translations[obj.dyn_settings.get(index, "locale")]["i18n_popup_close"];
4021                        } else {
4022                            popup_content += 'Close';
4023                        }
4024                    }
4025                    popup_content += ' X';
4026                    popup_content += '</i></i>';
4027                    popup_content += '</i><i class="lb-tt-lb"></i><i class="lb-tt-rb"></i><i class="lb-tt-a"></i></i>';
4028
4029                    a_el[0].innerHTML = popup_content + a_el[0].innerHTML;
4030
4031                    // Run scripts
4032                    if (popup_html) {
4033                        obj.stripAndExecuteScript(popup_html);
4034                    }
4035
4036                    // show copyright
4037                    var cr_el = [];
4038                    if (type == 1) {
4039                        // click on Like
4040                        cr_el = obj.q('#lb-like-'+index+' .lb-share-tt-tm');
4041                    } else {
4042                        // click on Dislike
4043                        if (obj.getParameter(index, "popup_dislike")) {
4044                            cr_el = obj.q('#lb-dislike-'+index+' .lb-share-tt-tm');
4045                        }
4046                    }
4047                    if (obj.isDefined(cr_el[0])) {
4048                        if (obj.checkPlan(obj.plans.VIP) && obj.getParameter(index, 'white_label')) {
4049                            // hide copyright
4050                            obj.setCssProperty(cr_el[0], "left", "-1000px");
4051                        } else {
4052                            // show copyright
4053                            if (obj.getParameter(index, 'popup_style') == 'dar
4053k') {
4054                                obj.setCssProperty(cr_el[0], "color", "#f9f6f6");
4055                            } else {
4056                                obj.setCssProperty(cr_el[0], "color", "#787869");
4057                            }
4058                            obj.setCssProperty(cr_el[0], "padding", "0");
4059                            obj.setCssProperty(cr_el[0], "margin", "0");
4060                            obj.setCssProperty(cr_el[0], "text-indent", "0");
4061                            obj.setCssProperty(cr_el[0], "left", "1px");
4062                            obj.setCssProperty(cr_el[0], "top", "1px");
4063                            obj.setCssProperty(cr_el[0], "border", "0");
4064                            obj.setCssProperty(cr_el[0], "font-size", "9px");
4065                        }
4066                    }
4067
4068                    // addthis
4069                    if (typeof(a2a) == "undefined" && !obj.addthis_loaded) {
4070
4071                        if (obj.checkPlan(obj.plans.PRO)) {
4072                            var addthis_pubid = obj.getParameter(index, "addthis_pubid");
4073                        } else {
4074                            var addthis_pubid = obj.getDefaultValue('addthis_pubid');
4075                        }
4076
4077                        var addthis_s = document.createElement('script'); addthis_s.type = 'text/javascript'; addthis_s.async = true;
4078                        addthis_s.src = 'https://static.addtoany.com/menu/page.js';
4079                        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(addthis_s);
4080                    } else {
4081                        // Does not work for specific element.
4082                        a2a.init('page');
4083                        // if (type == 1) {
4084                        //     var at_el = obj.q('#lb-like-'+index+' .addthis_toolbox');
4085                        // } else {
4086                        //     var at_el = obj.q('#lb-dislike-'+index+' .addthis_toolbox');
4087                        // }
4088                        // if (obj.isDefined(at_el[0]) && typeof(addthis) != "undefined") {
4089                        //     //addthis.toolbox(at_el[0]);
4090                        //     a2a.init('page', {
4091                        //         target: at_el[0]
4092                        //         // Additional instance configs can be set here
4093                        //     });
4094                        // }
4095                    }
4096                    obj.addthis_loaded = true;
4097
4098                    // add class
4099                    click_el[0].className += " lb-share-active";
4100
4101                    // get popup el
4102                    popup_el[0] = a_el[0].firstChild;
4103                }
4104                obj.setPopupWidth(index);
4105                obj.setPopupAndTooltipsPosition(index);
4106
4107                // do not close popup on click on it
4108                /*if (popup_el && obj.isDefined(popup_el[0])) {
4109                    obj.addEventListener(el_popup[0], 'click', obj.stopPropagation);
4110                }*/
4111
4112                obj.triggerEvent(obj.event_types.popupopen, index);
4113            }
4114            obj.adjustPopupPosition(index);
4115
4116            if (obj.getParameter(index, "ef_voting") && popup_el[0]) {
4117                obj.setCssProperty(popup_el[0], "display", "none");
4118                window.setTimeout(function() { obj.setCssProperty(popup_el[0], "display", "block"); }, obj.ef_time);
4119            }
4120        }
4121
4122        // hide popup
4123        obj.popupHide = function (event, index) {
4124            var el = obj.q('#lb-like-'+index+'.lb-share-active');
4125            var clicked_el_id;
4126            // check if Like or Dislike share active now
4127            if (typeof(el[0]) != "undefined") {
4128                clicked_el_id = 'lb-like';
4129            } else {
4130                clicked_el_id = 'lb-dislike';
4131                el = obj.q('#lb-dislike-'+index+'.lb-share-active');
4132            }
4133            if (typeof(el[0]) != "undefined") {
4134                el[0].className = el[0].className.replace(/\blb\-share\-active\b/, '');
4135                obj.triggerEvent(obj.event_types.popupclose, index);
4136            }
4137            var share_el = obj.q('#'+clicked_el_id+'-'+index+' .lb-share-tt');
4138            if (typeof(share_el[0]) != "undefined") {
4139                obj.setCssProperty(share_el[0], "display", "none");
4140            }
4141            // to avoid firing Vote()
4142            // BuddyPress Activity Plus does not add images in Chrome
4143            // If event is set the Close button has been clicked
4144            if (event) {
4145                obj.stopPropagation(event);
4146            }
4147        }
4148
4149        // Show information message instead of the button
4150        obj.infoMessage = function (index, wrapper, message) {
4151            if (obj.getParameter(index, "info_message")) {
4152                
4153                var anchor = 'Like Button Notice';
4154                var url = 'https://likebtn.com';
4155                var engine = obj.getParameter(index, "engine");
4156
4157                if (engine && engine.toLowerCase() == 'wordpress') {
4158                    //anchor = 'Like Button notice';
4159                    url = 'https://likebtn.com/en/wordpress-like-button-plugin';
4160                    message += '. To remove such notices uncheck Show Info Notices chekbox on plugin Settings tab.'
4161                }
4162                var message_escaped = obj.escapeHTML(message.replace(/<\/?[^>]+(>|$)/g, "").replace(/"/g, "'"));
4163                var html = '<a href="'+url+'" class="likebtn-im" title="'+message_escaped+'">'+anchor+'</a> (';
4164                // if (obj.getParameter(index, "info_message")) {
4165                //     html += message_escaped;
4166                // } else {
4167                html += '<a href="javascript:void(0);" onclick="this.outerHTML=LikeBtn.Base64.decode(\''+obj.Base64.encode(message)+'\');" class="likebtn-im" title="Click to view notice">view</a>';
4168                //}
4169                html += ')';
4170                wrapper.innerHTML = html;
4171                wrapper.style.whiteSpace = "normal";
4172            }
4173            
4174            obj.setLoaded(index, wrapper);
4175        }
4176
4177        
4178        // set cookie
4179        obj.setCookie = function (name, value, props) {
4180            props = props || {}
4181            var exp = props.expires
4182            if (typeof exp == "number" && exp) {
4183                var d = new Date()
4184                d.setTime(d.getTime() + exp*1000)
4185                exp = props.expires = d
4186            }
4187            if (exp && exp.toUTCString) { props.expires = exp.toUTCString() }
4188
4189            value = encodeURIComponent(value)
4190            var updatedCookie = name + "=" + value
4191            for (var propName in props) {
4192                updatedCookie += "; " + propName
4193                var propValue = props[propName]
4194                if(propValue !== true){ updatedCookie += "=" + propValue }
4195            }
4196
4197            document.cookie = updatedCookie;
4198        }
4199
4200        // set cookie
4201        obj.getCookie = function (name) {
4202            var matches = document.cookie.match(new RegExp(
4203                "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
4204            ));
4205            return matches ? decodeURIComponent(matches[1]) : undefined
4206        }
4207
4208        // remove cookie
4209        obj.removeCookie = function (name) {
4210            // expiration date in the past
4211            var exp_date = new Date();
4212            exp_date.setSeconds(exp_date.getSeconds() - 3600);
4213
4214            obj.setCookie(name, "", {expires:exp_date, path:"/"});
4215        }
4216
4217        // set data using localStorage or cookie
4218        obj.setData = function (name, value, props, eternal) {
4219            if (obj.supportsLocalStorage()) {
4220                // use localStorage
4221                props = props || {}
4222                // Does not expire by default
4223                var expires = 0;
4224                if (!eternal) {
4225                    if (obj.isDefined(props.expires) && props.expires) {
4226                        if (typeof(props.expires) == "number") {
4227                            // Millisecond from now
4228                            var d = new Date();
4229                            expires = d.getTime() + props.expires*1000;
4230                        } else if (typeof(props.expires) == "object" && props.expires.getTime()) {
4231                            expires = Math.round(props.expires.getTime() / 1000);
4232                        }
4233                    }
4234                }
4235                data = {
4236                    v: value,
4237                    e: expires
4238                };
4239                localStorage.setItem(name, obj.JSON.encode(data));
4240
4241                // remove data from cookie
4242                if (obj.isDefined(obj.getCookie(name))) {
4243                    obj.removeCookie(name);
4244                }
4245            } else {
4246                // use cookie
4247                obj.setCookie(name, value, props);
4248            }
4249        }
4250
4251        // get data using localStorage or cookie
4252        obj.getData = function (name) {
4253            if (obj.supportsLocalStorage()) {
4254                // use localStorage
4255                data = localStorage.getItem(name);
4256                if (!data) {
4257                    // if item NOT found in localStorage, check cookie
4258                    return obj.getCookie(name);
4259                } else {
4260                    // if item found in localStorage, remove data from cookie
4261                    if (obj.isDefined(obj.getCookie(name))) {
4262                        obj.removeCookie(name);
4263                    }
4264                }
4265
4266                data = obj.JSON.decode(data);
4267
4268                // Check expiration time
4269                if (obj.isDefined(data.e) && data.e && !isNaN(parseInt(data.e))) {
4270                    var d = new Date();
4271                    if (d.getTime() > parseInt(data.e)*1000) {
4272                        obj.removeData(name);
4273                        return undefined;
4274                    }
4275                }
4276
4277                // return data
4278                if (obj.isDefined(data.v)) {
4279                    return data.v;
4280                } else {
4281                    return undefined;
4282                }
4283            } else {
4284                // use cookie
4285                return obj.getCookie(name);
4286            }
4287        }
4288
4289        // remove data using localStorage or cookie
4290        obj.removeData = function (name) {
4291            // remove from localStorage
4292            if (obj.supportsLocalStorage()) {
4293                localStorage.removeItem(name);
4294            }
4295
4296            // remove cookie
4297            if (obj.isDefined(obj.getCookie(name))) {
4298                obj.removeCookie(name);
4299            }
4300        }
4301
4302        // Set CSS propery
4303        obj.setCssProperty = function (el, name, value, priority) {
4304            if (!priority) {
4305                priority = "important";
4306            }
4307            if (el && el.style) {
4308                if (el.style.setProperty) {
4309                    el.style.setProperty(name, value, priority);
4310                } else {
4311                    // Old way without priority
4312                    el.style[name] = value;
4313                }
4314            }
4315        }
4316
4317        // check if browser supports localStorage
4318        obj.supportsLocalStorage = function () {
4319            try {
4320                return 'localStorage' in window && window['localStorage'] !== null;
4321            } catch (e) {
4322                return false;
4323            }
4324        }
4325
4326        // has class
4327        obj.hasClass = function (el, cls) {
4328            if (!el.className || typeof(el.className.match) != "function") {
4329                return false;
4330            }
4331            return el.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
4332        }
4333
4334        // remove class
4335        obj.removeClass = function (el, cls) {
4336            var regexp = new RegExp(cls.replace(/-/, '\-'));
4337            el.className = obj.replaceAll(regexp, '', el.className);
4338        }
4339
4340        // get domain from the given URL
4341        obj.getDomainFromUrl = function (url) {
4342            if (!url) {
4343                return '';
4344            }
4345            var a = document.createElement('a');
4346            a.href = url;
4347            return a.hostname;
4348        }
4349
4350        // get domain from the given URL
4351        obj.getPathFromUrl = function (url) {
4352            if (!url) {
4353                return '';
4354            }
4355            var a = document.createElement('a');
4356            a.href = url;
4357
4358            return a.pathname;
4359        }
4360
4361        // get domain from the given URL
4362        obj.normalizeSubdirectory = function (path) {
4363            if (!path) {
4364                return '';
4365            }
4366            // Add slash at the beginning
4367            if (!/^\//.test(path)) {
4368                path = "/" + path;
4369            }
4370            // Add slash at the end
4371            if (!/\/$/.test(path)) {
4372                path = path + "/";
4373            }
4374            // Remove duplicated slashes
4375            path = obj.replaceAll(/\/\//, '/', path);
4376
4377            return path;
4378        }
4379
4380        // normalize host name
4381        obj.normalizeHost = function (host) {
4382            // Remove protocol
4383            host = obj.replaceAll(/https?:\/\//, '', host);
4384
4385            // Remove slash at the end if no subdirectory
4386            if (!/\/.+/.test(host)) {
4387                host = obj.replaceAll(/[\/]+$/, '', host);
4388            } else {
4389                // Add slash at the end if subdirectory
4390                if (!/\/$/.test(host)) {
4391                    host = host + "/";
4392                }
4393            }
4394
4395            // Host to Unicode
4396            host = obj.punycode.ToUnicode(host);
4397
4398            // Remove duplicated slashes
4399            host = obj.replaceAll(/\/\//, '/', host);
4400
4401            // Remove slash at the beginning
4402            host = obj.replaceAll(/^\//, '', host);
4403
4404            // Remove underscores (appears from tab)
4405            host = obj.replaceAll(/_/, '', host);
4406
4407            // Remove everything after space
4408            host = obj.replaceAll(/ .*/, '', host);
4409
4410            return host;
4411        }
4412
4413        // show/hide
4414        obj.getPlanName = function (plan_id) {
4415            for (plan_name in obj.plans) {
4416                if (plan_id == obj.plans[plan_name]) {
4417                    return plan_name;
4418                }
4419            }
4420            return undefined;
4421        }
4422
4423        // check if variable passed is defined
4424        obj.isDefined = function (variable) {
4425            if (typeof(variable) != "undefined") {
4426                return true;
4427            } else {
4428                return false;
4429            }
4430        }
4431
4432        // replace all
4433        obj.replaceAll = function(search, replace, str){
4434            if (typeof(str) != "string") {
4435                return str;
4436            }
4437            return str.split(search).join(replace);
4438        }
4439
4440        // Escape a string for using in regexp
4441        obj.regexpQuote = function(str){
4442            return (str+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
4443        }
4444
4445        // trigger an event
4446        obj.triggerEvent = function(event_type, index, data){
4447
4448            var event_handler = obj.getParameter(index, "event_handler");
4449            var callback;
4450            var event = {
4451                "type": "",
4452                "settings": {},
4453                "wrapper": null
4454            };
4455
4456            if (!obj.isDefined(event_handler) || !event_handler) {
4457                return false;
4458            }
4459            var callback = window[event_handler];
4460            if (typeof(callback) !== 'function') {
4461                return false;
4462            }
4463
4464            // populate event
4465            event.type = event_type;
4466            if (obj.isDefined(obj.settings.values[index])) {
4467                event.settings = obj.settings.values[index];
4468            }
4469            event.wrapper = obj.dyn_settings.get(index, "wrapper");
4470            if (data) {
4471                event.data = data;
4472            }
4473
4474            try {
4475                callback(event);
4476            } catch(e) {
4477                obj.log("Error occured in event handler function '" + event_handler + "': " + e.message);
4478            }
4479        }
4480
4481        // body click handler
4482        obj.onBodyClick = function(event) {
4483
4484            event = event || window.event;
4485                        // Do nothing if click on popup or its children
4486            if (event && event.target) {
4487                var target = event.target;
4488                if (obj.hasClass(target, 'lb-tt-m')) {
4489                    return;
4490                }
4491                var parents = obj.getParents(target);
4492                for (var p_index in parents) {
4493                    if (obj.hasClass(parents[p_index], 'lb-tt-m')) {
4494                        return;
4495                    }
4496                }
4497            }
4498
4499            // close all popups
4500            obj.closeAllPopups();
4501        }
4502
4503        // close all popups
4504        obj.closeAllPopups = function(index_exclude) {
4505            for (index = 0; index < obj.dyn_settings.values.length; index++) {
4506                if (index == index_exclude) {
4507                    continue;
4508                }
4509                if (!obj.dyn_settings.get(index, "no_popup_close") && obj.getParameter(index, "popup_hide_on_outside_click")) {
4510                    obj.popupHide(null, index);
4511                }
4512            }
4513        }
4514
4515        // window scroll handler
4516        obj.onWindowScroll = function() {
4517
4518            // lazy loading of buttons
4519            for (var index in obj.settings.values) {
4520                if (obj.getParameter(index, "counter_count")
4521                    && !obj.dyn_settings.get(index, "counted")
4522                    && obj.isVisible(index)
4523                ) {
4524
4525                    obj.counterCount(index);
4526                }
4527                if (obj.getParameter(index, "lazy_load")
4528                    && !obj.dyn_settings.get(index, "loaded")
4529                    && obj.isVisible(index)
4530                ) {
4531                    obj.buttonShow(index);
4532                    //obj.load(index);
4533                }
4534            }
4535        }
4536
4537        // is element visible
4538        obj.isVisible = function(index) {
4539
4540            var doc = document.documentElement;
4541            var body = doc.getElementsByTagName('body')[0];
4542
4543            
4544            var wrapper = obj.dyn_settings.get(index, "wrapper");
4545
4546            if (!obj.isDefined(wrapper)) {
4547                return false;
4548            }
4549
4550            var scroll_top = typeof(window.pageYOffset) != "undefined" ? window.pageYOffset : doc.scrollTop ? doc.scrollTop : document.body.scrollTop ? document.body.scrollTop : NaN;
4551            if (isNaN(parseInt(scroll_top))) {
4552                return true;
4553            }
4554            var viewport_top = scroll_top - (doc.clientTop || 0);
4555            
4556            var el_top = obj.getElementTop(wrapper);
4557
4558            viewport_height = window.innerHeight || doc.clientHeight || body.clientHeight;
4559
4560            if (el_top > viewport_top && el_top < (viewport_top + viewport_height)) {
4561                return true;
4562            } else {
4563                return false;
4564            }
4565        }
4566
4567        // Check if element has specified parent
4568        obj.getParents = function(a) {
4569            var parents = [];
4570            while (a) {
4571                parents.unshift(a);
4572                a = a.parentNode;
4573            }
4574            return parents;           
4575        }
4576
4577        // Apply like button to the wrapper
4578        obj.apply = function(wrapper, properties, keep_properties) {
4579            if (typeof(wrapper) !== "object") {
4580                obj.log("Wrong wrapper");
4581                return false;
4582            }
4583
4584            properties = properties || {};
4585            keep_properties = keep_properties || [];
4586
4587            // Remove unmodifiable properties
4588            for (var property_name in obj.settings.schema) {
4589                if (typeof(obj.settings.schema[property_name].nonmodifiable) != "undefined" 
4590                    && typeof(properties[property_name]) != "undefined") {
4591                    delete properties[property_name];
4592                }
4593            }
4594
4595            obj.clean(wrapper, keep_properties);
4596            obj.setProperties(wrapper, properties);
4597
4598            // add likebtn class
4599            if (wrapper.className.indexOf("likebtn-wrapper") == -1) {
4600                wrapper.className += " likebtn-wrapper";
4601            }
4602
4603            obj.init();
4604        }
4605
4606        // Execute scripts
4607        obj.stripAndExecuteScript = function(text) {
4608            var dummy = document.createElement('div');
4609            dummy.innerHTML = text;
4610            var scripts = dummy.getElementsByTagName("script");
4611            for (var i = 0; i < scripts.length; i++) {
4612                if (scripts[i].src != "") {
4613                    var tag = document.createElement("script");
4614                    tag.src = scripts[i].src;
4615                    document.getElementsByTagName("head")[0].appendChild(tag);
4616                } else {
4617                    eval(scripts[i].innerHTML);
4618                }
4619            }
4620            /*var scripts = '';
4621            var cleaned = text.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
4622                scripts += arguments[1] + '\n';
4623                return '';
4624            });
4625
4626            //if (window.execScript){
4627            //    window.execScript(scripts);
4628            //} else {
4629            var head = document.getElementsByTagName('head')[0];
4630            var scriptElement = document.createElement('script');
4631            scriptElement.setAttribute('type', 'text/javascript');
4632            scriptElement.text = scripts;
4633            head.appendChild(scriptElement);
4634            head.removeChild(scriptElement);
4635            //}
4636            return cleaned;*/
4637        };
4638
4639        // Set properties for the specified button
4640        obj.setProperties = function(wrapper, properties) {
4641            // remove attrs
4642            for (property in properties) {
4643                wrapper.setAttribute('data-'+property, properties[property]);
4644            }
4645        }
4646
4647        // Clean button wrapper
4648        obj.clean = function(wrapper, keep_properties) {
4649            keep_properties = keep_properties || [];
4650
4651            if (!wrapper) {
4652                return false;
4653            }
4654            // remove attrs
4655            for (property in obj.settings.schema) {
4656                if (obj.inArray(property, keep_properties)) {
4657                    continue;
4658                }
4659                wrapper.removeAttribute('data-'+property);
4660            }
4661            // remove lb- classes
4662            var classes = wrapper.className.split(' ');
4663            var new_class = '';
4664            for (i in classes) {
4665                if (!/^lb\-/.test(classes[i])) {
4666                    new_class += ' '+classes[i];
4667                }
4668            }
4669            wrapper.className = new_class;
4670
4671            while (wrapper.hasChildNodes()) {
4672                wrapper.removeChild(wrapper.firstChild);
4673            }
4674        }
4675
4676        // Get hash of all the identifier of the button
4677        obj.getIdsHash = function(identifier, group_identifier, site_id) {
4678            return obj.hashCodeMd5((identifier || '')+(group_identifier || '')+(site_id || ''));
4679        }
4680
4681        
4682        // get element top
4683        obj.getElementTop = function(el) {
4684            if ( !el.getClientRects().length ) {
4685                return 0;
4686            }
4687
4688            rect = el.getBoundingClientRect();
4689            win = el.ownerDocument.defaultView;
4690            return rect.top + win.pageYOffset;
4691
4692            /*var top = el.offsetTop;
4693            while (el=el.offsetParent) {
4694                top += el.offsetTop;
4695            }
4696            return top;*/
4697        }
4698
4699        // get element left
4700        obj.getElementLeft = function(el) {
4701            if ( !el.getClientRects().length ) {
4702                return 0;
4703            }
4704
4705            rect = el.getBoundingClientRect();
4706            win = el.ownerDocument.defaultView;
4707            return rect.left + win.pageXOffset;
4708        }
4709
4710        // crossbrowser addEventListener
4711        obj.addEventListener = function(object, type, listener) {
4712            // check if already registered
4713            if (obj.inArray(obj.encodeEventListener(object, type, listener), obj.event_listeners)) {
4714                return false;
4715            }
4716
4717            if (typeof(object.addEventListener) === 'function') {
4718                object.addEventListener(type, listener); // DOM 3
4719            } else {
4720                object.attachEvent('on'+type, listener); // IE
4721            }
4722            obj.rememberEventListener(object, type, listener);
4723        }
4724
4725        // crossbrowser addEventListener
4726        obj.rememberEventListener = function(object, type, listener) {
4727            var event_listener = obj.encodeEventListener(object, type, listener);
4728            if (!obj.inArray(event_listener, obj.event_listeners)) {
4729                obj.event_listeners.push(event_listener);
4730            }
4731        }
4732
4733        // crossbrowser addEventListener
4734        obj.encodeEventListener = function(object, type, listener) {
4735            return object.name + type + listener.name;
4736        }
4737
4738        // corssbrowser stopPropagation
4739        obj.stopPropagation = function(event) {
4740            event = event || window.event;
4741            try {
4742                if (typeof(event) != "undefined" && event) {
4743                    if (typeof(event.stopPropagation) != "undefined") {
4744                        event.stopPropagation();   // W3C model
4745                    } else {
4746                        event.cancelBubble = true; // IE model
4747                    }
4748                }
4749            } catch (e) {}
4750        }
4751
4752        // try to guess used engine
4753        obj.guessEngine = function() {
4754            
4755            var generator_el = obj.q("meta[name='generator']");
4756            var generator = '';
4757            if (obj.isDefined(generator_el[0])) {
4758                generator = generator_el[0].getAttribute('content');
4759            }
4760
4761            // Blogger
4762            if (generator == 'blogger') {
4763                return 'blogger';
4764            }
4765
4766            // Weebly
4767            if (typeof(Weebly) !== "undefined") {
4768                return 'weebly';
4769            }
4770
4771            // uCoz
4772            if (typeof(ucoz_server) !== "undefined") {
4773                return 'ucoz';
4774            }
4775
4776            // Tumblr
4777            if (typeof(Tumblr) !== "undefined") {
4778                return 'tumblr';
4779            }
4780
4781            // vBulletin
4782            if (generator.match(new RegExp('^vBulletin'))) {
4783                return 'vbulletin';
4784            }
4785
4786            // Extra
4787             
4788            // DLE
4789            if (generator.match(new RegExp('^DataLife'))) {
4790                return 'dle';
4791            }
4792            // Jimdo
4793            if (typeof(jimdoData) !== "undefined") {
4794                return 'jimdo';
4795            }
4796            // Squarespace
4797            if (typeof(SQUARESPACE_ROLLUPS) !== "undefined") {
4798                return 'squarespace';
4799            }
4800
4801            return '';
4802        }
4803
4804        // http://www.sitepoint.com/javascript-json-serialization/
4805        obj.JSON = {};
4806        // encode JSON
4807        obj.JSON.encode = function (enc_obj) {
4808            var t = typeof (enc_obj);
4809            if (t != "object" || enc_obj === null) {
4810                // simple data type
4811                if (t == "string") {
4812                    enc_obj = obj.JSON.escape(enc_obj);
4813                    enc_obj = '"'+enc_obj+'"';
4814                }
4815                return String(enc_obj);
4816            } else {
4817                // recurse array or object
4818                var n, v, json = [], arr = (enc_obj && enc_obj.constructor == Array);
4819                for (n in enc_obj) {
4820                    v = enc_obj[n];
4821                    t = typeof(v);
4822                    if (t == "function") {
4823                        continue;
4824                    }
4825                    if (t == "string") {
4826                        v = obj.JSON.escape(v);
4827                        v = '"'+v+'"';
4828                    } else if (t == "object" && v !== null) {
4829                        v = obj.JSON.encode(v);
4830                    }
4831                    json.push((arr ? "" : '"' + n + '":') + String(v));
4832                }
4833                return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
4834            }
4835        };
4836
4837        // query single element
4838        obj.q1 = function (selector) {
4839            var els = obj.q(selector);
4840            if (els[0]) {
4841                return els[0];
4842            } else {
4843                return null;
4844            }
4845        }
4846
4847        // escape JSON value
4848        obj.JSON.escape = function (json_value) {
4849            return json_value.replace(/\\/g, "\\\\")
4850                             .replace(/\n/g, "\\n")
4851                             .replace(/"/g, "\\\"")
4852                             .replace(/\r/g, "\\r")
4853                             .replace(/\t/g, "\\t")
4854                             //.replace(/\b/g, "\\b")
4855                             .replace(/\f/g, "\\f");
4856        };
4857        // decode JSON
4858        obj.JSON.decode = function (str_json) {
4859            var dec_obj = {};
4860            try {
4861                dec_obj = window["eval"]("(function(){return " + str_json + ";})()");
4862            } catch(e) {}
4863            return dec_obj;
4864        }
4865
4866        // base 64
4867        // http://md5x.ru/a/Realizaciy_Base64_na_Javascript.html
4868        obj.Base64 = {_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
4868+/=",encode:function(c){var a="";var k,h,f,j,g,e,d;var b=0;c=obj.Base64._utf8_encode(c);while(b<c.length){k=c.charCodeAt(b++);h=c.charCodeAt(b++);f=c.charCodeAt(b++);j=k>>2;g=((k&3)<<4)|(h>>4);e=((h&15)<<2)|(f>>6);d=f&63;if(isNaN(h)){e=d=64}else{if(isNaN(f)){d=64}}a=a+this._keyStr.charAt(j)+this._keyStr.charAt(g)+this._keyStr.charAt(e)+this._keyStr.charAt(d)}return a},decode:function(c){var a="";var k,h,f;var j,g,e,d;var b=0;c=c.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(b<c.length){j=this._keyStr.indexOf(c.charAt(b++));g=this._keyStr.indexOf(c.charAt(b++));e=this._keyStr.indexOf(c.charAt(b++));d=this._keyStr.indexOf(c.charAt(b++));k=(j<<2)|(g>>4);h=((g&15)<<4)|(e>>2);f=((e&3)<<6)|d;a=a+String.fromCharCode(k);if(e!=64){a=a+String.fromCharCode(h)}if(d!=64){a=a+String.fromCharCode(f)}}a=obj.Base64._utf8_decode(a);return a},_utf8_encode:function(b){b=b.replace(/\r\n/g,"\n");var a="";for(var e=0;e<b.length;e++){var d=b.charCodeAt(e);if(d<128){a+=String.fromCharCode(d)}else{if((d>127)&&(d<2048)){a+=String.fromCharCode((d>>6)|192);a+=String.fromCharCode((d&63)|128)}else{a+=String.fromCharCode((d>>12)|224);a+=String.fromCharCode(((d>>6)&63)|128);a+=String.fromCharCode((d&63)|128)}}}return a},_utf8_decode:function(a){var b="";var d=0;var e=c1=c2=0;while(d<a.length){e=a.charCodeAt(d);if(e<128){b+=String.fromCharCode(e);d++}else{if((e>191)&&(e<224)){c2=a.charCodeAt(d+1);b+=String.fromCharCode(((e&31)<<6)|(c2&63));d+=2}else{c2=a.charCodeAt(d+1);c3=a.charCodeAt(d+2);b+=String.fromCharCode(((e&15)<<12)|((c2&63)<<6)|(c3&63));d+=3}}}return b}};
4869
4870        // MD5
4871        // https://github.com/blueimp/JavaScript-MD5
4872        obj.md5 = new function md5() {
4873            /*
4874            * Add integers, wrapping at 2^32. This uses 16-bit operations internally
4875            * to work around bugs in some JS interpreters.
4876            */
4877            function safe_add(x, y) {
4878                var lsw = (x & 0xFFFF) + (y & 0xFFFF),
4879                    msw = (x >> 16) + (y >> 16) + (lsw >> 16);
4880                return (msw << 16) | (lsw & 0xFFFF);
4881            }
4882
4883            /*
4884            * Bitwise rotate a 32-bit number to the left.
4885            */
4886            function bit_rol(num, cnt) {
4887                return (num << cnt) | (num >>> (32 - cnt));
4888            }
4889
4890            /*
4891            * These functions implement the four basic operations the algorithm uses.
4892            */
4893            function md5_cmn(q, a, b, x, s, t) {
4894                return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
4895            }
4896            function md5_ff(a, b, c, d, x, s, t) {
4897                return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
4898            }
4899            function md5_gg(a, b, c, d, x, s, t) {
4900                return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
4901            }
4902            function md5_hh(a, b, c, d, x, s, t) {
4903                return md5_cmn(b ^ c ^ d, a, b, x, s, t);
4904            }
4905            function md5_ii(a, b, c, d, x, s, t) {
4906                return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
4907            }
4908
4909            /*
4910            * Calculate the MD5 of an array of little-endian words, and a bit length.
4911            */
4912            function binl_md5(x, len) {
4913                /* append padding */
4914                x[len >> 5] |= 0x80 << (len % 32);
4915                x[(((len + 64) >>> 9) << 4) + 14] = len;
4916
4917                var i, olda, oldb, oldc, oldd,
4918                    a =  1732584193,
4919                    b = -271733879,
4920                    c = -1732584194,
4921                    d =  271733878;
4922
4923                for (i = 0; i < x.length; i += 16) {
4924                    olda = a;
4925                    oldb = b;
4926                    oldc = c;
4927                    oldd = d;
4928
4929                    a = md5_ff(a, b, c, d, x[i],       7, -680876936);
4930                    d = md5_ff(d, a, b, c, x[i +  1], 12, -389564586);
4931                    c = md5_ff(c, d, a, b, x[i +  2], 17,  606105819);
4932                    b = md5_ff(b, c, d, a, x[i +  3], 22, -1044525330);
4933                    a = md5_ff(a, b, c, d, x[i +  4],  7, -176418897);
4934                    d = md5_ff(d, a, b, c, x[i +  5], 12,  1200080426);
4935                    c = md5_ff(c, d, a, b, x[i +  6], 17, -1473231341);
4936                    b = md5_ff(b, c, d, a, x[i +  7], 22, -45705983);
4937                    a = md5_ff(a, b, c, d, x[i +  8],  7,  1770035416);
4938                    d = md5_ff(d, a, b, c, x[i +  9], 12, -1958414417);
4939                    c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
4940                    b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
4941                    a = md5_ff(a, b, c, d, x[i + 12],  7,  1804603682);
4942                    d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
4943                    c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
4944                    b = md5_ff(b, c, d, a, x[i + 15], 22,  1236535329);
4945
4946                    a = md5_gg(a, b, c, d, x[i +  1],  5, -165796510);
4947                    d = md5_gg(d, a, b, c, x[i +  6],  9, -1069501632);
4948                    c = md5_gg(c, d, a, b, x[i + 11], 14,  643717713);
4949                    b = md5_gg(b, c, d, a, x[i],      20, -373897302);
4950                    a = md5_gg(a, b, c, d, x[i +  5],  5, -701558691);
4951                    d = md5_gg(d, a, b, c, x[i + 10],  9,  38016083);
4952                    c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
4953                    b = md5_gg(b, c, d, a, x[i +  4], 20, -405537848);
4954                    a = md5_gg(a, b, c, d, x[i +  9],  5,  568446438);
4955                    d = md5_gg(d, a, b, c, x[i + 14],  9, -1019803690);
4956                    c = md5_gg(c, d, a, b, x[i +  3], 14, -187363961);
4957                    b = md5_gg(b, c, d, a, x[i +  8], 20,  1163531501);
4958                    a = md5_gg(a, b, c, d, x[i + 13],  5, -1444681467);
4959                    d = md5_gg(d, a, b, c, x[i +  2],  9, -51403784);
4960                    c = md5_gg(c, d, a, b, x[i +  7], 14,  1735328473);
4961                    b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
4962
4963                    a = md5_hh(a, b, c, d, x[i +  5],  4, -378558);
4964                    d = md5_hh(d, a, b, c, x[i +  8], 11, -2022574463);
4965                    c = md5_hh(c, d, a, b, x[i + 11], 16,  1839030562);
4966                    b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
4967                    a = md5_hh(a, b, c, d, x[i +  1],  4, -1530992060);
4968                    d = md5_hh(d, a, b, c, x[i +  4], 11,  1272893353);
4969                    c = md5_hh(c, d, a, b, x[i +  7], 16, -155497632);
4970                    b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
4971                    a = md5_hh(a, b, c, d, x[i + 13],  4,  681279174);
4972                    d = md5_hh(d, a, b, c, x[i],      11, -358537222);
4973                    c = md5_hh(c, d, a, b, x[i +  3], 16, -722521979);
4974                    b = md5_hh(b, c, d, a, x[i +  6], 23,  76029189);
4975                    a = md5_hh(a, b, c, d, x[i +  9],  4, -640364487);
4976                    d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
4977                    c = md5_hh(c, d, a, b, x[i + 15], 16,  530742520);
4978                    b = md5_hh(b, c, d, a, x[i +  2], 23, -995338651);
4979
4980                    a = md5_ii(a, b, c, d, x[i],       6, -198630844);
4981                    d = md5_ii(d, a, b, c, x[i +  7], 10,  1126891415);
4982                    c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
4983                    b = md5_ii(b, c, d, a, x[i +  5], 21, -57434055);
4984                    a = md5_ii(a, b, c, d, x[i + 12],  6,  1700485571);
4985                    d = md5_ii(d, a, b, c, x[i +  3], 10, -1894986606);
4986                    c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
4987                    b = md5_ii(b, c, d, a, x[i +  1], 21, -2054922799);
4988                    a = md5_ii(a, b, c, d, x[i +  8],  6,  1873313359);
4989                    d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
4990                    c = md5_ii(c, d, a, b, x[i +  6], 15, -1560198380);
4991                    b = md5_ii(b, c, d, a, x[i + 13], 21,  1309151649);
4992                    a = md5_ii(a, b, c, d, x[i +  4],  6, -145523070);
4993                    d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
4994                    c = md5_ii(c, d, a, b, x[i +  2], 15,  718787259);
4995                    b = md5_ii(b, c, d, a, x[i +  9], 21, -343485551);
4996
4997                    a = safe_add(a, olda);
4998                    b = safe_add(b, oldb);
4999                    c = safe_add(c, oldc);
5000                    d = safe_add(d, oldd);
5001                }
5002                return [a, b, c, d];
5003            }
5004
5005            /*
5006            * Convert an array of little-endian words to a string
5007            */
5008            function binl2rstr(input) {
5009                var i,
5010                    output = '';
5011                for (i = 0; i < input.length * 32; i += 8) {
5012                    output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
5013                }
5014                return output;
5015            }
5016
5017            /*
5018            * Convert a raw string to an array of little-endian words
5019            * Characters >255 have their high-byte silently ignored.
5020            */
5021            function rstr2binl(input) {
5022                var i,
5023                    output = [];
5024                output[(input.length >> 2) - 1] = undefined;
5025                for (i = 0; i < output.length; i += 1) {
5026                    output[i] = 0;
5027                }
5028                for (i = 0; i < input.length * 8; i += 8) {
5029                    output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
5030                }
5031                return output;
5032            }
5033
5034            /*
5035            * Calculate the MD5 of a raw string
5036            */
5037            function rstr_md5(s) {
5038                return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
5039            }
5040
5041            /*
5042            * Calculate the HMAC-MD5, of a key and some data (raw strings)
5043            */
5044            function rstr_hmac_md5(key, data) {
5045                var i,
5046                    bkey = rstr2binl(key),
5047                    ipad = [],
5048                    opad = [],
5049                    hash;
5050                ipad[15] = opad[15] = undefined;
5051                if (bkey.length > 16) {
5052                    bkey = binl_md5(bkey, key.length * 8);
5053                }
5054                for (i = 0; i < 16; i += 1) {
5055                    ipad[i] = bkey[i] ^ 0x36363636;
5056                    opad[i] = bkey[i] ^ 0x5C5C5C5C;
5057                }
5058                hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
5059                return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
5060            }
5061
5062            /*
5063            * Convert a raw string to a hex string
5064            */
5065            function rstr2hex(input) {
5066                var hex_tab = '0123456789abcdef',
5067                    output = '',
5068                    x,
5069                    i;
5070                for (i = 0; i < input.length; i += 1) {
5071                    x = input.charCodeAt(i);
5072                    output += hex_tab.charAt((x >>> 4) & 0x0F) +
5073                        hex_tab.charAt(x & 0x0F);
5074                }
5075                return output;
5076            }
5077
5078            /*
5079            * Encode a string as utf-8
5080            */
5081            function str2rstr_utf8(input) {
5082                return unescape(encodeURIComponent(input));
5083            }
5084
5085            /*
5086            * Take string arguments and return either raw or hex encoded strings
5087            */
5088            function raw_md5(s) {
5089                return rstr_md5(str2rstr_utf8(s));
5090            }
5091            function hex_md5(s) {
5092                return rstr2hex(raw_md5(s));
5093            }
5094            function raw_hmac_md5(k, d) {
5095                return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
5096            }
5097            function hex_hmac_md5(k, d) {
5098                return rstr2hex(raw_hmac_md5(k, d));
5099            }
5100
5101            this.md5 = function(string, key, raw) {
5102                if (!key) {
5103                    if (!raw) {
5104                        return hex_md5(string);
5105                    }
5106                    return raw_md5(string);
5107                }
5108                if (!raw) {
5109                    return hex_hmac_md5(key, string);
5110                }
5111                return raw_hmac_md5(key, string);
5112            }
5113
5114            /*if (typeof define === 'function' && define.amd) {
5115                define(function () {
5116                    return md5;
5117                });
5118            } else {
5119                $.md5 = md5;
5120            }*/
5121        }();
5122
5123
5124        /*
5125        * Lightweight JSONP fetcher
5126        * Copyright 2010-2012 Erik Karlsson. All rights reserved.
5127        * BSD licensed
5128        */
5129        /*
5130        * Usage:
5131        *
5132        * JSONP.get( 'someUrl.php', {param1:'123', param2:'456'}, function(data){
5133        *   //do something with data, which is the JSON object you should retrieve from someUrl.php
5134        * });
5135        */
5136        obj.JSONP = (function(){
5137            var counter = 0, head, window = this, config = {};
5138            function load(url, pfnError) {
5139		var script = document.createElement('script'),
5140			done = false;
5141
5142		script.src = url;
5143		script.async = true;
5144
5145		var errorHandler = pfnError || config.error;
5146		if ( typeof errorHandler === 'function' ) {
5147			script.onerror = function(ex){
5148				errorHandler({url: url, event: ex});
5149			};
5150		}
5151
5152		script.onload = script.onreadystatechange = function() {
5153			if ( !done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") ) {
5154				done = true;
5155				script.onload = script.onreadystatechange = null;
5156				if ( script && script.parentNode ) {
5157					script.parentNode.removeChild( script );
5158				}
5159			}
5160		};
5161
5162		if ( !head ) {
5163			head = document.getElementsByTagName('head')[0];
5164		}
5165		head.appendChild( script );
5166            }
5167            function encode(str) {
5168                    return encodeURIComponent(str);
5169            }
5170            function jsonp(url, params, callback, callbackName, errorHandler) {
5171		var query = (url||'').indexOf('?') === -1 ? '?' : '&', key;
5172
5173		callbackName = (callbackName||config['callbackName']||'lb');
5174
5175		var uniqueName = callbackName + "_json"; // + (++counter);
5176
5177		params = params || {};
5178		for ( key in params ) {
5179			if ( params.hasOwnProperty(key) ) {
5180				query += encode(key) + "=" + encode(params[key]) + "&";
5181			}
5182		}
5183
5184		window[ uniqueName ] = function(data){
5185			callback(data);
5186			/*try {
5187				delete window[ uniqueName ];
5188			} catch (e) {}
5189			window[ uniqueName ] = null;*/
5190		};
5191
5192		load(url + query + callbackName + '=' + uniqueName, errorHandler);
5193		return uniqueName;
5194            }
5195            function setDefaults(obj){
5196                    config = obj;
5197            }
5198            return {
5199                    get:jsonp,
5200                    init:setDefaults
5201            };
5202        }());
5203
5204        // Converting UTF-8 domain name to ASCII
5205        // http://stackoverflow.com/questions/183485/can-anyone-recommend-a-good-free-javascript-for-punycode-to-unicode-conversion
5206        obj.punycode = new function Punycode() {
5207            // This object converts to and from puny-code used in IDN
5208            //
5209            // punycode.ToASCII ( domain )
5210            //
5211            // Returns a puny coded representation of "domain".
5212            // It only converts the part of the domain name that
5213            // has non ASCII characters. I.e. it dosent matter if
5214            // you call it with a domain that already is in ASCII.
5215            //
5216            // punycode.ToUnicode (domain)
5217            //
5218            // Converts a puny-coded domain name to unicode.
5219            // It only converts the puny-coded parts of the domain name.
5220            // I.e. it dosent matter if you call it on a string
5221            // that already has been converted to unicode.
5222            //
5223            //
5224            this.utf16 = {
5225                // The utf16-class is necessary to convert from javascripts internal character representation to unicode and back.
5226                decode:function(input){
5227                    var output = [], i=0, len=input.length,value,extra;
5228                    while (i < len) {
5229                        value = input.charCodeAt(i++);
5230                        if ((value & 0xF800) === 0xD800) {
5231                            extra = input.charCodeAt(i++);
5232                            if ( ((value & 0xFC00) !== 0xD800) || ((extra & 0xFC00) !== 0xDC00) ) {
5233                                throw new RangeError("UTF-16(decode): Illegal UTF-16 sequence");
5234                            }
5235                            value = ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
5236                        }
5237                        output.push(value);
5238                    }
5239                    return output;
5240                },
5241                encode:function(input){
5242                    var output = [], i=0, len=input.length,value;
5243                    while (i < len) {
5244                        value = input[i++];
5245                        if ( (value & 0xF800) === 0xD800 ) {
5246                            throw new RangeError("UTF-16(encode): Illegal UTF-16 value");
5247                        }
5248                        if (value > 0xFFFF) {
5249                            value -= 0x10000;
5250                            output.push(String.fromCharCode(((value >>>10) & 0x3FF) | 0xD800));
5251                            value = 0xDC00 | (value & 0x3FF);
5252                        }
5253                        output.push(String.fromCharCode(value));
5254                    }
5255                    return output.join("");
5256                }
5257            }
5258
5259            //Default parameters
5260            var initial_n = 0x80;
5261            var initial_bias = 72;
5262            var delimiter = "\x2D";
5263            var base = 36;
5264            var damp = 700;
5265            var tmin=1;
5266            var tmax=26;
5267            var skew=38;
5268            var maxint = 0x7FFFFFFF;
5269
5270            // decode_digit(cp) returns the numeric value of a basic code
5271            // point (for use in representing integers) in the range 0 to
5272            // base-1, or base if cp is does not represent a value.
5273
5274            function decode_digit(cp) {
5275                return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : cp - 97 < 26 ? cp - 97 : base;
5276            }
5277
5278            // encode_digit(d,flag) returns the basic code point whose value
5279            // (when used for representing integers) is d, which needs to be in
5280            // the range 0 to base-1. The lowercase form is used unless flag is
5281            // nonzero, in which case the uppercase form is used. The behavior
5282            // is undefined if flag is nonzero and digit d has no uppercase form.
5283
5284            function encode_digit(d, flag) {
5285                return d + 22 + 75 * (d < 26) - ((flag != 0) << 5);
5286                //  0..25 map to ASCII a..z or A..Z
5287                // 26..35 map to ASCII 0..9
5288            }
5289            //** Bias adaptation function **
5290            function adapt(delta, numpoints, firsttime ) {
5291                var k;
5292                delta = firsttime ? Math.floor(delta / damp) : (delta >> 1);
5293                delta += Math.floor(delta / numpoints);
5294
5295                for (k = 0; delta > (((base - tmin) * tmax) >> 1); k += base) {
5296                        delta = Math.floor(delta / ( base - tmin ));
5297                }
5298                return Math.floor(k + (base - tmin + 1) * delta / (delta + skew));
5299            }
5300
5301            // encode_basic(bcp,flag) forces a basic code point to lowercase if flag is zero,
5302            // uppercase if flag is nonzero, and returns the resulting code point.
5303            // The code point is unchanged if it is caseless.
5304            // The behavior is undefined if bcp is not a basic code point.
5305
5306            function encode_basic(bcp, flag) {
5307                bcp -= (bcp - 97 < 26) << 5;
5308                return bcp + ((!flag && (bcp - 65 < 26)) << 5);
5309            }
5310
5311            // Main decode
5312            this.decode=function(input,preserveCase) {
5313                // Dont use utf16
5314                var output=[];
5315                var case_flags=[];
5316                var input_length = input.length;
5317
5318                var n, out, i, bias, basic, j, ic, oldi, w, k, digit, t, len;
5319
5320                // Initialize the state:
5321
5322                n = initial_n;
5323                i = 0;
5324                bias = initial_bias;
5325
5326                // Handle the basic code points: Let basic be the number of input code
5327                // points before the last delimiter, or 0 if there is none, then
5328                // copy the first basic code points to the output.
5329
5330                basic = input.lastIndexOf(delimiter);
5331                if (basic < 0) basic = 0;
5332
5333                for (j = 0; j < basic; ++j) {
5334                    if(preserveCase) case_flags[output.length] = ( input.charCodeAt(j) -65 < 26);
5335                    if ( input.charCodeAt(j) >= 0x80) {
5336                        throw new RangeError("Illegal input >= 0x80");
5337                    }
5338                    output.push( input.charCodeAt(j) );
5339                }
5340
5341                // Main decoding loop: Start just after the last delimiter if any
5342                // basic code points were copied; start at the beginning otherwise.
5343
5344                for (ic = basic > 0 ? basic + 1 : 0; ic < input_length; ) {
5345
5346                    // ic is the index of the next character to be consumed,
5347
5348                    // Decode a generalized variable-length integer into delta,
5349                    // which gets added to i. The overflow checking is easier
5350                    // if we increase i as we go, then subtract off its starting
5351                    // value at the end to obtain delta.
5352                    for (oldi = i, w = 1, k = base; ; k += base) {
5353                            if (ic >= input_length) {
5354                                throw RangeError ("punycode_bad_input(1)");
5355                            }
5356                            digit = decode_digit(input.charCodeAt(ic++));
5357
5358                            if (digit >= base) {
5359                                throw RangeError("punycode_bad_input(2)");
5360                            }
5361                            if (digit > Math.floor((maxint - i) / w)) {
5362                                throw RangeError ("punycode_overflow(1)");
5363                            }
5364                            i += digit * w;
5365                            t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
5366                            if (digit < t) { break; }
5367                            if (w > Math.floor(maxint / (base - t))) {
5368                                throw RangeError("punycode_overflow(2)");
5369                            }
5370                            w *= (base - t);
5371                    }
5372
5373                    out = output.length + 1;
5374                    bias = adapt(i - oldi, out, oldi === 0);
5375
5376                    // i was supposed to wrap around from out to 0,
5377                    // incrementing n each time, so we'll fix that now:
5378                    if ( Math.floor(i / out) > maxint - n) {
5379                        throw RangeError("punycode_overflow(3)");
5380                    }
5381                    n += Math.floor( i / out ) ;
5382                    i %= out;
5383
5384                    // Insert n at position i of the output:
5385                    // Case of last character determines uppercase flag:
5386                    if (preserveCase) { case_flags.splice(i, 0, input.charCodeAt(ic -1) -65 < 26);}
5387
5388                    output.splice(i, 0, n);
5389                    i++;
5390                }
5391                if (preserveCase) {
5392                    for (i = 0, len = output.length; i < len; i++) {
5393                        if (case_flags[i]) {
5394                            output[i] = (String.fromCharCode(output[i]).toUpperCase()).charCodeAt(0);
5395                        }
5396                    }
5397                }
5398                return this.utf16.encode(output);
5399            };
5400
5401            this.ToUnicode = function ( domain ) {
5402                var domain_array = domain.split(".");
5403                var out = [];
5404                for (var i=0; i < domain_array.length; ++i) {
5405                    var s = domain_array[i];
5406                    out.push(
5407                        s.match(/^xn--/) ?
5408                        this.decode(s.slice(4)) :
5409                        s
5410                    );
5411                }
5412                return out.join(".");
5413            }
5414        }();
5415
5416        // https://github.com/SheetJS/js-crc32/blob/master/crc32.js
5417        obj.crc32 =  function(str) {
5418            var makeCRCTable = function(){
5419                var c;
5420                var crcTable = [];
5421                for(var n =0; n < 256; n++){
5422                    c = n;
5423                    for(var k =0; k < 8; k++){
5424                        c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
5425                    }
5426                    crcTable[n] = c;
5427                }
5428                return crcTable;
5429            };
5430
5431            var crcTable = window.crcTable || (window.crcTable = makeCRCTable());
5432            var crc = 0 ^ (-1);
5433
5434            for (var i = 0; i < str.length; i++ ) {
5435                crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF];
5436            }
5437
5438            return (crc ^ (-1)) >>> 0;
5439        };
5440
5441        // Hash a string to integer with a range
5442        obj.numericHash = function(str, range) {
5443            var number = obj.crc32(str);
5444            return number % range;
5445        }
5446
5447        // @preserve Qwery - A Blazing Fast query selector engine
5448        // https://github.com/ded/qwery
5449        // copyright Dustin Diaz 2012
5450        // MIT License
5451        obj.q = (function() {
5452            function L() {
5453                this.c = {}
5454            }
5455            function D(e) {
5456                return A.g(e) || A.s(e, "(^|\\s+)" + e + "(\\s+|$)", 1)
5457            }
5458            function P(e, t) {
5459                var n = 0, r = e.length;
5460                for (; n < r; n++)
5461                    t(e[n])
5462            }
5463            function H(e) {
5464                for (var t = [], n = 0, r = e.length; n < r; ++n)
5465                    $(e[n]) ? t = t.concat(e[n]) : t[t.length] = e[n];
5466                return t
5467            }
5468            function B(e) {
5469                var t = 0, n = e.length, r = [];
5470                for (; t < n; t++)
5471                    r[t] = e[t];
5472                return r
5473            }
5474            function j(e) {
5475                while (e = e.previousSibling)
5476                    if (e[u] == 1)
5477                        break;
5478                return e
5479            }
5480            function F(e) {
5481                return e.match(C)
5482            }
5483            function I(e, t, n, r, i, s, a, c, h, p, d) {
5484                var v, m, g, y, b;
5485                if (this[u] !== 1)
5486                    return!1;
5487                if (t && t !== "*" && this[o] && this[o].toLowerCase() !== t)
5488                    return!1;
5489                if (n && (m = n.match(f)) && m[1] !== this.id)
5490                    return!1;
5491                if (n && (b = n.match(l)))
5492                    for (v = b.length; v--; )
5493                        if (!D(b[v].slice(1)).test(this.className))
5494                            return!1;
5495                if (h && Q.pseudos[h] && !Q.pseudos[h](this, d))
5496                    return!1;
5497                if (r && !a) {
5498                    y = this.attributes;
5499                    for (g in y)
5500                        if (Object.prototype.hasOwnProperty.call(y, g) && (y[g].name || g) == i)
5501                            return this
5502                }
5503                return r && !R(s, Z(this, i) || "", a) ? !1 : this
5504            }
5505            function q(e) {
5506                return O.g(e) || O.s(e, e.replace(b, "\\$1"))
5507            }
5508            function R(e, t, n) {
5509                switch (e) {
5510                    case"=":
5511                        return t == n;
5512                    case"^=":
5513                        return t.match(M.g("^=" + n) || M.s("^=" + n, "^" + q(n), 1));
5514                    case"$=":
5515                        return t.match(M.g("$=" + n) || M.s("$=" + n, q(n) + "$", 1));
5516                    case"*=":
5517                        return t.match(M.g(n) || M.s(n, q(n), 1));
5518                    case"~=":
5519                        return t.match(M.g("~=" + n) || M.s("~=" + n, "(?:^|\\s+)" + q(n) + "(?:\\s+|$)", 1));
5520                    case"|=":
5521                        return t.match(M.g("|=" + n) || M.s("|=" + n, "^" + q(n) + "(-|$)", 1))
5522                }
5523                return 0
5524            }
5525            function U(e, t) {
5526                var n = [], i = [], s, a, f, l, h, p, d, v, m = t, g = _.g(e) || _.s(e, e.split(N)), y = e.match(T);
5527                if (!g.length)
5528                    return n;
5529                l = (g = g.slice(0)).pop(), g.length && (f = g[g.length - 1].match(c)) && (m = K(t, f[1]));
5530                if (!m)
5531                    return n;
5532                d = F(l), p = m !== t && m[u] !== 9 && y && /^[+~]$/.test(y[y.length - 1]) ? function(e) {
5533                    while (m = m.nextSibling)
5534                        m[u] == 1 && (d[1] ? d[1] == m[o].toLowerCase() : 1) && (e[e.length] = m);
5535                    return e
5536                }([]) : m[r](d[1] || "*");
5537                for (s = 0, a = p.length; s < a; s++)
5538                    if (v = I.apply(p[s], d))
5539                        n[n.length] = v;
5540                return g.length ? (P(n, function(e) {
5541                    W(e, g, y) && (i[i.length] = e)
5542                }), i) : n
5543            }
5544            function z(e, t, n) {
5545                if (X(t))
5546                    return e == t;
5547                if ($(t))
5548                    return!!~H(t).indexOf(e);
5549                var r = t.split(","), i, s;
5550                while (t = r.pop()) {
5551                    i = _.g(t) || _.s(t, t.split(N)), s = t.match(T), i = i.slice(0);
5552                    if (I.apply(e, F(i.pop())) && (!i.length || W(e, i, s, n)))
5553                        return!0
5554                }
5555                return!1
5556            }
5557            function W(e, t, n, r) {
5558                function s(e, r, o) {
5559                    if (typeof(k[n[r]]) === "undefined") {
5560                        return null;
5561                    }
5562                    while (o = k[n[r]](o, e))
5563                        if (X(o) && I.apply(o, F(t[r]))) {
5564                            if (!r)
5565                                return o;
5566                            if (i = s(o, r - 1, o))
5567                                return i
5568                        }
5569                }
5570                var i;
5571                return(i = s(e, t.length - 1, e)) && (!r || Y(i, r))
5572            }
5573            function X(e, t) {
5574                return e && typeof e == "object" && (t = e[u]) && (t == 1 || t == 9)
5575            }
5576            function V(e) {
5577                var t = [], n, r;
5578                e:for (n = 0; n < e.length; ++n) {
5579                    for (r = 0; r < t.length; ++r)
5580                        if (t[r] == e[n])
5581                            continue e;
5582                    t[t.length] = e[n]
5583                }
5584                return t
5585            }
5586            function $(e) {
5587                return typeof e == "object" && isFinite(e.length)
5588            }
5589            function J(t) {
5590                return t ? typeof t == "string" ? Q(t)[0] : !t[u] && $(t) ? t[0] : t : e
5591            }
5592            function K(e, t, n) {
5593                return e[u] === 9 ? e.getElementById(t) : e.ownerDocument && ((n = e.ownerDocument.getElementById(t)) && Y(n, e) && n || !Y(e, e.ownerDocument) && a('[id="' + t + '"]', e)[0])
5594            }
5595            function Q(e, t) {
5596                var i, s, o = J(t);
5597                if (!o || !e)
5598                    return[];
5599                if (e === window || X(e))
5600                    return!t || e !== window && X(o) && Y(e, o) ? [e] : [];
5601                if (e && $(e))
5602                    return H(e);
5603                if (i = e.match(x)) {
5604                    if (i[1])
5605                        return(s = K(o, i[1])) ? [s] : [];
5606                    if (i[2])
5607                        return B(o[r](i[2]));
5608                    if (et && i[3])
5609                        return B(o[n](i[3]))
5610                }
5611                return a(e, o)
5612            }
5613            function G(e, t) {
5614                return function(n) {
5615                    var r, i;
5616                    if (v.test(n)) {
5617                        e[u] !== 9 && ((i = r = e.getAttribute("id")) || e.setAttribute("id", i = "__qwerymeupscotty"), n = '[id="' + i + '"]' + n, t(e.parentNode || e, n, !0), r || e.removeAttribute("id"));
5618                        return
5619                    }
5620                    n.length && t(e, n, !1)
5621                }
5622            }
5623            var e = document, t = e.documentElement, n = "getElementsByClassName", r = "getElementsByTagName", i = "querySelectorAll", s = "useNativeQSA", o = "tagName", u = "nodeType", a, f = /#([\w\-]+)/, l = /\.[\w\-]+/g, c = /^#([\w\-]+)$/, h = /^\.([\w\-]+)$/, p = /^([\w\-]+)$/, d = /^([\w]+)?\.([\w\-]+)$/, v = /(^|,)\s*[>~+]/, m = /^\s+|\s*([,\s\+\~>]|$)\s*/g, g = /[\s\>\+\~]/, y = /(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/, b = /([.*+?\^=!:${}()|\[\]\/\\])/g, w = /^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/, E = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/, S = /:([\w\-]+)(\(['"]?([^()]+)['"]?\))?/, x = new RegExp(c.source + "|" + p.source + "|" + h.source), T = new RegExp("(" + g.source + ")" + y.source, "g"), N = new RegExp(g.source + y.source), C = new RegExp(w.source + "(" + E.source + ")?" + "(" + S.source + ")?"), k = {" ": function(e) {
5624                    return e && e !== t && e.parentNode
5625                }, ">": function(e, t) {
5626                    return e && e.parentNode == t.parentNode && e.parentNode
5627                }, "~": function(e) {
5628                    return e && e.previousSibling
5629                }, "+": function(e, t, n, r) {
5630                    return e ? (n = j(e)) && (r = j(t)) && n == r && n : !1
5631                }};
5632            L.prototype = {g: function(e) {
5633                    return this.c[e] || undefined
5634                }, s: function(e, t, n) {
5635                    return t = n ? new RegExp(t) : t, this.c[e] = t
5636                }};
5637            var A = new L, O = new L, M = new L, _ = new L, Y = "compareDocumentPosition"in t ? function(e, t) {
5638                return(t.compareDocumentPosition(e) & 16) == 16
5639            } : "contains"in t ? function(e, n) {
5640                return n = n[u] === 9 || n == window ? t : n, n !== e && n.contains(e)
5641            } : function(e, t) {
5642                while (e = e.parentNode)
5643                    if (e === t)
5644                        return 1;
5645                return 0
5646            }, Z = function() {
5647                var t = e.createElement("p");
5648                return(t.innerHTML = '<a href="#x">x</a>') && t.firstChild.getAttribute("href") != "#x" ? function(e, t) {
5649                    return t === "class" ? e.className : t === "href" || t === "src" ? e.getAttribute(t, 2) : e.getAttribute(t)
5650                } : function(e, t) {
5651                    return e.getAttribute(t)
5652                }
5653            }(), et = !!e[n], tt = e.querySelector && e[i], nt = function(e, t) {
5654                var n = [], r, s;
5655                try {
5656                    return t[u] === 9 || !v.test(e) ? B(t[i](e)) : (P(r = e.split(","), G(t, function(e, t) {
5657                        s = e[i](t), s.length == 1 ? n[n.length] = s.item(0) : s.length && (n = n.concat(B(s)))
5658                    })), r.length > 1 && n.length > 1 ? V(n) : n)
5659                } catch (o) {
5660                }
5661                return rt(e, t)
5662            }, rt = function(e, t) {
5663                var n = [], i, s, o, a, f, l;
5664                e = e.replace(m, "$1");
5665                if (s = e.match(d)) {
5666                    f = D(s[2]), i = t[r](s[1] || "*");
5667                    for (o = 0, a = i.length; o < a; o++)
5668                        f.test(i[o].className) && (n[n.length] = i[o]);
5669                    return n
5670                }
5671                return P(l = e.split(","), G(t, function(e, r, i) {
5672                    f = U(r, e);
5673                    for (o = 0, a = f.length; o < a; o++)
5674                        if (e[u] === 9 || i || Y(f[o], t))
5675                            n[n.length] = f[o]
5676                })), l.length > 1 && n.length > 1 ? V(n) : n
5677            }, it = function(e) {
5678                typeof e[s] != "undefined" && (a = e[s] ? tt ? nt : rt : rt)
5679            };
5680            return it({useNativeQSA: !0}), Q.configure = it, Q.uniq = V, Q.is = z, Q.pseudos = {}, Q
5681        }());
5682
5683        return obj;
5684    }(window);
5685
5686        
5687    // GA
5688    /*var _gaq = _gaq || [];
5689    _gaq.push(['likebtn._setAccount', 'UA-37384414-2']);
5690    _gaq.push(['likebtn._setDomainName', 'likebtn.com']);
5691    _gaq.push(['likebtn._setCustomVar',
5692        1,                   // This custom var is set to slot #1.  Required parameter.
5693        'TrackCV',           // The name acts as a kind of category for the user activity.  Required parameter.
5694        '4017b00d29282db263e0bdc5aaadc58a1ed6bc1549',  // This value of the custom variable.  Required parameter.
5695        3                    // Sets the scope to page-level.  Optional parameter.
5696     ]);
5697    _gaq.push(['likebtn._trackPageview']);
5698
5699    (function() {
5700      var ga_likebtn = document.createElement('script'); ga_likebtn.type = 'text/javascript'; ga_likebtn.async = true;
5701      ga_likebtn.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
5702      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga_likebtn, s);
5703    })();*/
5704
5705    // https://developers.google.com/analytics/devguides/collection/analyticsjs/creating-trackers
5706    // https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#cookieDomain
5707    // website GA is not working in FF if // used as protocol at website GA
5708    }
5709
5710LikeBtn.init(true);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.