1
2/* API LEVEL TOGGLE */
3<?cs if:reference.apilevels ?>
4addLoadEvent(changeApiLevel);
5<?cs /if ?>
6
7var API_LEVEL_ENABLED_COOKIE = "api_level_enabled";
8var API_LEVEL_COOKIE = "api_level";
9var minLevel = 1;
10
11function toggleApiLevelSelector(checkbox) {
12  var date = new Date();
13  date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
14  var expiration = date.toGMTString();
15  if (checkbox.checked) {
16    $("#apiLevelSelector").removeAttr("disabled");
17    $("#api-level-toggle label").removeClass("disabled");
18    writeCookie(API_LEVEL_ENABLED_COOKIE, 1, null, expiration);
19  } else {
20    $("#apiLevelSelector").attr("disabled","disabled");
21    $("#api-level-toggle label").addClass("disabled");
22    writeCookie(API_LEVEL_ENABLED_COOKIE, 0, null, expiration);
23  }
24  changeApiLevel();
25}
26
27function buildApiLevelSelector() {
28  var maxLevel = SINCE_DATA.length;
29  var userApiLevelEnabled = readCookie(API_LEVEL_ENABLED_COOKIE);
30  var userApiLevel = readCookie(API_LEVEL_COOKIE);
31  userApiLevel = userApiLevel == 0 ? maxLevel : userApiLevel; // If there's no cookie (zero), use the max by default
32
33  if (userApiLevelEnabled == 0) {
34    $("#apiLevelSelector").attr("disabled","disabled");
35  } else {
36    $("#apiLevelCheckbox").attr("checked","checked");
37    $("#api-level-toggle label").removeClass("disabled");
38  }
39
40  minLevel = $("body").attr("class");
41  var select = $("#apiLevelSelector").html("").change(changeApiLevel);
42  for (var i = maxLevel-1; i >= 0; i--) {
43    var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]);
44  //  if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
45    select.append(option);
46  }
47
48  // get the DOM element and use setAttribute cuz IE6 fails when using jquery .attr('selected',true)
49  var selectedLevelItem = $("#apiLevelSelector option[value='"+userApiLevel+"']").get(0);
50  selectedLevelItem.setAttribute('selected',true);
51}
52
53function changeApiLevel() {
54  var maxLevel = SINCE_DATA.length;
55  var userApiLevelEnabled = readCookie(API_LEVEL_ENABLED_COOKIE);
56  var selectedLevel = maxLevel;
57
58  if (userApiLevelEnabled == 0) {
59    toggleVisisbleApis(selectedLevel, "body");
60  } else {
61    selectedLevel = $("#apiLevelSelector option:selected").val();
62    toggleVisisbleApis(selectedLevel, "body");
63
64    var date = new Date();
65    date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
66    var expiration = date.toGMTString();
67    writeCookie(API_LEVEL_COOKIE, selectedLevel, null, expiration);
68  }
69
70  if (selectedLevel < minLevel) {
71    var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class";
72    $("#naMessage").show().html("<div><p><strong>This " + thing + " is not available with API Level " + selectedLevel + ".</strong></p>"
73                              + "<p>To use this " + thing + ", your application must specify API Level " + minLevel + " or higher in its manifest "
74                              + "and be compiled against a version of the library that supports an equal or higher API Level. To reveal this "
75                              + "document, change the value of the API Level filter above.</p>"
76                              + "<p><a href='" +toRoot+ "guide/appendix/api-levels.html'>What is the API Level?</a></p></div>");
77  } else {
78    $("#naMessage").hide();
79  }
80}
81
82function toggleVisisbleApis(selectedLevel, context) {
83  var apis = $(".api",context);
84  apis.each(function(i) {
85    var obj = $(this);
86    var className = obj.attr("class");
87    var apiLevelIndex = className.lastIndexOf("-")+1;
88    var apiLevelEndIndex = className.indexOf(" ", apiLevelIndex);
89    apiLevelEndIndex = apiLevelEndIndex != -1 ? apiLevelEndIndex : className.length;
90    var apiLevel = className.substring(apiLevelIndex, apiLevelEndIndex);
91    if (apiLevel > selectedLevel) obj.addClass("absent").attr("title","Requires API Level "+apiLevel+" or higher");
92    else obj.removeClass("absent").removeAttr("title");
93  });
94}
95
96/* NAVTREE */
97
98function new_node(me, mom, text, link, children_data, api_level)
99{
100  var node = new Object();
101  node.children = Array();
102  node.children_data = children_data;
103  node.depth = mom.depth + 1;
104
105  node.li = document.createElement("li");
106  mom.get_children_ul().appendChild(node.li);
107
108  node.label_div = document.createElement("div");
109  node.label_div.className = "label";
110  if (api_level != null) {
111    $(node.label_div).addClass("api");
112    $(node.label_div).addClass("api-level-"+api_level);
113  }
114  node.li.appendChild(node.label_div);
115  node.label_div.style.paddingLeft = 10*node.depth + "px";
116
117  if (children_data == null) {
118    // 12 is the width of the triangle and padding extra space
119    node.label_div.style.paddingLeft = ((10*node.depth)+12) + "px";
120  } else {
121    node.label_div.style.paddingLeft = 10*node.depth + "px";
122    node.expand_toggle = document.createElement("a");
123    node.expand_toggle.href = "javascript:void(0)";
124    node.expand_toggle.onclick = function() {
125          if (node.expanded) {
126            $(node.get_children_ul()).slideUp("fast");
127            node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
128            node.expanded = false;
129          } else {
130            expand_node(me, node);
131          }
132       };
133    node.label_div.appendChild(node.expand_toggle);
134
135    node.plus_img = document.createElement("img");
136    node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
137    node.plus_img.className = "plus";
138    node.plus_img.border = "0";
139    node.expand_toggle.appendChild(node.plus_img);
140
141    node.expanded = false;
142  }
143
144  var a = document.createElement("a");
145  node.label_div.appendChild(a);
146  node.label = document.createTextNode(text);
147  a.appendChild(node.label);
148  if (link) {
149    a.href = me.toroot + link;
150  } else {
151    if (children_data != null) {
152      a.className = "nolink";
153      a.href = "javascript:void(0)";
154      a.onclick = node.expand_toggle.onclick;
155      // This next line shouldn't be necessary.  I'll buy a beer for the first
156      // person who figures out how to remove this line and have the link
157      // toggle shut on the first try. --joeo@android.com
158      node.expanded = false;
159    }
160  }
161
162
163  node.children_ul = null;
164  node.get_children_ul = function() {
165      if (!node.children_ul) {
166        node.children_ul = document.createElement("ul");
167        node.children_ul.className = "children_ul";
168        node.children_ul.style.display = "none";
169        node.li.appendChild(node.children_ul);
170      }
171      return node.children_ul;
172    };
173
174  return node;
175}
176
177function expand_node(me, node)
178{
179  if (node.children_data && !node.expanded) {
180    if (node.children_visited) {
181      $(node.get_children_ul()).slideDown("fast");
182    } else {
183      get_node(me, node);
184      if ($(node.label_div).hasClass("absent")) $(node.get_children_ul()).addClass("absent");
185      $(node.get_children_ul()).slideDown("fast");
186    }
187    node.plus_img.src = me.toroot + "assets/images/triangle-opened-small.png";
188    node.expanded = true;
189
190    // perform api level toggling because new nodes are new to the DOM
191    var selectedLevel = $("#apiLevelSelector option:selected").val();
192    toggleVisisbleApis(selectedLevel, "#side-nav");
193  }
194}
195
196function get_node(me, mom)
197{
198  mom.children_visited = true;
199  for (var i in mom.children_data) {
200    var node_data = mom.children_data[i];
201    mom.children[i] = new_node(me, mom, node_data[0], node_data[1],
202        node_data[2], node_data[3]);
203  }
204}
205
206function this_page_relative(toroot)
207{
208  var full = document.location.pathname;
209  var file = "";
210  if (toroot.substr(0, 1) == "/") {
211    if (full.substr(0, toroot.length) == toroot) {
212      return full.substr(toroot.length);
213    } else {
214      // the file isn't under toroot.  Fail.
215      return null;
216    }
217  } else {
218    if (toroot != "./") {
219      toroot = "./" + toroot;
220    }
221    do {
222      if (toroot.substr(toroot.length-3, 3) == "../" || toroot == "./") {
223        var pos = full.lastIndexOf("/");
224        file = full.substr(pos) + file;
225        full = full.substr(0, pos);
226        toroot = toroot.substr(0, toroot.length-3);
227      }
228    } while (toroot != "" && toroot != "/");
229    return file.substr(1);
230  }
231}
232
233function find_page(url, data)
234{
235  var nodes = data;
236  var result = null;
237  for (var i in nodes) {
238    var d = nodes[i];
239    if (d[1] == url) {
240      return new Array(i);
241    }
242    else if (d[2] != null) {
243      result = find_page(url, d[2]);
244      if (result != null) {
245        return (new Array(i).concat(result));
246      }
247    }
248  }
249  return null;
250}
251
252function load_navtree_data(toroot) {
253  var navtreeData = document.createElement("script");
254  navtreeData.setAttribute("type","text/javascript");
255  navtreeData.setAttribute("src", toroot+"navtree_data.js");
256  $("head").append($(navtreeData));
257}
258
259function init_default_navtree(toroot) {
260  init_navtree("nav-tree", toroot, NAVTREE_DATA);
261
262  // perform api level toggling because because the whole tree is new to the DOM
263  var selectedLevel = $("#apiLevelSelector option:selected").val();
264  toggleVisisbleApis(selectedLevel, "#side-nav");
265}
266
267function init_navtree(navtree_id, toroot, root_nodes)
268{
269  var me = new Object();
270  me.toroot = toroot;
271  me.node = new Object();
272
273  me.node.li = document.getElementById(navtree_id);
274  me.node.children_data = root_nodes;
275  me.node.children = new Array();
276  me.node.children_ul = document.createElement("ul");
277  me.node.get_children_ul = function() { return me.node.children_ul; };
278  //me.node.children_ul.className = "children_ul";
279  me.node.li.appendChild(me.node.children_ul);
280  me.node.depth = 0;
281
282  get_node(me, me.node);
283
284  me.this_page = this_page_relative(toroot);
285  me.breadcrumbs = find_page(me.this_page, root_nodes);
286  if (me.breadcrumbs != null && me.breadcrumbs.length != 0) {
287    var mom = me.node;
288    for (var i in me.breadcrumbs) {
289      var j = me.breadcrumbs[i];
290      mom = mom.children[j];
291      expand_node(me, mom);
292    }
293    mom.label_div.className = mom.label_div.className + " selected";
294    addLoadEvent(function() {
295      scrollIntoView("nav-tree");
296      });
297  }
298}
299
300/* TOGGLE INHERITED MEMBERS */
301
302/* Toggle an inherited class (arrow toggle)
303 * @param linkObj  The link that was clicked.
304 * @param expand  'true' to ensure it's expanded. 'false' to ensure it's closed.
305 *                'null' to simply toggle.
306 */
307function toggleInherited(linkObj, expand) {
308    var base = linkObj.getAttribute("id");
309    var list = document.getElementById(base + "-list");
310    var summary = document.getElementById(base + "-summary");
311    var trigger = document.getElementById(base + "-trigger");
312    var a = $(linkObj);
313    if ( (expand == null && a.hasClass("closed")) || expand ) {
314        list.style.display = "none";
315        summary.style.display = "block";
316        trigger.src = toRoot + "assets/images/triangle-opened.png";
317        a.removeClass("closed");
318        a.addClass("opened");
319    } else if ( (expand == null && a.hasClass("opened")) || (expand == false) ) {
320        list.style.display = "block";
321        summary.style.display = "none";
322        trigger.src = toRoot + "assets/images/triangle-closed.png";
323        a.removeClass("opened");
324        a.addClass("closed");
325    }
326    return false;
327}
328
329/* Toggle all inherited classes in a single table (e.g. all inherited methods)
330 * @param linkObj  The link that was clicked.
331 * @param expand  'true' to ensure it's expanded. 'false' to ensure it's closed.
332 *                'null' to simply toggle.
333 */
334function toggleAllInherited(linkObj, expand) {
335  var a = $(linkObj);
336  var table = $(a.parent().parent().parent()); // ugly way to get table/tbody
337  var expandos = $(".jd-expando-trigger", table);
338  if ( (expand == null && a.text() == "[Expand]") || expand ) {
339    expandos.each(function(i) {
340      toggleInherited(this, true);
341    });
342    a.text("[Collapse]");
343  } else if ( (expand == null && a.text() == "[Collapse]") || (expand == false) ) {
344    expandos.each(function(i) {
345      toggleInherited(this, false);
346    });
347    a.text("[Expand]");
348  }
349  return false;
350}
351
352/* Toggle all inherited members in the class (link in the class title)
353 */
354function toggleAllClassInherited() {
355  var a = $("#toggleAllClassInherited"); // get toggle link from class title
356  var toggles = $(".toggle-all", $("#doc-content"));
357  if (a.text() == "[Expand All]") {
358    toggles.each(function(i) {
359      toggleAllInherited(this, true);
360    });
361    a.text("[Collapse All]");
362  } else {
363    toggles.each(function(i) {
364      toggleAllInherited(this, false);
365    });
366    a.text("[Expand All]");
367  }
368  return false;
369}
370
371/* Expand all inherited members in the class. Used when initiating page search */
372function ensureAllInheritedExpanded() {
373  var toggles = $(".toggle-all", $("#doc-content"));
374  toggles.each(function(i) {
375    toggleAllInherited(this, true);
376  });
377  $("#toggleAllClassInherited").text("[Collapse All]");
378}
379
380
381/* HANDLE KEY EVENTS
382 * - Listen for Ctrl+F (Cmd on Mac) and expand all inherited members (to aid page search)
383 */
384var agent = navigator['userAgent'].toLowerCase();
385var mac = agent.indexOf("macintosh") != -1;
386
387$(document).keydown( function(e) {
388var control = mac ? e.metaKey && !e.ctrlKey : e.ctrlKey; // get ctrl key
389  if (control && e.which == 70) {  // 70 is "F"
390    ensureAllInheritedExpanded();
391  }
392});