diff --git a/_assets/css/api.scss b/_assets/css/api.scss new file mode 100644 index 0000000..fddd55e --- /dev/null +++ b/_assets/css/api.scss @@ -0,0 +1,339 @@ +// #page-edit-link { +// margin-top: 80px !important; +// } + +.api-toc-container~article h3 { + font-size: 22px; +} + +.api-breadcrumbs-container+#page-article :target:before { + content: ""; + display: block; + height: 175px; + margin: -175px 0 0; +} + +.api-breadcrumbs-container { + padding: 0 0 0 5.8em; + font-family: Roboto, Helvetica, Arial, sans-serif; + border-bottom: 1px solid #ebecee; + position: fixed; + left: 18%; + right: 0; + background-color: #fff; + top: 118px; + width: 100%; + max-width: 100%; + z-index: 5; + margin-top: 0; + margin-left: 0; +} + +.links-container>ul>li { + padding: 2px 10px; + font-size: 12px; +} + +.links-container>ul { + position: absolute; + max-height: 400px; + overflow: auto; + background: #fff; + box-shadow: 0 0 6px 1px rgba(0, 0, 0, 0.2); + padding: 5px 10px 5px 0; + list-style: none; + display: none; + margin: 0 0 0 25px; + left: 200px; + min-width: 150px; +} + +.links-container>a { + background: transparent url(../images/arrow.png) 100% 50% no-repeat; + padding-right: 18px; + padding-left: 14px; + margin-right: 10px; + padding-top: 14px; + padding-bottom: 14px; +} + +.links-container>a:first-of-type { + background: none !important; + padding-left: 0; +} + +.links-container>a:last-of-type { + font-weight: bold; + display: inline-block; + color: #e50870; +} + +.links-container>a:last-of-type::after { + background: none !important; +} + +.links-container>a:after { + background: transparent url(../images/shadow.png) 100% 50% no-repeat; + content: ""; + display: inline-block; + width: 17px; + height: 46px; + position: absolute; + margin-left: 16px; +} + +.links-container a:last-of-type ul { + display: none; +} + +.api-toc-container { + position: fixed; + left: 1400px; + z-index: 10; + border-left: 1px solid #ebecee; + padding-left: 15px; + overflow-wrap: break-word; + width: 270px; + margin-top: 60px; + /* bottom: 84px; */ +} + +@media (min-width: 1660px) { + .api-toc-container { + display: block; + } +} + +@media (min-width: 1580px) and (max-width: 1659px) { + .api-toc-container { + display: block; + left: 1320px; + width: 240px; + } +} + +@media (min-width: 1468px) and (max-width: 1579px) { + #page-article { + padding-right: 240px; + } + .api-toc-container { + display: block; + left: 1210px; + width: 240px; + } +} + +@media (min-width: 1200px) and (max-width: 1467px) { + #page-article { + padding-right: 240px; + max-width: 93em; + } + .api-toc-container { + display: block; + left: 76em; + width: 220px; + } +} + +@media (max-width: 1200px) { + .api-breadcrumbs-container { + padding-left: 2em; + left: 0; + } + .api-toc-container { + display: none; + left: 1210px; + } +} + +.api-toc-container li { + margin: 5px 0; +} + +.api-toc-container ul { + list-style: none; + margin: 0; + padding: 0; + overflow-y: auto; +} + +.api-toc-container .active-toc-item, .links-container>ul .selected-dropdown-breadcrumb { + color: #e50870; + font-weight: 600; +} + +.api-toc-title { + text-transform: uppercase; + padding-top: 10px; + padding-bottom: 10px; + font-weight: 600; +} + +#api-filter~h2:first-of-type { + margin-top: 30px; +} + +.api-breadcrumbs-container~#page-article article { + margin-top: 60px !important; +} + +h2 a:first-child+a code:before { + content: '-'; + margin-right: 7px; + color: #cccccc; +} + +#markdown-toc+#page-article ul, #related-properties+ul { + list-style-type: none; + margin-left: -18px; +} + +#markdown-toc+#page-article ul>li, #related-properties+ul>li { + margin-right: 25px; + width: 33%; +} + +#markdown-toc .section>a { + background: transparent !important; +} + +.nested-list-item { + font-size: 12px; + list-style-type: none; +} + +.hide-api-container, .hide-api-link { + display: none !important; +} + +.columns { + display: flex; + flex-direction: column; + flex-wrap: wrap; + overflow-wrap: break-word; +} + +.api-icon { + position: relative; + margin-top: 10px; + margin-bottom: 6px; + font-weight: 500; +} + +.api-icon:after { + position: absolute; + top: 2px; + left: -8px; + height: 0; + width: 0; + content: ""; + border: 2px solid #fff; + border-color: #fff #fff transparent transparent; +} + +.api-icon:before { + position: absolute; + width: 14px; + height: 14px; + top: 2px; + right: 18px; + bottom: -2px; + left: -18px; + content: "C"; + color: #fff; + font-size: 8px; + line-height: 15px; + font-weight: 900; + font-family: 'Roboto', sans-serif; + text-align: center; + vertical-align: middle; +} + +.constructor-parameters:before { + background-color: #4b6584; + content: "CP"; +} + +.properties:before { + background-color: #10ac84; + content: "P"; +} + +.class-methods:before { + background-color: #feca57; + content: "CM"; +} + +.configuration:before { + background-color: #1ab125; + content: "C"; +} + +.fields:before { + background-color: #0060be; + content: "F"; +} + +.methods:before { + background-color: #f57c00; + content: "M"; +} + +.events:before { + background-color: #ff4081; + content: "E"; +} + +#api-filter { + margin: 30px 0; + width: 270px; +} + +#api-filter .search { + padding: 7px 5px 7px 25px; + width: 100%; +} + +#api-filter .search-icon { + position: absolute; + margin-top: 9px; + margin-left: 8px; + font-size: 12px; + color: #b8b8b8; +} + +#api-filter input[type="search"] { + border-radius: 1px; + border-width: 1px; + border-style: solid; + border-color: #b8b8b8; +} + +#api-filter input[type="search"]:focus { + outline: none; +} + +#api-filter input[type="search"]::-webkit-search-decoration, #api-filter input[type="search"]::-webkit-search-cancel-button, #api-filter input[type="search"]::-webkit-search-results-button, #api-filter input[type="search"]::-webkit-search-results-decoration { + display: none; +} + +#page-inner-content { + min-height: 100%; +} + +#markdown-toc~footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; + margin-bottom: 0; +} + +.focused-field { + padding: 5px 0; + background-color: #eeeeee; +} + +.focused-field:focus { + background-color: #dddddd; +} diff --git a/_assets/css/bundle.scss b/_assets/css/bundle.scss index 60c60c0..d7cedf0 100644 --- a/_assets/css/bundle.scss +++ b/_assets/css/bundle.scss @@ -5,6 +5,7 @@ @import "icon-font"; @import "styles.scss"; +@import "api.scss"; @import "codemirror/codemirror.scss"; @import "codemirror/theme.scss"; diff --git a/_assets/js/api.js b/_assets/js/api.js new file mode 100644 index 0000000..9232ae5 --- /dev/null +++ b/_assets/js/api.js @@ -0,0 +1,490 @@ +var API_CATEGORIES = ['configuration', 'fields', 'methods', 'events', 'class methods', 'properties', 'constructor parameters']; +var NESTED_ELEMENT_MARK = '.'; +var COLUMNS_STYLE_CLASS_NAME = 'columns'; +var API_SUBPAGE_TITLE = 'related-properties'; +var MAX_NESTING_LEVEL = 10000; +var DEFAULT_COLUMN_COUNT = 3; +var MINIMUM_CHILDREN_COUNT = 6; +var COLUMN_HEIGHT_TOLLERANCE = 40; +var filterControl = null; +var previousSearch = ""; + +function getApiCategoryAndIndex(values) { + var startIndex = -1; + var category = ""; + $.each(values, function (index, value) { + if (API_CATEGORIES.indexOf(value.toLowerCase()) > -1) { + startIndex = index; + category = value; + return false; + } + }); + + return { + index: startIndex, + category: category + }; +} + +function findApiCategoryIndexFromPath(path) { + var startIndex = -1; + $.each(API_CATEGORIES, function (index, value) { + startIndex = path.indexOf(value.toLowerCase()); + if (startIndex > -1) { + return false; + } + }); + + return startIndex; +} + +function capitalizeSingle(value) { + var newValue = ''; + $.each(value.split(/ |-/), function (index, item) { + if (index > 0) { + newValue += ' '; + } + newValue += item.charAt(0).toUpperCase() + item.slice(1).toLowerCase(); + }); + return newValue; +} + +function capitalize(values) { + for (var i = 0; i < values.length; i++) { + values[i] = capitalizeSingle(values[i]); + } + + return values; +} + +function separatePageParts(values, breadcrumbs) { + var currentPageParts = values[values.length - 1].split('.'); + var previousLink = ""; + $.each(currentPageParts, function (index, pagePart) { + previousLink += previousLink !== "" ? "." + pagePart : pagePart; + breadcrumbs.push(previousLink); + }); + + return currentPageParts.length; +} + +function getBreadcrumbsInfo(values) { + var startIndex = getApiCategoryAndIndex(values).index; + var breadcrumbs = values.slice(startIndex - 1, values.length - 1); + capitalize(breadcrumbs); + var pagePartsCount = separatePageParts(values, breadcrumbs); + categoryInfo = getApiCategoryAndIndex(breadcrumbs); + + return { + categoryIndex: categoryInfo.index, + category: categoryInfo.category, + breadcrumbs: breadcrumbs, + nestingLevel: pagePartsCount + }; +} + +function buildToc() { + var tocContainer = $('.api-toc-container'); + if (tocContainer.length > 0) { + var listItems = ""; + var headersCount = 0; + $('h3').each(function () { + headersCount++; + var text = this.id === 'related-properties' ? 'Related Properties' : this.id; + listItems += '
  • ' + text + '
  • '; + }); + + if (headersCount > 1) { + tocContainer.append('
    In this article
    '); + + var list = tocContainer.children('ul:first-of-type'); + var windowHeight = $(window).outerHeight(); + var footerHeight = $("#feedback-section").outerHeight() + $("footer").outerHeight(); + var listTop = list.offset().top - $(window).scrollTop(); + list.css('max-height', windowHeight - listTop - footerHeight); + } + } +} + +function repeat(string, count) { + var result = ""; + for (var i = 0; i < count; i++) { + result += string; + } + + return result; +} + +function buildApiBreadcrumbs(data) { + var path = decodeURI($(location).attr('pathname')).split('/'); + var breadcrumbsInfo = getBreadcrumbsInfo(path); + var breadcrumbs = breadcrumbsInfo.breadcrumbs; + breadcrumbs = breadcrumbs.slice(0, breadcrumbs.length); + + var href = ''; + var lastHref = ''; + var links = ''; + var breadcrumbsContainer = $('.api-breadcrumbs-container'); + for (var i = 0; i < breadcrumbs.length; i++) { + var backStepsCount = breadcrumbsInfo.categoryIndex - i + 1; + var relativePathBackPath = backStepsCount >= 0 ? repeat("../", backStepsCount) : ""; + var breadcrumb = breadcrumbs[i]; + href = breadcrumb === breadcrumbsInfo.category ? + lastHref + '#' + breadcrumb : + relativePathBackPath + breadcrumb; + + href = href.replace(' ', '-'); + var linkText = i === 0 ? data.public_name : breadcrumb; + links += '' + linkText + ''; + if (i > 0) { + links += getBreadcrumbDropDownContent(data, breadcrumbsInfo, i - 1, lastHref); + } + lastHref = href; + } + + breadcrumbsContainer.append(''); +} + +function getBreadcrumbDropDownContent(data, breadcrumbsInfo, nestingLevel, lastHref) { + var dropDownContent = ''; + return dropDownContent; +} + +function getPrefix(item, prefixes) { + var result = ''; + var searchedItem = item.toLowerCase(); + $.each(prefixes, function (index, prefix) { + if (searchedItem === prefix.toLowerCase()) { + result = prefix + '#'; + return false; + } + }); + + return result; +} + +function shouldAppendItemToDropDown(item, scopeFilteringItem, nestingLevel, maxNestingLevel) { + var matchNestingLevel = item.split(NESTED_ELEMENT_MARK).length === nestingLevel; + var isInContextScope = item.toLowerCase().indexOf(scopeFilteringItem) === 0; + + return nestingLevel === 0 || + (maxNestingLevel > nestingLevel && isInContextScope && matchNestingLevel) || + matchNestingLevel && (!scopeFilteringItem || (scopeFilteringItem && isInContextScope)); +} + +function getMinNestingLevel() { + var minNestingLevel = MAX_NESTING_LEVEL; + var linksSection = $('#' + API_SUBPAGE_TITLE); + if (linksSection.length) { + var list = $(linksSection[linksSection.length - 1]).next('ul'); + list.children().each(function () { + minNestingLevel = Math.min(minNestingLevel, $(this).text().split(NESTED_ELEMENT_MARK).length - 1); + }); + } + + return minNestingLevel; +} + +function styleItems(listItems, category, mainNestingLevel) { + listItems.each(function () { + var itemText = $(this).text(); + var styleClassToAdd = itemText.split(NESTED_ELEMENT_MARK).length - 1 === mainNestingLevel ? 'api-icon ' + category : 'nested-list-item'; + $(this).addClass(styleClassToAdd); + }); +} + +function getVisibleChildrenCount(list) { + return list.children().not('li.hide-api-link').length; +} + +function getTotalParentHeight(list) { + var totalHeight = 0; + list.children().each(function () { + totalHeight += $(this).outerHeight(true); + }); + + return totalHeight; +} + +function arrangeColumns(list, columnsCount) { + columnsCount = columnsCount ? columnsCount : DEFAULT_COLUMN_COUNT; + var listItemsCount = getVisibleChildrenCount(list); + list.removeClass(COLUMNS_STYLE_CLASS_NAME); + + if (listItemsCount > MINIMUM_CHILDREN_COUNT) { + var averageItemHeight = list.data('item-height'); + if (!averageItemHeight) { + averageItemHeight = getTotalParentHeight(list) / listItemsCount; + } + var desiredItemsCount = listItemsCount / columnsCount; + list.addClass(COLUMNS_STYLE_CLASS_NAME); + list.height(averageItemHeight * desiredItemsCount + COLUMN_HEIGHT_TOLLERANCE); + list.data('item-height', averageItemHeight); + } else { + list.css('height', ''); + } +} + +function setupColumnsInternal(category, subCategory, mainNestingLevel) { + var headerSelector = $('#' + category); + if (headerSelector.length > 0) { + var list = $(headerSelector).next('ul'); + var listItems = list.children(); + + styleItems(listItems, subCategory, mainNestingLevel); + arrangeColumns(list); + } +} + +function setupColumns() { + for (var i = 0; i < API_CATEGORIES.length; i++) { + var category = API_CATEGORIES[i].replace(' ', '-'); + setupColumnsInternal(category, category, 0); + } + + var subCategory = $('#page-article > article').attr('class'); + if (subCategory) { + var mainNestingLevel = getMinNestingLevel(); + setupColumnsInternal(API_SUBPAGE_TITLE, subCategory.toLowerCase(), mainNestingLevel); + } +} + +function enumerateCategories() { + var lists = []; + for (var i = 0; i < API_CATEGORIES.length; i++) { + var headerSelector = $('#' + API_CATEGORIES[i]); + if (headerSelector.length > 0) { + var list = $(headerSelector).next('ul'); + var listItems = list.children(); + lists.push(list); + } + } + + return lists; +} + +function filter() { + var text = filterControl.val().toLowerCase(); + if (text === previousSearch) { + return; + } + + $.each(enumerateCategories(), function (index, list) { + list.removeClass('hide-api-container'); + list.prev('h2').removeClass('hide-api-container'); + + list.children().each(function () { + $(this).removeClass('hide-api-link'); + + if ($(this).text().toLowerCase().indexOf(text) === -1) { + $(this).addClass('hide-api-link'); + } + }); + + var listItemsCount = getVisibleChildrenCount(list); + if (listItemsCount === 0) { + list.addClass('hide-api-container'); + list.prev('h2').addClass('hide-api-container'); + } else { + arrangeColumns(list, DEFAULT_COLUMN_COUNT); + } + }); + + previousSearch = text; +} + +function getApiSectionIndex(hash) { + hash = hash.toLowerCase(); + var sectionIndex = -1; + $.each(API_CATEGORIES, function (index, element) { + sectionIndex = hash.indexOf("#" + element); + if (sectionIndex > -1) { + return false; + } + }); + + return sectionIndex; +} + +function ensureCorrectNavigation() { + var hash = window.location.hash; + var dashIndex = hash.indexOf('-'); + if (hash !== "" && dashIndex > -1) { + var hashIndex = getApiSectionIndex(hash); + if (hashIndex > -1 && hashIndex < dashIndex) { + var newPath = hash.replace('#', '/').replace('-', '/').toLowerCase(); + window.location.replace(window.location.origin + window.location.pathname.replace('.html', '') + newPath); + return true; + } + } + + return false; +} + +function updateActiveTocItem(headings) { + var fixedHeaderHeight = $("#page-header").height(); + var scrollOffset = $(document).scrollTop() + fixedHeaderHeight; + var heading = headings.filter(function () { + return $(this).offset().top + this.offsetHeight - scrollOffset > 0; + }).first(); + + if (heading.length) { + $('a').removeClass('active-toc-item'); + $('[href="#' + heading.attr('id') + '"]').addClass('active-toc-item'); + } +} + +function filterControlKeydown(e) { + var which = e.which; + var target = $(e.target); + + if(which === 13){//Enter + if(target.hasClass('focused-field')){ + target.attr('target', '_blank'); + + setTimeout(function(){ + $(target).removeAttr('target'); + }, 1); + } else { + $('.focused-field').focus(); + } + }else if(which === 40){//Arrow Down + e.preventDefault(); + selectNextAnchor(true); + }else if(which === 38){//Arrow Up + e.preventDefault(); + selectNextAnchor(false); + } +} + +function selectFirstAnchor(ul) { + var nextUl = ul; + var parent = nextUl.find('li:not(.hide-api-link)').first(); + var anchor = parent.find('a'); + + $('.focused-field').removeClass('focused-field'); + setTimeout(function(){ + anchor.addClass('focused-field'); + anchor.focus(); + }); +} + +function selectNextAnchor(dir) { + var links = $("#page-article li:not('.hide-api-link') a"); + var index = links.index($(".focused-field")); + + if(dir){ + index++; + }else{ + index--; + } + + if(index >= 0 && index < links.length){ + $('.focused-field').removeClass('focused-field'); + $(links[index]).addClass('focused-field'); + $(links[index]).focus(); + } +} + +function attachToApiPageEvents() { + filterControl = $('#api-filter input.search'); + if (filterControl.length) { + filterControl.on('keyup', function () { filter(); }); + $(window).on('keydown', function (e) { filterControlKeydown(e) }); + $('#page-article h2').on('click', function(e){ + var nextUl = $(e.target).parent().next('ul'); + + selectFirstAnchor(nextUl); + }); + + if(location.href.indexOf('#')===-1){ + filterControl.focus(); + } + } + breadcrumbDropDown = $('.links-container > a'); + if (breadcrumbDropDown.length) { + breadcrumbDropDown.mouseenter(function (e) { + e.preventDefault(); + $('.links-container').children('ul').hide(); + + var dropDownContent = $(this).next('ul'); + if (dropDownContent.length) { + dropDownContent.css('left', dropDownContent.position().left + $(this).position().left); + if (dropDownContent.is(':hidden')) { + dropDownContent.show(); + } else { + dropDownContent.hide(); + } + dropDownContent.mouseleave(function () { + $(this).hide(); + }); + } + }); + } + + var headingAnchors = $('h3'); + var apiContainer = $('.api-toc-container'); + if (apiContainer.length) { + updateActiveTocItem(headingAnchors); + $(window).scroll(function () { + updateActiveTocItem(headingAnchors); + }); + } +} + +function getDataForCurrentPage(data) { + var searchedApiReferenceControl = decodeURI(window.location.pathname).toLowerCase(); + var startIndex = searchedApiReferenceControl.indexOf('api/javascript'); + var endIndex = findApiCategoryIndexFromPath(searchedApiReferenceControl); + searchedApiReferenceControl = searchedApiReferenceControl.substring(startIndex, endIndex - 1); + $.each(data, function (index, dataItem) { + if (searchedApiReferenceControl === dataItem.control) { + dataItemForPage = dataItem; + return false; + } + }); + + return dataItemForPage; +} + +$(document).ready(function () { + $.get("/kendo-ui/api.json", function (data) { + if (!ensureCorrectNavigation()) { + setupColumns(); + if (!$('#markdown-toc').length) { + buildApiBreadcrumbs(getDataForCurrentPage(data)); + } + buildToc(); + attachToApiPageEvents(); + } + }); +}); diff --git a/_assets/js/dojo.js b/_assets/js/dojo.js new file mode 100644 index 0000000..597f4e8 --- /dev/null +++ b/_assets/js/dojo.js @@ -0,0 +1,269 @@ + +var dojoApi = (function($) { + var dojoApi = { + configuration: { + url: "https://dojo.telerik.com/", + currentKendoVersion: kendo.version + }, + post: function (snippet) { + if (!snippet.match(//i)) { + snippet = dojoApi.wrapInHtml(snippet); + } + snippet = dojoApi.fixLineEndings(snippet); + var form = $('
    ').appendTo(document.body); + $("").val(window.btoa(encodeURIComponent(snippet))).appendTo(form); + + form.submit(); + }, + fixLineEndings: function (code) { + return code.replace(/\n/g, " "); + }, + showHintButton: function (element, text) { + element = $(element); + + $("'+ + ''+ + 'Open In Dojo'+ + '').insertBefore(element); + } + }, + editSnippet: function(element) { + reset(); + + var pre = $(element).parent().nextAll("pre:first"); + + if (isCodeMirrorCurrent(pre)) { + showCodeMirror(); + } else { + destroyCodeMirror(); + createCodeMirror(pre); + } + + pre.hide(); + + $(element).addClass("active-button"); + $(element).next().removeClass("active-button"); + }, + runSnippet: function(element) { + reset(); + + var pre = $(element).parent().nextAll("pre:first"); + + var iframe = $('