@@ -27,10 +27,12 @@ function findApiCategoryIndex(values) {
2727}
2828
2929function capitalize ( values ) {
30- for ( var i = 0 ; i < 2 ; i ++ ) {
30+ for ( var i = 0 ; i < values . length ; i ++ ) {
3131 var value = values [ i ] ;
3232 values [ i ] = value . charAt ( 0 ) . toUpperCase ( ) + value . slice ( 1 ) . toLowerCase ( ) ;
3333 }
34+
35+ return values ;
3436}
3537
3638function separatePageParts ( values , breadcrumbs ) {
@@ -40,24 +42,40 @@ function separatePageParts(values, breadcrumbs) {
4042 previousLink += previousLink !== "" ? "." + pagePart : pagePart ;
4143 breadcrumbs . push ( previousLink ) ;
4244 } ) ;
45+
46+ return currentPageParts . length ;
4347}
4448
4549function getBreadcrumbsInfo ( values ) {
4650 var startIndex = findApiCategoryIndex ( values ) . index ;
4751 var breadcrumbs = values . slice ( startIndex - 1 , values . length - 1 ) ;
4852 capitalize ( breadcrumbs ) ;
49- separatePageParts ( values , breadcrumbs ) ;
53+ var pagePartsCount = separatePageParts ( values , breadcrumbs ) ;
5054 categoryInfo = findApiCategoryIndex ( breadcrumbs ) ;
5155
5256 return {
5357 categoryIndex : categoryInfo . index ,
5458 category : categoryInfo . category ,
55- breadcrumbs : breadcrumbs
59+ breadcrumbs : breadcrumbs ,
60+ nestingLevel : pagePartsCount
5661 } ;
5762}
5863
59- function shouldBuildBreadCrumbs ( ) {
60- return $ ( '#markdown-toc' ) . length === 0 ;
64+ function buildToc ( ) {
65+ var tocContainer = $ ( '.api-toc-container' ) ;
66+ if ( tocContainer . length > 0 ) {
67+ var listItems = "" ;
68+ var headersCount = 0 ;
69+ $ ( 'h3' ) . each ( function ( ) {
70+ headersCount ++ ;
71+ var text = this . id === 'related-properties' ? 'Related Properties' : this . id ;
72+ listItems += '<li class="api-toc-item"><a href="#' + this . id + '">' + text + '</a></li>' ;
73+ } ) ;
74+
75+ if ( headersCount > 1 ) {
76+ tocContainer . append ( '<div class="api-toc-title">In this article</div><ul>' + listItems + '</ul>' ) ;
77+ }
78+ }
6179}
6280
6381function repeat ( string , count ) {
@@ -69,35 +87,98 @@ function repeat(string, count) {
6987 return result ;
7088}
7189
72- function buildApiBreadcrumbs ( ) {
90+ function buildApiBreadcrumbs ( data ) {
91+ if ( $ ( '#markdown-toc' ) . length > 0 ) {
92+ return ;
93+ }
94+
7395 var path = $ ( location ) . attr ( 'pathname' ) . split ( '/' ) ;
7496 var breadcrumbsInfo = getBreadcrumbsInfo ( path ) ;
7597 var breadcrumbs = breadcrumbsInfo . breadcrumbs ;
76- breadcrumbs = breadcrumbs . slice ( 0 , breadcrumbs . length ) ; // Skip the last element
98+ breadcrumbs = breadcrumbs . slice ( 0 , breadcrumbs . length ) ;
7799
78100 var href = '' ;
79101 var lastHref = '' ;
80- for ( var i = 0 ; i < breadcrumbs . length - 1 ; i ++ ) {
102+ var links = '' ;
103+ var breadcrumbsContainer = $ ( '.api-breadcrumbs-container' ) ;
104+ for ( var i = 0 ; i < breadcrumbs . length ; i ++ ) {
81105 var backStepsCount = breadcrumbsInfo . categoryIndex - i + 1 ;
82106 var relativePathBackPath = backStepsCount >= 0 ? repeat ( "../" , backStepsCount ) : "" ;
83107 var breadcrumb = breadcrumbs [ i ] ;
84108 href = breadcrumb === breadcrumbsInfo . category ?
85109 lastHref + '#' + breadcrumb :
86110 relativePathBackPath + breadcrumb ;
87111
88- $ ( '.api-breadcrumbs-container' ) . append ( ' <a href="' + href . toLowerCase ( ) + '">' + breadcrumb + '</a>' ) ;
89- if ( i < breadcrumbs . length - 2 ) {
90- $ ( '.api-breadcrumbs-container' ) . append ( ' / ' ) ;
112+ links += ' <a href="' + href . toLowerCase ( ) + '">' + breadcrumb + '</a>' ;
113+ if ( i > 0 ) {
114+ links += getBreadcrumbDropDownContent ( data , breadcrumbsInfo , i - 1 , lastHref ) ;
91115 }
92116 lastHref = href ;
93117 }
118+
119+ breadcrumbsContainer . append ( '<div class="links-container">' + links + '</div>' ) ;
120+ }
121+
122+ function getBreadcrumbDropDownContent ( data , breadcrumbsInfo , nestingLevel , lastHref ) {
123+ var dropDownContent = '<ul>' ;
124+ var items = [ ] ;
125+ var isApiCategory = nestingLevel === 0 ;
126+ if ( isApiCategory ) {
127+ var keys = API_CATEGORIES ;
128+ $ . each ( capitalize ( keys ) , function ( index , key ) {
129+ if ( data . categories [ key ] ) {
130+ items . push ( key ) ;
131+ }
132+ } ) ;
133+ } else {
134+ items = data . categories [ breadcrumbsInfo . category ] ;
135+ }
136+
137+ var breadcrumbs = breadcrumbsInfo . breadcrumbs ;
138+ var scopeFilter = breadcrumbs [ nestingLevel ] != breadcrumbsInfo . category ? breadcrumbs [ nestingLevel ] : false ;
139+ for ( var j = 0 ; j < items . length ; j ++ ) {
140+ var item = items [ j ] ;
141+ if ( shouldAppendItemToDropDown ( item , scopeFilter , nestingLevel , breadcrumbsInfo . nestingLevel ) ) {
142+ var href ;
143+ if ( isApiCategory ) {
144+ href = lastHref + '#' + item . toLowerCase ( ) ;
145+ } else {
146+ href = getPrefix ( item , data . group_parents ) + item ;
147+ }
148+ var selectedDropDownClassName = breadcrumbs [ nestingLevel + 1 ] . toLowerCase ( ) === item . toLowerCase ( ) ? 'selected-dropdown-breadcrumb' : '' ;
149+ dropDownContent += '<li>' + '<a href="' + href . toLowerCase ( ) + '" class="' + selectedDropDownClassName + '">' + item + '</li>' ;
150+ }
151+ }
152+ dropDownContent += '</ul>' ;
153+ return dropDownContent ;
154+ }
155+
156+ function getPrefix ( item , prefixes ) {
157+ var result = '' ;
158+ $ . each ( prefixes , function ( index , prefix ) {
159+ if ( item . indexOf ( prefix ) > - 1 ) {
160+ result = prefix + '#' ;
161+ return false ;
162+ }
163+ } ) ;
164+
165+ return result ;
166+ }
167+
168+ function shouldAppendItemToDropDown ( item , scopeFilteringItem , nestingLevel , maxNestingLevel ) {
169+ var matchNestingLevel = item . split ( NESTED_ELEMENT_MARK ) . length === nestingLevel ;
170+ var isInContextScope = item . toLowerCase ( ) . indexOf ( scopeFilteringItem ) === 0 ;
171+
172+ return nestingLevel === 0 ||
173+ ( maxNestingLevel > nestingLevel && isInContextScope && matchNestingLevel ) ||
174+ matchNestingLevel && ( ! scopeFilteringItem || ( scopeFilteringItem && isInContextScope ) ) ;
94175}
95176
96177function getMinNestingLevel ( ) {
97178 var minNestingLevel = MAX_NESTING_LEVEL ;
98179 var linksSection = $ ( '#' + API_SUBPAGE_TITLE ) ;
99- if ( linksSection . length > 0 ) {
100- var list = $ ( linksSection ) . next ( 'ul' ) ;
180+ if ( linksSection . length ) {
181+ var list = $ ( linksSection [ linksSection . length - 1 ] ) . next ( 'ul' ) ;
101182 list . children ( ) . each ( function ( ) {
102183 minNestingLevel = Math . min ( minNestingLevel , $ ( this ) . text ( ) . split ( NESTED_ELEMENT_MARK ) . length - 1 ) ;
103184 } ) ;
@@ -112,7 +193,6 @@ function styleItems(listItems, category, mainNestingLevel) {
112193 var styleClassToAdd = itemText . split ( NESTED_ELEMENT_MARK ) . length - 1 === mainNestingLevel ? 'api-icon ' + category : 'nested-list-item' ;
113194 $ ( this ) . addClass ( styleClassToAdd ) ;
114195 } ) ;
115-
116196}
117197
118198function getVisibleChildrenCount ( list ) {
@@ -163,7 +243,7 @@ function setupColumns() {
163243 setupColumnsInternal ( API_CATEGORIES [ i ] , API_CATEGORIES [ i ] , 0 ) ;
164244 }
165245
166- var subCategory = $ ( '#page-article article:first-child ' ) . attr ( 'class' ) ;
246+ var subCategory = $ ( '#page-article > article' ) . attr ( 'class' ) ;
167247 if ( subCategory ) {
168248 var mainNestingLevel = getMinNestingLevel ( ) ;
169249 setupColumnsInternal ( API_SUBPAGE_TITLE , subCategory . toLowerCase ( ) , mainNestingLevel ) ;
@@ -214,32 +294,102 @@ function filter() {
214294 previousSearch = text ;
215295}
216296
297+ function getApiSectionIndex ( hash ) {
298+ hash = hash . toLowerCase ( ) ;
299+ var sectionIndex = - 1 ;
300+ $ . each ( API_CATEGORIES , function ( index , element ) {
301+ sectionIndex = hash . indexOf ( "#" + element ) ;
302+ if ( sectionIndex > - 1 ) {
303+ return false ;
304+ }
305+ } ) ;
306+
307+ return sectionIndex ;
308+ }
309+
217310function ensureCorrectNavigation ( ) {
218311 var hash = window . location . hash ;
219-
220- if ( hash !== "" ) {
221- var hashIndex = hash . indexOf ( '#' ) ;
222- var dashIndex = hash . indexOf ( '-' ) ;
312+ var dashIndex = hash . indexOf ( '-' ) ;
313+ if ( hash !== "" && dashIndex > - 1 ) {
314+ var hashIndex = getApiSectionIndex ( hash ) ;
223315 if ( hashIndex > - 1 && hashIndex < dashIndex ) {
224- var newPath = hash . replace ( '#' , '/' ) . replace ( '-' , '/' ) . toLowerCase ( ) ;
316+ var newPath = hash . replace ( '#' , '/' ) . replace ( '-' , '/' ) ;
225317 window . location . replace ( window . location . origin + window . location . pathname + newPath ) ;
226318 return true ;
227319 }
228320 }
321+
229322 return false ;
230323}
231324
232- $ ( document ) . ready ( function ( ) {
233- if ( ! ensureCorrectNavigation ( ) ) {
234- setupColumns ( ) ;
325+ function updateActiveTocItem ( headings ) {
326+ var fixedHeaderHeight = $ ( "#page-header" ) . height ( ) ;
327+ var scrollOffset = $ ( document ) . scrollTop ( ) + fixedHeaderHeight ;
328+ var heading = headings . filter ( function ( ) {
329+ return $ ( this ) . offset ( ) . top + this . offsetHeight - scrollOffset > 0 ;
330+ } ) . first ( ) ;
331+
332+ if ( heading . length ) {
333+ $ ( 'a' ) . removeClass ( 'active-toc-item' ) ;
334+ $ ( '[href="#' + heading . attr ( 'id' ) + '"]' ) . addClass ( 'active-toc-item' ) ;
335+ }
336+ }
337+
338+ function attachToApiPageEvents ( ) {
339+ filterControl = $ ( '#api-filter input.search' ) ;
340+ if ( filterControl . length ) {
341+ filterControl . on ( 'keyup' , function ( ) { filter ( ) ; } ) ;
342+ }
235343
236- if ( shouldBuildBreadCrumbs ( ) ) {
237- buildApiBreadcrumbs ( ) ;
344+ breadcrumbDropDown = $ ( '.links-container > a' ) ;
345+ if ( breadcrumbDropDown . length && breadcrumbDropDown . next ( 'ul' ) . length ) {
346+ breadcrumbDropDown . mouseenter ( function ( e ) {
347+ e . preventDefault ( ) ;
348+ $ ( '.links-container' ) . children ( 'ul' ) . hide ( ) ;
349+
350+ var dropDownContent = $ ( this ) . next ( 'ul' ) ;
351+ dropDownContent . css ( 'left' , dropDownContent . position ( ) . left + $ ( this ) . position ( ) . left ) ;
352+ if ( dropDownContent . is ( ':hidden' ) ) {
353+ dropDownContent . show ( ) ;
354+ } else {
355+ dropDownContent . hide ( ) ;
356+ }
357+
358+ dropDownContent . mouseleave ( function ( ) {
359+ $ ( this ) . hide ( ) ;
360+ } ) ;
361+ } ) ;
362+ }
363+
364+ var headingAnchors = $ ( 'h3' ) ;
365+ var apiContainer = $ ( '.api-toc-container' ) ;
366+ if ( apiContainer . length ) {
367+ updateActiveTocItem ( headingAnchors ) ;
368+ $ ( window ) . scroll ( function ( ) {
369+ updateActiveTocItem ( headingAnchors ) ;
370+ } ) ;
371+ }
372+ }
373+
374+ function getDataForCurrentPage ( data ) {
375+ var dataItemForPage ;
376+ $ . each ( data , function ( index , dataItem ) {
377+ if ( window . location . pathname . indexOf ( dataItem . control ) ) {
378+ dataItemForPage = dataItem ;
379+ return false ;
238380 }
381+ } ) ;
382+
383+ return dataItemForPage ;
384+ }
239385
240- filterControl = $ ( '#api-filter input.search' ) ;
241- if ( filterControl . length > 0 ) {
242- filterControl . on ( 'keyup' , function ( ) { filter ( ) ; } ) ;
386+ $ ( document ) . ready ( function ( ) {
387+ $ . get ( "/kendo-ui/api.json" , function ( data ) {
388+ if ( ! ensureCorrectNavigation ( ) ) {
389+ setupColumns ( ) ;
390+ buildApiBreadcrumbs ( getDataForCurrentPage ( data ) ) ;
391+ buildToc ( ) ;
392+ attachToApiPageEvents ( ) ;
243393 }
244- }
394+ } ) ;
245395} ) ;
0 commit comments