1; 2/** 3 * LearnPress frontend course app. 4 * 5 * @version 3.2.0 6 * @author ThimPress 7 * @package LearnPress/JS/Course 8 */ 9(function ($, LP, _) { 10 11 'use strict'; 12 13 function LP_Storage(key) { 14 var storage = window.localStorage; 15 this.key = key; 16 this.get = function (id) { 17 var val = storage.getItem(this.key) || '', 18 sections = val.split(','); 19 if (id) { 20 id = id + ''; 21 var pos = sections.indexOf(id); 22 if (pos >= 0) { 23 return sections[pos]; 24 } 25 } 26 return sections; 27 } 28 this.set = function (sections) { 29 if (typeof sections !== 'string') { 30 sections = sections.join(','); 31 } 32 storage.setItem(this.key, sections); 33 return sections.split(','); 34 } 35 this.hasSection = function (id) { 36 id = id + ''; 37 var sections = this.get(), 38 at = sections.indexOf(id); 39 40 return at >= 0 ? at : false; 41 } 42 this.add = function (id) { 43 id = id + ''; 44 var sections = this.get(); 45 if (this.hasSection(id)) { 46 return; 47 } 48 sections.push(id); 49 this.set(sections); 50 return sections; 51 } 52 this.remove = function (id) { 53 id = id + ''; 54 var at = this.hasSection(id); 55 if (at !== false) { 56 var sections = this.get(); 57 sections.splice(at, 1); 58 this.set(sections); 59 return sections; 60 } 61 return false; 62 } 63 } 64 65 /** 66 * LP_Course 67 * 68 * @param settings 69 * @constructor 70 */ 71 function LP_Course(settings) { 72 73 var sectionStorage = new LP_Storage('sections'), 74 $body = $('body'), 75 $content = $('.content-item-scrollable'), 76 $curriculum = $('#learn-press-course-curriculum'), 77 $contentItem = $('#learn-press-content-item'), 78 $curriculumScrollable = $curriculum.find('.curriculum-scrollable'), 79 $header = $('#course-item-content-header'), 80 $footer = $('#course-item-content-footer'), 81 $courseItems = $curriculum.find('.course-item'), 82 isShowingHeader = true, 83 fullScreen, contentTop = 0, headerTimer, 84 inPopup = false; 85 86 /** 87 * Toggle answer option check/uncheck 88 */ 89 function toggleAnswerOptions(event) { 90 var $el = $(event.target), 91 $chk; 92 if ($el.is('input.option-check')) { 93 return; 94 } 95 96 $chk = $el.closest('.answer-option').find('input.option-check'); 97 98 if (!$chk.length) { 99 return; 100 } 101 102 if ($chk.is(':disabled')) { 103 return; 104 } 105 if ($chk.is(':checkbox')) { 106 $chk[0].checked = !$chk[0].checked; 107 } else { 108 $chk[0].checked = true; 109 } 110 } 111 112 /** 113 * Show/Hide section content 114 */ 115 function toggleSection() { 116 var id = $(this).closest('.section').data('section-id'); 117 $(this).siblings('.section-content').slideToggle(function () { 118 if ($(this).is(':visible')) { 119 sectionStorage.remove(id); 120 } else { 121 sectionStorage.add(id); 122 } 123 }); 124 } 125 126 /** 127 * Init sections 128 */ 129 function initSections() { 130 var $activeSection = $('.course-item.current').closest('.section'), 131 sections = $('.curriculum-sections').find('.section'), 132 sectionId = $activeSection.data('section-id'), 133 hiddenSections = []; 134 135 if ($activeSection) { 136 hiddenSections = sectionStorage.remove(sectionId); 137 } else { 138 hiddenSections = sectionStorage.get(); 139 } 140 141 for (var i = 0; i < hiddenSections.length; i++) { 142 sections.filter('[data-section-id="' + hiddenSections[i] + '"]').find('.section-content').hide(); 143 } 144 } 145 146 /** 147 * Prepare form before submitting 148 * 149 * @param form 150 */ 151 function prepareForm(form) { 152 var $answerOptions = $('.answer-options'), 153 $form = $(form), 154 data = $answerOptions.serializeJSON(), 155 $hidden = $('<input type="hidden" name="question-data" />').val(JSON.stringify(data)); 156 157 if (($form.attr('method') + '').toLowerCase() !== 'post') { 158 return; 159 } 160 161 $form.find('input[name="question-data"]').remove(); 162 return $form.append($hidden).append($('<div />').append($answerOptions.clone()).hide()); 163 } 164 165 /** 166 * Tab course event 167 * 168 * @param e 169 * @param tab 170 */ 171 function onTabCourseClick(e, tab) { 172 173 if ($(document.body).hasClass('course-item-popup')) { 174 return; 175 } 176 177 var $tab = $(tab), 178 $parent = $tab.closest('.course-nav'); 179 180 if ($parent.siblings().length === 0) { 181 return; 182 } 183 LP.setUrl($tab.attr('href')) 184 } 185 186 /** 187 * Event on press any key into search 188 * 189 * @param e 190 * @returns {boolean} 191 */ 192 function onSearchInputKeypress(e) { 193 194 if (e.type === 'keypress' && e.keyCode === 13) { 195 return false;
196 } 197 198 var s = this.value, 199 r = new RegExp(s, 'ig'); 200 $courseItems.map(function () { 201 var $item = $(this), 202 itemName = $item.find('.item-name').text(); 203 if (itemName.match(r) || !s.length) { 204 $item.show(); 205 } else { 206 $item.hide(); 207 } 208 }); 209 210 $('.section').show().each(function () { 211 if (s.length) { 212 if (!$(this).find('.section-content').children(':visible').length) { 213 $(this).hide(); 214 } else { 215 $(this).show(); 216 } 217 } else { 218 $(this).show(); 219 } 220 }); 221 $(this).closest('.course-item-search').toggleClass('has-keyword', !!this.value.length); 222 } 223 224 function onClearSearchInputClick(e) { 225 var $form = $(this).closest('.course-item-search'); 226 $form.find('input').val('').trigger('keyup') 227 } 228 229 function onClickQM() { 230 $('#qm').css({'z-index': 999999999, position: 'relative'}); 231 $('html, body').css('overflow', 'auto'); 232 } 233 234 function getCurriculumWidth() { 235 return $curriculum.outerWidth(); 236 } 237 238 function maybeShowCurriculum(e) { 239 return; 240 var offset = $(this).offset(), 241 offsetX = e.pageX - offset.left, 242 curriculumWidth = getCurriculumWidth(); 243 244 if (!fullScreen || (offsetX > 50)) { 245 return; 246 } 247 248 timeoutToClose(); 249 250 if (!isShowingHeader) { 251 $curriculum.stop().animate({ 252 left: 0 253 }); 254 255 $contentItem.stop().animate({ 256 left: curriculumWidth 257 }); 258 259 $footer.stop().animate({ 260 left: curriculumWidth 261 }, function () { 262 $(document, window).trigger('learn-press/toggle-content-item'); 263 }); 264 265 $header.find('.course-item-search').show(); 266 toggleEventShowCurriculum(true); 267 isShowingHeader = true; 268 } 269 } 270 271 function toggleEventShowCurriculum(b) { 272 $(document)[b ? 'off' : 'on']('mousemove.maybe-show-curriculum', 'body', maybeShowCurriculum); 273 } 274 275 function timeoutToClose() { 276 headerTimer && clearTimeout(headerTimer); 277 headerTimer = setTimeout(function () { 278 var curriculumWidth = getCurriculumWidth(); 279 280 if (!fullScreen) { 281 return; 282 } 283 284 $curriculum.stop().animate({ 285 left: -curriculumWidth 286 }); 287 288 $contentItem.stop().animate({ 289 left: 0 290 }); 291 292 $footer.stop().animate({ 293 left: 0 294 }, function () { 295 $(document, window).trigger('learn-press/toggle-content-item'); 296 }); 297 298 $header.find('.course-item-search').hide(); 299 300 isShowingHeader = false;
301 toggleEventShowCurriculum(); 302 }, 3000); 303 } 304 305 function toggleContentItem(e) { 306 e.preventDefault(); 307 var curriculumWidth = getCurriculumWidth(); 308 fullScreen = $body.toggleClass('full-screen-content-item').hasClass('full-screen-content-item'); 309 $curriculum 310 .stop() 311 .animate({ 312 left: fullScreen ? -curriculumWidth : 0 313 }); 314 315 $contentItem 316 .stop() 317 .animate({ 318 left: fullScreen ? 0 : curriculumWidth 319 }); 320 321 $footer.stop().animate({ 322 left: fullScreen ? 0 : curriculumWidth 323 }, function () { 324 $(document, window).trigger('learn-press/toggle-content-item'); 325 }); 326 327 isShowingHeader = !fullScreen; 328 window.localStorage && window.localStorage.setItem('lp-full-screen', fullScreen ? 'yes' : 'no'); 329 330 fullScreen && toggleEventShowCurriculum(); 331 $header.find('.course-title').stop().animate({marginLeft: fullScreen ? -curriculumWidth : 0}) 332 $header.find('.course-item-search').stop().animate({opacity: fullScreen ? 0 : 1}); 333 } 334 335 function initEvents() { 336 // Live events 337 $(document) 338 .on('learn-press/nav-tabs/clicked', onTabCourseClick) 339 .on('keyup keypress', '.course-item-search input', onSearchInputKeypress) 340 .on('click', '.course-item-search button', onClearSearchInputClick) 341 .on('click', '#wp-admin-bar-query-monitor', onClickQM) 342 .on('click', '.answer-options .answer-option', toggleAnswerOptions) 343 .on('click', '.section-header', toggleSection) 344 .on('submit', 'form.lp-form', function () { 345 prepareForm(this); 346 }).on('click', '.toggle-content-item', toggleContentItem); 347 348 $curriculum.hover(function () { 349 headerTimer && clearTimeout(headerTimer); 350 }, function () { 351 if (fullScreen) timeoutToClose(); 352 }) 353 354 } 355 356 function initScrollbar() { 357 $content.addClass('scrollbar-light') 358 .scrollbar({ 359 scrollx: false 360 }); 361 362 $content.parent().css({ 363 position: 'absolute', 364 top: 0, 365 bottom: $('#course-item-content-footer:visible').outerHeight() || 0, 366 width: '100%' 367 }).css('opacity', 1).end().css('opacity', 1); 368 369 370 $curriculumScrollable.addClass('scrollbar-light') 371 .scrollbar({ 372 scrollx: false 373 }); 374 375 $curriculumScrollable.parent().css({ 376 position: 'absolute', 377 top: 0, 378 bottom: 0, 379 width: '100%' 380 }).css('opacity', 1).end().css('opacity', 1); 381 } 382 383 function fitVideo() { 384 var $wrapContent = $('.content-item-summary.content-item-video'); 385 386 if (!$wrapContent.length) { 387 return; 388 } 389 390 var $entryVideo = $wrapContent.find('.entry-video'), 391 $frame = $entryVideo.find('iframe'), 392 width = $frame.attr('width'), 393 height = $frame.attr('height'), 394 ratio = 1, 395 contentHeight, timer; 396 397 function resizeVideo() { 398 var frameWidth = $frame.width(); 399 contentHeight = frameWidth * ratio; 400 $frame.css({ 401 height: contentHeight, 402 marginLeft: ( $entryVideo.width() - frameWidth) / 2 403 }); 404 405 $wrapContent.css({ 406 paddingTop: contentHeight 407 }); 408 } 409 410 if (!$entryVideo.length) { 411 return false; 412 } 413 414 if (width && height) { 415 if (width.indexOf('%') === -1 && height.indexOf('%') === -1) { 416 ratio = height / width; 417 } 418 } 419 420 $(window).on('resize.fit-content-video learn-press/toggle-content-item', function () { 421 timer && clearTimeout(timer); 422 timer = setTimeout(resizeVideo, 250); 423 }).trigger('resize.fit-content-video'); 424 425 $('.content-item-scrollable').scroll(function () { 426 $(this).find('.entry-video').css('padding-top', this.scrollTop); 427 }); 428 } 429 430 /** 431 * Init 432 */
433 function init() { 434 inPopup = $body.hasClass('course-item-popup'); 435 initSections(); 436 initEvents(); 437 438 439 if (!inPopup) { 440 return; 441 } 442 443 $contentItem.appendTo($body); 444 $curriculum.appendTo($body); 445 446 if ($('#wpadminbar').length) { 447 $body.addClass('wpadminbar'); 448 contentTop = 32; 449 } 450 451 initScrollbar(); 452 fitVideo(); 453 454 fullScreen = window.localStorage && 'yes' === window.localStorage.getItem('lp-full-screen'); 455 if($(window).width()<=768){ 456 fullScreen = true; 457 } 458 if (fullScreen) { 459 var curriculumWidth = getCurriculumWidth(); 460 $body.addClass('full-screen-content-item'); 461 $contentItem.css('left', 0); 462 $curriculum.css('left', -curriculumWidth); 463 $footer.css('left', 0); 464 isShowingHeader = !fullScreen; 465 $header.find('.course-title').css({marginLeft: fullScreen ? -curriculumWidth : 0}) 466 $header.find('.course-item-search').css({opacity: fullScreen ? 0 : 1}); 467 toggleEventShowCurriculum(); 468 } 469 470 setTimeout(function () { 471 var $cs = $body.find('.curriculum-sections').parent(); 472 $cs.scrollTo($cs.find('.course-item.current'), 100); 473 474 if (window.location.hash) { 475 $('.content-item-scrollable:last').scrollTo($(window.location.hash)); 476 } 477 }, 300); 478 479 $body.css('opacity', 1); 480 481 } 482 483 new LP.Alerts(); 484 485 init(); 486 } 487 488 LP.Alerts = function () { 489 this.isShowing = false; 490 var $doc = $(document), 491 self = this, 492 trigger = function (action, args) { 493 var triggered = $doc.triggerHandler(action, args); 494 495 if (triggered !== undefined) { 496 return triggered; 497 } 498 499 return $.isArray(args) ? args[0] : undefined; 500 }, 501 confirmHandle = function (e) { 502 try { 503 var $form = $(this), 504 message = $form.data('confirm'), 505 action = $form.data('action'); 506 507 message = trigger('learn-press/confirm-message', [message, action]); 508 509 if (!message) { 510 return true; 511 } 512 513 jConfirm(message, '', function (confirm) { 514 confirm && $form.off('submit.learn-press-confirm', confirmHandle).submit(); 515 self.isShowing = false; 516 }); 517 518 self.isShowing = true; 519 520 return false; 521 } catch (ex) { 522 console.log(ex) 523 } 524 525 return true; 526 } 527 528 this.watchChange('isShowing', function (prop, oldVal, newVal) { 529 if (newVal) { 530 setTimeout(function () { 531 $.alerts._reposition(); 532 $('#popup_container').addClass('ready') 533 }, 30) 534 535 var $a = $('<a href="" class="close"><i class="fa fa-times"></i></a>') 536 $('#popup_container').append($a); 537 $a.on('click', function () { 538 $.alerts._hide(); 539 return false; 540 }); 541 } 542 $(document.body).toggleClass('confirm', newVal); 543 return newVal; 544 }); 545 546 var $forms = $('form[data-confirm]').on('submit.learn-press-confirm', confirmHandle); 547 } 548 549 550 $(document).ready(function () { 551 $(document).ready(function () { 552 new LP_Course({}); 553 554 $(this).on('submit', 'form[name="course-external-link"]', function () { 555 var redirect = $(this).attr('action'); 556 if (redirect) { 557 window.location.href = redirect; 558 return false;
559 } 560 }) 561 }); 562 }); 563}) 564(jQuery, LP, _);
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.