1212angularIO . directive ( 'apiList' , function ( ) {
1313 var API_FILTER_KEY = 'apiFilter' ;
1414 var API_TYPE_KEY = 'apiType' ;
15+ var API_STATUS_KEY = 'statusType' ;
16+ var QUERY_KEY = 'query' ;
17+ var TYPE_KEY = 'type' ;
18+ var STATUS_KEY = 'status' ;
19+
1520 return {
1621 restrict : 'E' ,
1722 template :
1823 '<div ng-cloak="ng-cloak" class="banner is-plain api-filter clearfix">' +
1924 ' <div class="form-select-menu">' +
20- ' <button ng-repeat="apiType in $ctrl.apiTypes" ng-if="$ctrl.apiType === apiType" class="form-select-button has-symbol" ng-click="$ctrl.toggleMenu()"><strong>Type:</strong><span class="symbol {{apiType.cssClass}}" ng-if="apiType.cssClass !== \'stable\'" ></span>{{apiType.title}}</button>' +
21- ' <button class="form-select-button is-default" ng-if="$ctrl.apiType === null" ng-click="$ctrl.toggleMenu()"><strong>All Types</strong></button>' +
22- ' <ul class="form-select-dropdown" ng-class="{ visible: $ctrl.showMenu === true }">' +
23- ' <li ng-class="{ active: !$ctrl.apiType }" ng-click="$ctrl.clearType()">All Types</li>' +
24- ' <li ng-repeat="apiType in $ctrl.apiTypes" ng-class="{ active: $ctrl.apiType === apiType }" ng-click="$ctrl.setType(apiType)"><span class="symbol {{apiType.cssClass}}"></span>{{apiType.title}}</li>' +
25+ ' <button ng-repeat="type in $ctrl.types" ng-if="$ctrl.type === type.matches[0]" class="form-select-button has-symbol" ng-click="$ctrl.toggleMenu(\'type\')"><strong>Type:</strong><span class="symbol {{type.cssClass}}" ng-if="type.cssClass !== \'stable\'" ></span>{{type.title}}</button>' +
26+ ' <button class="form-select-button is-default" ng-if="$ctrl.type === null" ng-click="$ctrl.toggleMenu(\'type\')"><strong>All Types</strong></button>' +
27+ ' <ul class="form-select-dropdown" ng-class="{ visible: $ctrl.showTypeMenu === true }">' +
28+ ' <li ng-class="{ active: !$ctrl.type }" ng-click="$ctrl.clear(\'type\')">All Types</li>' +
29+ ' <li ng-repeat="type in $ctrl.types" ng-class="{ active: $ctrl.type === type }" ng-click="$ctrl.set(type, \'type\')"><span class="symbol {{type.cssClass}}"></span>{{type.title}}</li>' +
30+ ' </ul>' +
31+ ' <div class="overlay" ng-class="{ visible: $ctrl.showTypeMenu === true }" ng-click="$ctrl.toggleMenu(\'type\')"></div>' +
32+ ' </div>' +
33+ ' ' +
34+ ' <div class="form-select-menu">' +
35+ ' <button ng-repeat="status in $ctrl.statuses" ng-if="$ctrl.status === status.matches[0]" class="form-select-button" ng-click="$ctrl.toggleMenu(\'status\')"><strong>Status:</strong>{{status.title}}</button>' +
36+ ' <button class="form-select-button is-default" ng-if="$ctrl.status === null" ng-click="$ctrl.toggleMenu(\'status\')"><strong>All Statuses</strong></button>' +
37+ ' <ul class="form-select-dropdown" ng-class="{ visible: $ctrl.showStatusMenu === true }">' +
38+ ' <li ng-class="{ active: !$ctrl.status }" ng-click="$ctrl.clear(\'status\')">All Statuses</li>' +
39+ ' <li ng-repeat="status in $ctrl.statuses" ng-class="{ active: $ctrl.status === status }" ng-click="$ctrl.set(status, \'status\')">{{status.title}}</li>' +
2540 ' </ul>' +
26- ' <div class="overlay" ng-class="{ visible: $ctrl.showMenu === true }" ng-click="$ctrl.toggleMenu()"></div>' +
41+ ' <div class="overlay" ng-class="{ visible: $ctrl.showStatusMenu === true }" ng-click="$ctrl.toggleMenu(\'status\' )"></div>' +
2742 ' </div>' +
43+ ' ' +
2844 ' <div class="form-search">' +
2945 ' <i class="material-icons">search</i>' +
30- ' <input placeholder="Filter" ng-model="$ctrl.apiFilter " ng-model-options="{updateOn: \'default blur\', debounce: {\'default\': 350, \'blur\': 0}}">' +
46+ ' <input placeholder="Filter" ng-model="$ctrl.query " ng-model-options="{updateOn: \'default blur\', debounce: {\'default\': 350, \'blur\': 0}}">' +
3147 ' </div>' +
3248 '</div>' +
49+ ' ' +
3350 '<article class="l-content-small grid-fluid docs-content">' +
34- ' <div ng-repeat="section in $ctrl.groupedSections" ng-if="$ctrl.isFiltered (section)" ng-cloak="ng-cloak">' +
51+ ' <div ng-repeat="section in $ctrl.groupedSections" ng-if="$ctrl.filterSections (section)" ng-cloak="ng-cloak">' +
3552 ' <h2>{{ section.title }}</h2>' +
3653 ' <ul class="api-list">' +
3754 ' <li ng-repeat="item in section.items" ng-show="item.show" class="api-item">' +
@@ -42,111 +59,214 @@ angularIO.directive('apiList', function () {
4259 '</article>' ,
4360 controllerAs : '$ctrl' ,
4461 controller : function ( $scope , $attrs , $http , $location ) {
45- // SET DEFAULTS
62+ // DEFAULT VALUES
4663 var $ctrl = this ;
47- $ctrl . showMenu = false ;
48- var isForDart = $attrs . lang === 'dart' ;
64+ $ctrl . showTypeMenu = false ;
65+ $ctrl . showStatusMenu = false ;
66+ $ctrl . status = null ;
67+ $ctrl . query = null ;
68+ $ctrl . type = null ;
69+ $ctrl . groupedSections = [ ] ;
4970
50- $ctrl . apiTypes = [
51- { cssClass : 'stable' , title : 'Only Stable' , matches : [ 'stable' ] } ,
71+
72+ // API TYPES
73+ $ctrl . types = [
5274 { cssClass : 'directive' , title : 'Directive' , matches : [ 'directive' ] } ,
5375 { cssClass : 'pipe' , title : 'Pipe' , matches : [ 'pipe' ] } ,
5476 { cssClass : 'decorator' , title : 'Decorator' , matches : [ 'decorator' ] } ,
5577 { cssClass : 'class' , title : 'Class' , matches : [ 'class' ] } ,
5678 { cssClass : 'interface' , title : 'Interface' , matches : [ 'interface' ] } ,
5779 { cssClass : 'function' , title : 'Function' , matches : [ 'function' ] } ,
5880 { cssClass : 'enum' , title : 'Enum' , matches : [ 'enum' ] } ,
81+ { cssClass : 'type-alias' , title : 'Type Alias' , matches : [ 'type-alias' ] } ,
5982 { cssClass : 'const' , title : 'Const' , matches : [ 'var' , 'let' , 'const' ] }
6083 ] ;
6184
62- if ( isForDart ) $ctrl . apiTypes = $ctrl . apiTypes . filter ( function ( t ) {
63- return ! t . cssClass . match ( / ^ ( s t a b l e | d i r e c t i v e | d e c o r a t o r | i n t e r f a c e | e n u m ) $ / ) ;
64- } ) ;
85+ // STATUSES
86+ $ctrl . statuses = [
87+ { cssClass : 'stable' , title : 'Stable' , matches : [ 'stable' ] } ,
88+ { cssClass : 'deprecated' , title : 'Deprecated' , matches : [ 'deprecated' ] } ,
89+ { cssClass : 'experimental' , title : 'Experimental' , matches : [ 'experimental' ] } ,
90+ { cssClass : 'security' , title : 'Security Risk' , matches : [ 'security' ] }
91+ ] ;
6592
66- $ctrl . apiFilter = getApiFilterFromLocation ( ) ;
67- $ctrl . apiType = getApiTypeFromLocation ( ) ;
68- $ctrl . groupedSections = [ ] ;
6993
70- $ctrl . setType = function ( type ) {
71- if ( type === $ctrl . apiType ) $ctrl . apiType = null ;
72- else $ctrl . apiType = type ;
73- $ctrl . showMenu = ! $ctrl . showMenu ;
74- } ;
94+ // SET FILTER VALUES
95+ getFilterValues ( ) ;
7596
76- // CLEAR FILTER
77- $ctrl . clearType = function ( ) {
78- $ctrl . apiType = null ;
79- $ctrl . showMenu = ! $ctrl . showMenu ;
80- } ;
8197
82- // TOGGLE FILTER MENU
83- $ctrl . toggleMenu = function ( ) {
84- $ctrl . showMenu = ! $ctrl . showMenu ;
85- } ;
98+ // GRAB DATA FOR SECTIONS
99+ $http . get ( $attrs . src ) . then ( function ( response ) {
100+ $ctrl . sections = response . data ;
86101
87- $ctrl . isFiltered = function ( section ) {
88- var apiFilter = ( $ctrl . apiFilter || '' ) . toLowerCase ( ) ;
89- var matchesModule = $ctrl . apiFilter === '' || $ctrl . apiFilter === null || section . title . toLowerCase ( ) . indexOf ( $ctrl . apiFilter . toLowerCase ( ) ) !== - 1 ;
90- var isVisible = false ;
102+ $ctrl . groupedSections = Object . keys ( $ctrl . sections ) . map ( function ( title ) {
103+ return { title : title , items : $ctrl . sections [ title ] } ;
104+ } ) ;
105+ } ) ;
91106
92- section . items . forEach ( function ( item ) {
93107
94- // Filter by stability (ericjim: only 'stable' for now)
95- if ( $ctrl . apiType && $ctrl . apiType . matches . length === 1 &&
96- $ctrl . apiType . matches [ 0 ] === 'stable' && item . stability === 'stable' ) {
97- item . show = true ;
98- isVisible = true ;
99- return isVisible ;
100- } // NOTE: other checks can be performed for stability (experimental, deprecated, etc)
108+ // SET SELECTED VALUE FROM MENUS/FORM
109+ $ctrl . set = function ( item , kind ) {
110+ var value = ( item && item . matches ) ? item . matches [ 0 ] : null ;
101111
102- // Filter by docType
103- var matchesDocType = ! $ctrl . apiType || $ctrl . apiType . matches . indexOf ( item . docType ) !== - 1 ;
104- var matchesTitle = ! apiFilter || item . title . toLowerCase ( ) . indexOf ( apiFilter ) !== - 1 ;
105- item . show = matchesDocType && ( matchesTitle || matchesModule ) ;
112+ switch ( kind ) {
113+ case 'type' : $ctrl . type = value ; break ;
114+ case 'query' : $ctrl . query = value ; break ;
115+ case 'status' : $ctrl . status = value ; break ;
116+ }
106117
107- if ( item . show ) {
108- isVisible = true ;
109- }
110- } ) ;
118+ $ctrl . toggleMenu ( kind ) ;
119+ }
111120
112- return isVisible ;
121+
122+ // CLEAR SELECTED VALUE FROM MENUS/FORM
123+ $ctrl . clear = function ( kind ) {
124+ switch ( kind ) {
125+ case 'type' : $ctrl . type = null ; break ;
126+ case 'query' : $ctrl . query = null ; break ;
127+ case 'status' : $ctrl . status = null ; break ;
128+ }
129+
130+ $ctrl . toggleMenu ( kind ) ;
113131 } ;
114132
115- $http . get ( $attrs . src ) . then ( function ( response ) {
116- $ctrl . sections = response . data ;
117- $ctrl . groupedSections = Object . keys ( $ctrl . sections ) . map ( function ( title ) {
118- return { title : title , items : $ctrl . sections [ title ] } ;
133+
134+ // TOGGLE MENU
135+ $ctrl . toggleMenu = function ( kind ) {
136+ console . log ( kind ) ;
137+
138+ switch ( kind ) {
139+ case 'type' : $ctrl . showTypeMenu = ! $ctrl . showTypeMenu ; ; break ;
140+ case 'status' : $ctrl . showStatusMenu = ! $ctrl . showStatusMenu ; ; break ;
141+ }
142+ }
143+
144+
145+ // UPDATE VALUES IF DART API
146+ var isForDart = $attrs . lang === 'dart' ;
147+ if ( isForDart ) {
148+ $ctrl . apiTypes = $ctrl . apiTypes . filter ( function ( t ) {
149+ return ! t . cssClass . match ( / ^ ( s t a b l e | d i r e c t i v e | d e c o r a t o r | i n t e r f a c e | e n u m ) $ / ) ;
119150 } ) ;
120- } ) ;
151+ }
121152
153+
154+ // SET URL WITH VALUES
122155 $scope . $watchGroup (
123- [ function ( ) { return $ctrl . apiFilter ; } , function ( ) { return $ctrl . apiType ; } , function ( ) { return $ctrl . sections ; } ] ,
156+ [
157+ function ( ) { return $ctrl . query ; } ,
158+ function ( ) { return $ctrl . type ; } ,
159+ function ( ) { return $ctrl . status ; } ,
160+ function ( ) { return $ctrl . sections ; }
161+ ] ,
162+
124163 function ( ) {
125- var apiFilter = ( $ctrl . apiFilter || '' ) . toLowerCase ( ) ;
164+ var queryURL = $ctrl . query ? $ctrl . query . toLowerCase ( ) : null ;
165+ var typeURL = $ctrl . type || null ;
166+ var statusURL = $ctrl . status || null ;
126167
127- $location . search ( API_FILTER_KEY , apiFilter || null ) ;
128- $location . search ( API_TYPE_KEY , $ctrl . apiType && $ctrl . apiType . title || null ) ;
168+ // SET URLS
169+ $location . search ( QUERY_KEY , queryURL ) ;
170+ $location . search ( STATUS_KEY , statusURL ) ;
171+ $location . search ( TYPE_KEY , typeURL ) ;
129172 }
130173 ) ;
131174
132- function getApiFilterFromLocation ( ) {
133- return $location . search ( ) [ API_FILTER_KEY ] || null ;
175+
176+ // GET VALUES FORM URL
177+ function getFilterValues ( ) {
178+ var urlParams = $location . search ( ) ;
179+
180+ $ctrl . status = urlParams [ STATUS_KEY ] || null ;
181+ $ctrl . query = urlParams [ QUERY_KEY ] || null ; ;
182+ $ctrl . type = urlParams [ TYPE_KEY ] || null ; ;
134183 }
135184
136- function getApiTypeFromLocation ( ) {
137- var apiFilter = $location . search ( ) [ API_TYPE_KEY ] ;
138- if ( ! apiFilter ) {
139- return null ;
140- } else if ( ! $ctrl . apiFilter || $ctrl . apiFilter . title != apiFilter ) {
141- for ( var i = 0 , ii = $ctrl . apiTypes . length ; i < ii ; i ++ ) {
142- if ( $ctrl . apiTypes [ i ] . title == apiFilter ) {
143- return $ctrl . apiTypes [ i ] ;
144- }
185+
186+ // CHECK IF IT'S A CONSTANT TYPE
187+ function isConst ( item ) {
188+ var isConst = false ;
189+
190+ switch ( item . docType ) {
191+ case 'let' : isConst = true ; break ;
192+ case 'var' : isConst = true ; break ;
193+ case 'const' : isConst = true ; break ;
194+ default : isConst = false ;
195+ }
196+
197+ return isConst ;
198+ }
199+
200+ // FILTER SECTION & ITEMS LOOP
201+ $ctrl . filterSections = function ( section ) {
202+ var showSection = false ;
203+
204+ section . items . forEach ( function ( item ) {
205+ item . show = false ;
206+
207+ // CHECK IF TYPE IS NULL & STATUS, QUERY
208+ if ( ( $ctrl . type === null ) && statusSelected ( item ) && queryEntered ( section , item ) ) {
209+ item . show = true ;
210+ }
211+
212+ // CHECK IF TYPE IS SELECTED & STATUS, QUERY
213+ if ( ( $ctrl . type === item . docType ) && statusSelected ( item ) && queryEntered ( section , item ) ) {
214+ item . show = true ;
215+ }
216+
217+ // CHECK IF TYPE IS CONST & STATUS, QUERY
218+ if ( ( $ctrl . type === 'const' ) && isConst ( item ) && statusSelected ( item ) && queryEntered ( section , item ) ) {
219+ item . show = true ;
145220 }
221+
222+ // SHOW SECTION IF ONE ITEM IS VISIBLE
223+ if ( ! showSection && item . show ) {
224+ showSection = true ;
225+ }
226+ } ) ;
227+
228+ return showSection ;
229+ }
230+
231+
232+ // CHECK FOR QUERY
233+ function queryEntered ( section , item ) {
234+ var isVisible = false ;
235+
236+ // CHECK IF QUERY MATCH SECTION OR ITEM
237+ var query = ( $ctrl . query || '' ) . toLowerCase ( ) ;
238+ var matchesSection = $ctrl . query === '' || $ctrl . query === null || section . title . toLowerCase ( ) . indexOf ( $ctrl . query . toLowerCase ( ) ) !== - 1 ;
239+ var matchesTitle = ! query || item . title . toLowerCase ( ) . indexOf ( query ) !== - 1 ;
240+
241+ // FILTER BY QUERY
242+ if ( matchesTitle || matchesSection ) {
243+ isVisible = true ;
146244 }
147- // If we get here then the apiType query didn't match any apiTypes
148- $location . search ( API_TYPE_KEY , null ) ;
245+
246+ return isVisible ;
149247 }
248+
249+
250+ // CHECK IF AN API ITEM IS VISIBLE BY STATUS
251+ function statusSelected ( item ) {
252+ var status = item . stability ;
253+ var insecure = item . secure === 'false' ? false : true ;
254+ var isVisible = false ;
255+
256+ if ( $ctrl . status === null ) {
257+ isVisible = true ;
258+ }
259+
260+ if ( status === $ctrl . status ) {
261+ isVisible = true ;
262+ }
263+
264+ if ( ( $ctrl . status === 'security' ) && insecure ) {
265+ isVisible = true ;
266+ }
267+
268+ return isVisible ;
269+ } ;
150270 }
151271 } ;
152272} ) ;
0 commit comments