1/** 2 * Common functions/utils used in all page 3 */ 4if (typeof window.LP == 'undefined') { 5 window.LP = window.LearnPress = {}; 6} 7 8 9(function ($) { 10 /** 11 * Manage event callbacks. 12 * Allow add/remove a callback function into custom event of an object. 13 * 14 * @constructor 15 */ 16 window.LP.Event_Callback = function (self) { 17 var callbacks = {}; 18 19 this.on = function (event, callback) { 20 var namespaces = event.split('.'), 21 namespace = ''; 22 23 if (namespaces.length > 1) { 24 event = namespaces[0]; 25 namespace = namespaces[1]; 26 } 27 28 if (!callbacks[event]) { 29 callbacks[event] = [[], {}]; 30 } 31 32 if (namespace) { 33 if (!callbacks[event][1][namespace]) { 34 callbacks[event][1][namespace] = []; 35 } 36 callbacks[event][1][namespace].push(callback); 37 } else { 38 callbacks[event][0].push(callback); 39 } 40 41 return self; 42 }; 43 44 this.off = function (event, callback) { 45 var namespaces = event.split('.'), 46 namespace = ''; 47 48 if (namespaces.length > 1) { 49 event = namespaces[0]; 50 namespace = namespaces[1]; 51 } 52 53 if (!callbacks[event]) { 54 return self; 55 } 56 var at = -1; 57 if (!namespace) { 58 if ($.isFunction(callback)) { 59 at = callbacks[event][0].indexOf(callback); 60 if (at < 0) { 61 return self; 62 } 63 callbacks[event][0].splice(at, 1); 64 } else { 65 callbacks[event][0] = []; 66 } 67 } else { 68 if (!callbacks[event][1][namespace]) { 69 return self; 70 } 71 72 if ($.isFunction(callback)) { 73 at = callbacks[event][1][namespace].indexOf(callback); 74 if (at < 0) { 75 return self; 76 } 77 callbacks[event][1][namespace].splice(at, 1); 78 } else { 79 callbacks[event][1][namespace] = []; 80 } 81 } 82 83 return self; 84 }; 85 86 this.callEvent = function (event, callbackArgs) { 87 if (!callbacks[event]) { 88 return; 89 } 90 91 if (callbacks[event][0]) { 92 for (var i = 0; i < callbacks[event][0].length; i++) { 93 $.isFunction(callbacks[event][0][i]) && callbacks[event][i][0].apply(self, callbackArgs); 94 } 95 } 96 97 if (callbacks[event][1]) { 98 for (var i in callbacks[event][1]) { 99 for (var j = 0; j < callbacks[event][1][i].length; j++) { 100 $.isFunction(callbacks[event][1][i][j]) && callbacks[event][1][i][j].apply(self, callbackArgs); 101 } 102 } 103 } 104 } 105 }; 106 $.fn.serializeJSON = function (path) { 107 var isInput = $(this).is('input') || $(this).is('select') || $(this).is('textarea'); 108 var unIndexed = isInput ? $(this).serializeArray() : $(this).find('input, select, textarea').serializeArray(), 109 indexed = {}, 110 validate = /(\[([a-zA-Z0-9_-]+)?\]?)/g, 111 arrayKeys = {}, 112 end = false; 113 $.each(unIndexed, function () { 114 var that = this, 115 match = this.name.match(/^([0-9a-zA-Z_-]+)/); 116 if (!match) { 117 return; 118 } 119 var keys = this.name.match(validate), 120 objPath = "indexed['" + match[0] + "']"; 121 122 if (keys) { 123 if (typeof indexed[match[0]] != 'object') { 124 indexed[match[0]] = {}; 125 } 126 127 $.each(keys, function (i, prop) { 128 prop = prop.replace(/\]|\[/g, ''); 129 var rawPath = objPath.replace(/'|\[|\]/g, ''), 130 objExp = '', 131 preObjPath = objPath; 132 133 if (prop == '') { 134 if (arrayKeys[rawPath] == undefined) { 135 arrayKeys[rawPath] = 0; 136 } else { 137 arrayKeys[rawPath]++; 138 } 139 objPath += "['" + arrayKeys[rawPath] + "']"; 140 } else { 141 if (!isNaN(prop)) { 142 arrayKeys[rawPath] = prop; 143 } 144 objPath += "['" + prop + "']"; 145 } 146 try { 147 if (i == keys.length - 1) { 148 objExp = objPath + "=that.value;"; 149 end = true; 150 } else { 151 objExp = objPath + "={}"; 152 end = false;
153 } 154 155 var evalString = "" + 156 "if( typeof " + objPath + " == 'undefined'){" + objExp + ";" + 157 "}else{" + 158 "if(end){" + 159 "if(typeof " + preObjPath + "!='object'){" + preObjPath + "={};}" + 160 objExp + 161 "}" + 162 "}"; 163 eval(evalString); 164 } catch (e) { 165 console.log('Error:' + e + "\n" + objExp); 166 } 167 }) 168 } else { 169 indexed[match[0]] = this.value; 170 } 171 }); 172 if (path) { 173 path = "['" + path.replace('.', "']['") + "']"; 174 var c = 'try{indexed = indexed' + path + '}catch(ex){console.log(c, ex);}'; 175 eval(c); 176 } 177 return indexed; 178 }; 179 $.fn.LP_Tooltip = function (options) { 180 options = $.extend({}, { 181 offset: [0, 0] 182 }, options || {}); 183 return $.each(this, function () { 184 var $el = $(this), 185 content = $el.data('content'); 186 if (!content || ($el.data('LP_Tooltip') !== undefined)) { 187 return; 188 } 189 190 console.log(content); 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('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 })(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: typeof _ !== 'undefined' ? _.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 }) : function () { 907 return ''; 908 }, 909 alert: function (localize, callback) { 910 var title = '', 911 message = ''; 912 if (typeof localize === 'string') { 913 message = localize; 914 } else { 915 if (typeof localize['title'] !== 'undefined') { 916 title = localize['title']; 917 } 918 if (typeof localize['message'] !== 'undefined') { 919 message = localize['message']; 920 } 921 } 922 $.alerts.alert(message, title, function (e) { 923 LP._on_alert_hide(); 924 callback && callback(e); 925 }); 926 this._on_alert_show(); 927 }, 928 confirm: function (localize, callback) { 929 var title = '', 930 message = ''; 931 932 if (typeof localize === 'string') { 933 message = localize; 934 } else { 935 if (typeof localize['title'] !== 'undefined') { 936 title = localize['title']; 937 } 938 if (typeof localize['message'] !== 'undefined') { 939 message = localize['message']; 940 } 941 } 942 $.alerts.confirm(message, title, function (e) { 943 LP._on_alert_hide(); 944 callback && callback(e); 945 }); 946 this._on_alert_show(); 947 948 }, 949 _on_alert_show: function () { 950 var $container = $('#popup_container'), 951 $placeholder = $('<span id="popup_container_placeholder" />').insertAfter($container).data('xxx', $container); 952 $container.stop().css('top', '-=50').css('opacity', '0').animate({ 953 top: '+=50', 954 opacity: 1 955 }, 250); 956 }, 957 _on_alert_hide: function () { 958 var $holder = $("#popup_container_placeholder"), 959 $container = $holder.data('xxx'); 960 if ($container) { 961 $container.replaceWith($holder); 962 } 963 $container.appendTo($(document.body)) 964 $container.stop().animate({ 965 top: '+=50', 966 opacity: 0 967 }, 250, function () { 968 $(this).remove(); 969 }); 970 }, 971 sendMessage: function (data, object, targetOrigin, transfer) { 972 if ($.isPlainObject(data)) { 973 data = JSON.stringify(data); 974 } 975 object = object || window; 976 targetOrigin = targetOrigin || '*'; 977 object.postMessage(data, targetOrigin, transfer); 978 }, 979 receiveMessage: function (event, b) { 980 var target = event.origin || event.originalEvent.origin, 981 data = event.data || event.originalEvent.data || ''; 982 if (typeof data === 'string' || data instanceof String) { 983 if (data.indexOf('{') === 0) { 984 data = LP.parseJSON(data); 985 } 986 } 987 LP.Hook.doAction('learn_press_receive_message', data, target); 988 } 989 }, LP); 990 991 $.fn.rows = function () { 992 var h = $(this).height(); 993 var lh = $(this).css('line-height').replace("px", ""); 994 $(this).attr({height: h, 'line-height': lh}); 995 return Math.floor(h / parseInt(lh)); 996 }; 997 998 $.fn.checkLines = function (p) { 999 return this.each(function () { 1000 var $e = $(this), 1001 rows = $e.rows(); 1002 1003 p.call(this, rows); 1004 }); 1005 }; 1006 1007 $.fn.findNext = function (selector) { 1008 var $selector = $(selector), 1009 $root = this.first(), 1010 index = $selector.index($root), 1011 $next = $selector.eq(index + 1); 1012 return $next.length ? $next : false;
1013 }; 1014 1015 $.fn.findPrev = function (selector) { 1016 var $selector = $(selector), 1017 $root = this.first(), 1018 index = $selector.index($root), 1019 $prev = $selector.eq(index - 1); 1020 return $prev.length ? $prev : false; 1021 }; 1022 1023 $.each(['progress'], function (i, property) { 1024 $.Tween.propHooks[property] = { 1025 get: function (tween) { 1026 return $(tween.elem).css('transform'); 1027 }, 1028 set: function (tween) { 1029 /*var style = tween.elem.style; 1030 var p_begin = parseColor($(tween.elem).css(property)); 1031 var p_end = parseColor(tween.end); 1032 tween.run = function(progress) { 1033 style[property] = calculateColor(p_begin, p_end, progress); 1034 }*/ 1035 if (tween.now < 180) { 1036 $(this).find('.progress-circle').removeClass('gt-50'); 1037 } else { 1038 $(this).find('.progress-circle').addClass('gt-50'); 1039 } 1040 $(tween.elem).find('.fill').css({ 1041 transform: 'rotate(' + tween.end + 'deg)' 1042 }); 1043 } 1044 }; 1045 }); 1046 1047 $.fn.progress = function (v) { 1048 return this.each(function () { 1049 var t = parseInt(v / 100 * 360), 1050 timer = null, 1051 $this = $(this); 1052 1053 if (t < 180) { 1054 $this.find('.progress-circle').removeClass('gt-50'); 1055 } else { 1056 $this.find('.progress-circle').addClass('gt-50'); 1057 } 1058 $this.find('.fill').css({ 1059 transform: 'rotate(' + t + 'deg)' 1060 }); 1061 1062 }); 1063 }; 1064 1065 var xxx = 0; 1066 1067 function QuickTip(el, options) { 1068 var $el = $(el), 1069 uniId = $el.attr('data-id') || LP.uniqueId(); 1070 1071 options = $.extend({ 1072 event: 'hover', 1073 autoClose: true, 1074 single: true, 1075 closeInterval: 1000, 1076 arrowOffset: null, 1077 tipClass: '' 1078 }, options, $el.data()); 1079 1080 $el.attr('data-id', uniId); 1081 1082 var content = $el.attr('data-content-tip') || $el.html(), 1083 $tip = $('<div class="learn-press-tip-floating">' + content + '</div>'), 1084 t = null, 1085 closeInterval = 0, 1086 useData = false, 1087 arrowOffset = options.arrowOffset === 'el' ? $el.outerWidth() / 2 : 8, 1088 $content = $('#__' + uniId); 1089 1090 if ($content.length === 0) { 1091 $(document.body).append($('<div />').attr('id', '__' + uniId).html(content).css('display', 'none')) 1092 } 1093 1094 content = $content.html(); 1095 1096 $tip.addClass(options.tipClass); 1097 1098 $el.data('content-tip', content); 1099 if ($el.attr('data-content-tip')) { 1100 //$el.removeAttr('data-content-tip'); 1101 useData = true; 1102 } 1103 1104 closeInterval = options.closeInterval; 1105 1106 if (options.autoClose === false) { 1107 $tip.append('<a class="close"></a>'); 1108 $tip.on('click', '.close', function () { 1109 close(); 1110 }) 1111 } 1112 1113 function show() { 1114 if (t) { 1115 clearTimeout(t); 1116 return; 1117 } 1118 1119 if (options.single) { 1120 $('.learn-press-tip').not($el).QuickTip('close'); 1121 } 1122 1123 $tip.appendTo(document.body); 1124 var pos = $el.offset(); 1125 1126 $tip.css({ 1127 top: pos.top - $tip.outerHeight() - 8, 1128 left: pos.left - $tip.outerWidth() / 2 + arrowOffset 1129 }); 1130 } 1131 1132 function hide() { 1133 t && clearTimeout(t); 1134 t = setTimeout(function () { 1135 $tip.detach(); 1136 t = null; 1137 }, closeInterval); 1138 } 1139 1140 function close() { 1141 closeInterval = 0; 1142 hide(); 1143 closeInterval = options.closeInterval; 1144 } 1145 1146 function open() { 1147 show(); 1148 } 1149 1150 if (!useData) { 1151 $el.html(''); 1152 } 1153 1154 if (options.event === 'click') { 1155 $el.on('click', function (e) { 1156 e.stopPropagation(); 1157 show(); 1158 }) 1159 } 1160 1161 $(document).on('learn-press/close-all-quick-tip', function () { 1162 close(); 1163 }); 1164 $el.hover( 1165 function (e) { 1166 e.stopPropagation(); 1167 if (options.event !== 'click') { 1168 show(); 1169 } 1170 }, 1171 function (e) { 1172 e.stopPropagation(); 1173 if (options.autoClose) { 1174 hide(); 1175 } 1176 } 1177 ).addClass('ready'); 1178 return { 1179 close: close, 1180 open: open 1181 } 1182 } 1183 1184 $.fn.QuickTip = function (options) { 1185 return $.each(this, function () { 1186 var $tip = $(this).data('quick-tip'); 1187 1188 if (!$tip) { 1189 $tip = new QuickTip(this, options); 1190 $(this).data('quick-tip', $tip); 1191 } 1192 1193 if ($.type(options) === 'string') { 1194 $tip[options] && $tip[options].apply($tip); 1195 } 1196 }) 1197 } 1198 1199 function __initSubtabs() { 1200 $('.learn-press-subtabs').each(function () { 1201 var $tabContainer = $(this), 1202 $tabs = $tabContainer.find('a'), 1203 current = null; 1204 $tabs.click(function (e) { 1205 var $tab = $(this), 1206 $contentID = $tab.attr('href'); 1207 $tab.parent().addClass('current').siblings().removeClass('current'); 1208 current = $($contentID).addClass('current'); 1209 current.siblings().removeClass('current'); 1210 //LP.setUrl($contentID); 1211 e.preventDefault(); 1212 }).filter(function () { 1213 return $(this).attr('href') === window.location.hash; 1214 }).trigger('click'); 1215 if (!current) { 1216 $tabs.first().trigger('click'); 1217 } 1218 }); 1219 } 1220 1221 $(document).ready(function () { 1222 if (typeof $.alerts !== 'undefined') { 1223 $.alerts.overlayColor = '#000'; 1224 $.alerts.overlayOpacity = 0.5; 1225 $.alerts.okButton = lpGlobalSettings.localize.button_ok; 1226 $.alerts.cancelButton = lpGlobalSettings.localize.button_cancel; 1227 } 1228 1229 $('.learn-press-message.fixed').each(function () { 1230 var $el = $(this), 1231 options = $el.data(); 1232 (function ($el, options) { 1233 if (options.delayIn) { 1234 setTimeout(function () { 1235 $el.show().hide().fadeIn(); 1236 }, options.delayIn); 1237 } 1238 if (options.delayOut) { 1239 setTimeout(function () { 1240 $el.fadeOut(); 1241 }, options.delayOut + (options.delayIn || 0)); 1242 } 1243 })($el, options); 1244 1245 }); 1246 1247 1248 $(document).on('input', '#meta-box-tab-course_payment', function (e) { 1249 var _self = $(this), 1250 _price = $('#_lp_price'), 1251 _sale_price = $('#_lp_sale_price'), 1252 _target = $(e.target).attr('id'); 1253 _self.find('#field-_lp_price div, #field-_lp_sale_price div').remove('.learn-press-tip-floating'); 1254 if (parseInt(_sale_price.val()) >= parseInt(_price.val())) { 1255 if (_target === '_lp_price') { 1256 _price.parent('.rwmb-input').append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_price + '</div>'); 1257 } else if (_target === '_lp_sale_price') { 1258 _sale_price.parent('.rwmb-input').append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_sale_price + '</div>'); 1259 } 1260 } 1261 }); 1262 1263 $(document).on('change', '#_lp_sale_start', function (e) { 1264 var _sale_start_date = $(this), 1265 _sale_end_date = $('#_lp_sale_end'), 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 (!_start_date) { 1272 _parent_start.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_start.append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_sale_start_date + '</div>') 1278 } 1279 }); 1280 1281 $(document).on('change', '#_lp_sale_end', function (e) { 1282 var _sale_end_date = $(this), 1283 _sale_start_date = $('#_lp_sale_start'), 1284 _start_date = Date.parse(_sale_start_date.val()), 1285 _end_date = Date.parse(_sale_end_date.val()), 1286 _parent_start = _sale_start_date.parent('.rwmb-input'), 1287 _parent_end = _sale_end_date.parent('.rwmb-input'); 1288 1289 if (!_end_date) { 1290 _parent_end.append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_invalid_date + '</div>') 1291 } 1292 1293 $('#field-_lp_sale_start div, #field-_lp_sale_end div').remove('.learn-press-tip-floating'); 1294 if (_start_date < _end_date) { 1295 _parent_end.append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_sale_end_date + '</div>') 1296 } 1297 }); 1298 1299 $('body') 1300 .on('click', '.learn-press-nav-tabs li a', function (e) { 1301 e.preventDefault(); 1302 var $tab = $(this), url = ''; 1303 $tab.closest('li').addClass('active').siblings().removeClass('active'); 1304 $($tab.attr('data-tab')).addClass('active').siblings().removeClass('active'); 1305 $(document).trigger('learn-press/nav-tabs/clicked', $tab); 1306 }); 1307 1308 setTimeout(function () { 1309 $('.learn-press-nav-tabs li.active:not(.default) a').trigger('click'); 1310 }, 300); 1311 1312 $('body.course-item-popup').parent().css('overflow', 'hidden'); 1313 /// 1314 (function () { 1315 var timer = null, 1316 callback = function () { 1317 $('.auto-check-lines').checkLines(function (r) { 1318 if (r > 1) { 1319 $(this).removeClass('single-lines'); 1320 } else { 1321 $(this).addClass('single-lines'); 1322 } 1323 $(this).attr('rows', r); 1324 }); 1325 }; 1326 $(window).on('resize.check-lines', function () { 1327 if (timer) { 1328 timer && clearTimeout(timer); 1329 timer = setTimeout(callback, 300); 1330 } else { 1331 callback(); 1332 } 1333 }); 1334 })(); 1335 1336// $(document).on('click', '[data-block-content="yes"]', function () { 1337// LP.blockContent(); 1338// }); 1339 1340 $('.learn-press-tooltip, .lp-passing-conditional').LP_Tooltip({offset: [24, 24]}); 1341 1342 $('.learn-press-icon').LP_Tooltip({offset: [30, 30]}); 1343 1344 $('.learn-press-message[data-autoclose]').each(function () {
1345 var $el = $(this), delay = parseInt($el.data('autoclose')); 1346 if (delay) { 1347 setTimeout(function ($el) { 1348 $el.fadeOut(); 1349 }, delay, $el); 1350 } 1351 }); 1352 1353 $(document).on('click', function () { 1354 $(document).trigger('learn-press/close-all-quick-tip') 1355 }) 1356 }); 1357 LearnPress = LP; 1358 1359})(jQuery);
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.