1jQuery(function ($) { 2 'use strict'; 3 4 var postData = { 5 STORAGE_KEY: 'expert_review_likes:' + base64Encode(window.location.origin), 6 _items: [], 7 /** 8 * @return {postData} 9 */ 10 init: function () { 11 var data = {items: []}; 12 if (typeof localStorage !== 'undefined') { 13 data = localStorage.getItem(this.STORAGE_KEY); 14 if (data) { 15 data = JSON.parse(data); 16 this._items = data.items; 17 } 18 } 19 return this; 20 }, 21 /** 22 * @return {postData} 23 */ 24 store: function () { 25 if (typeof localStorage !== 'undefined') { 26 var data = {items: this._items}; 27 localStorage.setItem(this.STORAGE_KEY, JSON.stringify(data)); 28 } 29 return this; 30 }, 31 /** 32 * @param {int} id 33 * @param {string} entity 34 * @return {postData} 35 */ 36 like: function (id, entity) { 37 this._act(id, 'like', entity); 38 return this; 39 }, 40 /** 41 * @param {int} id 42 * @param {string} entity 43 * @return {postData} 44 */ 45 dislike: function (id, entity) { 46 this._act(id, 'dislike', entity); 47 return this; 48 }, 49 /** 50 * @param {int} id 51 * @param {string} entity 52 * @return {postData} 53 */ 54 remove: function (id, entity) { 55 this._act(id, 'remove', entity); 56 return this; 57 }, 58 _act: function (id, action, entity) { 59 entity = entity || 'posts'; 60 var items = this._items.filter(function (item) { 61 if (item.hasOwnProperty('e')) { 62 return item.e !== entity || item.id !== id; 63 } 64 return item.id !== id; 65 }); 66 if (action !== 'remove') { 67 items.push({ 68 id: id, 69 a: action, 70 e: entity 71 }); 72 } 73 this._items = items; 74 }, 75 /** 76 * @param {int} id 77 * @param {string} entity 78 * @return {boolean} 79 */ 80 isLiked: function (id, entity) { 81 return this._check(id, 'like', entity); 82 }, 83 /** 84 * @param {int} id 85 * @param {string} entity 86 * @return {boolean} 87 */ 88 isDisliked: function (id, entity) { 89 return this._check(id, 'dislike', entity); 90 }, 91 _check: function (id, action, entity) { 92 // @todo cache check state? 93 entity = entity || 'posts'; 94 var items = this._items.filter(function (item) { 95 if (item.hasOwnProperty('e')) { 96 return item.e === entity && item.id === id; 97 } else if (entity === 'posts') { 98 return item.id === id; 99 } 100 return false; 101 }); 102 if (items.length) { 103 return items[0].a === action; 104 } 105 return false; 106 } 107 }; 108 109 postData.init(); 110 111 var initLikes = function () { 112 $('.js-expert-review-likes-button').each(function () { 113 var $this = $(this); 114 115 if ($this.data('init')) { 116 return; 117 } 118 $this.data('init', true); 119 120 var $container = $this.parents('.js-expert-review-likes-button-container'), 121 data = $this.parent().data(), 122 entity = $container.data('entity_type'); 123 124 entity = entity || 'posts'; 125 126 var id = null; 127 if (entity === 'posts') { 128 if (data.hasOwnProperty('name')) { 129 id = data.name; 130 } else if (data.hasOwnProperty('post_id')) { 131 id = data.post_id; 132 } 133 } else if (entity === 'comments') { 134 id = $container.data('comment_id'); 135 } 136 137 if (!id) { 138 return; 139 } 140 141 if ($this.data('type') === 'like' || $this.data('type') === 'toggle') { 142 $this.addClass(postData.isLiked(id, entity) ? 'voted' : ''); 143 } else if ($this.data('type') === 'dislike') { 144 $this.addClass(postData.isDisliked(id, entity) ? 'voted' : ''); 145 } 146 }); 147 }; 148 149 document.wpshopExpertReview_InitLikes = initLikes; 150 151 initLikes(); 152 153 $(document).on('journalx_load_post', function () { 154 setTimeout(initLikes, 100); 155 });
156 157 $(document).on('click', '.js-expert-review-likes-button', function (e) { 158 e.preventDefault(); 159 var $this = $(this), 160 $container = $this.parents('.js-expert-review-likes-button-container'), 161 entity = $container.data('entity_type'); 162 163 entity = entity || 'posts'; 164 165 var id = null, 166 type = $this.data('type'), 167 clickType = type === 'toggle' ? 'like' : type, 168 data = $this.parent().data(), 169 isNamed = false; 170 171 if ($this.hasClass('voted') && type !== 'toggle') { 172 return; 173 } 174 175 if (entity === 'posts') { 176 if (data.hasOwnProperty('name')) { 177 id = data.name; 178 isNamed = true; 179 } else if (data.hasOwnProperty('post_id')) { 180 id = data.post_id; 181 } 182 } else if (entity === 'comments') { 183 id = $container.data('comment_id'); 184 } 185 186 if (!id) { 187 return; 188 } 189 190 var isNewClick = true; 191 192 if (type === 'toggle') { 193 if (postData.isLiked(id, entity)) { 194 clickType = 'dislike'; 195 isNewClick = false; 196 } else if (postData.isDisliked(id, entity)) { 197 clickType = 'like'; 198 isNewClick = false; 199 } 200 } else if (type === 'like') { 201 if (postData.isLiked(id, entity)) { 202 return; 203 } 204 isNewClick = !postData.isDisliked(id, entity); 205 } else if (type === 'dislike') { 206 if (postData.isDisliked(id, entity)) { 207 return; 208 } 209 isNewClick = !postData.isLiked(id, entity); 210 } 211 212 var requestData = { 213 action: 'expert_review_save_like', 214 nonce: expert_review_ajax.nonce, 215 is_named: isNamed ? 1 : 0, 216 entity: entity, 217 id: id, 218 type: type, 219 click_type: clickType, 220 is_new: isNewClick ? 1 : 0 221 }; 222 223 $.ajax({
224 url: expert_review_ajax.url, 225 type: 'post', 226 data: requestData, 227 beforeSend: function () { 228 $this.addClass('loading'); 229 $this.prop('disabled', true); 230 } 231 }).done(function (response) { 232 if (response.success) { 233 var selector = isNamed ? 234 '.js-expert-review-likes-button-container[data-name="' + id + '"]' : 235 '.js-expert-review-likes-button-container[data-post_id="' + id + '"]'; 236 237 if (entity === 'comments') { 238 selector = '.js-expert-review-likes-button-container[data-comment_id="' + id + '"]'; 239 } 240 241 $(document).find(selector).each(function () { 242 var $this = $(this), 243 $likes = $this.find('.js-expert-review-likes-count'), 244 $dislikes = $this.find('.js-expert-review-dislikes-count') 245 ; 246 $likes.html(formatNumber(response.data.likes)); 247 $dislikes.html(formatNumber(response.data.dislikes)); 248 $this.find('.js-expert-review-likes-button').removeClass('voted'); 249 if (clickType !== 'dislike') { 250 $this.find('.js-expert-review-likes-button[data-type!="dislike"]').addClass('voted'); 251 } else if (type !== 'toggle') { 252 $this.find('.js-expert-review-likes-button[data-type="dislike"]').addClass('voted'); 253 } 254 }); 255 256 if (type === 'like') { 257 postData.like(id, entity); 258 } else if (type === 'dislike') { 259 postData.dislike(id, entity); 260 261 // when type = 'toggle' 262 } else if (clickType === 'like') { // toggle cases 263 postData.like(id, entity); 264 } else { 265 postData.remove(id, entity); 266 } 267 268 postData.store(); 269 270 if (isNamed) { 271 $(document).find('.js-expert-review-like-rate[data-name="' + id + '"]').text(response.data.rate); 272 $(document).find('.js-expert-review-like-activity[data-name="' + id + '"]').text(response.data.activity); 273 } 274 } else { 275 console.log(response); 276 } 277 }).always(function () { 278 $this.removeClass('loading'); 279 $this.prop('disabled', false); 280 }); 281 }); 282 283 function formatNumber($num) { 284 if ($num > 1000000) { 285 return ($num / 1000000).toFixed(1) + ' ' + 'm.'; 286 } 287 if ($num > 100000) { 288 return ($num / 1000).toFixed(0) + ' ' + 'k.'; 289 } 290 if ($num > 1000) { 291 return ($num / 1000).toFixed(1) + ' ' + 'k.'; 292 } 293 return $num; 294 } 295 296 function base64Encode(str) { 297 var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 298 var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, enc = ''; 299 300 do { 301 o1 = str.charCodeAt(i++); 302 o2 = str.charCodeAt(i++); 303 o3 = str.charCodeAt(i++); 304 305 bits = o1 << 16 | o2 << 8 | o3; 306 307 h1 = bits >> 18 & 0x3f; 308 h2 = bits >> 12 & 0x3f; 309 h3 = bits >> 6 & 0x3f; 310 h4 = bits & 0x3f; 311 312 enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); 313 } while (i < str.length); 314 315 switch (str.length % 3) { 316 case 1: 317 enc = enc.slice(0, -2) + '=='; 318 break; 319 case 2: 320 enc = enc.slice(0, -1) + '='; 321 break; 322 } 323 324 return enc; 325 } 326 327}); 328 329jQuery(function ($) { 330 'use strict'; 331 332 var pollStorage = new PollStorage(); 333 334 var initPoll = function () { 335 $('.js-expert-review-poll').each(function () { 336 var $this = $(this); 337 338 if ($this.data('init')) { 339 return; 340 } 341 $this.data('init', true); 342 343 var poll = $this.data('id'), 344 reset = parseInt($this.data('r')); 345 346 if (reset) { 347 pollStorage.reset(poll, reset); 348 } 349 350 var answer = pollStorage.getAnswer(poll); 351 352 if (answer) { 353 $this.addClass('voted'); 354 $this.find('.js-expert-review-poll-item[data-id="' + answer.a + '"]').addClass('voted'); 355 $this.find('.js-expert-review-poll-result-button').hide(); 356 } 357 358 var canVote = $this.data('can_vote'); 359 if (typeof canVote !== 'undefined' && !canVote) { 360 $this.addClass('voted'); 361 } else if (!answer) { 362 $this.find('.js-expert-review-poll-result-button').show(); 363 } 364 }); 365 }; 366 367 document.wpshopExpertReview_InitPoll = initPoll; 368 369 initPoll(); 370 371 $(document).on('journalx_load_post', function (){ 372 setTimeout(initPoll, 100); 373 });
374 375 $('body').on('journalx_load_post', initPoll); 376 377 378 $(document).on('click', '.js-expert-review-poll-item', function (e) { 379 e.preventDefault(); 380 var $this = $(this), 381 $container = $this.parents('.js-expert-review-poll'), 382 $loader = $('<div class="expert-review-poll__loader"><span></span></div>').clone(), 383 canVote = $this.data('can_vote'); 384 385 if (typeof canVote !== 'undefined' && !canVote) { 386 return; 387 } 388 389 if ($container.hasClass('voted')) { 390 return false; 391 } 392 393 var poll = $container.data('id'), 394 answer = $this.data('id'); 395 396 var requestData = { 397 action: 'expert_review_save_poll_vote', 398 nonce: expert_review_ajax.nonce, 399 question: poll, 400 answer: answer 401 }; 402 403 $.ajax({ 404 url: expert_review_ajax.url, 405 type: 'post', 406 data: requestData, 407 beforeSend: function () { 408 $container.append($loader); 409 $this.prop('disabled', true); 410 } 411 }).done(function (response) { 412 if (!response.success) { 413 console.log(response); 414 return; 415 } 416 $('.js-expert-review-poll[data-id="' + poll + '"]').each(function () { 417 var $this = $(this); 418 $this.addClass('voted'); 419 $this.find('.js-expert-review-poll-item[data-id="' + answer + '"]').addClass('voted'); 420 }); 421 pollStorage.vote(poll, answer); 422 423 $(document.body).trigger('expert_review_poll_voted', [$this, $container]); 424 425 $container.find('.js-expert-review-poll-result-button').hide(); 426 427 update_stat(poll, response.data); 428 }).always(function () { 429 $loader.remove(); 430 $this.prop('disabled', false); 431 }); 432 }); 433 434 $(document).on('click', '.js-expert-review-poll-result-button', function (e) { 435 e.preventDefault(); 436 var $this = $(e.currentTarget), txt = $this.data('toggle_txt'); 437 $this.blur(); 438 $this.data('toggle_txt', $this.text()); 439 $this.text(txt); 440 if ($this.hasClass('used')) { 441 $this.parents('.js-expert-review-poll').removeClass('voted'); 442 $this.removeClass('used'); 443 } else { 444 $this.parents('.js-expert-review-poll').addClass('voted'); 445 $this.addClass('used'); 446 } 447 }); 448 449 function update_stat(poll, data) { 450 $('.js-expert-review-poll[data-id="' + poll + '"]').each(function () { 451 var $container = $(this); 452 var total = data.total; 453 for (var answer in data.votes) { 454 var $el = $container.find('.js-expert-review-poll-item[data-id="' + answer + '"]'); 455 if ($el.length) { 456 var percent = Math.round(data.votes[answer] / (total || data.votes[answer]) * 100); 457 $el.find('.js-expert-review-poll-item-num').text(percent + '%'); 458 $el.find('.js-expert-review-poll-item-progress').css('width', percent + '%'); 459 } 460 } 461 var $total = $container.find('.js-expert-review-poll-count'); 462 if ($total.length) { 463 $total.text(total); 464 } 465 }); 466 } 467 468 function PollStorage() { 469 var STORAGE_KEY = 'expert_review_polls_v1:' + base64Encode(window.location.origin); 470 var data = {votes: {}, reset: 0}; 471 if (typeof localStorage !== 'undefined') { 472 var storedData = localStorage.getItem(STORAGE_KEY); 473 if (storedData) { 474 data = JSON.parse(storedData); 475 } 476 } 477 478 return { 479 vote: function (poll, answer) { 480 data.votes[poll] = { 481 a: answer, 482 t: Date.now() / 1000 | 0 483 }; 484 store(); 485 }, 486 getAnswer: function (poll) { 487 if (data.votes.hasOwnProperty(poll)) { 488 return data.votes[poll]; 489 } 490 return null; 491 }, 492 reset(poll, timestamp) { 493 if (typeof data.votes[poll] !== 'undefined') { 494 if (data.votes[poll].t < timestamp) { 495 delete data.votes[poll]; 496 } 497 store(); 498 } 499 }, 500 resetAll: function (timestamp) { 501 if (timestamp && (!data.reset || data.reset < timestamp)) { 502 data.reset = timestamp; 503 for (var poll in data.votes) { 504 if (data.votes[poll].t < timestamp) { 505 delete data.votes[poll]; 506 } 507 } 508 store(); 509 } 510 } 511 }; 512 513 function store() { 514 if (typeof localStorage !== 'undefined') { 515 localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); 516 } 517 } 518 519 function base64Encode(str) { 520 var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
520+/="; 521 var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, enc = ''; 522 523 do { 524 o1 = str.charCodeAt(i++); 525 o2 = str.charCodeAt(i++); 526 o3 = str.charCodeAt(i++); 527 528 bits = o1 << 16 | o2 << 8 | o3; 529 530 h1 = bits >> 18 & 0x3f; 531 h2 = bits >> 12 & 0x3f; 532 h3 = bits >> 6 & 0x3f; 533 h4 = bits & 0x3f; 534 535 enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); 536 } while (i < str.length); 537 538 switch (str.length % 3) { 539 case 1: 540 enc = enc.slice(0, -2) + '=='; 541 break; 542 case 2: 543 enc = enc.slice(0, -1) + '='; 544 break; 545 } 546 547 return enc; 548 } 549 } 550}); 551 552jQuery(function ($) { 553 var globals = expert_review_ajax || {}, 554 i18n = globals.i18n; 555 556 var $loaderProto = $('<div class="expert-review-popup__loader"><span></span></div>'); 557 558 $(document).on('click', '.js-expert-review-button', function (e) { 559 e.preventDefault(); 560 var $this = $(this); 561 var settings = $this.data('settings'); 562 switch (settings.type) { 563 case 'popup': 564 show_popup(settings); 565 break; 566 case 'comments': 567 scroll_to_comments(); 568 break; 569 case 'link': 570 if (e.ctrlKey || parseInt(globals.ask_question_link_new_tab)) { 571 $('<a href="' + settings.link + '" target="_blank" rel="noopener"></a>')[0].click(); 572 } else { 573 document.location = settings.link; 574 } 575 break; 576 default: 577 break; 578 } 579 }); 580 581 // submit question 582 $(document).on('click', '.js-expert-review-popup button[type="submit"]', function (e) { 583 e.preventDefault(); 584 585 var $this = $(this); 586 var $popup = $this.parents('.js-expert-review-popup'); 587 var $form = $popup.find('form'); 588 var $loader = $loaderProto.clone(); 589 590 var messageTimeout; 591 var prependMessage = function (message) { 592 $popup.find('form').prepend('<p class="fail-message">' + message + '</p>'); 593 clearTimeout(messageTimeout); 594 messageTimeout = setTimeout(function () { 595 $popup.find('.fail-message').remove(); 596 }, 5000); 597 }; 598 599 if (!validate($form)) { 600 return; 601 } 602 603 var data = form_data($popup.find('form')); 604 605 $.ajax({
606 url: globals.url, 607 type: 'post', 608 data: { 609 action: 'expert_review_submit_question', 610 nonce: globals.nonce, 611 data: data 612 }, 613 beforeSend: function () { 614 $this.prop('disabled', true); 615 $popup.find('.expert-review-popup').append($loader); 616 } 617 }).done(function (response) { 618 if (response.success) { 619 $popup.find('form').prepend('<p class="success-message">' + i18n.question_submitted + '</p>'); 620 setTimeout(function () { 621 $popup.remove(); 622 }, 3000); 623 document.dispatchEvent(new CustomEvent('expert_review_question:submit', { 624 'detail': { 625 'request': data, 626 'response': response 627 } 628 })); 629 } else if (response.data && Array.isArray(response.data)) { 630 response.data.reverse().forEach(function (item) { 631 var message = item.message; 632 if (item.code === 'legacy_form') { 633 console.error(message); 634 message = i18n.legacy_form; 635 } 636 prependMessage(message); 637 }); 638 } else if (response.data && response.data.message) { 639 prependMessage(response.data.message); 640 } 641 }).always(function () { 642 $this.prop('disabled', false); 643 $loader.remove(); 644 }); 645 }); 646 647 // click on close or cancel 648 $(document).on('click', '.js-expert-review-cancel, .js-expert-review-close-mark', function (e) { 649 e.preventDefault(); 650 $(this).parents('.js-expert-review-popup').remove(); 651 }); 652 653 // close on escape 654 $(document).keyup(function (e) { 655 if (e.keyCode === 27) { 656 $('.js-expert-review-close-mark').trigger('click'); 657 } 658 }); 659 660 // close on outside click 661 $('body').on('click', function (e) { 662 var $target = $(e.target); 663 if ($target.is(".js-expert-review-popup") && !$target.find().is(".js-expert-review-popup")) { 664 $('.js-expert-review-close-mark').trigger('click'); 665 } 666 }); 667 668 function show_popup(params) { 669 if (typeof expert_review_question_popup === 'function') { 670 $('body').append(expert_review_question_popup(i18n, params)); 671 return; 672 } 673 674 var contactInput = params.use_phone ? 675 ' <label>' + i18n.question_popup_phone + ': <input type="text" name="_p" class="required"></label>' : 676 ' <label>' + i18n.question_popup_email + ': <input type="text" name="_a" class="required"></label>'; 677 678 var consentCheckbox = globals.consent ? 679 ' <label><input type="checkbox" name="consent" value="1" class="required"> ' + i18n.consent + '</label>' 680 : ''; 681 682 var html = 683 '<div class="expert-review-popup-holder js-expert-review-popup"><div class="expert-review-popup">' + 684 ' <span class="expert-review-popup__close js-expert-review-close-mark">×</span>' + 685 ' <div class="expert-review-popup__content">' + 686 ' <form>' + 687 ' <label>' + i18n.question_popup_name + ': <input type="text" name="name" class="required"></label>' + 688 contactInput + 689 ' <input type="hidden" name="email">' + 690 ' <label>' + i18n.question_popup_question + ': <textarea name="text" class="required"></textarea></label>' + 691 consentCheckbox + 692 ' <button type="submit" class="expert-review-popup__submit">' + i18n.question_popup_submit + '</button>' + 693 ' <span class="expert-review-popup__cancel js-expert-review-cancel">' + i18n.question_popup_cancel + '</span>' + 694 $('<input type="hidden" name="settings">').val(JSON.stringify(params)).prop('outerHTML') + 695 ' </form>' + 696 ' </div>' + 697 '</div></div>'; 698 $('body').append(html); 699 } 700 701 function scroll_to_comments() { 702 if (typeof expert_review_scroll_to_comments === 'function') { 703 expert_review_scroll_to_comments(); 704 return; 705 } 706 707 var selector = "#comments"; 708 if (globals.comment_to_scroll_selector) { 709 selector = globals.comment_to_scroll_selector; 710 } 711 var $comments = $(selector); 712 if ($comments.length) { 713 $('html, body').animate({ 714 scrollTop: $comments.offset().top 715 }, 200); 716 } 717 } 718
719 var validationMessageTimeout; 720 721 function validate($form) { 722 $form.find('.js-expert-review-validation-message').remove(); 723 724 var result = true; 725 $form.find('input.required, textarea.required').each(function () { 726 var $this = $(this); 727 if ($this.is(':checkbox')) { 728 if (!$this.is(':checked')) { 729 result = false; 730 $this.parents('label').append('<p class="js-expert-review-validation-message validation-failed">' + i18n.field_must_be_checked + '</p>'); 731 } 732 } else { 733 if (!$this.val().trim()) { 734 result = false; 735 $this.parents('label').append('<p class="js-expert-review-validation-message validation-failed">' + i18n.field_cannot_be_empty + '</p>'); 736 } 737 } 738 }); 739 clearTimeout(validationMessageTimeout); 740 if (!result) { 741 validationMessageTimeout = setTimeout(function () { 742 $form.find('.js-expert-review-validation-message').hide(150, function () { 743 $(this).remove(); 744 }); 745 }, 5000); 746 } 747 return result; 748 } 749 750 function form_data($form) { 751 var formData = $form.serializeArray(); 752 var data = {}; 753 $.map(formData, function (n, i) { 754 data[n.name] = n.value; 755 }); 756 return data; 757 } 758 759 /** 760 * FAQ 761 */ 762 $(document).on('click', '.js-expert-review-faq-item-question', on_faq_item_click); 763 764 function on_faq_item_click(e) { 765 e.preventDefault(); 766 var $this = $(this), 767 $parent = $this.parent(); 768 769 if ($parent.hasClass('expand')) { 770 $parent.removeClass('expand'); 771 } else { 772 $parent.addClass('expand'); 773 } 774 775 $(this).parent().find('.js-expert-review-faq-item-answer').slideToggle(); 776 } 777});
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.