(function(window, $) { 'use strict'; // Polyfill if (!String.prototype.endsWith) { String.prototype.endsWith = function(searchString, position) { var subjectString = this.toString(); if (position === undefined || position > subjectString.length) { position = subjectString.length; } position -= searchString.length; var lastIndex = subjectString.indexOf(searchString, position); return lastIndex !== -1 && lastIndex === position; }; } if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { position = position || 0; return this.lastIndexOf(searchString, position) === position; }; } if (!String.prototype.includes) { String.prototype.includes = function() { return String.prototype.indexOf.apply(this, arguments) !== -1; }; } var getQueryString = function(name, defaultValue) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r !== null) return unescape(r[2]); return defaultValue; }; var debug = getQueryString('debug', 0); if(debug) console.error("DEBUG ENABLED."); var chapters = { learn: {col: 1}, start: {col: 1}, basic: {col: 1}, control: {col: 2}, component: {col: 2}, javascript: {col: 3}, view: {col: 3}, promotion: {col: 1, row: 2}, resource: {col: 1, row: 2}, contribution: {col: 1, row: 2} }; var LAST_RELOAD_ANIMATE_ID = 'lastReloadAnimate'; var LAST_QUERY_ID = 'LAST_QUERY_ID'; var INDEX_JSON = 'docs/index.json'; var ICONS_JSON = 'docs/icons.json'; var PKG_JSON = 'package.json'; var UNDEFINED = undefined; var dataVersion; var storageEnable; var docIndex, iconsIndex; var pkgLibs = {standard: null, lite: null, separate: null}; var documentTitle = 'ZUI'; var sectionsShowed; var queryGaCallback; var scrollBarWidth = -1; var bestPageWidth = 1120; var $body, $window, $grid, $sectionTemplate, $queryInput, $chapters, $pageAttrs, firstOpenPage = true, $choosedSection, $page, $pageHeader, $pageContent, $pageLoader, $pageBody, $navbar, $search, lastQueryString, $header, $sections, $chapterHeadings; // elements var isExternalUrl = function(url) { if(typeof url === 'string') { url = url.toLowerCase(); return url.startsWith('http://') || url.startsWith('https://'); } return false; }; var limitString = function(str, len) { if(str && str.length > len) { return str.substr(0, len) + '...[' + str.length + ']'; } return str; }; var checkScrollbar = function() { if (document.body.clientWidth >= window.innerWidth) return; if(scrollBarWidth < 0) { var scrollDiv = document.createElement('div'); scrollDiv.className = 'modal-scrollbar-measure'; $body.append(scrollDiv); scrollBarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; $body[0].removeChild(scrollDiv); } if (scrollBarWidth) { var bodyPad = parseInt(($body.css('padding-right') || 0), 10); $body.css('padding-right', bodyPad + scrollBarWidth); $navbar.css('padding-right', scrollBarWidth); } }; var resetScrollbar = function() { $body.css('padding-right', ''); $navbar.css('padding-right', ''); }; var loadData = function(url, callback, delayLoadRemote) { var cacheData = null; var isIndexJson = url === INDEX_JSON; var isIconsJson = url === ICONS_JSON; var isHasCache = false; if(isIndexJson && docIndex) { cacheData = {data: docIndex, version: docIndex.version}; isHasCache = true; } else if(isIconsJson && iconsIndex) { cacheData = iconsIndex; isHasCache = true; } else if(storageEnable) { var storedData = $.zui.store.get('//' + url, null); if(storedData !== null) { var storedVersion = $.zui.store.get('//' + url + '::V'); if(storedVersion) { cacheData = {data: storedData, version: storedVersion}; isHasCache = true; if(!docIndex && isIndexJson) { docIndex = storedData; } if(debug) console.log('Load', url, 'from storage:', cacheData); } } } if(isHasCache && (isIndexJson || cacheData.version === dataVersion)) { if(debug) console.log('Load', url, 'from cache:', cacheData); callback(cacheData.data, 'cache'); if(!isIndexJson && !debug) return; } var dataType = url.endsWith('.json') ? 'json' : 'html'; var loadFromRemote = function(){ $.get(url, function(data){ if(data !== null) { if(isIndexJson) { dataVersion = data.version; docIndex = data; } else if(isIconsJson) { iconsIndex = {data: data, version: dataVersion}; } cacheData = {data: data, version: dataVersion}; $.zui.store.set('//' + url, data); $.zui.store.set('//' + url + '::V', dataVersion); if(debug) console.log('Load', url, 'from remote:', cacheData); callback(data, 'remote'); } else if(isHasCache && !isIndexJson) { if(debug) console.log('Failed load', url, 'from remote, instead load cache:', cacheData); callback(cacheData.data, 'cache'); } }, dataType).error(function(){ if(debug) console.error("Ajax error:", url); if(isHasCache && !isIndexJson) { if(debug) console.log('Failed load', url, 'from remote with error, instead load cache:', cacheData); callback(cacheData.data, 'cache'); } if($body.hasClass('page-open')) { $pageBody.children('.loader').addClass('with-error'); } }); } if(delayLoadRemote !== false) { if(delayLoadRemote) { setTimeout(loadFromRemote, delayLoadRemote); } else { loadFromRemote(); } } }; var eachSection = function(callback, eachChapterCallback) { if (!docIndex) { console.error("Document index is empty."); return false; }; $.each(chapters, function(chapterName, chapter){ if(!docIndex.chapters[chapterName]) return; $.extend(chapter, docIndex.chapters[chapterName]); var sections = chapter.sections; var data = null; if(eachChapterCallback) { data = eachChapterCallback(chapter, sections); if(data === false) return false; } $.each(sections, function(i, section){ if(callback(chapter, section, data) === false) return false; }); }); return true; }; var displaySectionIcon = function($icon, section) { var icon = section.icon; $icon.attr('class', 'icon').text('').css('background-image', ''); if (icon === undefined || icon === null || icon === "") { icon = section.name.substr(0, 1).toUpperCase(); } if (icon.startsWith('icon-')) { $icon.addClass(icon); } else if(icon.endsWith('.png')) { $icon.css('background-image', 'url(' + icon + ')').addClass('with-img'); } else { $icon.addClass('text-icon').text(icon); } }; var displaySection = function() { var order = 0; if(eachSection(function(chapter, section, $sectionList){ var chapterName = chapter.id; section.chapter = chapterName; section.chapterName = chapter.name; var url = section.url; if(typeof url === 'undefined') { section.url = 'docs/part/' + section.chapter + '-' + section.id + '.html'; section.target = 'page'; } else if(isExternalUrl(url)) { section.target = 'external'; } else if(url && url.endsWith('.md')) { section.target = 'page'; section.targetType = 'markdown'; if(url === '.md') { section.url = 'docs/part/' + section.chapter + '-' + section.id + '.md'; } } else { section.target = ''; } var id = chapterName + '-' + section.id; var $tpl = $sectionTemplate.clone().data('section', section); $tpl.attr({ 'id': 'section-' + id, 'data-id': section.id, 'data-chapter': chapterName, 'data-order': order++, 'data-accent': chapter.accent, 'data-target': section.target }); var $head = $tpl.children('.card-heading'); var sectionUrl = '#' + chapterName + '/' + section.id; $head.find('.name').text(section.name).attr('href', sectionUrl); // $head.children('.desc').text(section.desc); displaySectionIcon($head.children('.icon'), section); var $topics = $tpl.find('.topics'); if (section.topics && section.topics.length) { var topicId = 0; $.each(section.topics, function(tName, topic){ if(typeof topic.id === 'undefined') topic.id = tName; var topicUrl = typeof topic.url === 'undefined' ? (sectionUrl + '/' + (topicId++)) : topic.url; $topics.append('
  • ' + topic.name + '
  • '); }); } else { $topics.remove('.card-content'); $tpl.addClass('without-topics'); } $sectionList.append($tpl.addClass('show' + (sectionsShowed ? ' in' : ''))); }, function(chapter, sections){ chapter.$.attr('data-accent', chapter.accent); var $sectionList = chapter.$sections; $sectionList.children().remove(); return $sectionList; })) { $body.children('.loader').removeClass('loading'); $sections = $grid.find('.section'); if(!sectionsShowed) { clearTimeout($grid.data(LAST_RELOAD_ANIMATE_ID)); $grid.data(LAST_RELOAD_ANIMATE_ID, setTimeout(function(){ $sections.addClass('in'); $chapterHeadings.addClass('in'); }, 100)); sectionsShowed = true; } } else if(debug) { console.error("Display sections failed."); } }; var scrollToThis = function($container, toTop, callback) { if($container === UNDEFINED) $container = $body; if(toTop === UNDEFINED || toTop === 'down') { toTop = $container.scrollTop() + ($window.height() - $container.offset().top) * 0.8; } else if(toTop === 'up') { toTop = $container.scrollTop() - ($window.height() - $container.offset().top) * 0.8; } $container.animate({scrollTop: toTop}, 200, 'swing', callback); }; var scrollToSection = function($section) { if($section) { var top = $section.offset().top; var height = $section.outerHeight(); var winHeight = $window.height(); var scrollTop = $body.scrollTop(); if(winHeight < (top + height)) { } } }; var isChoosedSection = function($section) { if($section === UNDEFINED) { $section = $choosedSection; } return $section && $section.hasClass('choosed') && $section.hasClass('show'); }; var chooseSection = function($section, keepOtherOpen, notOpenSelf) { if($sections) { if(isChoosedSection($section || null) && !notOpenSelf) { $choosedSection = $section.addClass('open'); scrollToSection($section); return; } var isOpened = $section && $section.hasClass('open'); $sections.removeClass(keepOtherOpen ? 'choosed' : 'choosed open'); if($section && $section.hasClass('section')) { $choosedSection = $section.addClass((notOpenSelf && !isOpened) ? 'choosed' : 'choosed open'); scrollToSection($section); } } }; var choosePrevSection = function() { var $all = $sections.filter('.show'); if(isChoosedSection()) { var order = parseInt($choosedSection.data('order')); var $section = $choosedSection; while((--order) > -1) { var $prev = $all.filter('[data-order="' + order + '"]'); if($prev.length) { $section = $prev; break; } } chooseSection($section); } else { chooseSection($all.first()); } }; var chooseNextSection = function() { var $all = $sections.filter('.show'); if(isChoosedSection()) { var order = parseInt($choosedSection.data('order')); var $section = $choosedSection; var allCount = $sections.length; while((order++) < allCount) { var $next = $all.filter('[data-order="' + order + '"]'); if($next.length) { $section = $next; break; } } chooseSection($section); } else { chooseSection($all.first()); } }; var distanceBetweenPoint = function(x1, y1, x2, y2) { return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2), 2); }; var chooseLeftSection = function() { var $all = $sections.filter('.show'); if(isChoosedSection()) { var offset = $choosedSection.offset(); var left = offset.left - $grid.children('.container').offset().left - 10; if(left < 50) { choosePrevSection(); return; } var top = offset.top; left = offset.left; var $section = $choosedSection; var delta = 99999; $all.each(function(){ var $this = $(this); var offset = $this.offset(); if((offset.left + 50) < left) { var thisDelta = distanceBetweenPoint(offset.left, offset.top, left, top); if(thisDelta < delta) { $section = $this; delta = thisDelta; } } }); chooseSection($section); } else { chooseSection($all.first()); } }; var chooseRightSection = function() { var $all = $sections.filter('.show'); if(isChoosedSection()) { var offset = $choosedSection.offset(); var $container = $grid.children('.container'); var left = offset.left - $container.offset().left - 10; if((left + 20 + $choosedSection.outerWidth() + 50) >= $container.outerWidth()) { chooseNextSection(); return; } var top = offset.top; left = offset.left; var $section = $choosedSection; var delta = 99999; $all.each(function(){ var $this = $(this); var offset = $this.offset(); if(offset.left > left) { var thisDelta = distanceBetweenPoint(offset.left, offset.top, left, top); if(thisDelta < delta) { $section = $this; delta = thisDelta; } } }); chooseSection($section); } else { chooseSection($all.first()); } }; var resetQuery = function() { $grid.find('.col.hide').removeClass('hide'); $chapters.removeClass('hide'); $sections.addClass('show'); $chapterHeadings.addClass('show'); $grid.data(LAST_RELOAD_ANIMATE_ID, setTimeout(function(){ $sections.addClass('in'); $chapterHeadings.addClass('in'); }, 20)); $body.removeClass('query-enabled').attr('data-query', ''); }; var chooseIcon = function($icon){ var $search = $('#section-control-icon'); if(!$icon || !$icon.length) { $search.removeClass('section-preview-show').data('preview', null); return; } $search.addClass('open section-preview-show'); var $preview = $search.children('.section-preview'); var oldIcon = $search.data('preview'); if(!$preview.length) { $preview = $('#iconPreviewTemplate').clone().attr('id', ''); $search.children('.card-heading').after($preview); } $search.children('.section-search').find('li.active').removeClass('active'); $icon.addClass('active'); if(oldIcon) $preview.find('.icon').removeClass('icon-' + oldIcon); var icon = $icon.data('icon'); $search.data('preview', icon.id); var id = 'icon-' + icon.id; $preview.find('.icon').addClass(id); $preview.find('.name').text(id); $preview.find('.unicode').text(icon.code); if(icon.alias && icon.alias.length) { $preview.find('.alias').removeClass('hide').find('.alias-values').text(icon.alias.join(',')); } else { $preview.find('.alias').addClass('hide'); } }; var queryIcon = function(keys) { if(!$.isArray(keys) && (keys || keys.length) ) { keys = [keys]; } var $section = $('#section-control-icon'); $body.attr('data-query', 'icons'); var $search = $section.children('.section-search'); if(!$search.length) { $search = $(''); $section.children('.card-heading').after($search); $search = $section.children('.section-search'); } loadData(ICONS_JSON, function(data){ var $list = $search.children('ul'); if(!$list.length) { $list = $('