├── index-blank-ie.html ├── src ├── System │ ├── .svn │ │ ├── format │ │ ├── all-wcprops │ │ ├── text-base │ │ │ └── ParseCLI.js.svn-base │ │ └── entries │ └── ParseCLI.js ├── Menu │ ├── SystrayClickHandler.js │ ├── Initialise.js │ ├── MenuItemClickHandler.js │ └── AddMenuItems.js ├── Network │ ├── Offline.js │ ├── Online.js │ ├── URLStatus.js │ └── Initialise.js ├── Database │ ├── ErrorHandler.js │ ├── SetupFirstRun.js │ ├── CreateDB.js │ ├── ConnectToFile.js │ ├── SaveOrCreateOption.js │ └── Query.js ├── Update │ ├── InvokeApplicationUpdate.js │ └── AppVersionCheck.js ├── jQueryAPI.js └── Chrome │ ├── Popup.js │ ├── APIBrowser.js │ └── Splash.js ├── badge.swf ├── certificate.pfx ├── icons ├── AIRApp_16.png ├── AIRApp_32.png ├── AIRApp_48.png └── AIRApp_128.png ├── assets ├── images │ ├── op1.png │ ├── op10.png │ ├── op2.png │ ├── op3.png │ ├── op4.png │ ├── op5.png │ ├── op6.png │ ├── op7.png │ ├── op8.png │ ├── op9.png │ ├── accept.png │ ├── badge.jpg │ ├── badge.png │ ├── cancel.png │ ├── close.png │ ├── delete.png │ ├── fav-on.png │ ├── icons.png │ ├── jquery.gif │ ├── shadow.png │ ├── bullet_go.png │ ├── close-ui.png │ ├── fav-off.png │ ├── open-ui.png │ ├── spinner.gif │ ├── background.png │ ├── large-spinner.gif │ ├── bg_home_tile_sml.jpg │ ├── jQueryAPIOffline.png │ ├── jQueryAPIOnline.png │ ├── logo_jquery_215x53.gif │ ├── bg_secondaryNav_left.gif │ └── bg_secondaryNav_right.gif ├── html │ ├── APIBrowser.html │ └── Splash.html └── css │ ├── Print.css │ ├── Splash.css │ └── APIBrowser.css ├── lib ├── air │ ├── servicemonitor.swf │ ├── applicationupdater.swf │ ├── AC_RunActiveContent.js │ ├── AIRAliases.js │ └── AIRMenuBuilder.js └── jqueryapi │ ├── cookie.js │ ├── jquery.tojson.js │ ├── jquery.history.js │ ├── api-browser.js │ ├── json2.js │ └── api-loader.js ├── update └── jquery-api-browser-2.0.air ├── .htaccess ├── update.xml ├── index-blank.html ├── application.html ├── no-scroll-application.xml ├── application.xml ├── index.html └── index.php /index-blank-ie.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/System/.svn/format: -------------------------------------------------------------------------------- 1 | 8 2 | -------------------------------------------------------------------------------- /badge.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/badge.swf -------------------------------------------------------------------------------- /certificate.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/certificate.pfx -------------------------------------------------------------------------------- /icons/AIRApp_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/icons/AIRApp_16.png -------------------------------------------------------------------------------- /icons/AIRApp_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/icons/AIRApp_32.png -------------------------------------------------------------------------------- /icons/AIRApp_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/icons/AIRApp_48.png -------------------------------------------------------------------------------- /src/Menu/SystrayClickHandler.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Menu.SystrayClickHandler = function( clickEvent ) { 2 | 3 | } -------------------------------------------------------------------------------- /assets/images/op1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op1.png -------------------------------------------------------------------------------- /assets/images/op10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op10.png -------------------------------------------------------------------------------- /assets/images/op2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op2.png -------------------------------------------------------------------------------- /assets/images/op3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op3.png -------------------------------------------------------------------------------- /assets/images/op4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op4.png -------------------------------------------------------------------------------- /assets/images/op5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op5.png -------------------------------------------------------------------------------- /assets/images/op6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op6.png -------------------------------------------------------------------------------- /assets/images/op7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op7.png -------------------------------------------------------------------------------- /assets/images/op8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op8.png -------------------------------------------------------------------------------- /assets/images/op9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/op9.png -------------------------------------------------------------------------------- /icons/AIRApp_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/icons/AIRApp_128.png -------------------------------------------------------------------------------- /assets/images/accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/accept.png -------------------------------------------------------------------------------- /assets/images/badge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/badge.jpg -------------------------------------------------------------------------------- /assets/images/badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/badge.png -------------------------------------------------------------------------------- /assets/images/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/cancel.png -------------------------------------------------------------------------------- /assets/images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/close.png -------------------------------------------------------------------------------- /assets/images/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/delete.png -------------------------------------------------------------------------------- /assets/images/fav-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/fav-on.png -------------------------------------------------------------------------------- /assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/icons.png -------------------------------------------------------------------------------- /assets/images/jquery.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/jquery.gif -------------------------------------------------------------------------------- /assets/images/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/shadow.png -------------------------------------------------------------------------------- /src/Network/Offline.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Network.Offline = function() { 2 | jQueryAPI.UserOnline = false; 3 | 4 | }; -------------------------------------------------------------------------------- /assets/images/bullet_go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/bullet_go.png -------------------------------------------------------------------------------- /assets/images/close-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/close-ui.png -------------------------------------------------------------------------------- /assets/images/fav-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/fav-off.png -------------------------------------------------------------------------------- /assets/images/open-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/open-ui.png -------------------------------------------------------------------------------- /assets/images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/spinner.gif -------------------------------------------------------------------------------- /lib/air/servicemonitor.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/lib/air/servicemonitor.swf -------------------------------------------------------------------------------- /assets/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/background.png -------------------------------------------------------------------------------- /assets/images/large-spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/large-spinner.gif -------------------------------------------------------------------------------- /lib/air/applicationupdater.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/lib/air/applicationupdater.swf -------------------------------------------------------------------------------- /assets/images/bg_home_tile_sml.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/bg_home_tile_sml.jpg -------------------------------------------------------------------------------- /assets/images/jQueryAPIOffline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/jQueryAPIOffline.png -------------------------------------------------------------------------------- /assets/images/jQueryAPIOnline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/jQueryAPIOnline.png -------------------------------------------------------------------------------- /update/jquery-api-browser-2.0.air: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/update/jquery-api-browser-2.0.air -------------------------------------------------------------------------------- /assets/images/logo_jquery_215x53.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/logo_jquery_215x53.gif -------------------------------------------------------------------------------- /assets/images/bg_secondaryNav_left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/bg_secondaryNav_left.gif -------------------------------------------------------------------------------- /assets/images/bg_secondaryNav_right.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jquery-archive/jquery-api-browser/HEAD/assets/images/bg_secondaryNav_right.gif -------------------------------------------------------------------------------- /src/Database/ErrorHandler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The database error handler 3 | * @param {Object} event The event callback 4 | */ 5 | jQueryAPI.Database.ErrorHandler = function(event) { 6 | air.trace(event.target); 7 | }; 8 | -------------------------------------------------------------------------------- /src/Database/SetupFirstRun.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Database.SetupFirstRun = function() { 2 | jQueryAPI.Database.Query({ 3 | 'queryString': 'CREATE TABLE IF NOT EXISTS options (key TEXT, value TEXT);' 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /src/Network/Online.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Network.Online = function() { 2 | jQueryAPI.UserOnline = true; 3 | 4 | jQueryAPI.Update.InvokeApplicationUpdate({ 5 | 'updateXML': 'http://api.jquery.com/update.xml' 6 | }); 7 | 8 | }; -------------------------------------------------------------------------------- /src/Network/URLStatus.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Network.URLStatus = function ( statusEvent ) { 2 | if (statusEvent.currentTarget.available) { 3 | jQueryAPI.Network.Online(); 4 | } else { 5 | jQueryAPI.Network.Offline(); 6 | } 7 | return; 8 | } -------------------------------------------------------------------------------- /assets/html/APIBrowser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQueryAPI Browser 5 | 6 | 7 | 8 |
9 |
10 | 11 | -------------------------------------------------------------------------------- /src/System/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 60 4 | /svn/!svn/ver/6118/trunk/tools/jquery-api-browser/src/System 5 | END 6 | ParseCLI.js 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 72 10 | /svn/!svn/ver/6118/trunk/tools/jquery-api-browser/src/System/ParseCLI.js 11 | END 12 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymLinks +ExecCGI 3 | RewriteEngine On 4 | RewriteBase / 5 | 6 | RewriteRule ^([A-Za-z0-9=\.]+)/?$ /?q=$1 [L] 7 | 8 | # if the file or directory don't exist 9 | RewriteCond %{REQUEST_FILENAME} -d [OR] 10 | RewriteCond %{REQUEST_FILENAME} -f 11 | RewriteRule .* - [L] 12 | 13 | 14 | -------------------------------------------------------------------------------- /update.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0 4 | http://api.jquery.com/browser/update/jquery-api-browser-2.0.air 5 | 7 | 8 | -------------------------------------------------------------------------------- /assets/css/Print.css: -------------------------------------------------------------------------------- 1 | html { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | html, body { 7 | overflow: auto; 8 | } 9 | 10 | #body { 11 | height: auto; 12 | } 13 | 14 | #navigation, 15 | #browser, 16 | #header, 17 | #credit { 18 | display: none; 19 | } 20 | 21 | #detail { 22 | position: static; 23 | bottom: auto; 24 | left: auto; 25 | } 26 | 27 | pre { 28 | overflow: visible; 29 | } -------------------------------------------------------------------------------- /src/System/ParseCLI.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.System.ParseCLI = function(arguments, callback) { 2 | 3 | jQuery.each(arguments, 4 | function(index, argument) { 5 | 6 | switch (argument) { 7 | case "debug-mode": 8 | jQueryAPI.DebugMode = false; 9 | break; 10 | default: 11 | // Do nothing 12 | break; 13 | } 14 | 15 | }); 16 | 17 | return callback(); 18 | 19 | }; -------------------------------------------------------------------------------- /src/System/.svn/text-base/ParseCLI.js.svn-base: -------------------------------------------------------------------------------- 1 | jQueryAPI.System.ParseCLI = function(arguments, callback) { 2 | 3 | jQuery.each(arguments, 4 | function(index, argument) { 5 | 6 | switch (argument) { 7 | case "debug-mode": 8 | jQueryAPI.DebugMode = false; 9 | break; 10 | default: 11 | // Do nothing 12 | break; 13 | } 14 | 15 | }); 16 | 17 | return callback(); 18 | 19 | }; -------------------------------------------------------------------------------- /src/Database/CreateDB.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates the database from the passed file location 3 | * @param {Object} databaseFile The location of the database file 4 | */ 5 | jQueryAPI.Database.CreateDB = function() { 6 | jQueryAPI.FirstRun = true; 7 | var connection = new air.SQLConnection(); 8 | connection.addEventListener(air.SQLErrorEvent.ERROR, jQueryAPI.Database.ErrorHandler); 9 | connection.open(jQueryAPI.Database.DatabaseFile, air.SQLMode.CREATE); 10 | connection.close(); 11 | return true; 12 | }; 13 | -------------------------------------------------------------------------------- /index-blank.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /assets/css/Splash.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #fff; 3 | } 4 | 5 | #splash-outer { 6 | background: #2A3139 url(/assets/images/bg_home_tile_sml.jpg) repeat-x scroll 0 -40px; 7 | width: 295px; 8 | height:295px; 9 | border: 3px solid #000; 10 | -webkit-border-radius: 10px; 11 | -moz-border-radius: 10px; 12 | } 13 | 14 | img { 15 | padding: 20px 40px; 16 | } 17 | 18 | ul { 19 | position: absolute; 20 | top: 150px; 21 | margin: 0; 22 | list-style: none; 23 | } 24 | 25 | li { 26 | margin: 0; 27 | padding: 5px; 28 | } -------------------------------------------------------------------------------- /src/System/.svn/entries: -------------------------------------------------------------------------------- 1 | 8 2 | 3 | dir 4 | 6496 5 | https://jqueryjs.googlecode.com/svn/trunk/tools/jquery-api-browser/src/System 6 | https://jqueryjs.googlecode.com/svn 7 | 8 | 9 | 10 | 2009-01-17T17:51:24.078978Z 11 | 6118 12 | remysharp 13 | 14 | 15 | svn:special svn:externals svn:needs-lock 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | c715fcbe-d12f-0410-84c4-316a508785bb 28 | 29 | ParseCLI.js 30 | file 31 | 32 | 33 | 34 | 35 | 2009-01-20T22:47:05.000000Z 36 | effaa654ac5ebcf6a5a5d740a2509b4b 37 | 2009-01-17T17:51:24.078978Z 38 | 6118 39 | remysharp 40 | 41 | -------------------------------------------------------------------------------- /src/Menu/Initialise.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Menu.Initialise = function() { 2 | function iconLoadComplete(event) { 3 | if (air.NativeApplication.supportsSystemTrayIcon) { 4 | air.NativeApplication.nativeApplication.icon.bitmaps = new Array(event.target.content.bitmapData); 5 | jQueryAPI.Menu.AddMenuItems(); 6 | } 7 | } 8 | 9 | var iconLoader = new runtime.flash.display.Loader(); 10 | iconLoader.contentLoaderInfo.addEventListener(air.Event.COMPLETE, iconLoadComplete); 11 | iconLoader.load(new air.URLRequest('app:/assets/images/jQueryAPIOffline.png')); 12 | }; -------------------------------------------------------------------------------- /assets/html/Splash.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Splash Screen 7 | 8 | 9 |
10 |
11 | jQuery: Write Less, Do More. 12 | 13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Update/InvokeApplicationUpdate.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Update.ShowFail = false; 2 | 3 | jQueryAPI.Update.Ignore = false; 4 | 5 | jQueryAPI.Update.InvokeApplicationUpdate = function(options) { 6 | function defaults() { 7 | return { 8 | 'updateXML': '' 9 | }; 10 | } 11 | 12 | options = jQuery.extend(defaults(), options); 13 | 14 | if (jQueryAPI.Update.Ignore === false) { 15 | var request = new air.URLRequest(options.updateXML); 16 | var loader = new air.URLLoader(); 17 | jQueryAPI.Update.ShowFail = options.displayFail; 18 | loader.addEventListener(air.Event.COMPLETE, jQueryAPI.Update.AppVersionCheck); 19 | loader.load(request); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/Network/Initialise.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Network.ServiceMonitor = null; 2 | 3 | jQueryAPI.Network.Initialise = function( callback ) { 4 | jQueryAPI.Network.ServiceMonitor = new air.URLMonitor(new air.URLRequest('http://www.jquery.com')); 5 | jQueryAPI.Network.ServiceMonitor.addEventListener(air.StatusEvent.STATUS, jQueryAPI.Network.URLStatus); 6 | jQueryAPI.Network.ServiceMonitor.pollInterval = 300000; 7 | jQueryAPI.Network.ServiceMonitor.start(); 8 | 9 | function checkLoop() { 10 | jQueryAPI.Network.ServiceMonitor.stop(); 11 | jQueryAPI.Network.ServiceMonitor.start(); 12 | } 13 | 14 | var timer = new air.Timer(30000,0); 15 | timer.addEventListener(air.TimerEvent.TIMER, checkLoop); 16 | timer.start(); 17 | 18 | return callback(); 19 | }; -------------------------------------------------------------------------------- /src/Menu/MenuItemClickHandler.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Menu.MenuItemClickHandler = function( clickEvent ) { 2 | 3 | switch (clickEvent.target.label) { 4 | case 'jQuery.com': 5 | air.navigateToURL(new air.URLRequest('http://www.jquery.com/')); 6 | break; 7 | case 'jQueryUI': 8 | air.navigateToURL(new air.URLRequest('http://ui.jquery.com/')); 9 | break; 10 | case 'jQuery Docs': 11 | air.navigateToURL(new air.URLRequest('http://docs.jquery.com/')); 12 | break; 13 | case 'Learning jQuery': 14 | air.navigateToURL(new air.URLRequest('http://www.learningjquery.com/')); 15 | break; 16 | case 'API Browser': 17 | jQueryAPI.Chrome.APIBrowser(); 18 | break; 19 | case 'Exit': 20 | air.NativeApplication.nativeApplication.exit(); 21 | break; 22 | default: 23 | break; 24 | } 25 | }; -------------------------------------------------------------------------------- /lib/jqueryapi/cookie.js: -------------------------------------------------------------------------------- 1 | // cookie functions http://www.quirksmode.org/js/cookies.html 2 | function createCookie(name,value,days) 3 | { 4 | var date, expires; 5 | 6 | if (days) { 7 | date = new Date(); 8 | date.setTime(date.getTime()+(days*24*60*60*1000)); 9 | expires = "; expires="+date.toGMTString(); 10 | } else { 11 | expires = ""; 12 | } 13 | document.cookie = name+"="+value+expires+"; path=/"; 14 | } 15 | 16 | function readCookie(name) { 17 | var nameEQ = name + "=", 18 | ca = document.cookie.split(';'), 19 | i, c; 20 | 21 | for (i=0; i < ca.length; i++) { 22 | c = ca[i]; 23 | while (c.charAt(0)==' ') { 24 | c = c.substring(1,c.length); 25 | } 26 | 27 | if (c.indexOf(nameEQ) == 0) { 28 | return c.substring(nameEQ.length,c.length); 29 | } 30 | } 31 | return null; 32 | } 33 | 34 | function eraseCookie(name) { 35 | createCookie(name,"",-1); 36 | } 37 | -------------------------------------------------------------------------------- /src/jQueryAPI.js: -------------------------------------------------------------------------------- 1 | var jQueryAPI; 2 | if (!jQueryAPI) jQueryAPI = function() {}; 3 | 4 | // Set up our namespaces 5 | jQueryAPI.Chrome = function() {}; 6 | jQueryAPI.Database = function() {}; 7 | jQueryAPI.Menu = function() {}; 8 | jQueryAPI.Network = function() {}; 9 | jQueryAPI.System = function() {}; 10 | jQueryAPI.Update = function() {}; 11 | 12 | jQueryAPI.Initialise = function() { 13 | jQueryAPI.DebugMode = false; 14 | jQueryAPI.FirstRun = false; 15 | jQueryAPI.UserOnline = false; 16 | jQueryAPI.DoPartialUpdate = false; 17 | jQueryAPI.DoFullUpdate = false; 18 | 19 | try { 20 | air.File.applicationStorageDirectory.resolvePath('update').deleteDirectory(true); 21 | } catch(err) { 22 | // Do nothing 23 | } 24 | 25 | air.NativeApplication.nativeApplication.addEventListener(air.InvokeEvent.INVOKE, jQueryAPI.InvokeApplication); 26 | }; 27 | 28 | jQueryAPI.InvokeApplication = function(invokeEvent) { 29 | jQueryAPI.System.ParseCLI(invokeEvent.arguments, 30 | function() { 31 | 32 | jQueryAPI.Database.ConnectToFile({ 33 | 'databaseFile': 'jQueryAPI1.sqlite', 34 | 'createFile': true 35 | }, 36 | function(){ 37 | jQueryAPI.Chrome.Splash(function(){ 38 | 39 | }); 40 | }); 41 | }); 42 | } -------------------------------------------------------------------------------- /src/Database/ConnectToFile.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Database.DatabaseFile = null; 2 | 3 | /** 4 | * Connects to a local SQLite database 5 | * @param {Object} options 6 | */ 7 | jQueryAPI.Database.ConnectToFile = function( options, callback ) { 8 | 9 | /** 10 | * Default options for connecting to a SQLite database 11 | * @param {String} airDir The type of directory in AIR to connect to 12 | * @param {String} The name of the database file 13 | * @param {Boolean} If the file does not exist, it will be created by default, this allows you to overide that 14 | */ 15 | function defaults() { 16 | return { 17 | 'airDir': 'applicationStorageDirectory', 18 | 'databaseFile': '', 19 | 'createFile': true 20 | }; 21 | } 22 | options = jQuery.extend(defaults(), options); 23 | 24 | var databaseFile = air.File[options.airDir]; 25 | databaseFile = databaseFile.resolvePath(options.databaseFile); 26 | 27 | if (!databaseFile.exists) { 28 | if (options.createFile) { 29 | jQueryAPI.Database.CreateDB(databaseFile); 30 | } else { 31 | databaseFile = null; 32 | } 33 | } 34 | jQueryAPI.Database.DatabaseFile = databaseFile; 35 | jQueryAPI.Database.SetupFirstRun(); 36 | return callback(); 37 | }; 38 | -------------------------------------------------------------------------------- /src/Database/SaveOrCreateOption.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Database.SaveOrCreateOption = function(options) { 2 | /** 3 | * Default options for a query 4 | * @param {String} queryString The query string to be passed to the database 5 | */ 6 | function defaults() { 7 | return { 8 | 'key': '', 9 | 'value': '', 10 | 'overwrite': true 11 | }; 12 | } 13 | options = jQuery.extend(defaults(), options); 14 | var exists = false; 15 | var result; 16 | 17 | //First we do a search for the item 18 | var checkExists = jQueryAPI.Database.Query({ 19 | 'queryString': 'SELECT * FROM options WHERE key = "' + options.key + '"' 20 | }); 21 | 22 | if (checkExists.result.data) { 23 | result = null; 24 | if (options.overwrite) { 25 | result = jQueryAPI.Database.Query({ 26 | 'queryString': 'UPDATE options SET value = "' + options.value + '" WHERE key = "' + options.key + '"' 27 | }); 28 | } 29 | exists = true; 30 | } else { 31 | exists = false; 32 | result = jQueryAPI.Database.Query({ 33 | 'queryString': 'INSERT INTO options (key, value) VALUES("' + options.key + '", "' + options.value + '")' 34 | }); 35 | } 36 | return { 37 | 'exists': exists, 38 | 'result': result 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /src/Database/Query.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Allows you to pass a query to the passed database file 3 | * @param {Object} databaseFile The location of the database file 4 | * @param {Object} options The object that contains the options 5 | */ 6 | jQueryAPI.Database.Query = function(options) { 7 | 8 | /** 9 | * Default options for a query 10 | * @param {String} queryString The query string to be passed to the database 11 | */ 12 | function defaults() { 13 | return { 14 | 'queryString': '' 15 | }; 16 | } 17 | options = jQuery.extend(defaults(), options); 18 | var transactionSuccessful = false; 19 | var result = false; 20 | 21 | try { 22 | var connection = new air.SQLConnection(); 23 | connection.open(jQueryAPI.Database.DatabaseFile, air.SQLMode.CREATE); 24 | 25 | var query = new air.SQLStatement(); 26 | query.addEventListener(air.SQLErrorEvent.ERROR, jQueryAPI.Database.ErrorHandler); 27 | query.sqlConnection = connection; 28 | query.text = options.queryString; 29 | query.execute(); 30 | var success = query.getResult(); 31 | if (success) { 32 | transactionSuccessful = true; 33 | result = success; 34 | } 35 | connection.close(); 36 | } catch(error) { 37 | transactionSuccessful = false; 38 | result = error; 39 | } 40 | return { 41 | 'success': transactionSuccessful, 42 | 'result': result 43 | }; 44 | }; 45 | -------------------------------------------------------------------------------- /src/Menu/AddMenuItems.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Menu.AddMenuItems = function() { 2 | 3 | air.NativeApplication.nativeApplication.icon.menu = new air.NativeMenu(); 4 | air.NativeApplication.nativeApplication.icon.addEventListener('click', jQueryAPI.Menu.SystrayClickHandler); 5 | 6 | var websitesMenu = new air.NativeMenu(); 7 | 8 | var websites = { 9 | 'jquery': new air.NativeMenuItem('jQuery.com', false), 10 | 'jqueryui': new air.NativeMenuItem('jQueryUI', false), 11 | 'jquerydocs': new air.NativeMenuItem('jQuery Docs', false), 12 | 'splittera': new air.NativeMenuItem('', true), 13 | 'learningjquery': new air.NativeMenuItem('Learning jQuery', false) 14 | } 15 | 16 | var menuItems = { 17 | 'openbrowser': new air.NativeMenuItem('API Browser', false), 18 | 'opensettings': new air.NativeMenuItem('Settings', false), 19 | 'closeMenu': new air.NativeMenuItem('Exit', false) 20 | }; 21 | 22 | jQuery.each(websites, 23 | function(i, website) { 24 | websitesMenu.addItem(website); 25 | website.addEventListener(air.Event.SELECT, jQueryAPI.Menu.MenuItemClickHandler); 26 | } 27 | ) 28 | 29 | air.NativeApplication.nativeApplication.icon.menu.addSubmenu(websitesMenu, 'Websites'); 30 | 31 | jQuery.each(menuItems, 32 | function(i, menuItem) { 33 | air.NativeApplication.nativeApplication.icon.menu.addItem(menuItem); 34 | menuItem.addEventListener(air.Event.SELECT, jQueryAPI.Menu.MenuItemClickHandler); 35 | }); 36 | 37 | } -------------------------------------------------------------------------------- /src/Chrome/Popup.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Chrome.Popup = function(options) { 2 | 3 | this.Initialise = function() { 4 | var windowOptions = new air.NativeWindowInitOptions(); 5 | windowOptions.systemChrome = air.NativeWindowSystemChrome.NONE; 6 | windowOptions.type = air.NativeWindowType.LIGHTWEIGHT; 7 | windowOptions.transparent = true; 8 | 9 | var windowBounds = new air.Rectangle(0, 0, 305, 305); 10 | 11 | var newHTMLLoader = air.HTMLLoader.createRootWindow(false, windowOptions, false, windowBounds); 12 | newHTMLLoader.paintsDefaultBackground = false; 13 | newHTMLLoader.stage.nativeWindow.alwaysInFront = true; 14 | newHTMLLoader.navigateInSystemBrowser = true; 15 | newHTMLLoader.addEventListener(air.Event.COMPLETE, this.CreateWindow); 16 | newHTMLLoader.load(new air.URLRequest('app:/assets/html/Splash.html')); 17 | }; 18 | 19 | this.CreateWindow = function(event) { 20 | var windowDom = jQuery('#splash-outer', event.target.window.document).get(0); 21 | 22 | function closeWindow() { 23 | event.target.window.close(); 24 | return false; 25 | } 26 | 27 | function runMain() { 28 | jQuery('#loading-message', windowDom) 29 | .empty() 30 | .append('
  • Application updating...
  • ') 31 | .append('
  • ' + options.message + '
  • '); 32 | } 33 | 34 | if (event.type === 'complete' && event.target.window.nativeWindow) { 35 | // Now we set up the window position 36 | var centerX = air.Screen.mainScreen.bounds.width / 2; 37 | var centerY = air.Screen.mainScreen.bounds.height / 2; 38 | event.target.window.nativeWindow.x = centerX - (event.target.window.nativeWindow.width / 2); 39 | event.target.window.nativeWindow.y = centerY - (event.target.window.nativeWindow.height / 2); 40 | event.target.window.nativeWindow.addEventListener(air.Event.ACTIVATE, runMain); 41 | event.target.window.nativeWindow.activate(); 42 | event.target.window.nativeWindow.visible = true; 43 | } 44 | 45 | }; 46 | 47 | this.Initialise(); 48 | }; -------------------------------------------------------------------------------- /lib/jqueryapi/jquery.tojson.js: -------------------------------------------------------------------------------- 1 | // http://www.overset.com/upload/jQuery.toJSON.js 2 | (function ($) { 3 | m = { 4 | '\b': '\\b', 5 | '\t': '\\t', 6 | '\n': '\\n', 7 | '\f': '\\f', 8 | '\r': '\\r', 9 | '"' : '\\"', 10 | '\\': '\\\\' 11 | }, 12 | $.toJSON = function (value, whitelist) { 13 | var a, // The array holding the partial texts. 14 | i, // The loop counter. 15 | k, // The member key. 16 | l, // Length. 17 | r = /["\\\x00-\x1f\x7f-\x9f]/g, 18 | v; // The member value. 19 | 20 | switch (typeof value) { 21 | case 'string': 22 | return r.test(value) ? 23 | '"' + value.replace(r, function (a) { 24 | var c = m[a]; 25 | if (c) { 26 | return c; 27 | } 28 | c = a.charCodeAt(); 29 | return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); 30 | }) + '"' : 31 | '"' + value + '"'; 32 | 33 | case 'number': 34 | return isFinite(value) ? String(value) : 'null'; 35 | 36 | case 'boolean': 37 | case 'null': 38 | return String(value); 39 | 40 | case 'object': 41 | if (!value) { 42 | return 'null'; 43 | } 44 | if (typeof value.toJSON === 'function') { 45 | return $.toJSON(value.toJSON()); 46 | } 47 | a = []; 48 | if (typeof value.length === 'number' && 49 | !(value.propertyIsEnumerable('length'))) { 50 | l = value.length; 51 | for (i = 0; i < l; i += 1) { 52 | a.push($.toJSON(value[i], whitelist) || 'null'); 53 | } 54 | return '[' + a.join(',') + ']'; 55 | } 56 | if (whitelist) { 57 | l = whitelist.length; 58 | for (i = 0; i < l; i += 1) { 59 | k = whitelist[i]; 60 | if (typeof k === 'string') { 61 | v = $.toJSON(value[k], whitelist); 62 | if (v) { 63 | a.push($.toJSON(k) + ':' + v); 64 | } 65 | } 66 | } 67 | } else { 68 | for (k in value) { 69 | if (typeof k === 'string') { 70 | v = $.toJSON(value[k], whitelist); 71 | if (v) { 72 | a.push($.toJSON(k) + ':' + v); 73 | } 74 | } 75 | } 76 | } 77 | return '{' + a.join(',') + '}'; 78 | } 79 | }; 80 | 81 | })(jQuery); 82 | -------------------------------------------------------------------------------- /application.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | AIR API Browser 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/Update/AppVersionCheck.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Update.AppVersionCheck = function(event) { 2 | var remoteVersionString = jQuery(event.target.data).find('version').text(); 3 | var remoteVersion = remoteVersionString.split('.'); 4 | var remoteAir = jQuery(event.target.data).find('url').text(); 5 | 6 | var xmlString = air.NativeApplication.nativeApplication.applicationDescriptor; 7 | var appXml = new DOMParser(); 8 | var xmlObject = appXml.parseFromString(xmlString, "text/xml"); 9 | var root = xmlObject.getElementsByTagName('application')[0]; 10 | var thisVersion = root.getElementsByTagName("version")[0].firstChild.data; 11 | 12 | // thisVersion = thisVersion.split('.'); 13 | 14 | var update = !!(thisVersion < remoteVersionString); 15 | var stream = new air.URLStream(); 16 | 17 | // completely wrong! If I'm on 1.0 and the update is 0.9 - then this deems true. 18 | // jQuery.each(remoteVersion, 19 | // function(i, item) { 20 | // alert(item + ' > ' + thisVersion[i]); 21 | // if (item > thisVersion[i]) 22 | // update = true; 23 | // }); 24 | 25 | if (update) { 26 | var doUpdate = confirm("We have found an update for the jQuery API Browser. Would you like to download now?"); 27 | if (doUpdate) { 28 | jQueryAPI.Chrome.Popup({ 29 | 'message': 'Downloading update...', 30 | 'showLink': false, 31 | 'popupLife': 6000 32 | }); 33 | stream.addEventListener(air.ProgressEvent.PROGRESS, updatingStatus); 34 | stream.addEventListener(air.Event.COMPLETE, updateApplication); 35 | stream.load(new air.URLRequest(remoteAir)); 36 | } else { 37 | jQueryAPI.Update.Ignore = true; // don't keep showing the screen for this session 38 | } 39 | } else { 40 | if (jQueryAPI.Update.ShowFail) { 41 | alert('No updates have been found at this time.'); 42 | jQueryAPI.Update.ShowFail = false; 43 | } 44 | } 45 | 46 | // Handlers 47 | function updatingStatus(event) { 48 | var percentage = Math.round((event.bytesLoaded / event.bytesTotal) * 100); 49 | } 50 | 51 | function updateApplication(event) { 52 | var filename = "update/jquery-api-browser-" + remoteVersionString + ".air"; 53 | var ba = new air.ByteArray(); 54 | stream.readBytes(ba, 0, stream.bytesAvailable); 55 | updateFile = air.File.applicationStorageDirectory.resolvePath(filename); 56 | fileStream = new air.FileStream(); 57 | fileStream.addEventListener(air.Event.CLOSE, installUpdate); 58 | fileStream.openAsync(updateFile, air.FileMode.WRITE); 59 | fileStream.writeBytes(ba, 0, ba.length); 60 | fileStream.close(); 61 | 62 | function installUpdate(event) { 63 | var updater = new air.Updater(); 64 | // Notice that the version name has to be present as a second parameter 65 | updater.update(updateFile, remoteVersionString); 66 | } 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /no-scroll-application.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | com.jquery.api 18 | 19 | 20 | jQueryAPI 21 | 22 | 23 | jQueryAPI 24 | 25 | 26 | 2.0 27 | 28 | 29 | The jQuery API Browser 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | application.html 38 | 39 | 40 | 41 | 42 | <!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. --> 43 | 44 | <!-- Whether the window is initially visible. Optional. Default false. --> 45 | <visible>true</visible> 46 | 47 | <!-- The window's initial width. Optional. --> 48 | <width>720</width> 49 | 50 | <!-- The window's initial height. Optional. --> 51 | <height>960</height> 52 | 53 | </initialWindow> 54 | 55 | <!-- The subpath of the standard default installation location to use. Optional. --> 56 | <!-- <installFolder></installFolder> --> 57 | 58 | <!-- The subpath of the Windows Start/Programs menu to use. Optional. --> 59 | <!-- <programMenuFolder></programMenuFolder> --> 60 | 61 | <!-- The icon the system uses for the application. For at least one resolution, 62 | specify the path to a PNG file included in the AIR package. Optional. --> 63 | <icon> 64 | <image16x16>icons/AIRApp_16.png</image16x16> 65 | <image32x32>icons/AIRApp_32.png</image32x32> 66 | <image48x48>icons/AIRApp_48.png</image48x48> 67 | <image128x128>icons/AIRApp_128.png</image128x128> 68 | </icon> 69 | 70 | <!-- Whether the application handles the update when a user double-clicks an update version 71 | of the AIR file (true), or the default AIR application installer handles the update (false). 72 | Optional. Default false. --> 73 | <!-- <customUpdateUI></customUpdateUI> --> 74 | 75 | <!-- Whether the application can be launched when the user clicks a link in a web browser. 76 | Optional. Default false. --> 77 | <!-- <allowBrowserInvocation></allowBrowserInvocation> --> 78 | 79 | <!-- Listing of file types for which the application can register. Optional. --> 80 | <fileTypes> 81 | <!-- Defines one file type. Optional. --> 82 | <!-- <fileType> --> 83 | <!-- The name that the system displays for the registered file type. Required. --> 84 | <!-- <name></name> --> 85 | <!-- The extension to register. Required. --> 86 | <!-- <extension></extension> --> 87 | <!-- The description of the file type. Optional. --> 88 | <!-- <description></description> --> 89 | <!-- The MIME type. Optional. --> 90 | <!-- <contentType></contentType> --> 91 | <!-- The icon to display for the file type. Optional. --> 92 | <!-- <icon> 93 | <image16x16></image16x16> 94 | <image32x32></image32x32> 95 | <image48x48></image48x48> 96 | <image128x128></image128x128> 97 | </icon> --> 98 | <!-- </fileType> --> 99 | </fileTypes> 100 | 101 | </application> 102 | -------------------------------------------------------------------------------- /src/Chrome/APIBrowser.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Chrome.APIBrowser = function() { 2 | this.Initialise = function() { 3 | try { 4 | var windowOptions = new air.NativeWindowInitOptions(); 5 | windowOptions.systemChrome = air.NativeWindowSystemChrome.STANDARD; 6 | windowOptions.type = air.NativeWindowType.NORMAL; 7 | 8 | var windowBounds = new air.Rectangle(0, 0, 960, 850); 9 | // setting true for scrollbars fixes the window trying to scroll on mouse scroll. 10 | var newHTMLLoader = air.HTMLLoader.createRootWindow(false, windowOptions, true, windowBounds); 11 | newHTMLLoader.paintsDefaultBackground = true; 12 | newHTMLLoader.stage.nativeWindow.alwaysInFront = false; 13 | newHTMLLoader.navigateInSystemBrowser = true; 14 | newHTMLLoader.addEventListener(air.Event.COMPLETE, this.CreateWindow); 15 | newHTMLLoader.load(new air.URLRequest('app:/index.html')); 16 | } catch (error) { 17 | // air.Introspector.Console.log(error); 18 | } 19 | 20 | }; 21 | this.CreateWindow = function(event) { 22 | function closeWindow() { 23 | event.target.window.nativeWindow.visible = false; 24 | return false; 25 | } 26 | 27 | function minimiseWindow() { 28 | event.target.window.nativeWindow.minimize(); 29 | return false; 30 | } 31 | 32 | function moveWindow() { 33 | event.target.window.nativeWindow.startMove(); 34 | } 35 | 36 | function setupDom() { 37 | 38 | } 39 | 40 | if (event.type === 'complete' && event.target.window.nativeWindow) { 41 | // Now we set up the window position 42 | var centerX = air.Screen.mainScreen.bounds.width / 2; 43 | var centerY = air.Screen.mainScreen.bounds.height / 2; 44 | event.target.window.nativeWindow.x = centerX - (event.target.window.nativeWindow.width / 2); 45 | event.target.window.nativeWindow.y = centerY - (event.target.window.nativeWindow.height / 2); 46 | // event.target.window.nativeWindow.addEventListener(air.Event.ACTIVATE, setupDom); 47 | event.target.window.nativeWindow.visible = true; 48 | event.target.window.focus(); // god knows why I can't use the order to front - but it doesn't focus. 49 | 50 | // patch connect the AIR globals to the API browser 51 | event.target.window.jQueryAPI = jQueryAPI; 52 | event.target.window.JSON = JSON; 53 | 54 | jQuery(event.target.window.document).ready(function () { 55 | // is this duplicating setupDom? It wouldn't trigger... 56 | // bind offline / online callbacks to add class 57 | var dom = this; 58 | var lastOnlineStatus = null; 59 | 60 | event.target.window.apiBrowserMain.call(); 61 | 62 | jQueryAPI.Network.ServiceMonitor.addEventListener(air.StatusEvent.STATUS, function (statusEvent) { 63 | if (statusEvent.currentTarget.available) { 64 | if (lastOnlineStatus != true) { 65 | lastOnlineStatus = true; 66 | jQuery('body', event.target.window.document).removeClass('offline'); 67 | } 68 | } else { 69 | if (lastOnlineStatus != false) { 70 | lastOnlineStatus = false; 71 | jQuery('body', event.target.window.document).addClass('offline'); 72 | } 73 | } 74 | 75 | event.target.window.online = lastOnlineStatus; 76 | }); 77 | }); 78 | } 79 | }; 80 | 81 | var alreadyOpen = false; 82 | jQuery(air.NativeApplication.nativeApplication.openedWindows).each(function(i, win) { 83 | if (/jQuery API Browser/.test(win.title)) { 84 | alreadyOpen = true; 85 | win.orderToFront(); 86 | } 87 | }); 88 | if (!alreadyOpen) { 89 | this.Initialise(); 90 | } 91 | }; -------------------------------------------------------------------------------- /src/Chrome/Splash.js: -------------------------------------------------------------------------------- 1 | jQueryAPI.Chrome.Splash = function(callback) { 2 | 3 | this.Initialise = function() { 4 | var windowOptions = new air.NativeWindowInitOptions(); 5 | windowOptions.systemChrome = air.NativeWindowSystemChrome.NONE; 6 | windowOptions.type = air.NativeWindowType.LIGHTWEIGHT; 7 | windowOptions.transparent = true; 8 | 9 | var windowBounds = new air.Rectangle(0, 0, 305, 305); 10 | 11 | var newHTMLLoader = air.HTMLLoader.createRootWindow(false, windowOptions, false, windowBounds); 12 | newHTMLLoader.paintsDefaultBackground = false; 13 | newHTMLLoader.stage.nativeWindow.alwaysInFront = true; 14 | newHTMLLoader.navigateInSystemBrowser = true; 15 | newHTMLLoader.addEventListener(air.Event.COMPLETE, this.CreateWindow); 16 | newHTMLLoader.load(new air.URLRequest('app:/assets/html/Splash.html')); 17 | } 18 | 19 | this.CreateWindow = function(event) { 20 | var windowDom = jQuery('#splash-outer', event.target.window.document).get(0); 21 | 22 | function closeWindow() { 23 | event.target.window.close(); 24 | return false; 25 | } 26 | 27 | function convertDocsToJSON() { 28 | $(document).bind('api-load-complete', function () { 29 | 30 | $.ajax({ 31 | url: 'app:lib/docs/plugins.xml', // generated from jquery source: /tools/wikiapi2xml/createjQueryXMLDocs.py 32 | dataType: 'xml', 33 | async : false, // block until complete 34 | success: parse // stored in /lib/jqueryapi/api-loader.js 35 | }); 36 | 37 | var myFile = air.File.applicationStorageDirectory.resolvePath('api-docs.js'); 38 | var myFileStream = new air.FileStream(); 39 | myFileStream.open(myFile, air.FileMode.WRITE); 40 | myFileStream.writeUTFBytes($.toJSON(jquerydocs)); 41 | 42 | // air.Introspector.Console.log('Converted docs XML to json and stored'); 43 | 44 | // finally attach search function: 45 | attachFind(jquerydocs); // stored in /lib/jquerydocs/api-loader.js 46 | }); 47 | 48 | // read in docs (false == not async and therefore block) 49 | loadDocs('app:lib/docs/api-docs.xml', false); // from api-loader.js and triggers api-load-complete 50 | } 51 | 52 | function runMain() { 53 | jQuery('#loading-message', windowDom).append('<li>Initialising Network Support...</li>'); 54 | jQueryAPI.Network.Initialise(function() { 55 | jQuery('#loading-message', windowDom).append('<li>Network Support Started...</a>'); 56 | jQuery('#loading-message', windowDom).append('<li>Doing Update Checks...</a>'); 57 | event.target.window.close(); 58 | 59 | var apidocsJSONDB = air.File.applicationStorageDirectory.resolvePath('api-docs.js'); 60 | 61 | if (false) { 62 | // download to /lib/docs/*.xml path 63 | // then... 64 | convertDocsToJSON(); 65 | } else if (false) { //}!apidocsJSONDB.exists) { // json versions don't exist yet 66 | convertDocsToJSON(); 67 | } else if (false) { 68 | // air.Introspector.Console.log('Loading stored json db'); 69 | // load JSON version and attach find 70 | 71 | var fileStream = new air.FileStream(); 72 | fileStream.open( apidocsJSONDB, air.FileMode.READ ); 73 | var data = fileStream.readMultiByte( apidocsJSONDB.size, air.File.systemCharset ); 74 | fileStream.close(); 75 | 76 | // FIXME need to eval the json object out to a place the api-browser.js can access... 77 | window.jquerydocs = eval(data); 78 | attachFind(jquerydocs); // stored in /lib/jquerydocs/api-loader.js 79 | } 80 | 81 | // alert('api browser load'); 82 | jQueryAPI.Chrome.APIBrowser(); 83 | }); 84 | 85 | } 86 | 87 | if (event.type === 'complete' && event.target.window.nativeWindow) { 88 | // Now we set up the window position 89 | var centerX = air.Screen.mainScreen.bounds.width / 2; 90 | var centerY = air.Screen.mainScreen.bounds.height / 2; 91 | event.target.window.nativeWindow.x = centerX - (event.target.window.nativeWindow.width / 2); 92 | event.target.window.nativeWindow.y = centerY - (event.target.window.nativeWindow.height / 2); 93 | event.target.window.nativeWindow.addEventListener(air.Event.ACTIVATE, runMain); 94 | event.target.window.nativeWindow.activate(); 95 | event.target.window.nativeWindow.visible = true; 96 | } 97 | 98 | } 99 | 100 | this.Initialise(); 101 | }; 102 | -------------------------------------------------------------------------------- /application.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8" standalone="no"?> 2 | <application xmlns="http://ns.adobe.com/air/application/1.0"> 3 | 4 | <!-- Adobe AIR Applicati 5 | on Descriptor File Template. 6 | 7 | Specifies parameters for identifying, installing, and launching AIR applications. 8 | 9 | xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/1.5 10 | The last segment of the namespace specifies the version 11 | of the AIR runtime required for this application to run. 12 | 13 | minimumPatchLevel - The minimum patch level of the AIR runtime required to run 14 | the application. Optional. 15 | --> 16 | 17 | <!-- The application identifier string, unique to this application. Required. --> 18 | <id>com.jquery.api</id> 19 | 20 | <!-- Used as the filename for the application. Required. --> 21 | <filename>jquery-api-browser</filename> 22 | 23 | <!-- The name that is displayed in the AIR application installer. Optional. --> 24 | <name>jQuery API Browser</name> 25 | 26 | <!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. --> 27 | <version>2.0</version> 28 | 29 | <!-- Description, displayed in the AIR application installer. Optional. --> 30 | <description>The jQuery API Browser</description> 31 | 32 | <!-- Copyright information. Optional --> 33 | <copyright/> 34 | 35 | <!-- Settings for the application's initial window. Required. --> 36 | <initialWindow> 37 | <!-- The main HTML file of the application. Required. --> 38 | <content>application.html</content> 39 | 40 | <!-- The title of the main window. Optional. --> 41 | <title/> 42 | 43 | <!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. --> 44 | <systemChrome>none</systemChrome> 45 | 46 | <!-- Whether the window is transparent. Only applicable when systemChrome is false. Optional. Default false. --> 47 | <transparent>true</transparent> 48 | 49 | <!-- Whether the window is initially visible. Optional. Default false. --> 50 | <visible>false</visible> 51 | 52 | <!-- Whether the user can minimize the window. Optional. Default true. --> 53 | <minimizable>false</minimizable> 54 | 55 | <!-- Whether the user can maximize the window. Optional. Default true. --> 56 | <maximizable>false</maximizable> 57 | 58 | <!-- Whether the user can resize the window. Optional. Default true. --> 59 | <resizable>false</resizable> 60 | 61 | <!-- The window's initial width. Optional. --> 62 | <width>0</width> 63 | 64 | <!-- The window's initial height. Optional. --> 65 | <height>0</height> 66 | 67 | <!-- The window's initial x position. Optional. --> 68 | <x>0</x> 69 | 70 | <!-- The window's initial y position. Optional. --> 71 | <y>0</y> 72 | 73 | <!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. --> 74 | <minSize>0 0</minSize> 75 | 76 | <!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. --> 77 | <maxSize>0 0</maxSize> 78 | </initialWindow> 79 | 80 | <!-- The subpath of the standard default installation location to use. Optional. --> 81 | <!-- <installFolder></installFolder> --> 82 | 83 | <!-- The subpath of the Windows Start/Programs menu to use. Optional. --> 84 | <!-- <programMenuFolder></programMenuFolder> --> 85 | 86 | <!-- The icon the system uses for the application. For at least one resolution, 87 | specify the path to a PNG file included in the AIR package. Optional. --> 88 | <icon> 89 | <image16x16>icons/AIRApp_16.png</image16x16> 90 | <image32x32>icons/AIRApp_32.png</image32x32> 91 | <image48x48>icons/AIRApp_48.png</image48x48> 92 | <image128x128>icons/AIRApp_128.png</image128x128> 93 | </icon> 94 | 95 | <!-- Whether the application handles the update when a user double-clicks an update version 96 | of the AIR file (true), or the default AIR application installer handles the update (false). 97 | Optional. Default false. --> 98 | <!-- <customUpdateUI></customUpdateUI> --> 99 | 100 | <!-- Whether the application can be launched when the user clicks a link in a web browser. 101 | Optional. Default false. --> 102 | <!-- <allowBrowserInvocation></allowBrowserInvocation> --> 103 | 104 | <!-- Listing of file types for which the application can register. Optional. --> 105 | <fileTypes> 106 | <!-- Defines one file type. Optional. --> 107 | <!-- <fileType> --> 108 | <!-- The name that the system displays for the registered file type. Required. --> 109 | <!-- <name></name> --> 110 | <!-- The extension to register. Required. --> 111 | <!-- <extension></extension> --> 112 | <!-- The description of the file type. Optional. --> 113 | <!-- <description></description> --> 114 | <!-- The MIME type. Optional. --> 115 | <!-- <contentType></contentType> --> 116 | <!-- The icon to display for the file type. Optional. --> 117 | <!-- <icon> 118 | <image16x16></image16x16> 119 | <image32x32></image32x32> 120 | <image48x48></image48x48> 121 | <image128x128></image128x128> 122 | </icon> --> 123 | <!-- </fileType> --> 124 | </fileTypes> 125 | 126 | </application> 127 | -------------------------------------------------------------------------------- /lib/jqueryapi/jquery.history.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery history plugin 3 | * 4 | * Copyright (c) 2006 Taku Sano (Mikage Sawatari) 5 | * Licensed under the MIT License: 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 8 | * Modified by Lincoln Cooper to add Safari support and only call the callback once during initialization 9 | * for msie when no initial hash supplied. 10 | */ 11 | 12 | (function ($) { 13 | 14 | var userAgent = navigator.userAgent.toLowerCase(); 15 | 16 | // Figure out what browser is being used 17 | var browser = { 18 | version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1], 19 | safari: /webkit/.test( userAgent ), 20 | opera: /opera/.test( userAgent ), 21 | msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), 22 | mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) 23 | }; 24 | 25 | /* 26 | * jQuery history plugin 27 | * 28 | * Copyright (c) 2006 Taku Sano (Mikage Sawatari) 29 | * Licensed under the MIT License: 30 | * http://www.opensource.org/licenses/mit-license.php 31 | * 32 | * Modified by Lincoln Cooper to add Safari support and only call the callback once during initialization 33 | * for msie when no initial hash supplied. 34 | * API rewrite by Lauris Buk�is-Haberkorns 35 | */ 36 | 37 | window.History = function () { 38 | this._curHash = ''; 39 | this._callback = function(hash){}; 40 | }; 41 | 42 | $.extend(History.prototype, { 43 | 44 | init: function(callback) { 45 | this._callback = callback; 46 | this._curHash = location.hash; 47 | 48 | if(browser.msie) { 49 | // To stop the callback firing twice during initilization if no hash present 50 | if (this._curHash == '') { 51 | this._curHash = '#'; 52 | } 53 | 54 | // add hidden iframe for IE 55 | $("body").prepend('<iframe id="jQuery_history" style="display: none;"></iframe>'); 56 | var iframe = $("#jQuery_history")[0].contentWindow.document; 57 | iframe.open(); 58 | iframe.close(); 59 | iframe.location.hash = this._curHash; 60 | } 61 | else if (browser.safari) { 62 | // etablish back/forward stacks 63 | this._historyBackStack = []; 64 | this._historyBackStack.length = history.length; 65 | this._historyForwardStack = []; 66 | this._isFirst = true; 67 | this._dontCheck = false; 68 | } 69 | this._callback(this._curHash.replace(/^#/, '')); 70 | setInterval(this._check, 100); 71 | }, 72 | 73 | add: function(hash) { 74 | // This makes the looping function do something 75 | this._historyBackStack.push(hash); 76 | 77 | this._historyForwardStack.length = 0; // clear forwardStack (true click occured) 78 | this._isFirst = true; 79 | }, 80 | 81 | _check: function() { 82 | if(browser.msie) { 83 | // On IE, check for location.hash of iframe 84 | var ihistory = $("#jQuery_history")[0]; 85 | var iframe = ihistory.contentDocument || ihistory.contentWindow.document; 86 | var current_hash = iframe.location.hash; 87 | if(current_hash != $.history._curHash) { 88 | 89 | location.hash = current_hash; 90 | $.history._curHash = current_hash; 91 | $.history._callback(current_hash.replace(/^#/, '')); 92 | 93 | } 94 | } else if (browser.safari) { 95 | if (!$.history._dontCheck) { 96 | var historyDelta = history.length - $.history._historyBackStack.length; 97 | 98 | if (historyDelta) { // back or forward button has been pushed 99 | $.history._isFirst = false; 100 | if (historyDelta < 0) { // back button has been pushed 101 | // move items to forward stack 102 | for (var i = 0; i < Math.abs(historyDelta); i++) $.history._historyForwardStack.unshift($.history._historyBackStack.pop()); 103 | } else { // forward button has been pushed 104 | // move items to back stack 105 | for (var i = 0; i < historyDelta; i++) $.history._historyBackStack.push($.history._historyForwardStack.shift()); 106 | } 107 | var cachedHash = $.history._historyBackStack[$.history._historyBackStack.length - 1]; 108 | if (cachedHash != undefined) { 109 | $.history._curHash = location.hash; 110 | $.history._callback(cachedHash); 111 | } 112 | } else if ($.history._historyBackStack[$.history._historyBackStack.length - 1] == undefined && !$.history._isFirst) { 113 | // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark) 114 | // document.URL doesn't change in Safari 115 | if (document.URL.indexOf('#') >= 0) { 116 | $.history._callback(document.URL.split('#')[1]); 117 | } else { 118 | $.history._callback(''); 119 | } 120 | $.history._isFirst = true; 121 | } 122 | } 123 | } else { 124 | // otherwise, check for location.hash 125 | var current_hash = location.hash; 126 | if(current_hash != $.history._curHash) { 127 | $.history._curHash = current_hash; 128 | $.history._callback(current_hash.replace(/^#/, '')); 129 | } 130 | } 131 | }, 132 | 133 | load: function(hash) { 134 | var newhash; 135 | 136 | if (browser.safari) { 137 | newhash = hash; 138 | } else { 139 | newhash = '#' + hash; 140 | location.hash = newhash; 141 | } 142 | this._curHash = newhash; 143 | 144 | if (browser.msie) { 145 | var ihistory = $("#jQuery_history")[0]; // TODO: need contentDocument? 146 | var iframe = ihistory.contentWindow.document; 147 | iframe.open(); 148 | iframe.close(); 149 | iframe.location.hash = newhash; 150 | this._callback(hash); 151 | } 152 | else if (browser.safari) { 153 | this._dontCheck = true; 154 | // Manually keep track of the history values for Safari 155 | this.add(hash); 156 | 157 | // Wait a while before allowing checking so that Safari has time to update the "history" object 158 | // correctly (otherwise the check loop would detect a false change in hash). 159 | var fn = function() {$.history._dontCheck = false;}; 160 | window.setTimeout(fn, 200); 161 | this._callback(hash); 162 | // N.B. "location.hash=" must be the last line of code for Safari as execution stops afterwards. 163 | // By explicitly using the "location.hash" command (instead of using a variable set to "location.hash") the 164 | // URL in the browser and the "history" object are both updated correctly. 165 | location.hash = newhash; 166 | } 167 | else { 168 | this._callback(hash); 169 | } 170 | } 171 | }); 172 | })(jQuery); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 2 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 3 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 4 | <head> 5 | <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 6 | <title>jQuery API Browser 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 18 | 29 |
    30 |
    31 |
    32 |

    Loading jQuery API database

    33 |
    34 |
    35 |
    36 |
    37 |

    Welcome to the jQuery API browser

    38 | 39 |

    To get started, click on a category on the left.

    40 | 41 |

    The API browser will work in Safari, Firefox 3 and IE7.

    42 | 43 |

    You can also use categorise your filtering by using:

    44 |
      45 |
    • added=1.3 for all the latest functions
    • 46 |
    • category=core for all the methods within on category
    • 47 |
    • Or just use it to search for method names
    • 48 |
    49 | 50 |

    Please send an feedback via the blog post or: remy at remysharp or Twitter if it's brief @rem

    51 |

    The API browser is available as this web app, or as a downloadable AIR.

    52 | 53 | 96 | 97 | 101 |
    102 |
    103 |
    104 |

    Built by Remy Sharp

    105 | 108 | 109 | 110 | 111 | 112 | 113 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /assets/css/APIBrowser.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | overflow: hidden; 5 | margin: 0; 6 | padding: 0 10px; 7 | font: 1em "Trebuchet MS",Verdana,Helvetica,Arial,sans-serif; 8 | font-size: 100%; 9 | position: relative; 10 | color: #fff; 11 | cursor: default; 12 | } 13 | 14 | a { 15 | cursor: pointer; 16 | } 17 | 18 | pre,code { 19 | cursor: auto; 20 | } 21 | 22 | body { 23 | background: #2A3139 url(../images/bg_home_tile_sml.jpg) repeat-x scroll 0 -40px; 24 | } 25 | 26 | code,pre { 27 | font-family: Monaco,"Courier New"; 28 | font-size: 90%; 29 | } 30 | 31 | #body { 32 | position: relative; 33 | height: 100%; /* FIXME causing window to scroll */ 34 | color: #000; 35 | } 36 | 37 | #browser { 38 | position: absolute; 39 | width: 300px; 40 | top: 0; 41 | right: 60em; 42 | left: 0; 43 | overflow-y: auto; 44 | background-color: #2A3139; 45 | } 46 | 47 | #detail { 48 | position: absolute; 49 | top: 0; 50 | right: 0px; 51 | left: 320px; 52 | overflow-y: auto; 53 | background-color: #fff; 54 | font-size: 90%; 55 | } 56 | 57 | #header { 58 | height: 140px; 59 | position: relative; 60 | } 61 | 62 | #detail, #browser { 63 | bottom: 160px; 64 | } 65 | 66 | #header img { 67 | top: 19px; 68 | position: absolute; 69 | } 70 | 71 | #search { 72 | position: absolute; 73 | width: 300px; 74 | display: block; 75 | margin: 0 auto; 76 | top: 60px; 77 | left: 0; 78 | right: 0; 79 | } 80 | 81 | .inner { 82 | padding: 20px; 83 | } 84 | 85 | #browser .inner { 86 | padding: 0; 87 | } 88 | 89 | dl, dt, dd { 90 | padding: 0; 91 | margin: 0; 92 | } 93 | 94 | dt { 95 | background-color: #2A3139; 96 | color: #eee; 97 | padding: 5px; 98 | cursor: pointer; 99 | } 100 | 101 | dt:hover { 102 | background-color: #67788B; 103 | } 104 | 105 | dt.active { 106 | background: #0066A0 url(../images/close-ui.png) no-repeat 97%; 107 | } 108 | 109 | #categories dt.active { 110 | font-weight: bold; 111 | } 112 | 113 | #subcategories dt.active { 114 | border-bottom: 2px solid #ccc; 115 | } 116 | 117 | dt.active:hover { 118 | background-color: #0066A0; 119 | } 120 | 121 | #functions dt.active { 122 | background: #0066A0 url(../images/open-ui.png) no-repeat 97%; 123 | } 124 | 125 | /*#subcategories dt.active:hover:after, 126 | #categories dt.active:hover:after { 127 | content: ' (remove filter)'; 128 | } 129 | */ 130 | p.cheat { 131 | margin: 0; 132 | padding: 0; 133 | padding-bottom: 1px; 134 | } 135 | 136 | h1 { 137 | margin: 0; 138 | } 139 | 140 | pre { 141 | padding: 10px; 142 | background-color: #eee; 143 | border: 1px solid #ccc; 144 | overflow: auto; 145 | } 146 | 147 | .liveExample a { 148 | display: none; 149 | position: absolute; 150 | top: 0; 151 | right: 0; 152 | padding: 5px; 153 | background: #ccc; 154 | } 155 | 156 | .liveExample:hover a { 157 | display: block; 158 | } 159 | 160 | .liveExample { 161 | border: 2px dashed #ccc; 162 | padding: 10px; 163 | } 164 | 165 | .liveExample:hover { 166 | border: 2px solid #ccc; 167 | } 168 | 169 | #detail iframe { 170 | border: 0; 171 | width: 100%; 172 | } 173 | 174 | /** Pretty printing styles. Used with prettify.js. */ 175 | 176 | .str { color: #080; } 177 | .kwd { color: #008; } 178 | .com { color: #800; } 179 | .typ { color: #606; } 180 | .lit { color: #066; } 181 | .pun { color: #660; } 182 | .pln { color: #000; } 183 | .tag { color: #008; } 184 | .atn { color: #606; } 185 | .atv { color: #080; } 186 | .dec { color: #606; } 187 | 188 | h1 .type { 189 | text-transform: lowercase; 190 | color: #ccc; 191 | font-size: 70%; 192 | } 193 | 194 | .meta { 195 | color: #aaa; 196 | font-size: 80%; 197 | } 198 | 199 | 200 | ul.options { 201 | padding: 0; 202 | } 203 | 204 | ul.options > li { 205 | padding: 10px 0; 206 | padding-left: 20px; 207 | list-style-position: inside; 208 | } 209 | 210 | ul.options:hover > li { 211 | opacity: 0.3; 212 | } 213 | 214 | ul.options:hover > li:hover { 215 | opacity: 1; 216 | } 217 | 218 | .loading { 219 | color: #fff; 220 | padding: 0 10px; 221 | } 222 | 223 | .external { 224 | text-decoration: none; 225 | color: #fff; 226 | cursor: pointer; 227 | } 228 | 229 | #navigation { 230 | background: #0F67A1 url(../images/bg_secondaryNav_left.gif) no-repeat scroll left top; 231 | clear: right; 232 | float: right; 233 | margin-top: 34px; 234 | } 235 | 236 | #navigation ul { 237 | background: transparent url(../images/bg_secondaryNav_right.gif) no-repeat scroll right top; 238 | padding: 0 0 0 8px; 239 | margin: 0; 240 | float: left; 241 | } 242 | 243 | #navigation li { 244 | border-right:1px solid #0D5995; 245 | border-left:1px solid #1175AE; 246 | float:left; 247 | height:34px; 248 | list-style: none; 249 | margin:0; 250 | padding:0; 251 | } 252 | 253 | #navigation li.first { 254 | border-left: 0; 255 | } 256 | 257 | #navigation li.last { 258 | border-right: 0; 259 | } 260 | 261 | #navigation li a, 262 | #navigation li label { 263 | color:#EEEEEE; 264 | float:left; 265 | padding:0 20px; 266 | position: relative; 267 | text-decoration:none; 268 | line-height: 34px; 269 | cursor: pointer; 270 | } 271 | 272 | #navigation li input { 273 | font-size: 16px; 274 | margin: 0 0 0 10px; 275 | width: 100px; 276 | border: 0; 277 | padding: 2px; 278 | -moz-border-radius: 2px; 279 | -webkit-border-radius: 2px; 280 | } 281 | 282 | #navigation .selected, 283 | #navigation a:hover { 284 | /* text-shadow: 2px 2px 2px #000;*/ 285 | } 286 | 287 | span.fav { 288 | display: inline-table; 289 | height: 16px; 290 | width: 16px; 291 | padding: 5px; 292 | background: url(../images/fav-off.png) no-repeat bottom; 293 | cursor: pointer; 294 | } 295 | 296 | span.fav:hover, 297 | span.fav.on { 298 | background: url(../images/fav-on.png) no-repeat bottom; 299 | } 300 | 301 | pre::selection, 302 | pre span::selection { 303 | background-color: inherit!important; 304 | } 305 | 306 | p::selection, 307 | dt::selection, 308 | h1::selection, 309 | h2::selection, 310 | h3::selection, 311 | li::selection, 312 | a::selection, 313 | span::selection, 314 | div::selection, 315 | strong::selection, 316 | em::selection, 317 | ul::selection, 318 | label::selection, 319 | img::selection { 320 | background-color: transparent; 321 | } 322 | 323 | /*#navigation li label < input:focus { 324 | text-shadow: 1px 1px 1px #333; 325 | } 326 | */ 327 | 328 | body.offline a.edit { 329 | display: none; 330 | } 331 | 332 | #credit { 333 | position: absolute; 334 | bottom: 4px; 335 | font-size: 60%; 336 | color: #666; 337 | margin: 0; 338 | right: 10px; 339 | } 340 | 341 | #credit a { 342 | color: #666; 343 | padding: 2px; 344 | } 345 | 346 | #credit a:hover { 347 | color: #ccc; 348 | } 349 | 350 | #navigation a, #navigation label { 351 | position: relative; 352 | outline: 0; 353 | } 354 | 355 | #navigation span { 356 | position: relative; 357 | top: 0; 358 | left: 0; 359 | } 360 | 361 | #navigation span.jq-shadow { 362 | display: none; 363 | } 364 | 365 | #navigation .selected span { 366 | color: #fff; 367 | } 368 | 369 | #navigation .selected span.jq-shadow { 370 | color:#131C25; 371 | display: block; 372 | position:absolute; 373 | top:0.1em; 374 | left: 1.3em; 375 | } 376 | -------------------------------------------------------------------------------- /lib/air/AC_RunActiveContent.js: -------------------------------------------------------------------------------- 1 | //v1.7 2 | // Flash Player Version Detection 3 | // Detect Client Browser type 4 | // Copyright 2005-2007 Adobe Systems Incorporated. All rights reserved. 5 | var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false; 6 | var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false; 7 | var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false; 8 | 9 | function ControlVersion() 10 | { 11 | var version; 12 | var axo; 13 | var e; 14 | 15 | // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry 16 | 17 | try { 18 | // version will be set for 7.X or greater players 19 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); 20 | version = axo.GetVariable("$version"); 21 | } catch (e) { 22 | } 23 | 24 | if (!version) 25 | { 26 | try { 27 | // version will be set for 6.X players only 28 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); 29 | 30 | // installed player is some revision of 6.0 31 | // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29, 32 | // so we have to be careful. 33 | 34 | // default to the first public version 35 | version = "WIN 6,0,21,0"; 36 | 37 | // throws if AllowScripAccess does not exist (introduced in 6.0r47) 38 | axo.AllowScriptAccess = "always"; 39 | 40 | // safe to call for 6.0r47 or greater 41 | version = axo.GetVariable("$version"); 42 | 43 | } catch (e) { 44 | } 45 | } 46 | 47 | if (!version) 48 | { 49 | try { 50 | // version will be set for 4.X or 5.X player 51 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); 52 | version = axo.GetVariable("$version"); 53 | } catch (e) { 54 | } 55 | } 56 | 57 | if (!version) 58 | { 59 | try { 60 | // version will be set for 3.X player 61 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); 62 | version = "WIN 3,0,18,0"; 63 | } catch (e) { 64 | } 65 | } 66 | 67 | if (!version) 68 | { 69 | try { 70 | // version will be set for 2.X player 71 | axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); 72 | version = "WIN 2,0,0,11"; 73 | } catch (e) { 74 | version = -1; 75 | } 76 | } 77 | 78 | return version; 79 | } 80 | 81 | // JavaScript helper required to detect Flash Player PlugIn version information 82 | function GetSwfVer(){ 83 | // NS/Opera version >= 3 check for Flash plugin in plugin array 84 | var flashVer = -1; 85 | 86 | if (navigator.plugins != null && navigator.plugins.length > 0) { 87 | if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) { 88 | var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; 89 | var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; 90 | var descArray = flashDescription.split(" "); 91 | var tempArrayMajor = descArray[2].split("."); 92 | var versionMajor = tempArrayMajor[0]; 93 | var versionMinor = tempArrayMajor[1]; 94 | var versionRevision = descArray[3]; 95 | if (versionRevision == "") { 96 | versionRevision = descArray[4]; 97 | } 98 | if (versionRevision[0] == "d") { 99 | versionRevision = versionRevision.substring(1); 100 | } else if (versionRevision[0] == "r") { 101 | versionRevision = versionRevision.substring(1); 102 | if (versionRevision.indexOf("d") > 0) { 103 | versionRevision = versionRevision.substring(0, versionRevision.indexOf("d")); 104 | } 105 | } 106 | var flashVer = versionMajor + "." + versionMinor + "." + versionRevision; 107 | } 108 | } 109 | // MSN/WebTV 2.6 supports Flash 4 110 | else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4; 111 | // WebTV 2.5 supports Flash 3 112 | else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3; 113 | // older WebTV supports Flash 2 114 | else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2; 115 | else if ( isIE && isWin && !isOpera ) { 116 | flashVer = ControlVersion(); 117 | } 118 | return flashVer; 119 | } 120 | 121 | // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available 122 | function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) 123 | { 124 | versionStr = GetSwfVer(); 125 | if (versionStr == -1 ) { 126 | return false; 127 | } else if (versionStr != 0) { 128 | if(isIE && isWin && !isOpera) { 129 | // Given "WIN 2,0,0,11" 130 | tempArray = versionStr.split(" "); // ["WIN", "2,0,0,11"] 131 | tempString = tempArray[1]; // "2,0,0,11" 132 | versionArray = tempString.split(","); // ['2', '0', '0', '11'] 133 | } else { 134 | versionArray = versionStr.split("."); 135 | } 136 | var versionMajor = versionArray[0]; 137 | var versionMinor = versionArray[1]; 138 | var versionRevision = versionArray[2]; 139 | 140 | // is the major.revision >= requested major.revision AND the minor version >= requested minor 141 | if (versionMajor > parseFloat(reqMajorVer)) { 142 | return true; 143 | } else if (versionMajor == parseFloat(reqMajorVer)) { 144 | if (versionMinor > parseFloat(reqMinorVer)) 145 | return true; 146 | else if (versionMinor == parseFloat(reqMinorVer)) { 147 | if (versionRevision >= parseFloat(reqRevision)) 148 | return true; 149 | } 150 | } 151 | return false; 152 | } 153 | } 154 | 155 | function AC_AddExtension(src, ext) 156 | { 157 | if (src.indexOf('?') != -1) 158 | return src.replace(/\?/, ext+'?'); 159 | else 160 | return src + ext; 161 | } 162 | 163 | function AC_Generateobj(objAttrs, params, embedAttrs) 164 | { 165 | var str = ''; 166 | if (isIE && isWin && !isOpera) 167 | { 168 | str += ' '; 177 | } 178 | str += ''; 179 | } 180 | else 181 | { 182 | str += ' Loading jQuery API database

    @', $categories, $html); 19 | 20 | if ($requested_page) { 21 | ob_start(); 22 | show_api_page($requested_page); 23 | $fn = ob_get_contents(); 24 | ob_end_clean(); 25 | 26 | $html = preg_replace('@
    .*?
    @s', '
    ' . $fn . '
    ', $html); 27 | } 28 | 29 | echo $html; 30 | 31 | function show_api_page($el) { 32 | $functionval = $el->getAttribute('name'); //preg_replace('/^jquery\./i', '$.', $el->getAttribute('name')); 33 | $params = $el->getElementsByTagName('params'); 34 | $all_params = array(); 35 | for ($i = 0; $i < $params->length; $i++) { 36 | array_push($all_params, trim($params->item($i)->getAttribute('name'))); 37 | } 38 | 39 | if (count($all_params)) { 40 | $id = strtolower(trim($functionval) . '_' . join($all_params, '_')); 41 | $params_str = count($all_params) ? '(' . join($all_params, ', ') . ')' : ''; 42 | } else { 43 | $id = strtolower(trim($functionval)); 44 | $params_str = ''; 45 | } 46 | 47 | $b = "\n "; 48 | $cat = $el->getAttribute('cat'); 49 | $catkey = stripspace($cat); 50 | $subcat = $el->parentNode->getAttribute('value'); 51 | $subcatkey = stripspace($subcat); 52 | 53 | $added = $el->getElementsByTagName('added')->item(0)->nodeValue; 54 | $desc = $el->getElementsByTagName('longdesc')->item(0)->nodeValue; 55 | 56 | if (!$desc) { 57 | $desc = $el->getElementsByTagName('desc')->item(0)->nodeValue; 58 | } 59 | 60 | $returns = htmlentities($el->getAttribute('return')); 61 | 62 | $examples = $el->getElementsByTagName('example'); 63 | 64 | echo '

    '; 65 | echo '' . $el->getAttribute('name') . $params_str . ' '; 66 | echo '' . strtolower($el->nodeName) . ' '; 67 | echo ''; 68 | echo '

    '; 69 | echo $b; 70 | 71 | echo '

    Category: ' . $cat . '/' . $subcat . ' (added ' . $added . ')

    '; 72 | echo $b; 73 | 74 | 75 | // TODO clean up markup quirks 76 | echo $desc; 77 | echo $b; 78 | 79 | // TODO detailed options 80 | 81 | echo '

    Returns

    '; 82 | echo '

    ' . $returns . '

    '; 83 | echo $b; 84 | 85 | if ($params->length) { 86 | echo '

    Parameters

    '; 87 | echo $b; 88 | echo '
      '; 89 | echo $b; 90 | 91 | for ($i = 0; $i < $params->length; $i++) { 92 | $p = $params->item($i); 93 | echo '
    • ' . $p->getAttribute('name') . ' '; 94 | echo '(' . $p->getAttribute('type') . ')'; 95 | 96 | if ($p->getAttribute('optional')) { 97 | echo ' optional'; 98 | } 99 | 100 | echo ': ' . $p->getElementsByTagName('desc')->item(0)->nodeValue . '
    • '; 101 | echo $b; 102 | } 103 | 104 | echo '
    '; 105 | echo $b; 106 | } 107 | 108 | if (count($examples)) { 109 | for ($i = 0; $i < $examples->length; $i++) { 110 | $e = $examples->item($i); 111 | echo '

    Example

    '; 112 | echo $b; 113 | 114 | echo '

    ' . $e->getElementsByTagName('desc')->item(0)->nodeValue . '

    '; 115 | 116 | $code = $e->getElementsByTagName('code'); 117 | if ($code->length) { 118 | echo '

    jQuery Code

    '; 119 | echo '
    ' . htmlentities($code->item(0)->nodeValue) . '
    '; 120 | echo $b; 121 | } 122 | } 123 | } 124 | } 125 | 126 | function getcategories($filename, $request) { 127 | $dom= new DOMDocument(); 128 | $dom->load($filename); 129 | $cats = $dom->getElementsByTagName('cat'); 130 | 131 | $html = "
      \n"; 132 | 133 | for ($i = 0; $i < $cats->length; $i++) { 134 | $cat = $cats->item($i); 135 | $catval = $cat->getAttribute('value'); 136 | $catkey = stripspace($catval); 137 | 138 | $selected = $catkey == $request[0] ? ' active' : ''; 139 | 140 | $html .= "\t" . '
    • ' . $catval . "

      \n"; 141 | $html .= "\t" . '
        ' . "\n"; 142 | 143 | $subcats = $cat->getElementsByTagName('subcat'); 144 | for ($j = 0; $j < $subcats->length; $j++) { 145 | $subcat = $subcats->item($j); 146 | $subcatval = $subcat->getAttribute('value'); 147 | $subcatkey = stripspace($subcatval); 148 | 149 | list($fn_html, $fn_selected) = getElements($catval, $subcat, $request, 'function'); 150 | list($sel_html, $sel_selected) = getElements($catval, $subcat, $request, 'selector'); 151 | list($prop_html, $prop_selected) = getElements($catval, $subcat, $request, 'property'); 152 | 153 | $selected = ($subcatkey == $request[1] || $fn_selected || $sel_selected || $prop_selected) ? ' class="active"' : ''; 154 | 155 | $html .= "\t\t" . '
      • ' . $subcatval . "\n"; 156 | 157 | $html .= "\t\t" . '
          ' . "\n"; 158 | $html .= $fn_html; 159 | $html .= $sel_html; 160 | $html .= $prop_html; 161 | 162 | $html .= "\t\t
      • \n"; 163 | } 164 | 165 | $html .= "\t
    • \n"; 166 | } 167 | 168 | return $html; 169 | } 170 | 171 | function getElements($catval, $subcat, $request, $tag) { 172 | global $requested_page; 173 | $html = ''; 174 | 175 | $catkey = stripspace($catval); 176 | $subcatkey = stripspace($subcat->getAttribute('value')); 177 | 178 | $element_found = false; 179 | 180 | $functions = getOrderedElements($subcat, $tag); 181 | for ($k = 0; $k < count($functions); $k++) { 182 | $function = $functions[$k]; 183 | 184 | $functionval = $function->getAttribute('name'); // preg_replace('/^jquery\./i', '$.', 185 | 186 | $params = $function->getElementsByTagName('params'); 187 | $all_params = array(); 188 | for ($l = 0; $l < $params->length; $l++) { 189 | array_push($all_params, trim($params->item($l)->getAttribute('name'))); 190 | } 191 | 192 | if (count($all_params)) { 193 | $id = strtolower(trim($functionval) . '_' . join($all_params, '_')); 194 | $params_str = count($all_params) ? '(' . join($all_params, ', ') . ')' : ''; 195 | } else { 196 | $id = strtolower(trim($functionval)); 197 | $params_str = ''; 198 | } 199 | 200 | $selected = ''; 201 | if ($catkey == $request[0] && $subcatkey == $request[1] && $id == $request[2]) { 202 | $requested_page = $function; 203 | $element_found = true; 204 | $selected = ' class="active"'; 205 | } 206 | 207 | $html .= "\t\t\t" . '
    • ' . $functionval . $params_str . '
    • ' . "\n"; 208 | } 209 | 210 | return array($html, $element_found); 211 | } 212 | 213 | function getOrderedElements($context, $tag) { 214 | $elements = $context->getElementsByTagName($tag); 215 | $ordered = array(); 216 | 217 | for ($i = 0; $i < $elements->length; $i++) { 218 | array_push($ordered, $elements->item($i)); 219 | } 220 | 221 | usort($ordered, 'elOrder'); 222 | return $ordered; 223 | } 224 | 225 | function elOrder($a, $b) { 226 | return strcasecmp($a->getAttribute('name'), $b->getAttribute('name')); 227 | } 228 | 229 | function stripspace($s) { 230 | return preg_replace('/\s+/', '_', $s); 231 | } 232 | 233 | // source: http://uk2.php.net/manual/en/function.xml-parse.php#87920 234 | function xml2array($url, $get_attributes = 1, $priority = 'tag') 235 | { 236 | $contents = ""; 237 | if (!function_exists('xml_parser_create')) 238 | { 239 | return array (); 240 | } 241 | $parser = xml_parser_create(''); 242 | if (!($fp = @ fopen($url, 'rb'))) 243 | { 244 | return array (); 245 | } 246 | while (!feof($fp)) 247 | { 248 | $contents .= fread($fp, 8192); 249 | } 250 | fclose($fp); 251 | xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); 252 | xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 253 | xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 254 | xml_parse_into_struct($parser, trim($contents), $xml_values); 255 | xml_parser_free($parser); 256 | if (!$xml_values) 257 | return; //Hmm... 258 | $xml_array = array (); 259 | $parents = array (); 260 | $opened_tags = array (); 261 | $arr = array (); 262 | $current = & $xml_array; 263 | $repeated_tag_index = array (); 264 | foreach ($xml_values as $data) 265 | { 266 | unset ($attributes, $value); 267 | extract($data); 268 | $result = array (); 269 | $attributes_data = array (); 270 | if (isset ($value)) 271 | { 272 | if ($priority == 'tag') 273 | $result = $value; 274 | else 275 | $result['value'] = $value; 276 | } 277 | if (isset ($attributes) and $get_attributes) 278 | { 279 | foreach ($attributes as $attr => $val) 280 | { 281 | if ($priority == 'tag') 282 | $attributes_data[$attr] = $val; 283 | else 284 | $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' 285 | } 286 | } 287 | if ($type == "open") 288 | { 289 | $parent[$level -1] = & $current; 290 | if (!is_array($current) or (!in_array($tag, array_keys($current)))) 291 | { 292 | $current[$tag] = $result; 293 | if ($attributes_data) 294 | $current[$tag . '_attr'] = $attributes_data; 295 | $repeated_tag_index[$tag . '_' . $level] = 1; 296 | $current = & $current[$tag]; 297 | } 298 | else 299 | { 300 | if (isset ($current[$tag][0])) 301 | { 302 | $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; 303 | $repeated_tag_index[$tag . '_' . $level]++; 304 | } 305 | else 306 | { 307 | $current[$tag] = array ( 308 | $current[$tag], 309 | $result 310 | ); 311 | $repeated_tag_index[$tag . '_' . $level] = 2; 312 | if (isset ($current[$tag . '_attr'])) 313 | { 314 | $current[$tag]['0_attr'] = $current[$tag . '_attr']; 315 | unset ($current[$tag . '_attr']); 316 | } 317 | } 318 | $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1; 319 | $current = & $current[$tag][$last_item_index]; 320 | } 321 | } 322 | elseif ($type == "complete") 323 | { 324 | if (!isset ($current[$tag])) 325 | { 326 | $current[$tag] = $result; 327 | $repeated_tag_index[$tag . '_' . $level] = 1; 328 | if ($priority == 'tag' and $attributes_data) 329 | $current[$tag . '_attr'] = $attributes_data; 330 | } 331 | else 332 | { 333 | if (isset ($current[$tag][0]) and is_array($current[$tag])) 334 | { 335 | $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; 336 | if ($priority == 'tag' and $get_attributes and $attributes_data) 337 | { 338 | $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; 339 | } 340 | $repeated_tag_index[$tag . '_' . $level]++; 341 | } 342 | else 343 | { 344 | $current[$tag] = array ( 345 | $current[$tag], 346 | $result 347 | ); 348 | $repeated_tag_index[$tag . '_' . $level] = 1; 349 | if ($priority == 'tag' and $get_attributes) 350 | { 351 | if (isset ($current[$tag . '_attr'])) 352 | { 353 | $current[$tag]['0_attr'] = $current[$tag . '_attr']; 354 | unset ($current[$tag . '_attr']); 355 | } 356 | if ($attributes_data) 357 | { 358 | $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; 359 | } 360 | } 361 | $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken 362 | } 363 | } 364 | } 365 | elseif ($type == 'close') 366 | { 367 | $current = & $parent[$level -1]; 368 | } 369 | } 370 | return ($xml_array); 371 | } 372 | 373 | ?> -------------------------------------------------------------------------------- /lib/jqueryapi/api-browser.js: -------------------------------------------------------------------------------- 1 | // globals 2 | if (!window.runtime) { 3 | airapp = false; 4 | } else { 5 | airapp = true; 6 | } 7 | 8 | lastRoot = 'api'; 9 | 10 | $.fn.textDropShadow = function() { 11 | return this.each(function () { 12 | var $text = $(this); 13 | $text.html(''+$text.html()+''+$text.html()+''); 14 | return $text; 15 | }); 16 | }; 17 | 18 | function apiBrowserMain() { 19 | $('#navigation a').textDropShadow(); 20 | $('#navigation label').prepend('Filter'); 21 | 22 | // handle external links 23 | window.favs = {}; 24 | 25 | if (airapp) { 26 | $('#credit a').click(function () { 27 | window.runtime.flash.net.navigateToURL(new window.runtime.flash.net.URLRequest(this.href)); 28 | return false; 29 | }); 30 | } 31 | 32 | $(window).click(function (event) { 33 | var $elm = $(event.target); 34 | if (event.target.nodeName == 'SPAN' && $elm.is('.fav')) { 35 | $elm.toggleClass('on'); 36 | 37 | // silly hack for last minute bug 38 | var key = $elm.attr('id').toLowerCase().replace(/^\$\./, ''); 39 | 40 | if ($elm.is('.on')) { 41 | // bit dopy, and hacky, but will do for now 42 | jquerydocs.data[key].fav = 'true'; 43 | favs[key] = 1; 44 | } else { 45 | jquerydocs.data[key].fav = 'false'; 46 | delete favs[key]; 47 | } 48 | 49 | if (!airapp) { 50 | // commit fav to cookie 51 | createCookie('favs', $.toJSON(favs), 365); 52 | } else { 53 | var FileSystem = window.runtime.flash.filesystem; 54 | 55 | var file = FileSystem.File.applicationStorageDirectory.resolvePath('favs.json'); 56 | var fileStream = new FileSystem.FileStream(); 57 | fileStream.open(file, FileSystem.FileMode.WRITE); 58 | fileStream.writeUTFBytes($.toJSON(favs)); 59 | fileStream.close(); 60 | } 61 | 62 | return false; 63 | } 64 | }); 65 | 66 | var timer = null; 67 | var last = ''; 68 | $('#query').keyup(function () { 69 | if (this.value != last) { 70 | if (timer) { 71 | clearTimeout(timer); 72 | } 73 | last = this.value; 74 | if (jquerydocs.find) { 75 | timer = setTimeout(queryDocs, 250); 76 | } 77 | } 78 | }).focus(function () { 79 | $(this).parent().addClass('selected'); 80 | }).blur(function () { 81 | $(this).parent().removeClass('selected'); 82 | }); 83 | 84 | function queryDocs() { 85 | if (jquerydocs == null) { 86 | return; 87 | } 88 | jquerydocs = _jquerydocs; // reset 89 | 90 | // the query trimmed 91 | var q = $('#query').val().toLowerCase().replace( /^\s+|\s+$/g,""); 92 | 93 | if (q == '') { 94 | loadCategories(); 95 | return; 96 | } 97 | 98 | var $wrapper = $('#browser > div'); 99 | $wrapper.empty(); 100 | 101 | var items = []; 102 | 103 | if (q.indexOf('=') !== -1) { 104 | q = q.split('='); 105 | items = jquerydocs.find(q[1], q[0]); // hidden feature to search by a specific field, i.e. added=1.3 106 | } else { 107 | items = jquerydocs.find(q); 108 | } 109 | 110 | showFunctions(items, $wrapper); 111 | if (items.length) { 112 | $('#functions').show(); 113 | } else { 114 | $('#browser > div').html('

      No functions found.

      '); 115 | } 116 | } 117 | 118 | if (!window.jquerydocs.initialised) { 119 | loadDocs('lib/docs/api-docs.xml'); // from api-loader.js and triggers api-load-complete 120 | } else { 121 | init(); 122 | } 123 | } 124 | 125 | $(document).bind('api-load-complete', function () { 126 | // cache the original 127 | window._jquerydocs = jquerydocs; 128 | 129 | // version notices 130 | $('#version').html(jquerydocs.version); 131 | document.title += ' v' + jquerydocs.version; // note - I have to manually insert the version since it's lacking :-( 132 | 133 | // now manually load the plugins API - I'm avoiding using loadDocs because it triggers a callback to api-load-complete 134 | // which causes our infinite loop :-( 135 | $.ajax({ 136 | url: 'lib/docs/plugins.xml', // generated from jquery source: /tools/wikiapi2xml/createjQueryXMLDocs.py 137 | dataType: 'xml', 138 | async : false, 139 | success: parse 140 | }); 141 | 142 | attachFind(jquerydocs); 143 | 144 | if (window.location.search) { 145 | $('#query').val(window.location.search.substr(1)).keyup(); 146 | } 147 | 148 | init(); 149 | }); 150 | 151 | $.fn.stackSelect = function (fn) { 152 | return this.length ? this.animate({ 153 | height: 0, 154 | opacity: 0, 155 | padding: 0 156 | }, 200, function () { 157 | $(this).hide(); 158 | fn.call(this); 159 | }) : fn.call(this); 160 | }; 161 | 162 | function loadFavs() { 163 | if (!airapp) { 164 | // read favs from cookie 165 | eval('favs = ' + readCookie('favs'));// need to change to Crockford's json parser 166 | } else { 167 | var FileSystem = window.runtime.flash.filesystem; 168 | 169 | var file = FileSystem.File.applicationStorageDirectory.resolvePath('favs.json'); 170 | if (file.exists) { 171 | var fileStream = new FileSystem.FileStream(); 172 | fileStream.open( file, FileSystem.FileMode.READ ); 173 | var data = fileStream.readMultiByte( file.size, FileSystem.File.systemCharset ); 174 | fileStream.close(); 175 | 176 | favs = JSON.parse(data); 177 | } 178 | } 179 | 180 | if (favs == null) { 181 | favs = {}; 182 | } else { 183 | for (var k in favs) { 184 | jquerydocs.data[k].fav = 'true'; 185 | } 186 | } 187 | } 188 | 189 | function loadCategories(root) { 190 | var html = []; 191 | var categories = jquerydocs.categories; 192 | root = (root || "").toLowerCase(); 193 | 194 | if (root) { 195 | lastRoot = root; 196 | } else { 197 | root = lastRoot; 198 | } 199 | 200 | for (var i = 0; i < categories.length; i++) { 201 | if (categories[i].root == root) { 202 | html.push('
      ' + categories[i].name.replace(/^UI\//, '') + '
      '); 203 | } 204 | } 205 | 206 | if (html.length) { 207 | $('#browser > div').html('
      ' + html.join('') + '
      '); 208 | } else { 209 | $('#browser > div').html('

      No functions found.

      '); 210 | } 211 | } 212 | 213 | // TODO find out why it's not in id order 214 | function showFunctions(items, $wrapper) { 215 | var argsA = [], 216 | args, 217 | html = [], 218 | i, j; 219 | 220 | $wrapper.find('> #functions, dd').remove(); 221 | 222 | for (i = 0; i < items.length; i++) { 223 | argsA = []; 224 | args = ''; 225 | 226 | if (items[i].params.length) { 227 | for (j = 0; j < items[i].params.length; j++) { 228 | argsA.push(items[i].params[j].name); 229 | } 230 | args = '(' + argsA.join(', ') + ')'; 231 | } else if (items[i].type == 'function') { 232 | args = '()'; 233 | } 234 | 235 | html.push('
      ' + items[i].name + args + '
      '); 236 | } 237 | 238 | step = (200 * $wrapper.find('dl').length) + 10; 239 | var $html = $('
      ' + html.join('') + '
      ').css('display', 'none'); 240 | $wrapper.append($html); 241 | } 242 | 243 | 244 | function init() { 245 | var $wrapper = $('#browser > div'), 246 | $categories = $('#categories'), 247 | $detail = $('#detail > div'), 248 | blank_iframe = 'index-blank.html', 249 | title = document.title, 250 | html = [], 251 | categories = jquerydocs.categories; 252 | 253 | loadFavs(); 254 | loadCategories(); 255 | 256 | var $nav = $('#navigation a').click(function () { 257 | $nav.removeClass('selected'); 258 | $(this).addClass('selected'); 259 | 260 | $('#query').val(''); 261 | 262 | if (this.hash.substr(1) == 'favs') { 263 | $wrapper.empty(); 264 | var items = jquerydocs.find('true', 'fav'); 265 | showFunctions(items, $wrapper); 266 | if (items.length) { 267 | $('#functions').show(); 268 | } else { 269 | $('#browser > div').html('

      No functions found.

      '); 270 | } 271 | } else { 272 | loadCategories(this.hash.substr(1)); 273 | } 274 | 275 | return false; 276 | }); 277 | 278 | $wrapper.click(function (event) { 279 | categories = jquerydocs.categories; 280 | var dt = (event.target.nodeName == 'DT'), 281 | $selected = $(event.target), 282 | step = 210, 283 | i, j, // loop indices 284 | q = $selected.text(), // search term 285 | items, // matches 286 | item, // specific function 287 | argsA = [], 288 | args = '', 289 | html = [], 290 | deselect = false, 291 | category, 292 | subcategory, 293 | fns = []; 294 | 295 | if (dt) { 296 | 297 | var inId = $selected.parent().attr('id'); 298 | 299 | if ($selected.is('.active') && $selected.parent('#functions').length == 0) { 300 | // go up a level 301 | deselect = true; 302 | 303 | if ($selected.parent('#subcategories').length) { 304 | $selected = $('#categories').find('.active'); 305 | } else { 306 | $('#functions, #subcategories').slideUp(function () { 307 | $(this).remove(); 308 | }); 309 | $('#categories').find('dt').removeClass('active').css('padding', 5).animate({ 310 | opacity : 1, 311 | height : '100%' 312 | }); 313 | return; 314 | } 315 | } else { 316 | $selected.parent().find('dt').removeClass('active'); 317 | $selected.addClass('active'); 318 | } 319 | 320 | if ($selected.parents('#categories').length) { // category selected 321 | category = $selected.attr('id'); 322 | 323 | $categories.find('dt').removeClass('active'); 324 | $selected.addClass('active'); 325 | $wrapper.find('> dl:not(#categories), dd').remove(); 326 | 327 | if (jquerydocs.categories[category].subcategories && jquerydocs.categories[category].subcategories.length) { 328 | for (i = 0; i < categories[category].subcategories.length; i++) { 329 | html.push('
      ' + categories[category].subcategories[i].name + '
      '); 330 | } 331 | 332 | var $html = $('
      ' + html.join('') + '
      '); 333 | $html.css('display', 'none'); 334 | 335 | $wrapper.append($html); 336 | $wrapper.find('#categories dt:not(.active)').stackSelect(function () { 337 | $wrapper.find('#subcategories').slideDown(); 338 | }); 339 | } 340 | } else if ($selected.parents('#subcategories').length) { // subcategory selected 341 | category = $('#categories .active').attr('id'); 342 | subcategory = $selected.attr('id').replace(/subcategory/, ''); 343 | fns = []; 344 | for (i = 0; i < jquerydocs.categories[category].subcategories[subcategory].functions.length; i++) { 345 | fns.push(jquerydocs.categories[category].subcategories[subcategory].functions[i]); 346 | } 347 | 348 | showFunctions(jquerydocs.find(fns), $wrapper); // function because we get reused. 349 | 350 | $wrapper.find('#subcategories dt:not(.active)').stackSelect(function () { 351 | $wrapper.find('#functions').slideDown(); 352 | }); 353 | } else if ($selected.parents('#functions').length) { // function selected 354 | item = jquerydocs.data[$selected.attr('id')]; 355 | 356 | $detail.empty(); 357 | 358 | document.title = q + ' :: ' + title; 359 | 360 | html.push('

      ' + q + ' ' + item.type + '

      '); 361 | html.push('

      Category: ' + item.category + '/' + item.subcategory + (item.added ? ' (added ' + item.added + ')' : '') + '

      '); 362 | html.push(item.longdesc || '

      ' + item.desc + '

      '); // longdesc is usally HTML 363 | html.push('

      Returns

      '); 364 | html.push('

      ' + (item['return'] || 'Nothing') + '

      '); 365 | 366 | if (item.params.length) { 367 | html.push('

      Parameters

      '); 368 | html.push('
        '); 369 | for (i = 0; i < item.params.length; i++) { 370 | html.push('
      • ' + item.params[i].name + ' '); 371 | if (item.params[i].type) { 372 | html.push('(' + item.params[i].type + ')'); 373 | } 374 | html.push(': ' + item.params[i].desc + '
      • '); 375 | } 376 | html.push('
      '); 377 | } 378 | 379 | // detailed options 380 | if (item.options && item.options.length) { 381 | html.push('

      Options

      '); 382 | html.push('
        '); 383 | for (i = 0; i < item.options.length; i++) { 384 | html.push('
      • ' + item.options[i].name + ' '); 385 | if (item.options[i].type) { 386 | html.push('(' + item.options[i].type + ')'); 387 | } 388 | html.push(': ' + item.options[i].desc + '
      • '); 389 | } 390 | html.push('
      '); 391 | 392 | } 393 | 394 | for (i = 0; i < item.examples.length; i++) { 395 | html.push('

      Example

      '); 396 | if (item.examples[i].desc) { 397 | html.push('

      ' + item.examples[i].desc + '

      '); 398 | } 399 | html.push('

      jQuery Code

      '); 400 | html.push('
      ' + item.examples[i].htmlCode + '
      '); 401 | 402 | // this is special code that will convert in to a real running example once run through 'runExample(item)' 403 | if (item.examples[i].html) { 404 | 405 | // prepare for a JSBin link - currently point to live 406 | j = item.examples[i].runCode.replace("", function () { 407 | return ""; 408 | }); 409 | 410 | html.push(''); 411 | } 412 | } 413 | 414 | // step = (200 * $wrapper.find('dl').length) + 10; 415 | $detail.append('
      ' + html.join('') + '
      '); 416 | $detail.parent().get(0).scrollTop = 0; // reset the overflow position 417 | fixLinks($detail.find('dd')); // makes links to more docs absolute rather than relative (should do in the api-docs.js) 418 | 419 | // in place of runExamples to allow AIR to run the iframe's contents 420 | if (airapp) { 421 | $('div.liveExample a.external').click(function () { 422 | window.runtime.flash.net.navigateToURL(new window.runtime.flash.net.URLRequest(this.href)); 423 | return false; 424 | }); 425 | 426 | for (i = 0; i < item.examples.length; i++) { 427 | win = document.getElementById(item.examples[i].id); 428 | if (win) { // some examples don't have code 429 | $(win).bind('load', { example: item.examples[i] }, function (event) { 430 | var example = event.data.example; 431 | this.contentWindow.childSandboxBridge.write( 432 | example.runCode.replace("", '')); 433 | }); 434 | } 435 | } 436 | } else { 437 | runExample(item); 438 | } 439 | 440 | // code highlight 441 | prettyPrint($detail.get(0)); 442 | } 443 | } 444 | }); 445 | } 446 | -------------------------------------------------------------------------------- /lib/jqueryapi/json2.js: -------------------------------------------------------------------------------- 1 | /* 2 | http://www.JSON.org/json2.js 3 | 2008-11-19 4 | 5 | Public Domain. 6 | 7 | NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 8 | 9 | See http://www.JSON.org/js.html 10 | 11 | This file creates a global JSON object containing two methods: stringify 12 | and parse. 13 | 14 | JSON.stringify(value, replacer, space) 15 | value any JavaScript value, usually an object or array. 16 | 17 | replacer an optional parameter that determines how object 18 | values are stringified for objects. It can be a 19 | function or an array of strings. 20 | 21 | space an optional parameter that specifies the indentation 22 | of nested structures. If it is omitted, the text will 23 | be packed without extra whitespace. If it is a number, 24 | it will specify the number of spaces to indent at each 25 | level. If it is a string (such as '\t' or ' '), 26 | it contains the characters used to indent at each level. 27 | 28 | This method produces a JSON text from a JavaScript value. 29 | 30 | When an object value is found, if the object contains a toJSON 31 | method, its toJSON method will be called and the result will be 32 | stringified. A toJSON method does not serialize: it returns the 33 | value represented by the name/value pair that should be serialized, 34 | or undefined if nothing should be serialized. The toJSON method 35 | will be passed the key associated with the value, and this will be 36 | bound to the object holding the key. 37 | 38 | For example, this would serialize Dates as ISO strings. 39 | 40 | Date.prototype.toJSON = function (key) { 41 | function f(n) { 42 | // Format integers to have at least two digits. 43 | return n < 10 ? '0' + n : n; 44 | } 45 | 46 | return this.getUTCFullYear() + '-' + 47 | f(this.getUTCMonth() + 1) + '-' + 48 | f(this.getUTCDate()) + 'T' + 49 | f(this.getUTCHours()) + ':' + 50 | f(this.getUTCMinutes()) + ':' + 51 | f(this.getUTCSeconds()) + 'Z'; 52 | }; 53 | 54 | You can provide an optional replacer method. It will be passed the 55 | key and value of each member, with this bound to the containing 56 | object. The value that is returned from your method will be 57 | serialized. If your method returns undefined, then the member will 58 | be excluded from the serialization. 59 | 60 | If the replacer parameter is an array of strings, then it will be 61 | used to select the members to be serialized. It filters the results 62 | such that only members with keys listed in the replacer array are 63 | stringified. 64 | 65 | Values that do not have JSON representations, such as undefined or 66 | functions, will not be serialized. Such values in objects will be 67 | dropped; in arrays they will be replaced with null. You can use 68 | a replacer function to replace those with JSON values. 69 | JSON.stringify(undefined) returns undefined. 70 | 71 | The optional space parameter produces a stringification of the 72 | value that is filled with line breaks and indentation to make it 73 | easier to read. 74 | 75 | If the space parameter is a non-empty string, then that string will 76 | be used for indentation. If the space parameter is a number, then 77 | the indentation will be that many spaces. 78 | 79 | Example: 80 | 81 | text = JSON.stringify(['e', {pluribus: 'unum'}]); 82 | // text is '["e",{"pluribus":"unum"}]' 83 | 84 | 85 | text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); 86 | // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' 87 | 88 | text = JSON.stringify([new Date()], function (key, value) { 89 | return this[key] instanceof Date ? 90 | 'Date(' + this[key] + ')' : value; 91 | }); 92 | // text is '["Date(---current time---)"]' 93 | 94 | 95 | JSON.parse(text, reviver) 96 | This method parses a JSON text to produce an object or array. 97 | It can throw a SyntaxError exception. 98 | 99 | The optional reviver parameter is a function that can filter and 100 | transform the results. It receives each of the keys and values, 101 | and its return value is used instead of the original value. 102 | If it returns what it received, then the structure is not modified. 103 | If it returns undefined then the member is deleted. 104 | 105 | Example: 106 | 107 | // Parse the text. Values that look like ISO date strings will 108 | // be converted to Date objects. 109 | 110 | myData = JSON.parse(text, function (key, value) { 111 | var a; 112 | if (typeof value === 'string') { 113 | a = 114 | /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 115 | if (a) { 116 | return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], 117 | +a[5], +a[6])); 118 | } 119 | } 120 | return value; 121 | }); 122 | 123 | myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { 124 | var d; 125 | if (typeof value === 'string' && 126 | value.slice(0, 5) === 'Date(' && 127 | value.slice(-1) === ')') { 128 | d = new Date(value.slice(5, -1)); 129 | if (d) { 130 | return d; 131 | } 132 | } 133 | return value; 134 | }); 135 | 136 | 137 | This is a reference implementation. You are free to copy, modify, or 138 | redistribute. 139 | 140 | This code should be minified before deployment. 141 | See http://javascript.crockford.com/jsmin.html 142 | 143 | USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 144 | NOT CONTROL. 145 | */ 146 | 147 | /*jslint evil: true */ 148 | 149 | /*global JSON */ 150 | 151 | /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, 152 | call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, 153 | getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, 154 | lastIndex, length, parse, prototype, push, replace, slice, stringify, 155 | test, toJSON, toString, valueOf 156 | */ 157 | 158 | // Create a JSON object only if one does not already exist. We create the 159 | // methods in a closure to avoid creating global variables. 160 | 161 | if (!this.JSON) { 162 | JSON = {}; 163 | } 164 | (function () { 165 | 166 | function f(n) { 167 | // Format integers to have at least two digits. 168 | return n < 10 ? '0' + n : n; 169 | } 170 | 171 | if (typeof Date.prototype.toJSON !== 'function') { 172 | 173 | Date.prototype.toJSON = function (key) { 174 | 175 | return this.getUTCFullYear() + '-' + 176 | f(this.getUTCMonth() + 1) + '-' + 177 | f(this.getUTCDate()) + 'T' + 178 | f(this.getUTCHours()) + ':' + 179 | f(this.getUTCMinutes()) + ':' + 180 | f(this.getUTCSeconds()) + 'Z'; 181 | }; 182 | 183 | String.prototype.toJSON = 184 | Number.prototype.toJSON = 185 | Boolean.prototype.toJSON = function (key) { 186 | return this.valueOf(); 187 | }; 188 | } 189 | 190 | var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 191 | escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 192 | gap, 193 | indent, 194 | meta = { // table of character substitutions 195 | '\b': '\\b', 196 | '\t': '\\t', 197 | '\n': '\\n', 198 | '\f': '\\f', 199 | '\r': '\\r', 200 | '"' : '\\"', 201 | '\\': '\\\\' 202 | }, 203 | rep; 204 | 205 | 206 | function quote(string) { 207 | 208 | // If the string contains no control characters, no quote characters, and no 209 | // backslash characters, then we can safely slap some quotes around it. 210 | // Otherwise we must also replace the offending characters with safe escape 211 | // sequences. 212 | 213 | escapable.lastIndex = 0; 214 | return escapable.test(string) ? 215 | '"' + string.replace(escapable, function (a) { 216 | var c = meta[a]; 217 | return typeof c === 'string' ? c : 218 | '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 219 | }) + '"' : 220 | '"' + string + '"'; 221 | } 222 | 223 | 224 | function str(key, holder) { 225 | 226 | // Produce a string from holder[key]. 227 | 228 | var i, // The loop counter. 229 | k, // The member key. 230 | v, // The member value. 231 | length, 232 | mind = gap, 233 | partial, 234 | value = holder[key]; 235 | 236 | // If the value has a toJSON method, call it to obtain a replacement value. 237 | 238 | if (value && typeof value === 'object' && 239 | typeof value.toJSON === 'function') { 240 | value = value.toJSON(key); 241 | } 242 | 243 | // If we were called with a replacer function, then call the replacer to 244 | // obtain a replacement value. 245 | 246 | if (typeof rep === 'function') { 247 | value = rep.call(holder, key, value); 248 | } 249 | 250 | // What happens next depends on the value's type. 251 | 252 | switch (typeof value) { 253 | case 'string': 254 | return quote(value); 255 | 256 | case 'number': 257 | 258 | // JSON numbers must be finite. Encode non-finite numbers as null. 259 | 260 | return isFinite(value) ? String(value) : 'null'; 261 | 262 | case 'boolean': 263 | case 'null': 264 | 265 | // If the value is a boolean or null, convert it to a string. Note: 266 | // typeof null does not produce 'null'. The case is included here in 267 | // the remote chance that this gets fixed someday. 268 | 269 | return String(value); 270 | 271 | // If the type is 'object', we might be dealing with an object or an array or 272 | // null. 273 | 274 | case 'object': 275 | 276 | // Due to a specification blunder in ECMAScript, typeof null is 'object', 277 | // so watch out for that case. 278 | 279 | if (!value) { 280 | return 'null'; 281 | } 282 | 283 | // Make an array to hold the partial results of stringifying this object value. 284 | 285 | gap += indent; 286 | partial = []; 287 | 288 | // Is the value an array? 289 | 290 | if (Object.prototype.toString.apply(value) === '[object Array]') { 291 | 292 | // The value is an array. Stringify every element. Use null as a placeholder 293 | // for non-JSON values. 294 | 295 | length = value.length; 296 | for (i = 0; i < length; i += 1) { 297 | partial[i] = str(i, value) || 'null'; 298 | } 299 | 300 | // Join all of the elements together, separated with commas, and wrap them in 301 | // brackets. 302 | 303 | v = partial.length === 0 ? '[]' : 304 | gap ? '[\n' + gap + 305 | partial.join(',\n' + gap) + '\n' + 306 | mind + ']' : 307 | '[' + partial.join(',') + ']'; 308 | gap = mind; 309 | return v; 310 | } 311 | 312 | // If the replacer is an array, use it to select the members to be stringified. 313 | 314 | if (rep && typeof rep === 'object') { 315 | length = rep.length; 316 | for (i = 0; i < length; i += 1) { 317 | k = rep[i]; 318 | if (typeof k === 'string') { 319 | v = str(k, value); 320 | if (v) { 321 | partial.push(quote(k) + (gap ? ': ' : ':') + v); 322 | } 323 | } 324 | } 325 | } else { 326 | 327 | // Otherwise, iterate through all of the keys in the object. 328 | 329 | for (k in value) { 330 | if (Object.hasOwnProperty.call(value, k)) { 331 | v = str(k, value); 332 | if (v) { 333 | partial.push(quote(k) + (gap ? ': ' : ':') + v); 334 | } 335 | } 336 | } 337 | } 338 | 339 | // Join all of the member texts together, separated with commas, 340 | // and wrap them in braces. 341 | 342 | v = partial.length === 0 ? '{}' : 343 | gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + 344 | mind + '}' : '{' + partial.join(',') + '}'; 345 | gap = mind; 346 | return v; 347 | } 348 | } 349 | 350 | // If the JSON object does not yet have a stringify method, give it one. 351 | 352 | if (typeof JSON.stringify !== 'function') { 353 | JSON.stringify = function (value, replacer, space) { 354 | 355 | // The stringify method takes a value and an optional replacer, and an optional 356 | // space parameter, and returns a JSON text. The replacer can be a function 357 | // that can replace values, or an array of strings that will select the keys. 358 | // A default replacer method can be provided. Use of the space parameter can 359 | // produce text that is more easily readable. 360 | 361 | var i; 362 | gap = ''; 363 | indent = ''; 364 | 365 | // If the space parameter is a number, make an indent string containing that 366 | // many spaces. 367 | 368 | if (typeof space === 'number') { 369 | for (i = 0; i < space; i += 1) { 370 | indent += ' '; 371 | } 372 | 373 | // If the space parameter is a string, it will be used as the indent string. 374 | 375 | } else if (typeof space === 'string') { 376 | indent = space; 377 | } 378 | 379 | // If there is a replacer, it must be a function or an array. 380 | // Otherwise, throw an error. 381 | 382 | rep = replacer; 383 | if (replacer && typeof replacer !== 'function' && 384 | (typeof replacer !== 'object' || 385 | typeof replacer.length !== 'number')) { 386 | throw new Error('JSON.stringify'); 387 | } 388 | 389 | // Make a fake root object containing our value under the key of ''. 390 | // Return the result of stringifying the value. 391 | 392 | return str('', {'': value}); 393 | }; 394 | } 395 | 396 | 397 | // If the JSON object does not yet have a parse method, give it one. 398 | 399 | if (typeof JSON.parse !== 'function') { 400 | JSON.parse = function (text, reviver) { 401 | 402 | // The parse method takes a text and an optional reviver function, and returns 403 | // a JavaScript value if the text is a valid JSON text. 404 | 405 | var j; 406 | 407 | function walk(holder, key) { 408 | 409 | // The walk method is used to recursively walk the resulting structure so 410 | // that modifications can be made. 411 | 412 | var k, v, value = holder[key]; 413 | if (value && typeof value === 'object') { 414 | for (k in value) { 415 | if (Object.hasOwnProperty.call(value, k)) { 416 | v = walk(value, k); 417 | if (v !== undefined) { 418 | value[k] = v; 419 | } else { 420 | delete value[k]; 421 | } 422 | } 423 | } 424 | } 425 | return reviver.call(holder, key, value); 426 | } 427 | 428 | 429 | // Parsing happens in four stages. In the first stage, we replace certain 430 | // Unicode characters with escape sequences. JavaScript handles many characters 431 | // incorrectly, either silently deleting them, or treating them as line endings. 432 | 433 | cx.lastIndex = 0; 434 | if (cx.test(text)) { 435 | text = text.replace(cx, function (a) { 436 | return '\\u' + 437 | ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 438 | }); 439 | } 440 | 441 | // In the second stage, we run the text against regular expressions that look 442 | // for non-JSON patterns. We are especially concerned with '()' and 'new' 443 | // because they can cause invocation, and '=' because it can cause mutation. 444 | // But just to be safe, we want to reject all unexpected forms. 445 | 446 | // We split the second stage into 4 regexp operations in order to work around 447 | // crippling inefficiencies in IE's and Safari's regexp engines. First we 448 | // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we 449 | // replace all simple value tokens with ']' characters. Third, we delete all 450 | // open brackets that follow a colon or comma or that begin the text. Finally, 451 | // we look to see that the remaining characters are only whitespace or ']' or 452 | // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. 453 | 454 | if (/^[\],:{}\s]*$/. 455 | test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). 456 | replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). 457 | replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { 458 | 459 | // In the third stage we use the eval function to compile the text into a 460 | // JavaScript structure. The '{' operator is subject to a syntactic ambiguity 461 | // in JavaScript: it can begin a block or an object literal. We wrap the text 462 | // in parens to eliminate the ambiguity. 463 | 464 | j = eval('(' + text + ')'); 465 | 466 | // In the optional fourth stage, we recursively walk the new structure, passing 467 | // each name/value pair to a reviver function for possible transformation. 468 | 469 | return typeof reviver === 'function' ? 470 | walk({'': j}, '') : j; 471 | } 472 | 473 | // If the text is not JSON parseable, then a SyntaxError is thrown. 474 | 475 | throw new SyntaxError('JSON.parse'); 476 | }; 477 | } 478 | })(); -------------------------------------------------------------------------------- /lib/jqueryapi/api-loader.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | if (!window.jquerydocs) { 4 | window.jquerydocs = {}; 5 | } else { 6 | // we've already been included, bomb out 7 | return; 8 | } 9 | 10 | window.apiloader = {}; 11 | 12 | var msie = /*@cc_on!@*/0; 13 | apiloader.blank_iframe = msie ? 'index-blank-ie.html' : 'index-blank.html'; 14 | apiloader.online = window.runtime ? false : true; 15 | apiloader.example_jquery = { 16 | 'online' : 'http://code.jquery.com/jquery-1.3.js', 17 | 'offline' : 'http://code.jquery.com/jquery-1.3.js' //app:/lib/jquery/jquery-1.3.js' 18 | }; 19 | 20 | var guid = 0; 21 | 22 | var re_opt = /options/i; 23 | 24 | init(); 25 | 26 | window.loadDocs = function(data, async) { 27 | $(document).trigger('api-loading'); 28 | 29 | if (typeof async == 'undefined') { 30 | async = true; 31 | } 32 | 33 | if (typeof data != 'undefined' && typeof data != 'string') { 34 | jquerydocs = data; 35 | attachFind(jquerydocs); 36 | $(document).trigger('api-load-success'); 37 | $(document).trigger('api-load-complete'); 38 | } else { 39 | // parser 40 | $.ajax({ 41 | url: data || 'jquery-docs.xml', // generated from jquery source: /tools/wikiapi2xml/createjQueryXMLDocs.py 42 | dataType: 'xml', 43 | success: parse, 44 | async: async, 45 | error: function () { 46 | attachFind(jquerydocs); 47 | $(document).trigger('api-load-error'); 48 | }, 49 | complete: function () { 50 | $(document).trigger('api-load-complete'); 51 | } 52 | }); 53 | } 54 | }; 55 | 56 | function init() { 57 | jquerydocs.letters = []; 58 | 59 | jquerydocs.data = {}; 60 | jquerydocs.searchNames = []; 61 | jquerydocs.categories = []; 62 | } 63 | 64 | window.parse = function(xml) { 65 | var docinfo = $('docs', xml); 66 | 67 | if (!jquerydocs.startdoc) { // only initialise this once 68 | jquerydocs.startdoc = docinfo.attr('startdoc'); 69 | jquerydocs.version = docinfo.attr('version'); 70 | jquerydocs.timestamp = docinfo.attr('timestamp'); 71 | } 72 | 73 | var letters = jquerydocs.letters; // holder before sorting and inserting 74 | 75 | var dict = getDictionary(); 76 | var root = docinfo.attr('startdoc').toLowerCase(); 77 | 78 | // loop through all types collecting data 79 | $('cat', xml).each(function (i) { 80 | var catName = this.getAttribute('value'); 81 | var category = {}; 82 | category.name = catName; 83 | category.root = root; 84 | category.subcategories = []; 85 | 86 | $('subcat', this).each(function (i) { 87 | var subcatName = this.getAttribute('value'); 88 | var subcategory = { name : subcatName, functions : [] }; 89 | 90 | $('function,property,selector', this).each(function () { 91 | var data = {}; 92 | guid++; 93 | 94 | // some function names have spaces around them - so trim 95 | var name = this.getAttribute('name').replace( /^\s+|\s+$/g, ''); 96 | 97 | var searchName = name.toLowerCase().replace(/^jquery\./, ''); 98 | letters.push(name.toLowerCase().substr(0,1)); 99 | 100 | name = name.replace(/^jquery\./i, '$.'); 101 | 102 | jquerydocs.searchNames.push(searchName + guid); 103 | subcategory.functions.push(searchName + guid); 104 | 105 | data['id'] = guid; 106 | data['searchname'] = searchName; 107 | data['name'] = name; 108 | data['type'] = this.nodeName.toLowerCase(); 109 | data['category'] = this.getAttribute('cat'); 110 | data['subcategory'] = subcatName; 111 | data['return'] = escapeHTML(this.getAttribute('return')); 112 | data['added'] = $('added', this).text(); 113 | data['sample'] = $('> sample', this).text(); 114 | data['desc'] = $('> desc', this).text(); 115 | data['longdesc'] = deWikify($('> longdesc', this).text()); 116 | 117 | // silly hack because of conversion issue from wiki to text (the .ready function 118 | // has HTML in the description), but also includes HTML that should be printed, 119 | // in particular the body tag :-( 120 | data.longdesc = data.longdesc.replace(//, '<body>'); 121 | 122 | // some descs are in HTML format, some aren't 123 | if (!(/

      /).test(data.longdesc)) { 124 | data.longdesc = '

      ' + data.longdesc.split(/\n\n/).join('

      ') + '

      '; 125 | } 126 | 127 | // strip our empty p tag if there was no description 128 | if (data.longdesc == '

      ') { 129 | data.longdesc = ''; 130 | } 131 | 132 | /** params - we'll also search for Options to decide whether we need to parse */ 133 | var readOptions = false; 134 | data.params = []; 135 | $('params', this).each(function (i) { 136 | var type = escapeHTML(this.getAttribute('type')); 137 | var name = this.getAttribute('name'); 138 | var opt = this.getAttribute('optional') || ""; 139 | var desc = $('desc', this).text(); 140 | 141 | if (re_opt.test(type)) { 142 | readOptions = true; 143 | } 144 | 145 | data.params.push({ 146 | optional : (/true/i).test(opt), // bool 147 | name : name, 148 | type : type, 149 | desc : desc 150 | }); 151 | }); 152 | 153 | if (readOptions) { 154 | data.options = []; 155 | $('option', this).each(function () { 156 | var option = {}; 157 | option['name'] = this.getAttribute('name'); 158 | option['default'] = this.getAttribute('default') || ''; 159 | option['type'] = escapeHTML(this.getAttribute('type')); 160 | option['desc'] = deWikify($('desc', this).text()); 161 | 162 | data.options.push(option); 163 | }); 164 | } 165 | 166 | data.examples = []; 167 | /** examples */ 168 | $('example', this).each(function (i) { 169 | var iframe = '', exampleId = ''; 170 | var example = {}; 171 | 172 | example['code'] = $('code', this).text(); 173 | example['htmlCode'] = escapeHTML(example.code); 174 | example['desc'] = deWikify(escapeHTML($('desc', this).text())); 175 | example['css'] = $('css', this).text() || ''; 176 | example['inhead'] = $('inhead', this).text() || ''; 177 | example['html'] = $('html', this).text() || ''; 178 | 179 | exampleId = guid + 'iframeExample' + i; 180 | example['id'] = exampleId; 181 | 182 | if (example.html) { 183 | 184 | iframe = ''; 185 | 186 | // we're storing the example iframe source to insert in to 187 | // the iframe only once it's inserted in to the DOM. 188 | example['runCode'] = iframeTemplate().replace(/%([a-z]*)%/ig, function (m, l) { 189 | return example[l] || ""; 190 | }); 191 | } else { 192 | example.runCode = ''; 193 | } 194 | 195 | data.examples.push(example); 196 | }); 197 | 198 | jquerydocs.data[searchName + data.id] = data; 199 | }); 200 | 201 | category.subcategories.push(subcategory); 202 | }); 203 | 204 | jquerydocs.categories.push(category); // FIXME should I warn if this exists? 205 | }); 206 | 207 | jquerydocs.letters = unique($.map(letters.sort(), function (i) { 208 | return i.substr(0,1); 209 | })); 210 | 211 | // attachFind(jquerydocs); 212 | 213 | $(document).trigger('api-load-success'); 214 | }; 215 | 216 | // helpers 217 | 218 | window.attachFind = function(o) { 219 | var categoryRootLookup = {}; 220 | var i = jquerydocs.categories.length; 221 | while (i--) { 222 | categoryRootLookup[jquerydocs.categories[i].name] = jquerydocs.categories[i].root; 223 | } 224 | 225 | o.find = function (s, by) { 226 | var found = [], 227 | tmp = {}, 228 | tmpNames = [], 229 | lettersLK = {}, 230 | letters = [], 231 | catsLK = {}, 232 | cats = [], 233 | catPointer = 0, 234 | subLK = {}, 235 | sub = [], 236 | subcatPointer = 0; 237 | data = {}; // reusing i from above 238 | 239 | function add(data, i) { 240 | mapFields(data); 241 | 242 | tmp[jquerydocs.searchNames[i]] = data; 243 | tmpNames.push(jquerydocs.searchNames[i]); 244 | 245 | if (!lettersLK[jquerydocs.searchNames[i].substr(0, 1)]) { 246 | lettersLK[jquerydocs.searchNames[i].substr(0, 1)] = true; 247 | letters.push(jquerydocs.searchNames[i].substr(0, 1)); 248 | } 249 | 250 | if (typeof catsLK[data.category] == 'undefined') { 251 | catsLK[data.category] = catPointer; 252 | cats.push({ name : data.category, subcategories : [], root : categoryRootLookup[data.category] }); 253 | 254 | subLK[data.category] = {}; 255 | 256 | subcatPointer = 0; 257 | catPointer++; 258 | } 259 | 260 | if (typeof subLK[data.category][data.subcategory] == 'undefined') { 261 | subLK[data.category][data.subcategory] = subcatPointer; 262 | cats[catsLK[data.category]].subcategories.push({ name : data.subcategory, functions : [] }); 263 | 264 | subcatPointer++; 265 | } 266 | 267 | // bug here... 268 | cats[catsLK[data.category]].subcategories[subLK[data.category][data.subcategory]].functions.push(jquerydocs.searchNames[i]); 269 | } 270 | 271 | if (typeof s == 'string') { 272 | s = s.toLowerCase(); 273 | by = (by || 'searchname').toLowerCase(); 274 | 275 | if (by == 'name') by = 'searchname'; // search without the $. 276 | 277 | for (i = 0; i < jquerydocs.searchNames.length; i++) { 278 | if (jquerydocs.data[jquerydocs.searchNames[i]][by] && jquerydocs.data[jquerydocs.searchNames[i]][by].toLowerCase().indexOf(s) == 0) { 279 | add(jquerydocs.data[jquerydocs.searchNames[i]], i); 280 | } 281 | } 282 | } else if (s instanceof Array) { 283 | for (i = 0; i < s.length; i++) { 284 | if (jquerydocs.data[s[i]]) { 285 | add(jquerydocs.data[s[i]], i); 286 | } 287 | } 288 | } 289 | 290 | tmpNames = tmpNames.sort().reverse(); // never sure if this is faster with the reverse 291 | i = tmpNames.length; 292 | while (i--) { 293 | found.push(tmp[tmpNames[i]]); 294 | } 295 | 296 | // this is kind of noddy, but returns the same object as we queried - which is cool! 297 | found.letters = letters; 298 | found.categories = cats; 299 | found.data = tmp; 300 | found.searchNames = tmpNames; 301 | attachFind(found); 302 | 303 | return found; 304 | }; 305 | }; 306 | 307 | function mapFields(data, dict) { 308 | if (data.fieldsMapped) { 309 | return; 310 | } 311 | 312 | var key, type; 313 | 314 | if (!dict) { 315 | dict = getDictionary(); 316 | } 317 | 318 | for (key in dict) { 319 | type = typeof data[key]; 320 | if (type != 'undefined') { 321 | if (type == 'object') { 322 | mapFields(data[key], dict); 323 | } 324 | 325 | data[dict[key]] = data[key]; 326 | } 327 | } 328 | } 329 | 330 | function unique(a) { 331 | var ret = [], done = {}; 332 | 333 | try { 334 | for ( var i = 0, length = a.length; i < length; i++ ) { 335 | var id = a[ i ] ; 336 | 337 | if ( !done[ id ] ) { 338 | done[ id ] = true; 339 | ret.push( a[ i ] ); 340 | } 341 | } 342 | 343 | } catch( e ) { 344 | ret = a; 345 | } 346 | 347 | return ret; 348 | } 349 | 350 | function iframeTemplate() { 351 | // array so that we maintain some formatting 352 | return [ 353 | '', 355 | '<' + 'html>', 356 | '<' + 'head>', 357 | '', 358 | '<' + 'script src="' + apiloader.example_jquery[apiloader.online ? 'online' : 'offline'] + '"><' + '/script>', 359 | '%inhead%', 360 | '<' + 'style>', 361 | '%css%', 362 | '<' + '/style>', 363 | '<' + '/head>', 364 | '<' + 'body>', 365 | '%html%', 366 | '<' + 'script>', 367 | '$(document).ready(function(){', '%code%', ' });', 368 | '<' + '/script>', 369 | '<' + '/body>', 370 | '<' + '/html>' 371 | ].join("\n"); 372 | } 373 | 374 | function getDictionary() { 375 | return { 376 | 'a' : 'id', 377 | 'b' : 'searchname', 378 | 'c' : 'name', 379 | 'd' : 'type', 380 | 'e' : 'category', 381 | 'f' : 'subcategory', 382 | 'g' : 'return', 383 | 'h' : 'added', 384 | 'i' : 'sample', 385 | 'j' : 'desc', 386 | 'k' : 'longdesc', 387 | 'l' : 'params', 388 | 'm' : 'optional', 389 | 'n' : 'options', 390 | 'o' : 'default', 391 | 'p' : 'examples', 392 | 'q' : 'code', 393 | 'r' : 'htmlCode', 394 | 's' : 'css', 395 | 't' : 'inhead', 396 | 'u' : 'html', 397 | 'v' : 'runCode' 398 | }; 399 | } 400 | 401 | /** public utility functions */ 402 | 403 | window.escapeHTML = function (s) { 404 | // converts null to string 405 | return (s+"").replace(/[<>]/g, function (m) { 406 | if (m == '<') return '<'; 407 | else if (m == '>') return '>'; 408 | }); 409 | }; 410 | 411 | window.cleanSelector = function(s) { 412 | return (s+"").replace(/[\$\.]/g, function (m) { 413 | // handle escaping characters that break the selector engine 414 | if (m == '$') { 415 | return '\\$'; 416 | } else if (m == '.') { 417 | return '\\.'; 418 | } 419 | }); 420 | }; 421 | 422 | window.linkifyTypes = function(type) { 423 | // cheeky way to avoid doing a massive if (m == x || m == y || m == etc) - we just do an .indexOf() 424 | var nodocs = '|jQuery|XMLHttpRequest|Plugins|Validator|Validation|undefined|or|Any|DOM|Map|top|left|lt|gt|\(s\)||'; // note we purposely include an empty match 425 | 426 | return type ? $.map(type.replace(/DOMElement/g, 'DOM Element').split(/, /), function (n) { 427 | // match words and linkify, then italic to the optionals 428 | return n.replace(/boolean/, 'Boolean').replace(/\b[a-z]*\b/gi, function (m, l) { 429 | // special case 430 | if (m == 'Elements') { 431 | return 'Elements'; 432 | // no specific documentation for these types 433 | } else if (nodocs.indexOf('|' + m + '|') !== -1) { 434 | return m; 435 | } else { 436 | return '' + m + ''; 437 | } 438 | }); 439 | }).join(', ') : ""; 440 | }; 441 | 442 | window.deWikify = function (s) { 443 | return (""+s).replace(/'''.*?'''/g, function (m) { 444 | return '' + m.replace(/'''/g, '') + ''; 445 | }).replace(/''.*?''/g, function (m) { 446 | return '' + m.replace(/''/g, '') + ''; 447 | }).replace(/\[http.*?\]/, function (m) { 448 | var p = m.replace(/^\[/, '').replace(/\]$/, '').split(/ /); 449 | return '' + (p.length == 2 ? p[1] : p[0]) + ''; 450 | }).replace(/(((^|\n)(\*|[0-9]+.).*)+)/g, function (m) { 451 | var type = 'ol'; 452 | // strip leading new line 453 | m = m.replace( /^\s+|\s+$/g, "" ); 454 | if (m.match(/^\*/)) type = 'ul'; 455 | return '<' + type + '>
    • ' + m.replace(/\*?/g, '').split(/\n/).join("
    • ") + '
    • '; 456 | }); 457 | }; 458 | 459 | window.runExample = function(data) { 460 | if (!data.examples || data.examples.length == 0) return; 461 | 462 | var i, win, example; 463 | 464 | for (i = 0; i < data.examples.length; i++) { 465 | example = data.examples[i]; 466 | 467 | win = $('#' + cleanSelector(example.id)).get(0); 468 | if (win) { 469 | win = win.contentDocument || win.contentWindow.document; 470 | if (msie) { 471 | 472 | } 473 | // from docs.jquery.com 474 | win.write(example.runCode 475 | .replace("$(document).ready(function(){", "window.onload = (function(){try{") 476 | .replace(/}\);\s*<\/sc/, "}catch(e){}});", "")); 478 | 479 | win.close(); 480 | } 481 | } 482 | }; 483 | 484 | window.fixLinks = function (context) { 485 | // since the source comes from the wiki, we need to adjust some of the links 486 | $('a', context).each(function () { 487 | var href = this.getAttribute('href'); 488 | if (href && !href.match(/http/) && !href.match(/^#/) && this.className != 'fnName') { 489 | this.host = 'docs.jquery.com'; 490 | this.pathname = this.pathname.replace(window.location.pathname, ''); 491 | } 492 | }); 493 | }; 494 | 495 | })(); 496 | -------------------------------------------------------------------------------- /lib/air/AIRMenuBuilder.js: -------------------------------------------------------------------------------- 1 | /* AIRMenuBuilder.js - Revision: 1.5 */ 2 | 3 | /* 4 | ADOBE SYSTEMS INCORPORATED 5 | Copyright 2007-2008 Adobe Systems Incorporated. All Rights Reserved. 6 | 7 | NOTICE: Adobe permits you to modify and distribute this file only in accordance with 8 | the terms of Adobe AIR SDK license agreement. You may have received this file from a 9 | source other than Adobe. Nonetheless, you may modify or 10 | distribute this file only in accordance with such agreement. 11 | */ 12 | 13 | (function AIRMenuBuilder () { 14 | 15 | function constructor ( ) { 16 | window ['air'] = window ['air'] || {}; 17 | window.air['ui'] = window.air['ui'] || {}; 18 | window.air.ui['Menu'] = new Menu(); 19 | registry = new FieldsRegistry(); 20 | currentOS = runtime.flash.system.Capabilities.os; 21 | } 22 | 23 | var currentOS = null; 24 | var registry = null; 25 | 26 | var File = runtime.flash.filesystem.File; 27 | var FileStream = runtime.flash.filesystem.FileStream; 28 | var FileMode = runtime.flash.filesystem.FileMode; 29 | var NativeMenu = runtime.flash.display.NativeMenu; 30 | var NativeMenuItem = runtime.flash.display.NativeMenuItem; 31 | var SELECT = runtime.flash.events.Event.SELECT; 32 | var KEYBOARD = runtime.flash.ui.Keyboard; 33 | var COMPLETE = runtime.flash.events.Event.COMPLETE; 34 | var IO_ERROR = runtime.flash.events.IOErrorEvent.IO_ERROR; 35 | var NativeApplication = runtime.flash.desktop.NativeApplication; 36 | var NativeWindow = runtime.flash.display.NativeWindow; 37 | var Loader = runtime.flash.display.Loader; 38 | var URLRequest = runtime.flash.net.URLRequest; 39 | var BitmapData = runtime.flash.display.BitmapData; 40 | 41 | /** 42 | * CLASS FieldsRegistry 43 | * @class 44 | * @private 45 | */ 46 | function FieldsRegistry () { 47 | 48 | this.proof = function (name, value) { 49 | if (!validateName(name)) { return null }; 50 | switch (name) { 51 | case FieldsRegistry.ENABLED: 52 | case FieldsRegistry.ALT_KEY: 53 | case FieldsRegistry.SHIFT_KEY: 54 | case FieldsRegistry.CMD_KEY: 55 | case FieldsRegistry.CTRL_KEY: 56 | case FieldsRegistry.TOGGLED: 57 | case FieldsRegistry.DEFAULT_KEY: 58 | return (typeof value == 'boolean')? 59 | value: (typeof value == 'string')? 60 | (value.toLowerCase() == 'false')? false : 61 | true : getDefault (name); 62 | case FieldsRegistry.KEY_EQUIVALENT: 63 | var d; 64 | return (typeof value == 'string')? 65 | (value.length == 1)? value : 66 | getDefault (name) : getDefault (name); 67 | case FieldsRegistry.LABEL: 68 | return (typeof value == 'string')? 69 | (value.length != 0)? value: 70 | getDefault (name) : getDefault (name); 71 | case FieldsRegistry.MNEMONIC_INDEX: 72 | var n; 73 | return (typeof value == 'number')? 74 | value: (typeof value == 'string')? 75 | (!isNaN ( n = parseInt(value) ))? n : 76 | getDefault (name) : getDefault (name); 77 | case FieldsRegistry.TYPE: 78 | return (typeof value == 'string') ? 79 | (validateType(value))? value : 80 | getDefault (name) : getDefault (name); 81 | case FieldsRegistry.ON_SELECT: 82 | var f; 83 | return (typeof value == 'function')? 84 | value : (typeof value == 'string')? 85 | (typeof (f = window[value]) == 'function')? 86 | f : getDefault (name) : getDefault (name); 87 | } 88 | } 89 | 90 | this.iterateFields = function (callback, scope) { 91 | var f, n, fr = FieldsRegistry; 92 | for (f in fr) { 93 | n = fr [f] !== fr.prototype? fr [f] : null; 94 | if (n && !validateType(n)) { 95 | callback.call ( scope || window, n ) 96 | }; 97 | } 98 | } 99 | 100 | var validateType = function (type) { 101 | return type == FieldsRegistry.REGULAR || 102 | type == FieldsRegistry.SEPARATOR || 103 | type == FieldsRegistry.CHECK; 104 | } 105 | 106 | var validateName = function (fieldName) { 107 | for (var f in FieldsRegistry) { 108 | if (FieldsRegistry[f] == fieldName) { return true }; 109 | } 110 | return false; 111 | } 112 | 113 | 114 | var getDefault = function (fieldName) { 115 | switch (fieldName) { 116 | case FieldsRegistry.ALT_KEY: 117 | case FieldsRegistry.SHIFT_KEY: 118 | case FieldsRegistry.TOGGLED: 119 | return false; 120 | case FieldsRegistry.ENABLED: 121 | case FieldsRegistry.DEFAULT_KEY: 122 | return true; 123 | case FieldsRegistry.KEY_EQUIVALENT: 124 | case FieldsRegistry.ON_SELECT: 125 | return null; 126 | case FieldsRegistry.LABEL: 127 | return ' '; 128 | case FieldsRegistry.MNEMONIC_INDEX: 129 | return -1; 130 | case FieldsRegistry.TYPE: 131 | return FieldsRegistry.REGULAR; 132 | case FieldsRegistry.CMD_KEY: 133 | case FieldsRegistry.CTRL_KEY: 134 | default: 135 | return null; 136 | } 137 | } 138 | 139 | } 140 | FieldsRegistry.ALT_KEY = 'altKey'; 141 | FieldsRegistry.CMD_KEY = 'cmdKey'; 142 | FieldsRegistry.CTRL_KEY = 'ctrlKey'; 143 | FieldsRegistry.ENABLED = 'enabled'; 144 | FieldsRegistry.KEY_EQUIVALENT = 'keyEquivalent'; 145 | FieldsRegistry.LABEL = 'label'; 146 | FieldsRegistry.MNEMONIC_INDEX = 'mnemonicIndex'; 147 | FieldsRegistry.SHIFT_KEY = 'shiftKey'; 148 | FieldsRegistry.TOGGLED = 'toggled'; 149 | FieldsRegistry.TYPE = 'type'; 150 | FieldsRegistry.ON_SELECT = 'onSelect'; 151 | FieldsRegistry.DEFAULT_KEY = 'defaultKeyEquivalentModifiers'; 152 | FieldsRegistry.SEPARATOR = 'separator'; 153 | FieldsRegistry.CHECK = 'check'; 154 | FieldsRegistry.REGULAR = 'regular'; 155 | 156 | /** 157 | * CLASS Menu 158 | * Description 159 | * Loads a user menu defined as XML or JSON, and sets it as one of the 160 | * supported menu types. 161 | * @class 162 | * @author ciacob 163 | */ 164 | function Menu() { 165 | 166 | var buildMenu = function (source, type) { 167 | var b = new Builder(); 168 | b.loadData (source, type); 169 | return b.build(); 170 | } 171 | 172 | var attachMenu = function (menu, type, target, icons) { 173 | var s = new Shell(); 174 | s.link(menu, type, target, icons); 175 | } 176 | 177 | /** 178 | * Load a menu defined in XML format. 179 | * @param source 180 | * An object containing XML menu(s) to be loaded for various OS-es. 181 | * @return 182 | * A NativeMenu object built from the given XML source. 183 | */ 184 | this.createFromXML = function ( source ) { 185 | return buildMenu ( source, Builder.XML ); 186 | } 187 | 188 | /** 189 | * Same as air.ui.Menu.fromXML, except it handles JSON data. 190 | */ 191 | this.createFromJSON = function ( source ) { 192 | return buildMenu ( source, Builder.JSON ); 193 | } 194 | 195 | /** 196 | * - on Windows: sets the given nativeMenu object as the NativeWindow's 197 | * menu; 198 | * - on Mac: inserts the items of the given nativeMenu object between 199 | * the 'Edit' and 'Window' default menus; 200 | * @param nativeMenu 201 | * A NativeMenu returned by one of the air.ui.Menu.from... 202 | * functions. 203 | * @param overwrite 204 | * A boolean that will change the behavior on Mac. If true, the 205 | * default menus will be replaced entirely by the given nativeMenu 206 | */ 207 | this.setAsMenu = function ( nativeMenu, overwrite ) { 208 | if (!arguments.length) { 209 | throw (new Error( 210 | "No argument given for the 'setAsMenu()' method." 211 | )); 212 | } 213 | var style = overwrite? Shell.MENU | Shell.OVERWRITE : Shell.MENU; 214 | attachMenu (nativeMenu, style); 215 | } 216 | 217 | /** 218 | * Displays the given menu as a contextual menu when the user right 219 | * clicks a certain DOM element. 220 | * @param nativeMenu 221 | * A NativeMenu returned by one of the air.ui.Menu.from... 222 | * functions. 223 | * @param domElement 224 | * The DOM Element to link with the given nativeMenu. The 225 | * contextual menu will only show when the user right clicks over 226 | * domElement. This attribute is optional. If missing, the context 227 | * menu will display on every right-click over the application. 228 | */ 229 | this.setAsContextMenu = function ( nativeMenu, domElement ) { 230 | if (!arguments.length) { 231 | throw (new Error( 232 | "No argument given for the 'setAsContextMenu()' method." 233 | )); 234 | } 235 | if (arguments.length < 2) { domElement = Shell.UNSPECIFIED }; 236 | attachMenu (nativeMenu, Shell.CONTEXT, domElement); 237 | } 238 | 239 | /** 240 | * Sets the given nativeMenu as the 241 | * ''NativeApplication.nativeApplication.icon.menu'' property. 242 | * @param nativeMenu 243 | * A NativeMenu returned by one of the air.ui.Menu.from... 244 | * functions. 245 | * @param icons 246 | * An array holding icon file paths or bitmap data objects. 247 | * If specified, these will be used as the application's 248 | * tray/dock icons. 249 | * @throws 250 | * If no bitmap data was set for the ''icon'' object and no default 251 | * icons are specified in the application descriptor. 252 | */ 253 | this.setAsIconMenu = function ( nativeMenu, icons ) { 254 | if (!arguments.length) { 255 | throw (new Error( 256 | "No argument given for the 'setAsIconMenu()' method." 257 | )); 258 | } 259 | attachMenu (nativeMenu, Shell.ICON, null, icons); 260 | } 261 | 262 | } 263 | 264 | /** 265 | * CLASS DataSource 266 | * @public 267 | * @abstract 268 | */ 269 | function DataSource() { 270 | var _this = this; 271 | 272 | var legalExtensions = ['xml', 'js']; 273 | 274 | var rSeed = null; 275 | 276 | var DATA_OBJECT = 1; 277 | var INLINE_STRING = 2; 278 | var FILE_PATH = 3; 279 | var FILE_OBJECT = 4; 280 | var ILLEGAL_TYPE = 5; 281 | 282 | function getFileContent (file) { 283 | var ret = ''; 284 | var fileStream = new FileStream(); 285 | fileStream.open(file, FileMode.READ); 286 | try { 287 | ret = fileStream.readUTFBytes(file.size); 288 | } catch(e) { 289 | throw( 290 | new Error(["Error\n", "ID: ", e.errorID, "\n", "Message: ", 291 | e.message, "\n"].join('')) 292 | ); 293 | } 294 | fileStream.close(); 295 | return ret; 296 | } 297 | 298 | function checkExtension (url, whiteList) { 299 | var match = url.match(/\.([^\.]*)$/); 300 | var extension = match? match[1] : null; 301 | for(var i=0; i 0); 467 | if (isError) { 468 | var errText = doc.getElementsByTagName(err)[0].innerText; 469 | var msg = errText.split(':'); 470 | msg.length -= 1; 471 | msg = msg.join(':\n'); 472 | throw (new Error ([ 473 | 'Could not parse data: malformed XML file.', msg 474 | ].join('\n'))); 475 | } 476 | that.document = doc; 477 | } 478 | } 479 | 480 | that.getRoot = function() { 481 | return that.document.documentElement; 482 | } 483 | 484 | that.getChildren = function (node) { 485 | var ret = []; 486 | if(node) { 487 | if(node.hasChildNodes && node.hasChildNodes()){ 488 | var children = node.childNodes; 489 | for(var i=0; i 0) { 693 | var prev = iterable[i-1]; 694 | prev['nextSibling'] = child; 695 | } 696 | } 697 | } 698 | } 699 | return ret; 700 | } 701 | 702 | that.getNextSibling = function (node) { 703 | if (node) { 704 | if(node !== that.getRoot()) { 705 | if (node['nextSibling']) { return node['nextSibling'] }; 706 | } 707 | } 708 | return null; 709 | } 710 | 711 | that.getParent = function (node) { 712 | if (node) { 713 | if(node !== that.getRoot()) { 714 | if (node['parent']) { return node['parent'] }; 715 | } 716 | } 717 | return null; 718 | } 719 | 720 | that.hasChildren = function (node) { 721 | if (node) { 722 | var iterable = (node === that.getRoot())? node: 723 | (node ['items'])? node ['items']: null; 724 | if (iterable) { 725 | return iterable.length && iterable.length > 0; 726 | } 727 | return false; 728 | } 729 | return false; 730 | } 731 | 732 | that.addChildAt = function (node, newChild, index) { 733 | if (node && newChild) { 734 | var children = that.getChildren (node) || (function() { 735 | node['items'] = []; 736 | return node['items']; 737 | })(); 738 | index = Math.min(Math.max(0, index), children.length); 739 | children.splice (index, 0, newChild); 740 | if (index > 0) { 741 | children [index-1]['nextSibling'] = children [index] 742 | }; 743 | if (index < children.length-1) { 744 | children[index]['nextSibling'] = children [index]+1 745 | }; 746 | node['items'] = children; 747 | } 748 | } 749 | 750 | that.removeChildAt = function (node, index) { 751 | if (node) { 752 | var children = that.getChildren (node) || (function() { 753 | node['items'] = []; 754 | return node['items']; 755 | })(); 756 | index = Math.min(Math.max(0, index), children.length); 757 | var removed = children [index]; 758 | children.splice (index, 1); 759 | if(index > 0 && index < children.length) { 760 | children [index-1]['nextSibling'] = children [index]; 761 | } 762 | node['items'] = children; 763 | return removed; 764 | } 765 | return null; 766 | } 767 | 768 | that.createNode = function (properties) { 769 | var node = {}; 770 | for (var p in properties) { 771 | that.setProperty (node, p, properties[p]) 772 | }; 773 | if (that.getProperty (node, 'id') == null) { 774 | that.setProperty (node, 'id', that.generateUID()); 775 | } 776 | return node; 777 | } 778 | 779 | that.getProperty = function (node, propName) { 780 | if (node) { return registry.proof(propName, node[propName]) }; 781 | return null; 782 | } 783 | 784 | that.setProperty = function (node, propName, propValue) { 785 | if (node) { 786 | node[propName] = registry.proof(propName, propValue); 787 | } 788 | } 789 | 790 | this.$JSONDataSource.apply (this, arguments); 791 | } 792 | 793 | /** 794 | * CLASS Builder 795 | * @private 796 | * @class 797 | */ 798 | function Builder() { 799 | 800 | var ds, root = null; 801 | 802 | function createDataSource (source, type) { 803 | var ret = null; 804 | if (type == Builder.XML) { ret = new XMLDataSource ( source ) }; 805 | if (type == Builder.JSON) { ret = new JSONDataSource( source )}; 806 | return ret; 807 | } 808 | 809 | function buildMenu() { 810 | var w = new Walker(ds, buildItem); 811 | w.walk (); 812 | } 813 | 814 | function buildItem (item) { 815 | 816 | // Get & parse info about the item to be built: 817 | var summary = ds.getSummary (item); 818 | var isFirstLevel = (!ds.getParent(item)); 819 | var isItemDisabled = (!summary[FieldsRegistry.ENABLED]); 820 | var hasChildren = ds.hasChildren(item); 821 | var isItemSeparator = (summary [FieldsRegistry.TYPE] == 822 | FieldsRegistry.SEPARATOR); 823 | var isItemAToggle = (summary [FieldsRegistry.TYPE] == 824 | FieldsRegistry.CHECK); 825 | 826 | // Build the NativeMenuItem to represent this item: 827 | var ret = parseLabelForMnemonic (summary [FieldsRegistry.LABEL]); 828 | var nmi = new NativeMenuItem ( ret[0], isItemSeparator ); 829 | 830 | 831 | // Attach features for this item: 832 | var parsedMnemonicIndex = ret[1]; 833 | if (parsedMnemonicIndex >= 0) { 834 | summary [FieldsRegistry.MNEMONIC_INDEX] = parsedMnemonicIndex; 835 | }; 836 | var mnemonicIndex = summary [FieldsRegistry.MNEMONIC_INDEX]; 837 | if (mnemonicIndex != -1) { nmi.mnemonicIndex = mnemonicIndex }; 838 | if (isItemAToggle) { 839 | var toggler = function (event) { 840 | var val = !ds.getProperty (item, 841 | FieldsRegistry.TOGGLED); 842 | ds.setProperty (item, FieldsRegistry.TOGGLED, val); 843 | nmi.checked = val; 844 | } 845 | nmi.addEventListener (SELECT, toggler); 846 | nmi.checked = summary [FieldsRegistry.TOGGLED]; 847 | } 848 | if (summary [FieldsRegistry.ON_SELECT]) { 849 | var f = function (event) { 850 | var target = event.target; 851 | summary [FieldsRegistry.ON_SELECT].call ( 852 | window, event, summary 853 | ); 854 | } 855 | nmi.addEventListener (SELECT, f); 856 | } 857 | attachKeyEquivalentHandler (nmi, summary); 858 | if ( isItemDisabled ) { nmi.enabled = false }; 859 | 860 | // Attach our item within the menu structure: 861 | item['_widget_'] = nmi; 862 | if (hasChildren) { nmi.submenu = new NativeMenu() }; 863 | var data = nmi.data || (nmi.data = {}); 864 | data['item'] = item; 865 | var parMnu = null; 866 | var parItem = ds.getParent(item); 867 | if (parItem) { 868 | var parWidget = parItem['_widget_']; 869 | parMnu = parWidget.submenu; 870 | if (!parMnu) { return }; 871 | } else { 872 | parMnu = root || ( root = new NativeMenu() ); 873 | } 874 | parMnu.addItem(nmi); 875 | } 876 | 877 | function qReplace (tStr, searchStr , replaceStr) { 878 | var index; 879 | while ((index = tStr.indexOf (searchStr)) >= 0) { 880 | var arr = tStr.split(''); 881 | arr.splice (index, searchStr.length, 882 | replaceStr); 883 | tStr = arr.join(''); 884 | } 885 | return tStr; 886 | } 887 | 888 | function parseLabelForMnemonic (label) { 889 | var l = label; 890 | if (l) { 891 | l = qReplace(l, '__', '[UNDERSCORE]'); 892 | l = qReplace(l, '_', '[MNEMONIC]'); 893 | l = qReplace(l, '[UNDERSCORE]', '_'); 894 | var mi = l.indexOf ('[MNEMONIC]'); 895 | l = qReplace(l, '[MNEMONIC]', ''); 896 | if (mi >= 0) { return [l, mi] }; 897 | } 898 | return [l, -1]; 899 | } 900 | 901 | function attachKeyEquivalentHandler (nativeItem, summary) { 902 | if (summary[FieldsRegistry.DEFAULT_KEY]) { 903 | // Linux implementation needs this check: 904 | var def = nativeItem.keyEquivalentModifiers && 905 | nativeItem.keyEquivalentModifiers[0]? 906 | nativeItem.keyEquivalentModifiers[0] : null; 907 | if (def && typeof def != "undefined") { 908 | if (summary[FieldsRegistry.CTRL_KEY] === false) { 909 | if (def == KEYBOARD.CONTROL) { def = null }; 910 | } 911 | if (summary[FieldsRegistry.CMD_KEY] === false) { 912 | if (def == KEYBOARD.COMMAND) { def = null }; 913 | } 914 | } 915 | } 916 | var key; 917 | if (key = summary[FieldsRegistry.KEY_EQUIVALENT]) { 918 | var mods = []; 919 | if (def) { mods.push(def) }; 920 | if (summary[FieldsRegistry.CTRL_KEY]) { 921 | mods.push (KEYBOARD.CONTROL); 922 | } 923 | if (summary[FieldsRegistry.CMD_KEY]) { 924 | mods.push (KEYBOARD.COMMAND); 925 | } 926 | if (summary[FieldsRegistry.ALT_KEY]) { 927 | mods.push (KEYBOARD.ALTERNATE); 928 | } 929 | key = (summary[FieldsRegistry.SHIFT_KEY])? 930 | key.toUpperCase() : key.toLowerCase(); 931 | nativeItem.keyEquivalent = key; 932 | nativeItem.keyEquivalentModifiers = mods; 933 | } 934 | } 935 | 936 | this.loadData = function (source, type) { 937 | if (source) { ds = createDataSource (source, type) } 938 | else { throw new Error([ 939 | "Cannot create menu. ", 940 | "Provided data source is null" 941 | ].join('')) } 942 | } 943 | 944 | this.build = function() { 945 | if(ds) {buildMenu()}; 946 | return root; 947 | } 948 | } 949 | Builder.XML = 0x10; 950 | Builder.JSON = 0x20; 951 | 952 | /** 953 | * CLASS NIConnector 954 | * @private 955 | * @class 956 | */ 957 | function NIConnector () { 958 | 959 | var that = this; 960 | 961 | var LAST = 0x1; 962 | var BEFORE_LAST = 0x2; 963 | 964 | var ni; 965 | var nativeMenu; 966 | var overwrite; 967 | var allSet; 968 | var isMac; 969 | 970 | function $NIConnector (oNi, oNewNativeMenu, bOverwriteExisting) { 971 | if (oNi && oNewNativeMenu) { 972 | allSet = true; 973 | ni = oNi; 974 | nativeMenu = oNewNativeMenu; 975 | overwrite = bOverwriteExisting; 976 | isMac = currentOS.indexOf('Mac') >= 0; 977 | if (typeof NIConnector.defaultMenu == "undefined") { 978 | var app = NativeApplication.nativeApplication; 979 | NIConnector.defaultMenu = app.menu; 980 | } 981 | } 982 | } 983 | 984 | 985 | function isDefaultApplicationMenu () { 986 | var app = NativeApplication.nativeApplication; 987 | return (app.menu == NIConnector.defaultMenu); 988 | } 989 | 990 | function purge () { 991 | while (ni.menu.numItems) { ni.menu.removeItemAt (0) } 992 | } 993 | 994 | function add ( style ) { 995 | if (!ni.menu) { 996 | replace(); 997 | return; 998 | } 999 | var addFunction = (style == LAST)? 1000 | ni.menu.addItem : function (item) { 1001 | ni.menu.addItemAt (item, ni.menu.numItems-1); 1002 | } 1003 | var item; 1004 | while (nativeMenu.numItems && (item = nativeMenu.removeItemAt(0))) { 1005 | if(isMac && !item.submenu) { continue }; 1006 | addFunction.call (that, item); 1007 | } 1008 | } 1009 | 1010 | function replace () { 1011 | ni.menu = nativeMenu; 1012 | } 1013 | 1014 | this.doConnect = function () { 1015 | if (allSet) { 1016 | if (overwrite) { 1017 | if (isMac) { 1018 | purge (); 1019 | add (LAST); 1020 | } 1021 | else { replace() }; 1022 | } 1023 | else { 1024 | if (isMac) { 1025 | if (isDefaultApplicationMenu()) { add (BEFORE_LAST) } 1026 | else { add (LAST) }; 1027 | } else { add (LAST) }; 1028 | } 1029 | } 1030 | } 1031 | 1032 | $NIConnector.apply (this, arguments); 1033 | } 1034 | NIConnector.defaultMenu; 1035 | 1036 | 1037 | /** 1038 | * CLASS Shell 1039 | * @private 1040 | * @class 1041 | */ 1042 | function Shell() { 1043 | 1044 | function $Shell(){} 1045 | 1046 | var that = this; 1047 | 1048 | var CONTEXT_MENU = 'contextmenu'; 1049 | var app = NativeApplication.nativeApplication; 1050 | 1051 | var uidSeed = 0; 1052 | var DEFAULT_ID = "DEFAULT_ID"; 1053 | 1054 | var isMac = currentOS.indexOf('Mac') >= 0; 1055 | 1056 | var isBitmapData = function(obj) { 1057 | return obj && 1058 | obj.constructor && 1059 | obj.constructor === (new BitmapData (1, 1)); 1060 | } 1061 | 1062 | var resolveDomEl = function (obj) { 1063 | var ret = null; 1064 | if (obj) { 1065 | if (typeof obj == 'object' && obj.nodeType == 1) { ret = obj }; 1066 | if (typeof obj == 'string') { 1067 | var el; 1068 | if (el = document.getElementById(obj)) { ret = el }; 1069 | } 1070 | } 1071 | return ret; 1072 | } 1073 | 1074 | var checkUserIcon = function (obj) { 1075 | var icon = app.icon; 1076 | return icon.bitmaps.length > 0; 1077 | } 1078 | 1079 | var getIcons = function (userIcons) { 1080 | var ret = []; 1081 | var entries = []; 1082 | if (userIcons && userIcons.length) { 1083 | entries = userIcons; 1084 | } else { 1085 | var p = new DOMParser(); 1086 | var descr = String(app.applicationDescriptor); 1087 | var descrDoc = p.parseFromString(descr, "text/xml"); 1088 | var appEl = descrDoc.getElementsByTagName('application')[0]; 1089 | var iconEl = appEl.getElementsByTagName('icon')[0]; 1090 | if (iconEl) { 1091 | var iconEntries = iconEl.getElementsByTagName('*'); 1092 | for (var i=0; i 0; 1188 | if (!haveDefaultIcons) { 1189 | if (!isMac) { 1190 | throw (new Error([ 1191 | "Cannot set the icon menu.", 1192 | "On operating systems that do not provide a default", 1193 | "tray icon, you must specify one before calling", 1194 | "setAsIconMenu().", 1195 | "Alternativelly, you can specify default icons in the", 1196 | "application's XML descriptor." 1197 | ].join('\n'))); 1198 | } 1199 | } 1200 | var doAttach = function(bitmaps){ 1201 | setBitmaps (bitmaps); 1202 | app.icon.menu = menu; 1203 | } 1204 | if (defaultIcons) { 1205 | loadDefaultBitmaps(defaultIcons, doAttach); 1206 | } 1207 | } 1208 | } 1209 | 1210 | this.link = function (oMenu, style, target, icons) { 1211 | if (Shell.MENU & style) { 1212 | var bOverwrite = style & Shell.OVERWRITE; 1213 | return linkMenu(oMenu, bOverwrite); 1214 | } 1215 | if (Shell.CONTEXT & style) {return linkContextMenu(oMenu, target)}; 1216 | if (Shell.ICON & style) { return linkIconMenu(oMenu, icons) }; 1217 | } 1218 | 1219 | $Shell.apply (this, arguments); 1220 | } 1221 | Shell.UNSPECIFIED = -1; 1222 | Shell.MENU = 1; 1223 | Shell.CONTEXT = 2; 1224 | Shell.ICON = 4; 1225 | Shell.OVERWRITE = 8; 1226 | 1227 | Shell.resolve = function (pathOrFile) { 1228 | var file = null; 1229 | try { 1230 | file = File(pathOrFile); 1231 | } catch(e) { 1232 | file = File.applicationDirectory.resolvePath (pathOrFile); 1233 | if (!file.exists) { 1234 | try { 1235 | file = new File (pathOrFile); 1236 | } catch(e) { 1237 | // must be a path, both 'relative' AND 'non-existing'. 1238 | } 1239 | } 1240 | } 1241 | return file; 1242 | } 1243 | 1244 | /** 1245 | * CLASS Walker 1246 | * @class 1247 | * @private 1248 | */ 1249 | function Walker() { 1250 | var t, c, currentItem, allSet, item; 1251 | 1252 | function $Walker (target, callback) { 1253 | if (target && target instanceof DataSource) { 1254 | t = target; 1255 | } 1256 | if (callback && typeof callback == "function") { 1257 | c = callback; 1258 | } 1259 | if (t && c) { allSet = true }; 1260 | } 1261 | 1262 | function getNearestAncestorSibling(node) { 1263 | while (node) { 1264 | node = t.getParent(node); 1265 | if(node) { 1266 | var s = t.getNextSibling(node); 1267 | if (s) { return s }; 1268 | } 1269 | } 1270 | return null; 1271 | } 1272 | 1273 | function getFirstChildOfRoot() { 1274 | return t.getChildren(t.getRoot())[0] || null; 1275 | } 1276 | 1277 | function doTraverse() { 1278 | if (allSet) { 1279 | while (item = getNext()) { c.call (window, item) }; 1280 | 1281 | } else { 1282 | throw (new Error([ 1283 | 'Cannot traverse data tree.', 1284 | 'Please check the arguments you provided to the Walker class.', 1285 | ].join('\n'))); 1286 | } 1287 | } 1288 | 1289 | function getNext() { 1290 | if (currentItem === null) { return null }; 1291 | 1292 | if (typeof currentItem == 'undefined') { 1293 | currentItem = getFirstChildOfRoot(); 1294 | } 1295 | 1296 | if (t.hasChildren(currentItem)) { 1297 | var parentNode = currentItem; 1298 | currentItem = t.getChildren(currentItem)[0]; 1299 | return parentNode; 1300 | } 1301 | 1302 | if(t.getNextSibling(currentItem)) { 1303 | var current = currentItem; 1304 | currentItem = t.getNextSibling(currentItem); 1305 | return current; 1306 | } 1307 | 1308 | var ci = currentItem; 1309 | currentItem = getNearestAncestorSibling(currentItem); 1310 | return ci; 1311 | } 1312 | 1313 | this.walk = function (callback) { 1314 | doTraverse(); 1315 | if (typeof callback == "function") { callback.call (this) }; 1316 | } 1317 | 1318 | $Walker.apply (this, arguments); 1319 | } 1320 | 1321 | constructor.apply (this, arguments); 1322 | })(); --------------------------------------------------------------------------------