nitdoc: create js module utils
[nit.git] / share / nitdoc / scripts / Nitdoc.UI.js
1 /* This file is part of NIT ( http://www.nitlanguage.org ).
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14
15 Documentation generator for the nit language.
16 Generate API documentation in HTML format from nit source code.
17 */
18
19 var Nitdoc = Nitdoc || {};
20
21 /*
22 * Nitdoc UI module
23 *
24 * Enhance nitdoc usability with JS features
25 */
26
27 Nitdoc.UI = function() {
28
29 // Allow user to fold sidebar nav elements on click
30 var enableFolding = function(containerSelector) {
31 var container = $(containerSelector);
32 var foldLink = $(document.createElement("a"))
33 .addClass("nitdoc-ui-fold")
34 .html("-");
35
36 container.find("nav h3")
37 .prepend(foldLink)
38 .css("cursor", "pointer")
39 .toggle(
40 function() {
41 $(this).find("a.nitdoc-ui-fold").html("+");
42 $(this).nextAll().toggle();
43 },
44 function() {
45 $(this).find("a.nitdoc-ui-fold").html("-");
46 $(this).nextAll().toggle();
47 }
48 );
49 }
50
51 // Allow user to copy signatures to clipboard with ZeroClipboard flahs plugin
52 // See: https://github.com/zeroclipboard/ZeroClipboard
53 var enableCopyToClipboard = function(copySelector) {
54 $(copySelector).each(function() {
55 var btn = $(document.createElement("button"))
56 .addClass("nitdoc-ui-copy")
57 .attr("data-clipboard-text", $(this).attr("data-untyped-signature"))
58 .append(
59 $(document.createElement("img"))
60 .attr("src", './resources/icons/copy.png')
61 );
62 $(this).append(btn);
63 });
64
65 var clip = new ZeroClipboard($("button.nitdoc-ui-copy"), {
66 moviePath: "./ZeroClipboard.swf"
67 });
68 }
69
70 // Allow user to filter sidebar box entries by name
71 var enableSidebarTextFilters = function(filterSelector) {
72 var div = $(document.createElement("div"))
73 .addClass("nitdoc-ui-filter")
74 .append(
75 $(document.createElement("input"))
76 .addClass("nitdoc-ui-filter-field")
77 .addClass("nitdoc-ui-filter-field-notused")
78 .attr("type", "text")
79 .attr("value", "filter...")
80 .keyup(function() {
81 var box = $(this).parents("nav.filterable");
82 var value = $(this).val();
83 box.find("ul li:not(:icontains('" + value + "'))").hide();
84 box.find("ul li:icontains('" + value + "')").show();
85 })
86 .focusout(function() {
87 if($(this).val() == "") {
88 $(this).addClass("nitdoc-ui-filter-field-notused");
89 $(this).val("filter...");
90 }
91 })
92 .focusin(function() {
93 if($(this).val() == "filter...") {
94 $(this).removeClass("nitdoc-ui-filter-field-notused");
95 $(this).val("");
96 }
97 })
98 );
99 $(filterSelector).after(div);
100 preloadSidebarTextFilters();
101 }
102
103 // Prealod filters using search query
104 var preloadSidebarTextFilters = function() {
105 var anchor = Nitdoc.Utils.extractAnchor(document.location.hash);
106 if(!anchor || anchor.indexOf("q=") == -1) return;
107
108 var query = anchor.substring(2);
109 if(!query) return;
110
111 $(".nitdoc-ui-filter input:text")
112 .val(query)
113 .removeClass("nitdoc-ui-notused")
114 .trigger("keyup");
115 }
116
117 // Allow user to filter side bar box entries by Introduced/Refined/inHerited type
118 var enableSidebarTypeFilters = function(filterSelector) {
119 var box = $(filterSelector);
120 var types = {};
121
122 box.find("li").each(function() {
123 var span = $(this).find("span:first");
124 if(!types[span.html()]) types[span.html()] = {
125 title: span.attr("title"),
126 class: $(this).attr("class")
127 }
128 });
129
130 for(var type in types) {
131 var a = $(document.createElement("a"))
132 .addClass("nitdoc-ui-filter-link")
133 .html(type)
134 .attr("title", "Hide " + types[type].title)
135 .attr("data-filter-class", types[type].class)
136 .toggle(
137 function() {
138 var hclass = $(this).attr("data-filter-class");
139 $(this).parents(filterSelector).find("li." + hclass).hide();
140 $(this).addClass("nitdoc-ui-filter-hidden")
141 },
142 function() {
143 var hclass = $(this).attr("data-filter-class");
144 $(this).parents(filterSelector).find("li." + hclass).show();
145 $(this).removeClass("nitdoc-ui-filter-hidden")
146 }
147 )
148 $(filterSelector).find(".nitdoc-ui-filter").append(a);
149 }
150 }
151
152 // Allow user to filter sidebar box entries by name
153 var enableSearchPageField = function(filterSelector) {
154 var div = $(document.createElement("div"))
155 .addClass("nitdoc-ui-searchpage-filter")
156 .append(
157 $(document.createElement("input"))
158 .addClass("nitdoc-ui-searchpage-field")
159 .addClass("nitdoc-ui-filter-field-notused")
160 .attr("type", "text")
161 .attr("value", "filter...")
162 .keyup(function() {
163 var box = $(this).parents(".content.fullpage").find("article.filterable");
164 var value = $(this).val();
165 box.find("ul li:not(:icontains('" + value + "'))").hide();
166 box.find("ul li:icontains('" + value + "')").show();
167 })
168 .focusout(function() {
169 if($(this).val() == "") {
170 $(this).addClass("nitdoc-ui-filter-field-notused");
171 $(this).val("filter...");
172 }
173 })
174 .focusin(function() {
175 if($(this).val() == "filter...") {
176 $(this).removeClass("nitdoc-ui-filter-field-notused");
177 $(this).val("");
178 }
179 })
180 );
181 $(filterSelector).after(div);
182 preloadSearchPageField();
183 }
184
185 // Prealod filter using search query
186 var preloadSearchPageField = function() {
187 var anchor = Nitdoc.Utils.extractAnchor(document.location.hash);
188 if(!anchor || anchor.indexOf("q=") == -1) return;
189
190 var query = anchor.substring(2);
191 if(!query) return;
192
193 $(".nitdoc-ui-searchpage-field")
194 .val(query)
195 .removeClass("nitdoc-ui-notused")
196 .trigger("keyup");
197 }
198
199 // Public interface
200 var ui = {
201 enableFolding: enableFolding,
202 enableCopyToClipboard: enableCopyToClipboard,
203 enableSidebarTextFilters: enableSidebarTextFilters,
204 enableSidebarTypeFilters: enableSidebarTypeFilters,
205 enableSearchPageField: enableSearchPageField
206 };
207
208 return ui;
209 }();
210
211 // Init UI on page load
212 $(document).ready(function() {
213 Nitdoc.UI.enableFolding(".sidebar");
214 Nitdoc.UI.enableCopyToClipboard(".signature");
215 Nitdoc.UI.enableSidebarTextFilters("nav.filterable h3");
216 Nitdoc.UI.enableSidebarTypeFilters("nav.filterable");
217 Nitdoc.UI.enableSearchPageField(".content.fullpage h1:contains('Search')");
218 });
219
220 /*
221 * Utils module
222 *
223 * Utility functions
224 */
225
226 Nitdoc.Utils = function() {
227
228 // Extract anchor part (after #) from URL string
229 var extractAnchor = function(url) {
230 var index = url.indexOf("#");
231 if (index >= 0) {
232 return url.substring(index + 1);
233 }
234 return null;
235 }
236
237 // Public interface
238 var utils = {
239 extractAnchor: extractAnchor
240 };
241
242 return utils;
243 }();
244
245 // JQuery Case Insensitive :icontains selector
246 $.expr[':'].icontains = function(obj, index, meta, stack){
247 return (obj.textContent.replace(/\[[0-9]+\]/g, "") || obj.innerText.replace(/\[[0-9]+\]/g, "") || jQuery(obj).text().replace(/\[[0-9]+\]/g, "") || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0;
248 };
249