1/** 2 * Common functions/utils used in all page 3 */ 4 5 6if (typeof window.LP === 'undefined') { 7 window.LP = window.LearnPress = {}; 8} 9 10 11(function ($) { 12 /** 13 * Manage event callbacks. 14 * Allow add/remove a callback function into custom event of an object. 15 * 16 * @constructor 17 */ 18 window.LP.Event_Callback = function (self) { 19 var callbacks = {}; 20 21 this.on = function (event, callback) { 22 var namespaces = event.split('.'), 23 namespace = ''; 24 25 if (namespaces.length > 1) { 26 event = namespaces[0]; 27 namespace = namespaces[1]; 28 } 29 30 if (!callbacks[event]) { 31 callbacks[event] = [[], {}]; 32 } 33 34 if (namespace) { 35 if (!callbacks[event][1][namespace]) { 36 callbacks[event][1][namespace] = []; 37 } 38 callbacks[event][1][namespace].push(callback); 39 } else { 40 callbacks[event][0].push(callback); 41 } 42 43 return self; 44 }; 45 46 this.off = function (event, callback) { 47 var namespaces = event.split('.'), 48 namespace = ''; 49 50 if (namespaces.length > 1) { 51 event = namespaces[0]; 52 namespace = namespaces[1]; 53 } 54 55 if (!callbacks[event]) { 56 return self; 57 } 58 var at = -1; 59 if (!namespace) { 60 if ($.isFunction(callback)) { 61 at = callbacks[event][0].indexOf(callback); 62 if (at < 0) { 63 return self; 64 } 65 callbacks[event][0].splice(at, 1); 66 } else { 67 callbacks[event][0] = []; 68 } 69 } else { 70 if (!callbacks[event][1][namespace]) { 71 return self; 72 } 73 74 if ($.isFunction(callback)) { 75 at = callbacks[event][1][namespace].indexOf(callback); 76 if (at < 0) { 77 return self; 78 } 79 callbacks[event][1][namespace].splice(at, 1); 80 } else { 81 callbacks[event][1][namespace] = []; 82 } 83 } 84 85 return self; 86 }; 87 88 this.callEvent = function (event, callbackArgs) { 89 if (!callbacks[event]) { 90 return; 91 } 92 93 if (callbacks[event][0]) { 94 for (var i = 0; i < callbacks[event][0].length; i++) { 95 $.isFunction(callbacks[event][0][i]) && callbacks[event][i][0].apply(self, callbackArgs); 96 } 97 } 98 99 if (callbacks[event][1]) { 100 for (var i in callbacks[event][1]) { 101 for (var j = 0; j < callbacks[event][1][i].length; j++) { 102 $.isFunction(callbacks[event][1][i][j]) && callbacks[event][1][i][j].apply(self, callbackArgs); 103 } 104 } 105 } 106 } 107 }; 108 $.fn.serializeJSON = function (path) { 109 var isInput = $(this).is('input') || $(this).is('select') || $(this).is('textarea'); 110 var unIndexed = isInput ? $(this).serializeArray() : $(this).find('input, select, textarea').serializeArray(), 111 indexed = {}, 112 validate = /(\[([a-zA-Z0-9_-]+)?\]?)/g, 113 arrayKeys = {}, 114 end = false; 115 $.each(unIndexed, function () { 116 var that = this, 117 match = this.name.match(/^([0-9a-zA-Z_-]+)/); 118 if (!match) { 119 return; 120 } 121 var keys = this.name.match(validate), 122 objPath = "indexed['" + match[0] + "']"; 123 124 if (keys) { 125 if (typeof indexed[match[0]] !== 'object') { 126 indexed[match[0]] = {}; 127 } 128
129 $.each(keys, function (i, prop) { 130 prop = prop.replace(/\]|\[/g, ''); 131 var rawPath = objPath.replace(/'|\[|\]/g, ''), 132 objExp = '', 133 preObjPath = objPath; 134 135 if (prop === '') { 136 if (arrayKeys[rawPath] === undefined) { 137 arrayKeys[rawPath] = 0; 138 } else { 139 arrayKeys[rawPath]++; 140 } 141 objPath += "['" + arrayKeys[rawPath] + "']"; 142 } else { 143 if (!isNaN(prop)) { 144 arrayKeys[rawPath] = prop; 145 } 146 objPath += "['" + prop + "']"; 147 } 148 try { 149 if (i === keys.length - 1) { 150 objExp = objPath + "= !(that.value + '').length || isNaN(that.value) ? that.value : Number(that.value);"; 151 end = true; 152 } else { 153 objExp = objPath + "={}"; 154 end = false; 155 } 156 157 var evalString = "" + 158 "if( typeof " + objPath + " == 'undefined'){" + objExp + ";" + 159 "}else{" + 160 "if(end){" + 161 "if(typeof " + preObjPath + "!='object'){" + preObjPath + "={};}" + 162 objExp + 163 "}" + 164 "}"; 165 eval(evalString); 166 } catch (e) { 167 console.log('Error:' + e + "\n" + objExp); 168 } 169 }) 170 } else { 171 indexed[match[0]] = this.value; 172 } 173 }); 174 if (path) { 175 path = "['" + path.replace('.', "']['") + "']"; 176 var c = 'try{indexed = indexed' + path + '}catch(ex){console.log(c, ex);}'; 177 eval(c); 178 } 179 return indexed; 180 }; 181 $.fn.LP_Tooltip = function (options) { 182 options = $.extend({}, { 183 offset: [0, 0] 184 }, options || {}); 185 return $.each(this, function () { 186 var $el = $(this), 187 content = $el.data('content'); 188 if (!content || ($el.data('LP_Tooltip') !== undefined)) { 189 return; 190 } 191 var $tooltip = null; 192 $el.hover(function (e) { 193 $tooltip = $('<div class="learn-press-tooltip-bubble"/>').html(content).appendTo($('body')).hide(); 194 var position = $el.offset(); 195 if ($.isArray(options.offset)) { 196 var top = options.offset[1], 197 left = options.offset[0]; 198 if ($.isNumeric(left)) { 199 position.left += left; 200 } else { 201 202 } 203 if ($.isNumeric(top)) { 204 position.top += top; 205 } else { 206 207 } 208 } 209 $tooltip.css({ 210 top: position.top, 211 left: position.left 212 }); 213 $tooltip.fadeIn(); 214 }, function () { 215 $tooltip && $tooltip.remove(); 216 }); 217 $el.data('LP_Tooltip', true); 218 }); 219 }; 220 $.fn.hasEvent = function (name) { 221 var events = $(this).data('events'); 222 if (typeof events.LP === 'undefined') { 223 return false; 224 } 225 for (i = 0; i < events.LP.length; i++) { 226 if (events.LP[i].namespace === name) { 227 return true; 228 } 229 } 230 return false; 231 }; 232 $.fn.dataToJSON = function () { 233 var json = {}; 234 $.each(this[0].attributes, function () { 235 var m = this.name.match(/^data-(.*)/); 236 if (m) { 237 json[m[1]] = this.value; 238 } 239 }); 240 return json; 241 }; 242 243 String.prototype.getQueryVar = function (name) { 244 name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
245 var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), 246 results = regex.exec(this); 247 return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 248 }; 249 String.prototype.addQueryVar = function (name, value) { 250 var url = this, 251 m = url.split('#'); 252 url = m[0]; 253 if (name.match(/\[/)) { 254 url += url.match(/\?/) ? '&' : '?'; 255 url += name + '=' + value; 256 } else { 257 if ((url.indexOf('&' + name + '=') !== -1) || (url.indexOf('?' + name + '=') !== -1)) { 258 url = url.replace(new RegExp(name + "=([^&#]*)", 'g'), name + '=' + value); 259 } else { 260 url += url.match(/\?/) ? '&' : '?'; 261 url += name + '=' + value; 262 } 263 } 264 return url + (m[1] ? '#' + m[1] : ''); 265 }; 266 String.prototype.removeQueryVar = function (name) { 267 var url = this; 268 var m = url.split('#'); 269 url = m[0]; 270 name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); 271 var regex = new RegExp("[\\?&]" + name + "([\[][^=]*)?=([^&#]*)", 'g'); 272 url = url.replace(regex, ''); 273 return url + (m[1] ? '#' + m[1] : ''); 274 }; 275 276 if ($.isEmptyObject("") === false) { 277 $.isEmptyObject = function (a) { 278 for (prop in a) { 279 if (a.hasOwnProperty(prop)) { 280 return false; 281 } 282 } 283 return true; 284 }; 285 } 286 287 LP.MessageBox = { 288 /* 289 * 290 */ 291 $block: null, 292 $window: null, 293 events: {}, 294 instances: [], 295 instance: null, 296 quickConfirm: function (elem, args) { 297 var $e = $(elem); 298 $('[learn-press-quick-confirm]').each(function () { 299 ($ins = $(this).data('quick-confirm')) && (console.log($ins), $ins.destroy()); 300 }); 301 !$e.attr('learn-press-quick-confirm') && $e.attr('learn-press-quick-confirm', 'true').data('quick-confirm', 302 new (function (elem, args) { 303 var $elem = $(elem), 304 $div = $('<span class="learn-press-quick-confirm"></span>').insertAfter($elem), //($(document.body)), 305 offset = $(elem).position() || {left: 0, top: 0}, 306 timerOut = null, 307 timerHide = null, 308 n = 3, 309 hide = function () { 310 $div.fadeOut('fast', function () { 311 $(this).remove(); 312 $div.parent().css('position', ''); 313 }); 314 $elem.removeAttr('learn-press-quick-confirm').data('quick-confirm', undefined); 315 stop(); 316 }, 317 stop = function () { 318 timerHide && clearInterval(timerHide); 319 timerOut && clearInterval(timerOut); 320 }, 321 start = function () { 322 timerOut = setInterval(function () { 323 if (--n === 0) { 324 hide.call($div[0]); 325 $.isFunction(args.onCancel) && args.onCancel(args.data); 326 stop(); 327 } 328 $div.find('span').html(' (' + n + ')'); 329 }, 1000); 330 331 timerHide = setInterval(function () { 332 if (!$elem.is(':visible') || $elem.css("visibility") === 'hidden') { 333 stop(); 334 $div.remove(); 335 $div.parent().css('position', ''); 336 $.isFunction(args.onCancel) && args.onCancel(args.data); 337 } 338 }, 350); 339 }; 340 args = $.extend({ 341 message: '', 342 data: null, 343 onOk: null, 344 onCancel: null, 345 offset: {top: 0, left: 0} 346 }, args || {}); 347 $div.html(args.message || $elem.attr('data-confirm-remove') || 'Are you sure?').append('<span> (' + n + ')</span>').css({}); 348 $div.click(function () { 349 $.isFunction(args.onOk) && args.onOk(args.data); 350 hide(); 351 }).hover(function () { 352 stop(); 353 }, function () { 354 start(); 355 }); 356 //$div.parent().css('position', 'relative'); 357 $div.css({ 358 left: ((offset.left + $elem.outerWidth()) - $div.outerWidth()) + args.offset.left, 359 top: offset.top + $elem.outerHeight() + args.offset.top + 5 360 }).hide().fadeIn('fast'); 361 start(); 362 363 this.destroy = function () { 364 $div.remove(); 365 $elem.removeAttr('learn-press-quick-confirm').data('quick-confirm', undefined); 366 stop(); 367 368 }; 369 }
369)(elem, args) 370 ); 371 }, 372 show: function (message, args) { 373 //this.hide(); 374 $.proxy(function () { 375 args = $.extend({ 376 title: '', 377 buttons: '', 378 events: false, 379 autohide: false, 380 message: message, 381 data: false, 382 id: LP.uniqueId(), 383 onHide: null 384 }, args || {}); 385 386 this.instances.push(args); 387 this.instance = args; 388 389 var $doc = $(document), 390 $body = $(document.body); 391 if (!this.$block) { 392 this.$block = $('<div id="learn-press-message-box-block"></div>').appendTo($body); 393 394 } 395 if (!this.$window) { 396 this.$window = $('<div id="learn-press-message-box-window"><div id="message-box-wrap"></div> </div>').insertAfter(this.$block); 397 this.$window.click(function () { 398 }); 399 } 400 //this.events = args.events || {}; 401 this._createWindow(message, args.title, args.buttons); 402 this.$block.show(); 403 this.$window.show().attr('instance', args.id); 404 $(window) 405 .bind('resize.message-box', $.proxy(this.update, this)) 406 .bind('scroll.message-box', $.proxy(this.update, this)); 407 this.update(true); 408 if (args.autohide) { 409 setTimeout(function () { 410 LP.MessageBox.hide(); 411 $.isFunction(args.onHide) && args.onHide.call(LP.MessageBox, args); 412 }, args.autohide); 413 } 414 }, this)(); 415 }, 416 blockUI: function (message) { 417 418 message = (message !== false ? (message ? message : 'Wait a moment') : '') + '<div class="message-box-animation"></div>'; 419 this.show(message); 420 }, 421 hide: function (delay, instance) { 422 if (instance) { 423 this._removeInstance(instance.id); 424 } else if (this.instance) { 425 this._removeInstance(this.instance.id); 426 } 427 if (this.instances.length === 0) { 428 if (this.$block) { 429 this.$block.hide(); 430 } 431 if (this.$window) { 432 this.$window.hide(); 433 } 434 $(window) 435 .unbind('resize.message-box', this.update) 436 .unbind('scroll.message-box', this.update); 437 } else { 438 if (this.instance) { 439 this._createWindow(this.instance.message, this.instance.title, this.instance.buttons); 440 } 441 } 442 443 }, 444 update: function (force) { 445 var that = this, 446 $wrap = this.$window.find('#message-box-wrap'), 447 timer = $wrap.data('timer'), 448 _update = function () { 449 LP.Hook.doAction('learn_press_message_box_before_resize', that); 450 var $content = $wrap.find('.message-box-content').css("height", "").css('overflow', 'hidden'), 451 width = $wrap.outerWidth(), 452 height = $wrap.outerHeight(), 453 contentHeight = $content.height(), 454 windowHeight = $(window).height(), 455 top = $wrap.offset().top; 456 if (contentHeight > windowHeight - 50) { 457 $content.css({ 458 height: windowHeight - 25 459 }); 460 height = $wrap.outerHeight(); 461 } else { 462 $content.css("height", "").css('overflow', ''); 463 } 464 $wrap.css({ 465 marginTop: ($(window).height() - height) / 2 466 }); 467 LP.Hook.doAction('learn_press_message_box_resize', height, that); 468 }; 469 if (force) _update(); 470 timer && clearTimeout(timer); 471 timer = setTimeout(_update, 250); 472 }, 473 _removeInstance: function (id) { 474 for (var i = 0; i < this.instances.length; i++) { 475 if (this.instances[i].id === id) { 476 477 this.instances.splice(i, 1); 478 479 var len = this.instances.length; 480 if (len) { 481 this.instance = this.instances[len - 1]; 482 this.$window.attr('instance', this.instance.id); 483 } else { 484 this.instance = false; 485 this.$window.removeAttr('instance'); 486 } 487 break; 488 } 489 } 490 }, 491 _getInstance: function (id) { 492 for (var i = 0; i < this.instances.length; i++) { 493 if (this.instances[i].id === id) { 494 return this.instances[i]; 495 } 496 } 497 }, 498 _createWindow: function (message, title, buttons) { 499 var $wrap = this.$window.find('#message-box-wrap').html(''); 500 if (title) { 501 $wrap.append('<h3 class="message-box-title">' + title + '</h3>'); 502 } 503 $wrap.append($('<div class="message-box-content"></div>').html(message)); 504 if (buttons) { 505 var $buttons = $('<div class="message-box-buttons"></div>'); 506 switch (buttons) { 507 case 'yesNo': 508 $buttons.append(this._createButton(LP_Settings.localize.button_yes, 'yes')); 509 $buttons.append(this._createButton(LP_Settings.localize.button_no, 'no')); 510 break; 511 case 'okCancel': 512 $buttons.append(this._createButton(LP_Settings.localize.button_ok, 'ok')); 513 $buttons.append(this._createButton(LP_Settings.localize.button_cancel, 'cancel')); 514 break; 515 default: 516 $buttons.append(this._createButton(LP_Settings.localize.button_ok, 'ok')); 517 } 518 $wrap.append($buttons); 519 } 520 }, 521 _createButton: function (title, type) { 522 var $button = $('<button type="button" class="button message-box-button message-box-button-' + type + '">' + title + '</button>'), 523 callback = 'on' + (type.substr(0, 1).toUpperCase() + type.substr(1)); 524 $button.data('callback', callback).click(function () { 525 var instance = $(this).data('instance'), 526 callback = instance.events[$(this).data('callback')]; 527 if ($.type(callback) === 'function') { 528 if (callback.apply(LP.MessageBox, [instance]) === false) { 529 // return; 530 } else { 531 LP.MessageBox.hide(null, instance); 532 } 533 } else { 534 LP.MessageBox.hide(null, instance); 535 } 536 }).data('instance', this.instance); 537 return $button; 538 } 539 }; 540 LP.Hook = { 541 hooks: {action: {}, filter: {}}, 542 addAction: function (action, callable, priority, tag) { 543 this.addHook('action', action, callable, priority, tag); 544 return this; 545 }, 546 addFilter: function (action, callable, priority, tag) { 547 this.addHook('filter', action, callable, priority, tag); 548 return this; 549 }, 550 doAction: function (action) { 551 this.doHook('action', action, arguments); 552 return this; 553 }, 554 applyFilters: function (action) { 555 return this.doHook('filter', action, arguments); 556 }, 557 removeAction: function (action, tag) { 558 this.removeHook('action', action, tag); 559 return this; 560 }, 561 removeFilter: function (action, priority, tag) { 562 this.removeHook('filter', action, priority, tag); 563 return this; 564 }, 565 addHook: function (hookType, action, callable, priority, tag) { 566 if (undefined === this.hooks[hookType][action]) { 567 this.hooks[hookType][action] = []; 568 } 569 var hooks = this.hooks[hookType][action]; 570 if (undefined === tag) { 571 tag = action + '_' + hooks.length; 572 } 573 this.hooks[hookType][action].push({tag: tag, callable: callable, priority: priority}); 574 return this; 575 }, 576 doHook: function (hookType, action, args) { 577 578 // splice args from object into array and remove first index which is the hook name 579 args = Array.prototype.slice.call(args, 1); 580 581 if (undefined !== this.hooks[hookType][action]) { 582 var hooks = this.hooks[hookType][action], hook; 583 //sort by priority 584 hooks.sort(function (a, b) { 585 return a["priority"] - b["priority"]; 586 }); 587 for (var i = 0; i < hooks.length; i++) { 588 hook = hooks[i].callable; 589 if (typeof hook !== 'function')
590 hook = window[hook]; 591 if ('action' === hookType) { 592 hook.apply(null, args); 593 } else { 594 args[0] = hook.apply(null, args); 595 } 596 } 597 } 598 if ('filter' === hookType) { 599 return args[0]; 600 } 601 return this; 602 }, 603 removeHook: function (hookType, action, priority, tag) { 604 if (undefined !== this.hooks[hookType][action]) { 605 var hooks = this.hooks[hookType][action]; 606 for (var i = hooks.length - 1; i >= 0; i--) { 607 if ((undefined === tag || tag === hooks[i].tag) && (undefined === priority || priority === hooks[i].priority)) { 608 hooks.splice(i, 1); 609 } 610 } 611 } 612 return this; 613 } 614 }; 615 LP = $.extend({ 616 setUrl: function (url, ember, title) { 617 if (url) { 618 history.pushState({}, title, url); 619 LP.Hook.doAction('learn_press_set_location_url', url); 620 } 621 }, 622 toggleGroupSection: function (el, target) { 623 var $el = $(el), 624 isHide = $el.hasClass('hide-if-js'); 625 if (isHide) { 626 $el.hide().removeClass('hide-if-js'); 627 } 628 $el.removeClass('hide-if-js').slideToggle(function () { 629 var $this = $(this); 630 if ($this.is(':visible')) { 631 $(target).addClass('toggle-on').removeClass('toggle-off'); 632 } else { 633 $(target).addClass('toggle-off').removeClass('toggle-on'); 634 } 635 }); 636 }, 637 overflow: function (el, v) { 638 var $el = $(el), 639 overflow = $el.css('overflow'); 640 if (v) { 641 $el.css('overflow', v).data('overflow', overflow); 642 } else { 643 $el.css('overflow', $el.data('overflow')); 644 } 645 }, 646 getUrl: function () { 647 return window.location.href; 648 }, 649 addQueryVar: function (name, value, url) { 650 return (url === undefined ? window.location.href : url).addQueryVar(name, value); 651 }, 652 removeQueryVar: function (name, url) { 653 return (url === undefined ? window.location.href : url).removeQueryVar(name); 654 }, 655 reload: function (url) { 656 if (!url) { 657 url = window.location.href; 658 } 659 window.location.href = url; 660 }, 661 662 parseResponse: function (response, type) { 663 var m = response.match(/<-- LP_AJAX_START -->(.*)<-- LP_AJAX_END -->/); 664 if (m) { 665 response = m[1]; 666 } 667 return (type || "json") === "json" ? this.parseJSON(response) : response; 668 }, 669 parseJSON: function (data) { 670 var m = (data + '').match(/<-- LP_AJAX_START -->(.*)<-- LP_AJAX_END -->/); 671 try { 672 if (m) { 673 data = $.parseJSON(m[1]); 674 } else { 675 data = $.parseJSON(data); 676 } 677 } catch (e) { 678 data = {}; 679 } 680 return data; 681 }, 682 ajax: function (args) { 683 var type = args.type || 'post', 684 dataType = args.dataType || 'json', 685 data = args.action ? $.extend(args.data, {'lp-ajax': args.action}) : args.data, 686 beforeSend = args.beforeSend || function () { 687 }, 688 url = args.url || window.location.href; 689// console.debug( beforeSend ); 690 $.ajax({
691 data: data, 692 url: url, 693 type: type, 694 dataType: 'html', 695 beforeSend: beforeSend.apply(null, args), 696 success: function (raw) { 697 var response = LP.parseResponse(raw, dataType); 698 $.isFunction(args.success) && args.success(response, raw); 699 }, 700 error: function () { 701 $.isFunction(args.error) && args.error.apply(null, LP.funcArgs2Array()); 702 } 703 }); 704 }, 705 doAjax: function (args) { 706 var type = args.type || 'post', 707 dataType = args.dataType || 'json', 708 action = ((args.prefix === undefined) || 'learnpress_') + args.action, 709 data = args.action ? $.extend(args.data, {action: action}) : args.data; 710 711 $.ajax({ 712 data: data, 713 url: (args.url || window.location.href), 714 type: type, 715 dataType: 'html', 716 success: function (raw) { 717 var response = LP.parseResponse(raw, dataType); 718 $.isFunction(args.success) && args.success(response, raw); 719 }, 720 error: function () { 721 $.isFunction(args.error) && args.error.apply(null, LP.funcArgs2Array()); 722 } 723 }); 724 }, 725 726 funcArgs2Array: function (args) { 727 var arr = []; 728 for (var i = 0; i < args.length; i++) { 729 arr.push(args[i]); 730 } 731 return arr; 732 }, 733 addFilter: function (action, callback) { 734 var $doc = $(document), 735 event = 'LP.' + action; 736 $doc.on(event, callback); 737 LP.log($doc.data('events')); 738 return this; 739 }, 740 applyFilters: function () { 741 var $doc = $(document), 742 action = arguments[0], 743 args = this.funcArgs2Array(arguments); 744 if ($doc.hasEvent(action)) { 745 args[0] = 'LP.' + action; 746 return $doc.triggerHandler.apply($doc, args); 747 } 748 return args[1]; 749 }, 750 addAction: function (action, callback) { 751 return this.addFilter(action, callback); 752 }, 753 doAction: function () { 754 var $doc = $(document), 755 action = arguments[0], 756 args = this.funcArgs2Array(arguments); 757 if ($doc.hasEvent(action)) { 758 args[0] = 'LP.' + action; 759 $doc.trigger.apply($doc, args); 760 } 761 }, 762 toElement: function (element, args) { 763 if ($(element).length === 0) { 764 return; 765 } 766 args = $.extend({ 767 delay: 300, 768 duration: 'slow', 769 offset: 50, 770 container: null, 771 callback: null, 772 invisible: false 773 }, args || {}); 774 var $container = $(args.container), 775 rootTop = 0; 776 if ($container.length === 0) { 777 $container = $('body, html'); 778 } 779 rootTop = $container.offset().top; 780 var to = ($(element).offset().top + $container.scrollTop()) - rootTop - args.offset; 781 782 function isElementInView(element, fullyInView) { 783 var pageTop = $container.scrollTop(); 784 var pageBottom = pageTop + $container.height(); 785 var elementTop = $(element).offset().top - $container.offset().top; 786 var elementBottom = elementTop + $(element).height(); 787 788 if (fullyInView === true) { 789 return ((pageTop < elementTop) && (pageBottom > elementBottom)); 790 } else { 791 return ((elementTop <= pageBottom) && (elementBottom >= pageTop)); 792 } 793 } 794 795 if (args.invisible && isElementInView(element, true)) { 796 return; 797 } 798 $container.fadeIn(10) 799 .delay(args.delay) 800 .animate({ 801 scrollTop: to 802 }, args.duration, args.callback); 803 }, 804 uniqueId: function (prefix, more_entropy) { 805 if (typeof prefix === 'undefined') { 806 prefix = ''; 807 } 808 809 var retId;
810 var formatSeed = function (seed, reqWidth) { 811 seed = parseInt(seed, 10) 812 .toString(16); // to hex str 813 if (reqWidth < seed.length) { // so long we split 814 return seed.slice(seed.length - reqWidth); 815 } 816 if (reqWidth > seed.length) { // so short we pad 817 return new Array(1 + (reqWidth - seed.length)) 818 .join('0') + seed; 819 } 820 return seed; 821 }; 822 823 // BEGIN REDUNDANT 824 if (!this.php_js) { 825 this.php_js = {}; 826 } 827 // END REDUNDANT 828 if (!this.php_js.uniqidSeed) { // init seed with big random int 829 this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15); 830 } 831 this.php_js.uniqidSeed++; 832 833 retId = prefix; // start with prefix, add current milliseconds hex string 834 retId += formatSeed(parseInt(new Date() 835 .getTime() / 1000, 10), 8); 836 retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string 837 if (more_entropy) { 838 // for more entropy we add a float lower to 10 839 retId += (Math.random() * 10) 840 .toFixed(8) 841 .toString(); 842 } 843 844 return retId; 845 }, 846 log: function () { 847 //if (typeof LEARN_PRESS_DEBUG != 'undefined' && LEARN_PRESS_DEBUG && console) { 848 for (var i = 0, n = arguments.length; i < n; i++) { 849 console.log(arguments[i]); 850 } 851 //} 852 }, 853 blockContent: function () { 854 if ($('#learn-press-block-content').length === 0) { 855 $(LP.template('learn-press-template-block-content', {})).appendTo($('body')); 856 } 857 LP.hideMainScrollbar().addClass('block-content'); 858 $(document).trigger('learn_press_block_content'); 859 }, 860 unblockContent: function () { 861 setTimeout(function () { 862 LP.showMainScrollbar().removeClass('block-content'); 863 $(document).trigger('learn_press_unblock_content'); 864 }, 350); 865 }, 866 hideMainScrollbar: function (el) { 867 if (!el) { 868 el = 'html, body'; 869 } 870 var $el = $(el); 871 $el.each(function () { 872 var $root = $(this), 873 overflow = $root.css('overflow'); 874 $root.css('overflow', 'hidden').attr('overflow', overflow); 875 }); 876 return $el; 877 }, 878 showMainScrollbar: function (el) { 879 if (!el) { 880 el = 'html, body'; 881 } 882 var $el = $(el); 883 $el.each(function () { 884 var $root = $(this), 885 overflow = $root.attr('overflow'); 886 $root.css('overflow', overflow).removeAttr('overflow'); 887 }); 888 return $el; 889 }, 890 template: _.memoize(function (id, data) { 891 var compiled, 892 options = { 893 evaluate: /<#([\s\S]+?)#>/g, 894 interpolate: /\{\{\{([\s\S]+?)\}\}\}/g, 895 escape: /\{\{([^\}]+?)\}\}(?!\})/g, 896 variable: 'data' 897 }; 898 899 var tmpl = function (data) { 900 compiled = compiled || _.template($('#' + id).html(), null, options); 901 return compiled(data); 902 }; 903 return data ? tmpl(data) : tmpl; 904 }, function (a, b) { 905 return a + '-' + JSON.stringify(b); 906 }), 907 alert: function (localize, callback) { 908 var title = '', 909 message = ''; 910 if (typeof localize === 'string') { 911 message = localize; 912 } else { 913 if (typeof localize['title'] !== 'undefined') { 914 title = localize['title']; 915 } 916 if (typeof localize['message'] !== 'undefined') { 917 message = localize['message']; 918 } 919 } 920 $.alerts.alert(message, title, function (e) { 921 LP._on_alert_hide(); 922 callback && callback(e); 923 }); 924 this._on_alert_show(); 925 }, 926 confirm: function (localize, callback) { 927 var title = '', 928 message = ''; 929 930 if (typeof localize === 'string') { 931 message = localize; 932 } else { 933 if (typeof localize['title'] !== 'undefined') { 934 title = localize['title']; 935 } 936 if (typeof localize['message'] !== 'undefined') { 937 message = localize['message']; 938 } 939 } 940 $.alerts.confirm(message, title, function (e) { 941 LP._on_alert_hide(); 942 callback && callback(e); 943 }); 944 this._on_alert_show(); 945 946 }, 947 _on_alert_show: function () { 948 var $container = $('#popup_container'), 949 $placeholder = $('<span id="popup_container_placeholder" />').insertAfter($container).data('xxx', $container); 950 $container.stop().css('top', '-=50').css('opacity', '0').animate({ 951 top: '+=50', 952 opacity: 1 953 }, 250); 954 }, 955 _on_alert_hide: function () { 956 var $holder = $("#popup_container_placeholder"), 957 $container = $holder.data('xxx'); 958 if ($container) { 959 $container.replaceWith($holder); 960 } 961 $container.appendTo($(document.body)) 962 $container.stop().animate({ 963 top: '+=50', 964 opacity: 0 965 }, 250, function () { 966 $(this).remove(); 967 }); 968 }, 969 sendMessage: function (data, object, targetOrigin, transfer) { 970 if ($.isPlainObject(data)) { 971 data = JSON.stringify(data); 972 } 973 object = object || window; 974 targetOrigin = targetOrigin || '*'; 975 object.postMessage(data, targetOrigin, transfer); 976 }, 977 receiveMessage: function (event, b) { 978 var target = event.origin || event.originalEvent.origin, 979 data = event.data || event.originalEvent.data || ''; 980 if (typeof data === 'string' || data instanceof String) { 981 if (data.indexOf('{') === 0) { 982 data = LP.parseJSON(data); 983 } 984 } 985 LP.Hook.doAction('learn_press_receive_message', data, target); 986 } 987 }, LP); 988 989 $.fn.rows = function () { 990 var h = $(this).height(); 991 var lh = $(this).css('line-height').replace("px", ""); 992 $(this).attr({height: h, 'line-height': lh}); 993 return Math.floor(h / parseInt(lh)); 994 }; 995 996 $.fn.checkLines = function (p) { 997 return this.each(function () { 998 var $e = $(this), 999 rows = $e.rows(); 1000 1001 p.call(this, rows); 1002 }); 1003 }; 1004 1005 $.fn.findNext = function (selector) { 1006 var $selector = $(selector), 1007 $root = this.first(), 1008 index = $selector.index($root), 1009 $next = $selector.eq(index + 1); 1010 return $next.length ? $next : false; 1011 }; 1012 1013 $.fn.findPrev = function (selector) { 1014 var $selector = $(selector), 1015 $root = this.first(), 1016 index = $selector.index($root), 1017 $prev = $selector.eq(index - 1); 1018 return $prev.length ? $prev : false; 1019 }; 1020 1021 $.each(['progress'], function (i, property) { 1022 $.Tween.propHooks[property] = { 1023 get: function (tween) { 1024 return $(tween.elem).css('transform'); 1025 }, 1026 set: function (tween) { 1027 /*var style = tween.elem.style; 1028 var p_begin = parseColor($(tween.elem).css(property)); 1029 var p_end = parseColor(tween.end); 1030 tween.run = function(progress) { 1031 style[property] = calculateColor(p_begin, p_end, progress); 1032 }*/ 1033 if (tween.now < 180) { 1034 $(this).find('.progress-circle').removeClass('gt-50'); 1035 } else { 1036 $(this).find('.progress-circle').addClass('gt-50'); 1037 } 1038 $(tween.elem).find('.fill').css({ 1039 transform: 'rotate(' + tween.end + 'deg)' 1040 }); 1041 } 1042 }; 1043 });
1044 1045 $.fn.progress = function (v) { 1046 return this.each(function () { 1047 var t = parseInt(v / 100 * 360), 1048 timer = null, 1049 $this = $(this); 1050 1051 if (t < 180) { 1052 $this.find('.progress-circle').removeClass('gt-50'); 1053 } else { 1054 $this.find('.progress-circle').addClass('gt-50'); 1055 } 1056 $this.find('.fill').css({ 1057 transform: 'rotate(' + t + 'deg)' 1058 }); 1059 1060 }); 1061 }; 1062 1063 function QuickTip(el, options) { 1064 var $el = $(el); 1065 1066 options = $.extend({ 1067 event: 'hover', 1068 autoClose: true, 1069 single: true, 1070 closeInterval: 1000, 1071 arrowOffset: null, 1072 tipClass: '' 1073 }, options, $el.data()); 1074 1075 var content = $el.data('content-tip') || $el.html(), 1076 $tip = $('<div class="learn-press-tip-floating">' + content + '</div>'), 1077 t = null, 1078 closeInterval = 0, 1079 useData = false, 1080 arrowOffset = options.arrowOffset == 'el' ? $el.outerWidth() / 2 : 8; 1081 1082 $tip.addClass(options.tipClass); 1083 1084 if ($el.attr('data-content-tip')) { 1085 $el.removeAttr('data-content-tip'); 1086 useData = true; 1087 } 1088 1089 closeInterval = options.closeInterval; 1090 1091 if (options.autoClose === false) { 1092 $tip.append('<a class="close"></a>'); 1093 $tip.on('click', '.close', function () { 1094 close(); 1095 }) 1096 } 1097 1098 function show() { 1099 if (t) { 1100 clearTimeout(t); 1101 return; 1102 } 1103 1104 if (options.single) { 1105 $('.learn-press-tip').not($el).QuickTip('close'); 1106 } 1107 1108 $tip.appendTo(document.body); 1109 var pos = $el.offset(); 1110 1111 $tip.css({ 1112 top: pos.top - $tip.outerHeight() - 8, 1113 left: pos.left - $tip.outerWidth() / 2 + arrowOffset 1114 }); 1115 } 1116 1117 function hide() { 1118 t && clearTimeout(t); 1119 t = setTimeout(function () { 1120 $tip.detach(); 1121 t = null; 1122 }, closeInterval); 1123 } 1124 1125 function close() { 1126 closeInterval = 0; 1127 hide(); 1128 closeInterval = options.closeInterval; 1129 } 1130 1131 function open() { 1132 show(); 1133 } 1134 1135 if (!useData) { 1136 $el.html(''); 1137 } 1138 1139 if (options.event === 'click') { 1140 $el.on('click', function (e) { 1141 e.stopPropagation(); 1142 show(); 1143 }) 1144 } 1145 $el.hover( 1146 function (e) { 1147 e.stopPropagation(); 1148 if (options.event !== 'click') { 1149 show(); 1150 } 1151 }, 1152 function (e) { 1153 e.stopPropagation(); 1154 if (options.autoClose) { 1155 hide(); 1156 } 1157 } 1158 ).addClass('ready'); 1159 1160 return { 1161 close: close, 1162 open: open 1163 } 1164 } 1165 1166 $.fn.QuickTip = function (options) { 1167 return $.each(this, function () { 1168 var $tip = $(this).data('quick-tip'); 1169 1170 if (!$tip) { 1171 $tip = new QuickTip(this, options); 1172 $(this).data('quick-tip', $tip); 1173 } 1174 1175 if ($.type(options) === 'string') { 1176 $tip[options] && $tip[options].apply($tip); 1177 } 1178 }) 1179 } 1180 1181 function __initSubtabs() { 1182 $('.learn-press-subtabs').each(function () { 1183 var $tabContainer = $(this), 1184 $tabs = $tabContainer.find('a'), 1185 current = null; 1186 $tabs.click(function (e) { 1187 var $tab = $(this), 1188 $contentID = $tab.attr('href'); 1189 $tab.parent().addClass('current').siblings().removeClass('current'); 1190 current = $($contentID).addClass('current'); 1191 current.siblings().removeClass('current'); 1192 //LP.setUrl($contentID); 1193 e.preventDefault(); 1194 }).filter(function () { 1195 return $(this).attr('href') === window.location.hash; 1196 }).trigger('click'); 1197 if (!current) { 1198 $tabs.first().trigger('click'); 1199 } 1200 }); 1201 } 1202 1203 $(document).ready(function () { 1204 if (typeof $.alerts !== 'undefined') { 1205 $.alerts.overlayColor = '#000'; 1206 $.alerts.overlayOpacity = 0.5; 1207 $.alerts.okButton = lpGlobalSettings.localize.button_ok; 1208 $.alerts.cancelButton = lpGlobalSettings.localize.button_cancel; 1209 } 1210 1211 $('.learn-press-message.fixed').each(function () { 1212 var $el = $(this), 1213 options = $el.data(); 1214 (function ($el, options) { 1215 if (options.delayIn) { 1216 setTimeout(function () { 1217 $el.show().hide().fadeIn(); 1218 }, options.delayIn); 1219 } 1220 if (options.delayOut) { 1221 setTimeout(function () { 1222 $el.fadeOut(); 1223 }, options.delayOut + (options.delayIn || 0)); 1224 } 1225 })($el, options); 1226 1227 }); 1228 1229 1230 $(document).on('input', '#meta-box-tab-course_payment', function (e) { 1231 var _self = $(this), 1232 _price = $('#_lp_price'), 1233 _sale_price = $('#_lp_sale_price'), 1234 _target = $(e.target).attr('id'); 1235 _self.find('#field-_lp_price div, #field-_lp_sale_price div').remove('.learn-press-tip-floating'); 1236 if (parseInt(_sale_price.val()) >= parseInt(_price.val())) { 1237 if (_target === '_lp_price') { 1238 _price.parent('.rwmb-input').append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_price + '</div>'); 1239 } else if (_target === '_lp_sale_price') { 1240 _sale_price.parent('.rwmb-input').append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_sale_price + '</div>'); 1241 } 1242 } 1243 }); 1244 1245 $(document).on('change', '#_lp_sale_start', function (e) { 1246 var _sale_start_date = $(this), 1247 _sale_end_date = $('#_lp_sale_end'), 1248 _start_date = Date.parse(_sale_start_date.val()), 1249 _end_date = Date.parse(_sale_end_date.val()), 1250 _parent_start = _sale_start_date.parent('.rwmb-input'), 1251 _parent_end = _sale_end_date.parent('.rwmb-input'); 1252 1253 if (!_start_date) { 1254 _parent_start.append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_invalid_date + '</div>') 1255 } 1256 1257 $('#field-_lp_sale_start div, #field-_lp_sale_end div').remove('.learn-press-tip-floating'); 1258 if (_start_date < _end_date) { 1259 _parent_start.append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_sale_start_date + '</div>') 1260 } 1261 }); 1262 1263 $(document).on('change', '#_lp_sale_end', function (e) { 1264 var _sale_end_date = $(this), 1265 _sale_start_date = $('#_lp_sale_start'), 1266 _start_date = Date.parse(_sale_start_date.val()), 1267 _end_date = Date.parse(_sale_end_date.val()), 1268 _parent_start = _sale_start_date.parent('.rwmb-input'), 1269 _parent_end = _sale_end_date.parent('.rwmb-input'); 1270 1271 if (!_end_date) { 1272 _parent_end.append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_invalid_date + '</div>') 1273 } 1274 1275 $('#field-_lp_sale_start div, #field-_lp_sale_end div').remove('.learn-press-tip-floating'); 1276 if (_start_date < _end_date) { 1277 _parent_end.append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_sale_end_date + '</div>') 1278 } 1279 }); 1280 1281 $('body') 1282 .on('click', '.learn-press-nav-tabs li a', function (e) { 1283 e.preventDefault(); 1284 var $tab = $(this), url = ''; 1285 $tab.closest('li').addClass('active').siblings().removeClass('active'); 1286 $($tab.attr('data-tab')).addClass('active').siblings().removeClass('active'); 1287 $(document).trigger('learn-press/nav-tabs/clicked', $tab); 1288 }); 1289 1290 setTimeout(function () { 1291 $('.learn-press-nav-tabs li.active:not(.default) a').trigger('click'); 1292 }, 300); 1293 1294 $('body.course-item-popup').parent().css('overflow', 'hidden'); 1295 /// 1296 (function () { 1297 var timer = null, 1298 callback = function () { 1299 $('.auto-check-lines').checkLines(function (r) { 1300 if (r > 1) { 1301 $(this).removeClass('single-lines'); 1302 } else { 1303 $(this).addClass('single-lines'); 1304 } 1305 $(this).attr('rows', r); 1306 }); 1307 }; 1308 $(window).on('resize.check-lines', function () { 1309 if (timer) { 1310 timer && clearTimeout(timer); 1311 timer = setTimeout(callback, 300); 1312 } else { 1313 callback(); 1314 } 1315 }); 1316 })(); 1317 1318 $(document).on('click', '[data-block-content="yes"]', function () { 1319 LP.blockContent(); 1320 }); 1321 1322 $('.learn-press-tooltip, .lp-passing-conditional').LP_Tooltip({offset: [24, 24]}); 1323 1324 $('.learn-press-icon').LP_Tooltip({offset: [30, 30]}); 1325 1326 $('.learn-press-message[data-autoclose]').each(function () {
1327 var $el = $(this), delay = parseInt($el.data('autoclose')); 1328 if (delay) { 1329 setTimeout(function ($el) { 1330 $el.fadeOut(); 1331 }, delay, $el); 1332 } 1333 }); 1334 }); 1335 LearnPress = LP; 1336 1337})(jQuery); 1338 1339
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.