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