<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.appstudio.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mashiane</id>
	<title>NSB App Studio - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.appstudio.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mashiane"/>
	<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/Special:Contributions/Mashiane"/>
	<updated>2026-07-13T09:45:54Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Distributing_your_App&amp;diff=6117</id>
		<title>Distributing your App</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Distributing_your_App&amp;diff=6117"/>
		<updated>2014-06-16T07:03:51Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* A server of your own */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apps created with AppStudio can be installed and run by anyone who has an internet connection. Once they are running on a device, apps can be saved locally on the device and will be available even when there is no internet connection available.&lt;br /&gt;
&lt;br /&gt;
AppStudio web apps are not sold in Apple&#039;s App Store. However, they can be used on any iOS device, jailbroken or not, without going through any review by Apple. They are normal HTML5 apps, and as Steve Jobs has said, &amp;quot;HTML5 -- it&#039;s a completely open, uncontrolled platform. And we fully support it.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you want to sell your app, there are a few strategies.&lt;br /&gt;
&lt;br /&gt;
# Set up a web site which requires a sign on code to access the download info. Give the sign on code to people who have paid.&lt;br /&gt;
# Have a registration code input field in your program. The correct code has to be entered the first time the program is run.&lt;br /&gt;
# Use a third party web app store. It will handle billing and downloads, and give you a percentage of the revenue. Samples of such stores are OpenAppMkt and the Chrome Web Store.&lt;br /&gt;
# Make your app into a native app [[Submitting_to_the_iOS_App_Store|using PhoneGap and submit it to Apple]]. There is an option on the Run menu for this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Distributing Web Apps ==&lt;br /&gt;
&lt;br /&gt;
For a good background into how this all works, there is a great chapter in Mark Pilgrims&#039;s book Dive Into HTML5. The chapter on Offline Apps is here.&lt;br /&gt;
&lt;br /&gt;
Your app needs to be deployed to a web server so that it can be loaded and run. There are several choices for web servers you can use.&lt;br /&gt;
&lt;br /&gt;
=== AppStudio test server (nsbapp.com) ===&lt;br /&gt;
This is the default and will work without any extra setup. It is intended for testing only: do not rely on the app being available there forever. No PHP. If you are using the demo, you can only deploy to the test server.&lt;br /&gt;
&lt;br /&gt;
=== DropBox Public folder ===&lt;br /&gt;
Apps deploy and run well using your DropBox Public folder. Just give people the public link to the index.html file for your app. No PHP. To use it, select &amp;quot;Deploy to a local or DropBox public folder&amp;quot; in Deploy Options and put the path to your Dropbox folder in Local Path. (Something like c:\users\billg\Documents\My DropBox\Public)&lt;br /&gt;
&lt;br /&gt;
If you have a newer DropBox account, you may not have a Public folder.  You can add one to your account by logging into the DropBox website and then clicking on the following link: https://www.dropbox.com/enable_public_folder&lt;br /&gt;
&lt;br /&gt;
=== Local test server ===&lt;br /&gt;
You can set up a local server on your own system. This is good for testing, but not usually very good for outside users who want to run your app. To use it, select &amp;quot;Deploy to a local or DropBox public folder&amp;quot; in Deploy Options and put the appropriate path into Local Path.&lt;br /&gt;
&lt;br /&gt;
=== A server of your own ===&lt;br /&gt;
This is the most powerful and permanent solution. It involves getting a website of your own with the appropriate settings. Select &amp;quot;Deploy to local server&amp;quot; or &amp;quot;Deploy to FTP Server&amp;quot; in Deploy options and fill in the Server, Path, Username and password.&lt;br /&gt;
&lt;br /&gt;
There are a variety of own servers that you can use, for example Microsoft WebMatrix (IIS), Apache, EngineX, GWS to mention a few.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Using Microsoft WebMatrix&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Set Up WebMatrix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. Install Microsoft WebPlatform Installer&lt;br /&gt;
&lt;br /&gt;
2. Install WebMatrix using WPI&lt;br /&gt;
&lt;br /&gt;
3. Install PHP from using WPI&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Setting Up IIS Express to serve the Offline.appcache&#039;&#039;&lt;br /&gt;
You will do this once fortunately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Open the command prompt (run as administrator), and change the directory to where your IIS Express folder is,&lt;br /&gt;
this might be &amp;quot;c:\Program Files (x86)\IIS Express&amp;quot;, in your DOS prompt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Type the following:&lt;br /&gt;
&lt;br /&gt;
cd &amp;quot;Program Files (x86)&amp;quot; and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
cd &amp;quot;IIS Express&amp;quot; and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
&lt;br /&gt;
Then type the following&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;appcmd set config /section:staticContent /+[fileExtension=&#039;.appcache&#039;, mimeType=&#039;text/cache-manifest&#039;]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
&lt;br /&gt;
Usually WebMatrix stores all your sites on the &amp;quot;My Documents\My Web Sites&amp;quot; folder of your profile.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Set Up AppStudio to deploy to WebMatrix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4. In AppStudio, go to Tools &amp;gt; Preferences of your project&lt;br /&gt;
&lt;br /&gt;
5. Select Deploy to local server&lt;br /&gt;
&lt;br /&gt;
6. On Local Path, select Browse and select My Documents\My Web Sites&lt;br /&gt;
&lt;br /&gt;
7. Click Ok&lt;br /&gt;
&lt;br /&gt;
8. On the Run Menu, ensure you are in Deploy to local server&lt;br /&gt;
&lt;br /&gt;
9. Run your application, a prompt should pop up asking if you want to visit your site, click No. A folder will be created with your application files under My Documents\My Web Sites using your NSB project id.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SetUp Your Site to run PHP (ability to serve ajax)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Now, back to WebMatrix&lt;br /&gt;
&lt;br /&gt;
11. Start WebMatrix&lt;br /&gt;
&lt;br /&gt;
12. Click My Sites, if your site is not listed, select See All My Sites&lt;br /&gt;
&lt;br /&gt;
13. Select your site from the list&lt;br /&gt;
&lt;br /&gt;
14. Select the Site tab and then select Settings,&lt;br /&gt;
&lt;br /&gt;
15. Select None as .Net Framework&lt;br /&gt;
&lt;br /&gt;
16. On PHP settings, select Enable PHP and select the version you want of PHP&lt;br /&gt;
&lt;br /&gt;
17. Restart your site&lt;br /&gt;
&lt;br /&gt;
18. Select Run and select the browser that you want&lt;br /&gt;
&lt;br /&gt;
19. Test your site if all runs well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because a folder has already been created using your App id from NSBApp, you can also select Open &amp;gt; Folder in WebMatrix to open your site. With PHP installed, all your Ajax calls made within your NSBApp will execute well and you can test your application.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Testing your Mobile Application with MITE: 2200 emulated smartphones &amp;amp; tablets&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Before distributing mobile apps, you might want to test their performance and their delivery on &amp;quot;virtual&amp;quot; devices. Whilst Microsoft WebMatrix has functionality to install and test your mobile site using virtual packs for devices, there is also MITE, available at this website link, http://www.keynote.com/solutions/monitoring/mobile-web-monitoring-scripting-tool.&lt;br /&gt;
&lt;br /&gt;
== Getting your project ready ==&lt;br /&gt;
&lt;br /&gt;
An important thing to remember is that you need to keep your app on the server, even after it is deployed to a device. When an app starts, it attempts to contact its original download location to see if there is an update. If there is no internet connection, the app continues normally. But if there is a connection and the app cannot be found on the server, the app is marked obsolete and is cleared from the device. The nsbapp.com server clears all projects that have not been used for a while, so it is not a good place to permanently host your apps.&lt;br /&gt;
&lt;br /&gt;
When you deploy your app, it is transferred using passive ftp to your site. The ftp account information and directory are set in Deploy Settings. You may need to narrow the port range for passive ftp.&lt;br /&gt;
&lt;br /&gt;
=== Setting up your files ===&lt;br /&gt;
&lt;br /&gt;
There are a few files which need to be present in your project&#039;s directory for deployment. The Deploy option on the Run menu makes this easy: the files and folder are copied into your directory automatically.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;myProject.htm&#039;&#039;	&lt;br /&gt;
| Your app. This is created by the IDE: the actual name of the file is set in the IDE. This needs to be a valid UNIX filename - no spaces or special characters. After being copied to the server, it is renamed index.html.&lt;br /&gt;
|-&lt;br /&gt;
| LauncherIcon.png	&lt;br /&gt;
| The icon for the app, set in Project Properties. This has to be in .png format, and be 114x114 pixels in size. If you don&#039;t supply a filename of your own, a default file will be used. Important! Do not change the image (or any file) in the nsb folder. &lt;br /&gt;
|-&lt;br /&gt;
| SplashScreen.png	&lt;br /&gt;
| Optional. Not supported on all devices. Set in Project Properties. This image is displayed when the app is started from the Home screen on the device. The image should be in .png format and be exactly 320x460 (1004x768 on iPad). If you don&#039;t supply a filename of your own, a default file will be used. If you save your app to the home screen, you will need to delete and resave it t if you want to change the splash screen. Important! Do not change the image (or any file) in the nsb folder. &lt;br /&gt;
|-&lt;br /&gt;
| /nsb/	&lt;br /&gt;
| Required. This directory contains all the files that AppStudio itself needs at runtime. Do not make any changes to the contents of this directory.&lt;br /&gt;
|-&lt;br /&gt;
| OfflineApp.appcache	&lt;br /&gt;
| This contains a list of files to be included. It is created automatically at deploy time with filenames the IDE knows about, plus any files listed in the project&#039;s manifest property. Older apps may use the suffix .manifest, but .appcache is recommended (and, in the case of DropBox, required.) See &amp;quot;The Manifest File&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| images and js files	&lt;br /&gt;
|Any images and additional JavaScript (.js) libraries your app uses. Images can be anything that a browser can display: .gif, .jpg, .bmp, .png and more. Filenames should be good UNIX names: no spaces or slashes.&lt;br /&gt;
|-&lt;br /&gt;
|databases	&lt;br /&gt;
|SQLite databases can be included with your app. Simply put the name of the database in your manifest. AppStudio will take care of encoding the data and the schema and deploying it. When the app is loaded on the device, the database will be automatically reconstituted and will be usable right away.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Including Images with your project made simple ===&lt;br /&gt;
&lt;br /&gt;
# Put the images in your project folder. It&#039;s easiest to put them in a folder called images.&lt;br /&gt;
# In the manifest property, put &#039;images&#039;. Then all the images in that folder will be deployed with your app.&lt;br /&gt;
# In your app, refer to the images by the simple pathname:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   images/myImage1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Manifest File ===&lt;br /&gt;
&lt;br /&gt;
The Manifest file is a file in your project directory which contains a list of all the files in your app. This file is created automatically by AppStudio. You can maintain its contents in the IDE: it is in the top level of the Project Explorer, in the property Manifest. If you want your app to run in offline mode, you need to add the names of any images, folders or other files you app requires. These files must be located in the project&#039;s directory.&lt;br /&gt;
&lt;br /&gt;
Make sure your web server serves up .appcache files with the MIME type text/cache-manifest, or else this won&#039;t work. For more information on doing this, see &amp;quot;Setting up your server for manifest files&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Here is a sample manifest property:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mario.jpg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The manifest property should have a list of file names, one name per line. Folder names can also be included: they will automatically be expanded recursively. Subfolders are allowed.&lt;br /&gt;
You can put most types of files that HTML can use into it. The app file, icons, background and splash screen are automatically included in the application cache. You do not need to add them to the manifest file. Remember add your image files!&lt;br /&gt;
&lt;br /&gt;
To add an SQLite database, simply add its name to the manifest. An SQLImport() function will be automatically be invoked when you start your app to load the database the first time. If you want to use some of the options of [[SqlImport]], use the same format as that function:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customers.db,DB,loadComplete,NSB.overwriteAlways&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The manifest file can also be used to deliver updates to the files your app uses.&lt;br /&gt;
&lt;br /&gt;
When your app starts, it checks with the server (if available) and compares the manifest files to the one it last downloaded. If it has changed, an update is triggered. All the files in the new manifest are download and the application is restarted.&lt;br /&gt;
&lt;br /&gt;
You can force an update to your app at any time by executing the following statement:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 window.applicationCache.update()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is useful if a file you are reading from a remote site may have changed. In this case, the manifest file will not have been updated.&lt;br /&gt;
&lt;br /&gt;
=== Installing your App on a device ===&lt;br /&gt;
&lt;br /&gt;
If you have everything set up, your app will actually run your device right after you deploy. Go into your browser (Safari on iOS), and enter the URL for your app.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  http://www.nsbapp.com/myProject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You&#039;re running as an online app right now. Its appearance will be like a web page. But if you add it to the Home Screen, an icon will be created in the Launcher and the app will look like you intended and not part of the browser.&lt;br /&gt;
&lt;br /&gt;
To do this in iOS, tap on the plus (+) sign at the bottom of mobile Safari and choose &amp;quot;Add to Home Screen&amp;quot;. The app is now installed as an offline app, no different than any other app in the Home Screen.&lt;br /&gt;
&lt;br /&gt;
On Android, it&#039;s a little more complicated. Up till Android 4, the browser was call Android Browser and used a similar process to add the the Home screen. In Android 4, the Mobile Chrome browser was introduced. On some devices, usually those branded as Google, only Mobile Chrome is available. Mobile Chrome is not complete: it is still missing some cosmetic features. See https://code.google.com/p/chromium/issues/list?can=2&amp;amp;q=OS:Android&amp;amp;sort=-stars&amp;amp;colspec=ID%20Pri%20Mstone%20ReleaseBlock%20Area%20Feature%20Status%20Owner%20Summary%20Stars&lt;br /&gt;
&lt;br /&gt;
== Setting up your server for manifest files (Apache) ==&lt;br /&gt;
&lt;br /&gt;
If you are going to distribute your app from your own server, you will have to check if it is serving the OfflineApp.appcache (or .manifest) file with the correct MIME type. To test whether your server has the correct settings, use Check Deployment in the Run menu.&lt;br /&gt;
&lt;br /&gt;
=== Modify mime.types ===&lt;br /&gt;
&lt;br /&gt;
The first method to correct the MIME type is to modify the mime.types file. Here is where you will find it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;IfModule mime_module&amp;gt;&lt;br /&gt;
    #&lt;br /&gt;
    # TypesConfig points to the file containing the list of mappings from&lt;br /&gt;
    # filename extension to MIME-type.&lt;br /&gt;
    #&lt;br /&gt;
    TypesConfig /private/etc/apache2/mime.types&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your server is running Apache (most likely), you need to edit this file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  /user/local/apache2/conf/mime.types&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Add this line to the end:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text/cache-manifest appcache manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You will need to restart Apache so the settings take effect. Could be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  restart_apache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
from the shell.&lt;br /&gt;
&lt;br /&gt;
What&#039;s happening here is that the server needs to return the cache file back to you with the proper content type set. If you don&#039;t do this, the file will probably come back as &#039;text&#039;. If set properly, it will come back with a type of &#039;cache-manifest&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Use the .htaccess file ===&lt;br /&gt;
&lt;br /&gt;
If your webserver is hosted by an ISP you will may not be able to edit the &amp;quot;mime.types&amp;quot; file (server administrators are understandably reluctant to allow just anyone to modify their server&#039;s configuration!) If this is the case, you can usually provide a configuration file that will apply only to your personal server area. This file is named &amp;quot;.htaccess&amp;quot;, and is sometimes used to control password access to portions of your website.&lt;br /&gt;
&lt;br /&gt;
In the root of your website directory, if it doesn&#039;t already exist create the .htaccess file and include the line &amp;quot;AddType text/cache-manifest .manifest&amp;quot; (omit the quotes). The .htaccess file will now specify the new manifest MIME type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the minimum .htaccess file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  AddType text/cache-manifest .appcache &lt;br /&gt;
  AddType text/cache-manifest .manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The .htaccess file is used by Apache servers, and by some others as well. The Apache server may, as an option, ignore .htaccess files, so this technique may not work.&lt;br /&gt;
&lt;br /&gt;
For more information, see http://httpd.apache.org/docs/current/howto/htaccess.html and http://en.wikipedia.org/wiki/Htaccess .&lt;br /&gt;
&lt;br /&gt;
(with contributions from Paul Elliott)&lt;br /&gt;
&lt;br /&gt;
== Setting up your server for manifest files (IIS) ==&lt;br /&gt;
&lt;br /&gt;
If you are going to distribute your app from your own server, you will have to check if it is serving the OfflineApp.appcache file with the correct MIME type. To test what mime type a document is being returned as, use http://web-sniffer.net. Enter the url to your manifest file: for example, http://www.nsbapp.com/myProject/OfflineApp.appcache. The result will be displayed in &amp;quot;Content-Type&amp;quot;: it should be &#039;text/cache-manifest&#039;. If it is not, you&#039;ll need to change the setting in IIS. Here is where to look for it:&lt;br /&gt;
&lt;br /&gt;
[[File:TN05.01.png]]&lt;br /&gt;
&lt;br /&gt;
You will also need to add index.html to the list of names used by the default context page as follows, if it is not there already.&lt;br /&gt;
&lt;br /&gt;
[[File:TN05.02.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;with contributions from Tony O&#039;Brian&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Here are the contents of the working web.config file which resides in the website route directory on a Hostgator Windows server:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;configuration&amp;gt;&lt;br /&gt;
    &amp;lt;system.webServer&amp;gt;&lt;br /&gt;
        &amp;lt;staticContent&amp;gt;&lt;br /&gt;
            &amp;lt;remove fileExtension=&amp;quot;.appcache&amp;quot; /&amp;gt;&lt;br /&gt;
            &amp;lt;mimeMap fileExtension=&amp;quot;.appcache&amp;quot; mimeType=&amp;quot;text/cache-manifest&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;/staticContent&amp;gt;&lt;br /&gt;
    &amp;lt;/system.webServer&amp;gt;&lt;br /&gt;
&amp;lt;/configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;Contributed by Graham Pettican&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Setting up on a GoDaddy server ==&lt;br /&gt;
&lt;br /&gt;
Here is how to edit the MIME types on Apache: &lt;br /&gt;
http://support.godaddy.com/help/article/375/can-i-configure-mime-types-on-my-linux-hosting-account&lt;br /&gt;
&lt;br /&gt;
Here are the instructions for Windows hosting:  &lt;br /&gt;
http://support.godaddy.com/help/article/6286/modifying-or-adding-custom-mime-types-to-windows-hosting-accounts&lt;br /&gt;
&lt;br /&gt;
If your hosting is on a shared GoDaddy server runnimg Windows and IIS, it would seem that in order to set up your custom web.config file an upgrade to a virtual dedicated server is needed. Another, likely also less expensive approach, would be to switch to Linux hosting running Apache. Then you could create a .htaccess file to contain the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  AddType text/cache-manifest .appcache .manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Place this in the root of your site (in which case it affects the entire site) or in a directory where you will keep your apps (and in which case only that one directory will be affected)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;with contributions from Johann Vogel&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Distributing_your_App&amp;diff=6116</id>
		<title>Distributing your App</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Distributing_your_App&amp;diff=6116"/>
		<updated>2014-06-16T07:02:29Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* A server of your own */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apps created with AppStudio can be installed and run by anyone who has an internet connection. Once they are running on a device, apps can be saved locally on the device and will be available even when there is no internet connection available.&lt;br /&gt;
&lt;br /&gt;
AppStudio web apps are not sold in Apple&#039;s App Store. However, they can be used on any iOS device, jailbroken or not, without going through any review by Apple. They are normal HTML5 apps, and as Steve Jobs has said, &amp;quot;HTML5 -- it&#039;s a completely open, uncontrolled platform. And we fully support it.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you want to sell your app, there are a few strategies.&lt;br /&gt;
&lt;br /&gt;
# Set up a web site which requires a sign on code to access the download info. Give the sign on code to people who have paid.&lt;br /&gt;
# Have a registration code input field in your program. The correct code has to be entered the first time the program is run.&lt;br /&gt;
# Use a third party web app store. It will handle billing and downloads, and give you a percentage of the revenue. Samples of such stores are OpenAppMkt and the Chrome Web Store.&lt;br /&gt;
# Make your app into a native app [[Submitting_to_the_iOS_App_Store|using PhoneGap and submit it to Apple]]. There is an option on the Run menu for this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Distributing Web Apps ==&lt;br /&gt;
&lt;br /&gt;
For a good background into how this all works, there is a great chapter in Mark Pilgrims&#039;s book Dive Into HTML5. The chapter on Offline Apps is here.&lt;br /&gt;
&lt;br /&gt;
Your app needs to be deployed to a web server so that it can be loaded and run. There are several choices for web servers you can use.&lt;br /&gt;
&lt;br /&gt;
=== AppStudio test server (nsbapp.com) ===&lt;br /&gt;
This is the default and will work without any extra setup. It is intended for testing only: do not rely on the app being available there forever. No PHP. If you are using the demo, you can only deploy to the test server.&lt;br /&gt;
&lt;br /&gt;
=== DropBox Public folder ===&lt;br /&gt;
Apps deploy and run well using your DropBox Public folder. Just give people the public link to the index.html file for your app. No PHP. To use it, select &amp;quot;Deploy to a local or DropBox public folder&amp;quot; in Deploy Options and put the path to your Dropbox folder in Local Path. (Something like c:\users\billg\Documents\My DropBox\Public)&lt;br /&gt;
&lt;br /&gt;
If you have a newer DropBox account, you may not have a Public folder.  You can add one to your account by logging into the DropBox website and then clicking on the following link: https://www.dropbox.com/enable_public_folder&lt;br /&gt;
&lt;br /&gt;
=== Local test server ===&lt;br /&gt;
You can set up a local server on your own system. This is good for testing, but not usually very good for outside users who want to run your app. To use it, select &amp;quot;Deploy to a local or DropBox public folder&amp;quot; in Deploy Options and put the appropriate path into Local Path.&lt;br /&gt;
&lt;br /&gt;
=== A server of your own ===&lt;br /&gt;
This is the most powerful and permanent solution. It involves getting a website of your own with the appropriate settings. Select &amp;quot;Deploy to local server&amp;quot; or &amp;quot;Deploy to FTP Server&amp;quot; in Deploy options and fill in the Server, Path, Username and password.&lt;br /&gt;
&lt;br /&gt;
There are a variety of own servers that you can use, for example Microsoft WebMatrix (IIS), Apache, EngineX, GWS to mention a few.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Using Microsoft WebMatrix&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Set Up WebMatrix&#039;&#039;&lt;br /&gt;
1. Install Microsoft WebPlatform Installer&lt;br /&gt;
2. Install WebMatrix using WPI&lt;br /&gt;
3. Install PHP from using WPI&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Setting Up IIS Express to serve the Offline.appcache&#039;&#039;&lt;br /&gt;
You will do this once fortunately.&lt;br /&gt;
&lt;br /&gt;
Open the command prompt (run as administrator), and change the directory to where your IIS Express folder is,&lt;br /&gt;
this might be &amp;quot;c:\Program Files (x86)\IIS Express&amp;quot;, in your DOS prompt&lt;br /&gt;
&lt;br /&gt;
Type the following:&lt;br /&gt;
&lt;br /&gt;
cd &amp;quot;Program Files (x86)&amp;quot; and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
cd &amp;quot;IIS Express&amp;quot; and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
&lt;br /&gt;
Then type the following&lt;br /&gt;
&lt;br /&gt;
appcmd set config /section:staticContent /+[fileExtension=&#039;.appcache&#039;, mimeType=&#039;text/cache-manifest&#039;] and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
&lt;br /&gt;
Usually WebMatrix stores all your sites on the &amp;quot;My Documents\My Web Sites&amp;quot; folder of your profile.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Set Up AppStudio to deploy to WebMatrix&#039;&#039;&lt;br /&gt;
4. In AppStudio, go to Tools &amp;gt; Preferences of your project&lt;br /&gt;
5. Select Deploy to local server&lt;br /&gt;
6. On Local Path, select Browse and select My Documents\My Web Sites&lt;br /&gt;
7. Click Ok&lt;br /&gt;
8. On the Run Menu, ensure you are in Deploy to local server&lt;br /&gt;
9. Run your application, a prompt should pop up asking if you want to visit your site, click No. A folder will be created with your application files under My Documents\My Web Sites using your NSB project id.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SetUp Your Site to run PHP (ability to serve ajax)&#039;&#039;&lt;br /&gt;
Now, back to WebMatrix&lt;br /&gt;
&lt;br /&gt;
11. Start WebMatrix&lt;br /&gt;
&lt;br /&gt;
12. Click My Sites, if your site is not listed, select See All My Sites&lt;br /&gt;
&lt;br /&gt;
13. Select your site from the list&lt;br /&gt;
&lt;br /&gt;
14. Select the Site tab and then select Settings,&lt;br /&gt;
&lt;br /&gt;
15. Select None as .Net Framework&lt;br /&gt;
&lt;br /&gt;
16. On PHP settings, select Enable PHP and select the version you want of PHP&lt;br /&gt;
&lt;br /&gt;
17. Restart your site&lt;br /&gt;
&lt;br /&gt;
18. Select Run and select the browser that you want&lt;br /&gt;
&lt;br /&gt;
19. Test your site if all runs well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because a folder has already been created using your App id from NSBApp, you can also select Open &amp;gt; Folder in WebMatrix to open your site. With PHP installed, all your Ajax calls made within your NSBApp will execute well and you can test your application.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Testing your Mobile Application with MITE: 2200 emulated smartphones &amp;amp; tablets&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Before distributing mobile apps, you might want to test their performance and their delivery on &amp;quot;virtual&amp;quot; devices. Whilst Microsoft WebMatrix has functionality to install and test your mobile site using virtual packs for devices, there is also MITE, available at this website link, http://www.keynote.com/solutions/monitoring/mobile-web-monitoring-scripting-tool.&lt;br /&gt;
&lt;br /&gt;
== Getting your project ready ==&lt;br /&gt;
&lt;br /&gt;
An important thing to remember is that you need to keep your app on the server, even after it is deployed to a device. When an app starts, it attempts to contact its original download location to see if there is an update. If there is no internet connection, the app continues normally. But if there is a connection and the app cannot be found on the server, the app is marked obsolete and is cleared from the device. The nsbapp.com server clears all projects that have not been used for a while, so it is not a good place to permanently host your apps.&lt;br /&gt;
&lt;br /&gt;
When you deploy your app, it is transferred using passive ftp to your site. The ftp account information and directory are set in Deploy Settings. You may need to narrow the port range for passive ftp.&lt;br /&gt;
&lt;br /&gt;
=== Setting up your files ===&lt;br /&gt;
&lt;br /&gt;
There are a few files which need to be present in your project&#039;s directory for deployment. The Deploy option on the Run menu makes this easy: the files and folder are copied into your directory automatically.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;myProject.htm&#039;&#039;	&lt;br /&gt;
| Your app. This is created by the IDE: the actual name of the file is set in the IDE. This needs to be a valid UNIX filename - no spaces or special characters. After being copied to the server, it is renamed index.html.&lt;br /&gt;
|-&lt;br /&gt;
| LauncherIcon.png	&lt;br /&gt;
| The icon for the app, set in Project Properties. This has to be in .png format, and be 114x114 pixels in size. If you don&#039;t supply a filename of your own, a default file will be used. Important! Do not change the image (or any file) in the nsb folder. &lt;br /&gt;
|-&lt;br /&gt;
| SplashScreen.png	&lt;br /&gt;
| Optional. Not supported on all devices. Set in Project Properties. This image is displayed when the app is started from the Home screen on the device. The image should be in .png format and be exactly 320x460 (1004x768 on iPad). If you don&#039;t supply a filename of your own, a default file will be used. If you save your app to the home screen, you will need to delete and resave it t if you want to change the splash screen. Important! Do not change the image (or any file) in the nsb folder. &lt;br /&gt;
|-&lt;br /&gt;
| /nsb/	&lt;br /&gt;
| Required. This directory contains all the files that AppStudio itself needs at runtime. Do not make any changes to the contents of this directory.&lt;br /&gt;
|-&lt;br /&gt;
| OfflineApp.appcache	&lt;br /&gt;
| This contains a list of files to be included. It is created automatically at deploy time with filenames the IDE knows about, plus any files listed in the project&#039;s manifest property. Older apps may use the suffix .manifest, but .appcache is recommended (and, in the case of DropBox, required.) See &amp;quot;The Manifest File&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| images and js files	&lt;br /&gt;
|Any images and additional JavaScript (.js) libraries your app uses. Images can be anything that a browser can display: .gif, .jpg, .bmp, .png and more. Filenames should be good UNIX names: no spaces or slashes.&lt;br /&gt;
|-&lt;br /&gt;
|databases	&lt;br /&gt;
|SQLite databases can be included with your app. Simply put the name of the database in your manifest. AppStudio will take care of encoding the data and the schema and deploying it. When the app is loaded on the device, the database will be automatically reconstituted and will be usable right away.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Including Images with your project made simple ===&lt;br /&gt;
&lt;br /&gt;
# Put the images in your project folder. It&#039;s easiest to put them in a folder called images.&lt;br /&gt;
# In the manifest property, put &#039;images&#039;. Then all the images in that folder will be deployed with your app.&lt;br /&gt;
# In your app, refer to the images by the simple pathname:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   images/myImage1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Manifest File ===&lt;br /&gt;
&lt;br /&gt;
The Manifest file is a file in your project directory which contains a list of all the files in your app. This file is created automatically by AppStudio. You can maintain its contents in the IDE: it is in the top level of the Project Explorer, in the property Manifest. If you want your app to run in offline mode, you need to add the names of any images, folders or other files you app requires. These files must be located in the project&#039;s directory.&lt;br /&gt;
&lt;br /&gt;
Make sure your web server serves up .appcache files with the MIME type text/cache-manifest, or else this won&#039;t work. For more information on doing this, see &amp;quot;Setting up your server for manifest files&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Here is a sample manifest property:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mario.jpg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The manifest property should have a list of file names, one name per line. Folder names can also be included: they will automatically be expanded recursively. Subfolders are allowed.&lt;br /&gt;
You can put most types of files that HTML can use into it. The app file, icons, background and splash screen are automatically included in the application cache. You do not need to add them to the manifest file. Remember add your image files!&lt;br /&gt;
&lt;br /&gt;
To add an SQLite database, simply add its name to the manifest. An SQLImport() function will be automatically be invoked when you start your app to load the database the first time. If you want to use some of the options of [[SqlImport]], use the same format as that function:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customers.db,DB,loadComplete,NSB.overwriteAlways&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The manifest file can also be used to deliver updates to the files your app uses.&lt;br /&gt;
&lt;br /&gt;
When your app starts, it checks with the server (if available) and compares the manifest files to the one it last downloaded. If it has changed, an update is triggered. All the files in the new manifest are download and the application is restarted.&lt;br /&gt;
&lt;br /&gt;
You can force an update to your app at any time by executing the following statement:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 window.applicationCache.update()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is useful if a file you are reading from a remote site may have changed. In this case, the manifest file will not have been updated.&lt;br /&gt;
&lt;br /&gt;
=== Installing your App on a device ===&lt;br /&gt;
&lt;br /&gt;
If you have everything set up, your app will actually run your device right after you deploy. Go into your browser (Safari on iOS), and enter the URL for your app.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  http://www.nsbapp.com/myProject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You&#039;re running as an online app right now. Its appearance will be like a web page. But if you add it to the Home Screen, an icon will be created in the Launcher and the app will look like you intended and not part of the browser.&lt;br /&gt;
&lt;br /&gt;
To do this in iOS, tap on the plus (+) sign at the bottom of mobile Safari and choose &amp;quot;Add to Home Screen&amp;quot;. The app is now installed as an offline app, no different than any other app in the Home Screen.&lt;br /&gt;
&lt;br /&gt;
On Android, it&#039;s a little more complicated. Up till Android 4, the browser was call Android Browser and used a similar process to add the the Home screen. In Android 4, the Mobile Chrome browser was introduced. On some devices, usually those branded as Google, only Mobile Chrome is available. Mobile Chrome is not complete: it is still missing some cosmetic features. See https://code.google.com/p/chromium/issues/list?can=2&amp;amp;q=OS:Android&amp;amp;sort=-stars&amp;amp;colspec=ID%20Pri%20Mstone%20ReleaseBlock%20Area%20Feature%20Status%20Owner%20Summary%20Stars&lt;br /&gt;
&lt;br /&gt;
== Setting up your server for manifest files (Apache) ==&lt;br /&gt;
&lt;br /&gt;
If you are going to distribute your app from your own server, you will have to check if it is serving the OfflineApp.appcache (or .manifest) file with the correct MIME type. To test whether your server has the correct settings, use Check Deployment in the Run menu.&lt;br /&gt;
&lt;br /&gt;
=== Modify mime.types ===&lt;br /&gt;
&lt;br /&gt;
The first method to correct the MIME type is to modify the mime.types file. Here is where you will find it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;IfModule mime_module&amp;gt;&lt;br /&gt;
    #&lt;br /&gt;
    # TypesConfig points to the file containing the list of mappings from&lt;br /&gt;
    # filename extension to MIME-type.&lt;br /&gt;
    #&lt;br /&gt;
    TypesConfig /private/etc/apache2/mime.types&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your server is running Apache (most likely), you need to edit this file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  /user/local/apache2/conf/mime.types&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Add this line to the end:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text/cache-manifest appcache manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You will need to restart Apache so the settings take effect. Could be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  restart_apache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
from the shell.&lt;br /&gt;
&lt;br /&gt;
What&#039;s happening here is that the server needs to return the cache file back to you with the proper content type set. If you don&#039;t do this, the file will probably come back as &#039;text&#039;. If set properly, it will come back with a type of &#039;cache-manifest&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Use the .htaccess file ===&lt;br /&gt;
&lt;br /&gt;
If your webserver is hosted by an ISP you will may not be able to edit the &amp;quot;mime.types&amp;quot; file (server administrators are understandably reluctant to allow just anyone to modify their server&#039;s configuration!) If this is the case, you can usually provide a configuration file that will apply only to your personal server area. This file is named &amp;quot;.htaccess&amp;quot;, and is sometimes used to control password access to portions of your website.&lt;br /&gt;
&lt;br /&gt;
In the root of your website directory, if it doesn&#039;t already exist create the .htaccess file and include the line &amp;quot;AddType text/cache-manifest .manifest&amp;quot; (omit the quotes). The .htaccess file will now specify the new manifest MIME type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the minimum .htaccess file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  AddType text/cache-manifest .appcache &lt;br /&gt;
  AddType text/cache-manifest .manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The .htaccess file is used by Apache servers, and by some others as well. The Apache server may, as an option, ignore .htaccess files, so this technique may not work.&lt;br /&gt;
&lt;br /&gt;
For more information, see http://httpd.apache.org/docs/current/howto/htaccess.html and http://en.wikipedia.org/wiki/Htaccess .&lt;br /&gt;
&lt;br /&gt;
(with contributions from Paul Elliott)&lt;br /&gt;
&lt;br /&gt;
== Setting up your server for manifest files (IIS) ==&lt;br /&gt;
&lt;br /&gt;
If you are going to distribute your app from your own server, you will have to check if it is serving the OfflineApp.appcache file with the correct MIME type. To test what mime type a document is being returned as, use http://web-sniffer.net. Enter the url to your manifest file: for example, http://www.nsbapp.com/myProject/OfflineApp.appcache. The result will be displayed in &amp;quot;Content-Type&amp;quot;: it should be &#039;text/cache-manifest&#039;. If it is not, you&#039;ll need to change the setting in IIS. Here is where to look for it:&lt;br /&gt;
&lt;br /&gt;
[[File:TN05.01.png]]&lt;br /&gt;
&lt;br /&gt;
You will also need to add index.html to the list of names used by the default context page as follows, if it is not there already.&lt;br /&gt;
&lt;br /&gt;
[[File:TN05.02.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;with contributions from Tony O&#039;Brian&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Here are the contents of the working web.config file which resides in the website route directory on a Hostgator Windows server:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;configuration&amp;gt;&lt;br /&gt;
    &amp;lt;system.webServer&amp;gt;&lt;br /&gt;
        &amp;lt;staticContent&amp;gt;&lt;br /&gt;
            &amp;lt;remove fileExtension=&amp;quot;.appcache&amp;quot; /&amp;gt;&lt;br /&gt;
            &amp;lt;mimeMap fileExtension=&amp;quot;.appcache&amp;quot; mimeType=&amp;quot;text/cache-manifest&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;/staticContent&amp;gt;&lt;br /&gt;
    &amp;lt;/system.webServer&amp;gt;&lt;br /&gt;
&amp;lt;/configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;Contributed by Graham Pettican&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Setting up on a GoDaddy server ==&lt;br /&gt;
&lt;br /&gt;
Here is how to edit the MIME types on Apache: &lt;br /&gt;
http://support.godaddy.com/help/article/375/can-i-configure-mime-types-on-my-linux-hosting-account&lt;br /&gt;
&lt;br /&gt;
Here are the instructions for Windows hosting:  &lt;br /&gt;
http://support.godaddy.com/help/article/6286/modifying-or-adding-custom-mime-types-to-windows-hosting-accounts&lt;br /&gt;
&lt;br /&gt;
If your hosting is on a shared GoDaddy server runnimg Windows and IIS, it would seem that in order to set up your custom web.config file an upgrade to a virtual dedicated server is needed. Another, likely also less expensive approach, would be to switch to Linux hosting running Apache. Then you could create a .htaccess file to contain the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  AddType text/cache-manifest .appcache .manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Place this in the root of your site (in which case it affects the entire site) or in a directory where you will keep your apps (and in which case only that one directory will be affected)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;with contributions from Johann Vogel&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Distributing_your_App&amp;diff=6115</id>
		<title>Distributing your App</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Distributing_your_App&amp;diff=6115"/>
		<updated>2014-06-16T07:00:08Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* A server of your own */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apps created with AppStudio can be installed and run by anyone who has an internet connection. Once they are running on a device, apps can be saved locally on the device and will be available even when there is no internet connection available.&lt;br /&gt;
&lt;br /&gt;
AppStudio web apps are not sold in Apple&#039;s App Store. However, they can be used on any iOS device, jailbroken or not, without going through any review by Apple. They are normal HTML5 apps, and as Steve Jobs has said, &amp;quot;HTML5 -- it&#039;s a completely open, uncontrolled platform. And we fully support it.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you want to sell your app, there are a few strategies.&lt;br /&gt;
&lt;br /&gt;
# Set up a web site which requires a sign on code to access the download info. Give the sign on code to people who have paid.&lt;br /&gt;
# Have a registration code input field in your program. The correct code has to be entered the first time the program is run.&lt;br /&gt;
# Use a third party web app store. It will handle billing and downloads, and give you a percentage of the revenue. Samples of such stores are OpenAppMkt and the Chrome Web Store.&lt;br /&gt;
# Make your app into a native app [[Submitting_to_the_iOS_App_Store|using PhoneGap and submit it to Apple]]. There is an option on the Run menu for this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Distributing Web Apps ==&lt;br /&gt;
&lt;br /&gt;
For a good background into how this all works, there is a great chapter in Mark Pilgrims&#039;s book Dive Into HTML5. The chapter on Offline Apps is here.&lt;br /&gt;
&lt;br /&gt;
Your app needs to be deployed to a web server so that it can be loaded and run. There are several choices for web servers you can use.&lt;br /&gt;
&lt;br /&gt;
=== AppStudio test server (nsbapp.com) ===&lt;br /&gt;
This is the default and will work without any extra setup. It is intended for testing only: do not rely on the app being available there forever. No PHP. If you are using the demo, you can only deploy to the test server.&lt;br /&gt;
&lt;br /&gt;
=== DropBox Public folder ===&lt;br /&gt;
Apps deploy and run well using your DropBox Public folder. Just give people the public link to the index.html file for your app. No PHP. To use it, select &amp;quot;Deploy to a local or DropBox public folder&amp;quot; in Deploy Options and put the path to your Dropbox folder in Local Path. (Something like c:\users\billg\Documents\My DropBox\Public)&lt;br /&gt;
&lt;br /&gt;
If you have a newer DropBox account, you may not have a Public folder.  You can add one to your account by logging into the DropBox website and then clicking on the following link: https://www.dropbox.com/enable_public_folder&lt;br /&gt;
&lt;br /&gt;
=== Local test server ===&lt;br /&gt;
You can set up a local server on your own system. This is good for testing, but not usually very good for outside users who want to run your app. To use it, select &amp;quot;Deploy to a local or DropBox public folder&amp;quot; in Deploy Options and put the appropriate path into Local Path.&lt;br /&gt;
&lt;br /&gt;
=== A server of your own ===&lt;br /&gt;
This is the most powerful and permanent solution. It involves getting a website of your own with the appropriate settings. Select &amp;quot;Deploy to local server&amp;quot; or &amp;quot;Deploy to FTP Server&amp;quot; in Deploy options and fill in the Server, Path, Username and password.&lt;br /&gt;
&lt;br /&gt;
There are a variety of own servers that you can use, for example Microsoft WebMatrix (IIS), Apache, EngineX, GWS to mention a few.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Using Microsoft WebMatrix&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Set Up WebMatrix&#039;&#039;&lt;br /&gt;
1. Install Microsoft WebPlatform Installer&lt;br /&gt;
2. Install WebMatrix using WPI&lt;br /&gt;
3. Install PHP from using WPI&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Setting Up IIS Express to serve the Offline.appcache&#039;&#039;&lt;br /&gt;
You will do this once fortunately.&lt;br /&gt;
&lt;br /&gt;
Open the command prompt (run as administrator), and change the directory to where your IIS Express folder is,&lt;br /&gt;
this might be &amp;quot;c:\Program Files (x86)\IIS Express&amp;quot;, in your DOS prompt&lt;br /&gt;
&lt;br /&gt;
Type the following:&lt;br /&gt;
&lt;br /&gt;
cd &amp;quot;Program Files (x86)&amp;quot; and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
cd &amp;quot;IIS Express&amp;quot; and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
&lt;br /&gt;
Then type the following&lt;br /&gt;
&lt;br /&gt;
appcmd set config /section:staticContent /+[fileExtension=&#039;.appcache&#039;, mimeType=&#039;text/cache-manifest&#039;] and press the &amp;lt;Enter&amp;gt; key&lt;br /&gt;
&lt;br /&gt;
Usually WebMatrix stores all your sites on the &amp;quot;My Documents\My Web Sites&amp;quot; folder of your profile.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Set Up AppStudio to deploy to WebMatrix&#039;&#039;&lt;br /&gt;
4. In AppStudio, go to Tools &amp;gt; Preferences of your project&lt;br /&gt;
5. Select Deploy to local server&lt;br /&gt;
6. On Local Path, select Browse and select My Documents\My Web Sites&lt;br /&gt;
7. Click Ok&lt;br /&gt;
8. On the Run Menu, ensure you are in Deploy to local server&lt;br /&gt;
9. Run your application, a prompt should pop up asking if you want to visit your site, click No. A folder will be created with your application files under My Documents\My Web Sites using your NSB project id.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SetUp Your Site to run PHP (ability to serve ajax)&#039;&#039;&lt;br /&gt;
Now, back to WebMatrix&lt;br /&gt;
&lt;br /&gt;
11. Start WebMatrix&lt;br /&gt;
12. Click My Sites, if your site is not listed, select See All My Sites&lt;br /&gt;
13. Select your site from the list&lt;br /&gt;
14. Select the Site tab and then select Settings,&lt;br /&gt;
15. Select None as .Net Framework&lt;br /&gt;
16. On PHP settings, select Enable PHP and select the version you want of PHP&lt;br /&gt;
17. Restart your site&lt;br /&gt;
18. Select Run and select the browser that you want&lt;br /&gt;
19. Test your site if all runs well.&lt;br /&gt;
&lt;br /&gt;
Because a folder has already been created using your App id from NSBApp, you can also select Open &amp;gt; Folder in WebMatrix to open your site. With PHP installed, all your Ajax calls made within your NSBApp will execute well and you can test your application.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Testing your Mobile Application with MITE: 2200 emulated smartphones &amp;amp; tablets&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Before distributing mobile apps, you might want to test their performance and their delivery on &amp;quot;virtual&amp;quot; devices. Whilst Microsoft WebMatrix has functionality to install and test your mobile site using virtual packs for devices, there is also MITE, available at this website link, http://www.keynote.com/solutions/monitoring/mobile-web-monitoring-scripting-tool.&lt;br /&gt;
&lt;br /&gt;
== Getting your project ready ==&lt;br /&gt;
&lt;br /&gt;
An important thing to remember is that you need to keep your app on the server, even after it is deployed to a device. When an app starts, it attempts to contact its original download location to see if there is an update. If there is no internet connection, the app continues normally. But if there is a connection and the app cannot be found on the server, the app is marked obsolete and is cleared from the device. The nsbapp.com server clears all projects that have not been used for a while, so it is not a good place to permanently host your apps.&lt;br /&gt;
&lt;br /&gt;
When you deploy your app, it is transferred using passive ftp to your site. The ftp account information and directory are set in Deploy Settings. You may need to narrow the port range for passive ftp.&lt;br /&gt;
&lt;br /&gt;
=== Setting up your files ===&lt;br /&gt;
&lt;br /&gt;
There are a few files which need to be present in your project&#039;s directory for deployment. The Deploy option on the Run menu makes this easy: the files and folder are copied into your directory automatically.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;myProject.htm&#039;&#039;	&lt;br /&gt;
| Your app. This is created by the IDE: the actual name of the file is set in the IDE. This needs to be a valid UNIX filename - no spaces or special characters. After being copied to the server, it is renamed index.html.&lt;br /&gt;
|-&lt;br /&gt;
| LauncherIcon.png	&lt;br /&gt;
| The icon for the app, set in Project Properties. This has to be in .png format, and be 114x114 pixels in size. If you don&#039;t supply a filename of your own, a default file will be used. Important! Do not change the image (or any file) in the nsb folder. &lt;br /&gt;
|-&lt;br /&gt;
| SplashScreen.png	&lt;br /&gt;
| Optional. Not supported on all devices. Set in Project Properties. This image is displayed when the app is started from the Home screen on the device. The image should be in .png format and be exactly 320x460 (1004x768 on iPad). If you don&#039;t supply a filename of your own, a default file will be used. If you save your app to the home screen, you will need to delete and resave it t if you want to change the splash screen. Important! Do not change the image (or any file) in the nsb folder. &lt;br /&gt;
|-&lt;br /&gt;
| /nsb/	&lt;br /&gt;
| Required. This directory contains all the files that AppStudio itself needs at runtime. Do not make any changes to the contents of this directory.&lt;br /&gt;
|-&lt;br /&gt;
| OfflineApp.appcache	&lt;br /&gt;
| This contains a list of files to be included. It is created automatically at deploy time with filenames the IDE knows about, plus any files listed in the project&#039;s manifest property. Older apps may use the suffix .manifest, but .appcache is recommended (and, in the case of DropBox, required.) See &amp;quot;The Manifest File&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| images and js files	&lt;br /&gt;
|Any images and additional JavaScript (.js) libraries your app uses. Images can be anything that a browser can display: .gif, .jpg, .bmp, .png and more. Filenames should be good UNIX names: no spaces or slashes.&lt;br /&gt;
|-&lt;br /&gt;
|databases	&lt;br /&gt;
|SQLite databases can be included with your app. Simply put the name of the database in your manifest. AppStudio will take care of encoding the data and the schema and deploying it. When the app is loaded on the device, the database will be automatically reconstituted and will be usable right away.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Including Images with your project made simple ===&lt;br /&gt;
&lt;br /&gt;
# Put the images in your project folder. It&#039;s easiest to put them in a folder called images.&lt;br /&gt;
# In the manifest property, put &#039;images&#039;. Then all the images in that folder will be deployed with your app.&lt;br /&gt;
# In your app, refer to the images by the simple pathname:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   images/myImage1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Manifest File ===&lt;br /&gt;
&lt;br /&gt;
The Manifest file is a file in your project directory which contains a list of all the files in your app. This file is created automatically by AppStudio. You can maintain its contents in the IDE: it is in the top level of the Project Explorer, in the property Manifest. If you want your app to run in offline mode, you need to add the names of any images, folders or other files you app requires. These files must be located in the project&#039;s directory.&lt;br /&gt;
&lt;br /&gt;
Make sure your web server serves up .appcache files with the MIME type text/cache-manifest, or else this won&#039;t work. For more information on doing this, see &amp;quot;Setting up your server for manifest files&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Here is a sample manifest property:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mario.jpg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The manifest property should have a list of file names, one name per line. Folder names can also be included: they will automatically be expanded recursively. Subfolders are allowed.&lt;br /&gt;
You can put most types of files that HTML can use into it. The app file, icons, background and splash screen are automatically included in the application cache. You do not need to add them to the manifest file. Remember add your image files!&lt;br /&gt;
&lt;br /&gt;
To add an SQLite database, simply add its name to the manifest. An SQLImport() function will be automatically be invoked when you start your app to load the database the first time. If you want to use some of the options of [[SqlImport]], use the same format as that function:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
customers.db,DB,loadComplete,NSB.overwriteAlways&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The manifest file can also be used to deliver updates to the files your app uses.&lt;br /&gt;
&lt;br /&gt;
When your app starts, it checks with the server (if available) and compares the manifest files to the one it last downloaded. If it has changed, an update is triggered. All the files in the new manifest are download and the application is restarted.&lt;br /&gt;
&lt;br /&gt;
You can force an update to your app at any time by executing the following statement:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 window.applicationCache.update()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is useful if a file you are reading from a remote site may have changed. In this case, the manifest file will not have been updated.&lt;br /&gt;
&lt;br /&gt;
=== Installing your App on a device ===&lt;br /&gt;
&lt;br /&gt;
If you have everything set up, your app will actually run your device right after you deploy. Go into your browser (Safari on iOS), and enter the URL for your app.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  http://www.nsbapp.com/myProject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You&#039;re running as an online app right now. Its appearance will be like a web page. But if you add it to the Home Screen, an icon will be created in the Launcher and the app will look like you intended and not part of the browser.&lt;br /&gt;
&lt;br /&gt;
To do this in iOS, tap on the plus (+) sign at the bottom of mobile Safari and choose &amp;quot;Add to Home Screen&amp;quot;. The app is now installed as an offline app, no different than any other app in the Home Screen.&lt;br /&gt;
&lt;br /&gt;
On Android, it&#039;s a little more complicated. Up till Android 4, the browser was call Android Browser and used a similar process to add the the Home screen. In Android 4, the Mobile Chrome browser was introduced. On some devices, usually those branded as Google, only Mobile Chrome is available. Mobile Chrome is not complete: it is still missing some cosmetic features. See https://code.google.com/p/chromium/issues/list?can=2&amp;amp;q=OS:Android&amp;amp;sort=-stars&amp;amp;colspec=ID%20Pri%20Mstone%20ReleaseBlock%20Area%20Feature%20Status%20Owner%20Summary%20Stars&lt;br /&gt;
&lt;br /&gt;
== Setting up your server for manifest files (Apache) ==&lt;br /&gt;
&lt;br /&gt;
If you are going to distribute your app from your own server, you will have to check if it is serving the OfflineApp.appcache (or .manifest) file with the correct MIME type. To test whether your server has the correct settings, use Check Deployment in the Run menu.&lt;br /&gt;
&lt;br /&gt;
=== Modify mime.types ===&lt;br /&gt;
&lt;br /&gt;
The first method to correct the MIME type is to modify the mime.types file. Here is where you will find it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;IfModule mime_module&amp;gt;&lt;br /&gt;
    #&lt;br /&gt;
    # TypesConfig points to the file containing the list of mappings from&lt;br /&gt;
    # filename extension to MIME-type.&lt;br /&gt;
    #&lt;br /&gt;
    TypesConfig /private/etc/apache2/mime.types&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your server is running Apache (most likely), you need to edit this file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  /user/local/apache2/conf/mime.types&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Add this line to the end:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
text/cache-manifest appcache manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You will need to restart Apache so the settings take effect. Could be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  restart_apache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
from the shell.&lt;br /&gt;
&lt;br /&gt;
What&#039;s happening here is that the server needs to return the cache file back to you with the proper content type set. If you don&#039;t do this, the file will probably come back as &#039;text&#039;. If set properly, it will come back with a type of &#039;cache-manifest&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Use the .htaccess file ===&lt;br /&gt;
&lt;br /&gt;
If your webserver is hosted by an ISP you will may not be able to edit the &amp;quot;mime.types&amp;quot; file (server administrators are understandably reluctant to allow just anyone to modify their server&#039;s configuration!) If this is the case, you can usually provide a configuration file that will apply only to your personal server area. This file is named &amp;quot;.htaccess&amp;quot;, and is sometimes used to control password access to portions of your website.&lt;br /&gt;
&lt;br /&gt;
In the root of your website directory, if it doesn&#039;t already exist create the .htaccess file and include the line &amp;quot;AddType text/cache-manifest .manifest&amp;quot; (omit the quotes). The .htaccess file will now specify the new manifest MIME type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the minimum .htaccess file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  AddType text/cache-manifest .appcache &lt;br /&gt;
  AddType text/cache-manifest .manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The .htaccess file is used by Apache servers, and by some others as well. The Apache server may, as an option, ignore .htaccess files, so this technique may not work.&lt;br /&gt;
&lt;br /&gt;
For more information, see http://httpd.apache.org/docs/current/howto/htaccess.html and http://en.wikipedia.org/wiki/Htaccess .&lt;br /&gt;
&lt;br /&gt;
(with contributions from Paul Elliott)&lt;br /&gt;
&lt;br /&gt;
== Setting up your server for manifest files (IIS) ==&lt;br /&gt;
&lt;br /&gt;
If you are going to distribute your app from your own server, you will have to check if it is serving the OfflineApp.appcache file with the correct MIME type. To test what mime type a document is being returned as, use http://web-sniffer.net. Enter the url to your manifest file: for example, http://www.nsbapp.com/myProject/OfflineApp.appcache. The result will be displayed in &amp;quot;Content-Type&amp;quot;: it should be &#039;text/cache-manifest&#039;. If it is not, you&#039;ll need to change the setting in IIS. Here is where to look for it:&lt;br /&gt;
&lt;br /&gt;
[[File:TN05.01.png]]&lt;br /&gt;
&lt;br /&gt;
You will also need to add index.html to the list of names used by the default context page as follows, if it is not there already.&lt;br /&gt;
&lt;br /&gt;
[[File:TN05.02.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;with contributions from Tony O&#039;Brian&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Here are the contents of the working web.config file which resides in the website route directory on a Hostgator Windows server:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;configuration&amp;gt;&lt;br /&gt;
    &amp;lt;system.webServer&amp;gt;&lt;br /&gt;
        &amp;lt;staticContent&amp;gt;&lt;br /&gt;
            &amp;lt;remove fileExtension=&amp;quot;.appcache&amp;quot; /&amp;gt;&lt;br /&gt;
            &amp;lt;mimeMap fileExtension=&amp;quot;.appcache&amp;quot; mimeType=&amp;quot;text/cache-manifest&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;/staticContent&amp;gt;&lt;br /&gt;
    &amp;lt;/system.webServer&amp;gt;&lt;br /&gt;
&amp;lt;/configuration&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;Contributed by Graham Pettican&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Setting up on a GoDaddy server ==&lt;br /&gt;
&lt;br /&gt;
Here is how to edit the MIME types on Apache: &lt;br /&gt;
http://support.godaddy.com/help/article/375/can-i-configure-mime-types-on-my-linux-hosting-account&lt;br /&gt;
&lt;br /&gt;
Here are the instructions for Windows hosting:  &lt;br /&gt;
http://support.godaddy.com/help/article/6286/modifying-or-adding-custom-mime-types-to-windows-hosting-accounts&lt;br /&gt;
&lt;br /&gt;
If your hosting is on a shared GoDaddy server runnimg Windows and IIS, it would seem that in order to set up your custom web.config file an upgrade to a virtual dedicated server is needed. Another, likely also less expensive approach, would be to switch to Linux hosting running Apache. Then you could create a .htaccess file to contain the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  AddType text/cache-manifest .appcache .manifest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Place this in the root of your site (in which case it affects the entire site) or in a directory where you will keep your apps (and in which case only that one directory will be affected)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;with contributions from Johann Vogel&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=ReadFile&amp;diff=6034</id>
		<title>ReadFile</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=ReadFile&amp;diff=6034"/>
		<updated>2014-05-22T16:42:25Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ReadFile (&#039;&#039;filename&#039;&#039;[,&#039;&#039;method&#039;&#039;])&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
Note: This function can be replaced by the [[Ajax]]() function.&lt;br /&gt;
&lt;br /&gt;
ReadFile will read &#039;&#039;filename&#039;&#039; which can either be deployed with the app or be on the same server as the app. If the file is to be deployed with the app, include it in the manifest. This function will only work when deployed to a website: it will not work when running in the local browser. &lt;br /&gt;
&lt;br /&gt;
Use &#039;&#039;method&#039;&#039; to define the access method. Usually this parameter can be left out: the default is Get. The next most common value for this is Post. Post responses are never cached, whereas Get responses can be. Post also allows larger data transfers. Other methods are Connect, Delete, Head, Options, Put, Trace, or Track. For more information on these options, look up XMLHttpRequest on the web. The function is based on XMLHttpRequest. See the ReadFile.nsx sample.&lt;br /&gt;
&lt;br /&gt;
It returns two values: .status = 0 or 200 if the file was read successfully and .responseText which has the entire contents of the file. If the file is not read successfully, a different status code is returned in .status.&lt;br /&gt;
&lt;br /&gt;
There is no equivilent WriteFile. Use [[sql|Sql]], [[localstorage|LocalStorage]] or the PhoneGap API to save data.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Returning the latest file contents&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can also pass a file location to ReadFile using this approach&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dim usrFile, req&lt;br /&gt;
usrFile = &amp;quot;users/12345.xml?&amp;amp;&amp;quot; &amp;amp; SysInfo(10)&lt;br /&gt;
req = ReadFile(usrFile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This ?&amp;amp;&amp;quot; &amp;amp; SysInfo(10) at the end of the .xml ensures that the latest file on the server is returned. This is useful where you perhaps update the file and want to return the latest version later on within your application. Excluding this will only return the last cached file contents that you read.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rem ReadfileFile example&lt;br /&gt;
filename=&amp;quot;g.txt&amp;quot;&lt;br /&gt;
req=ReadFile(filename)&lt;br /&gt;
If req.status=200 Then&lt;br /&gt;
  MsgBox req.responseText&lt;br /&gt;
Else&lt;br /&gt;
  MsgBox &amp;quot;File could not be read&amp;quot;&lt;br /&gt;
End If&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Items ==&lt;br /&gt;
&lt;br /&gt;
[[ajax|Ajax]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Miscellaneous]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=ReadFile&amp;diff=6033</id>
		<title>ReadFile</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=ReadFile&amp;diff=6033"/>
		<updated>2014-05-22T16:42:01Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ReadFile (&#039;&#039;filename&#039;&#039;[,&#039;&#039;method&#039;&#039;])&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
Note: This function can be replaced by the [[Ajax]]() function.&lt;br /&gt;
&lt;br /&gt;
ReadFile will read &#039;&#039;filename&#039;&#039; which can either be deployed with the app or be on the same server as the app. If the file is to be deployed with the app, include it in the manifest. This function will only work when deployed to a website: it will not work when running in the local browser. &lt;br /&gt;
&lt;br /&gt;
Use &#039;&#039;method&#039;&#039; to define the access method. Usually this parameter can be left out: the default is Get. The next most common value for this is Post. Post responses are never cached, whereas Get responses can be. Post also allows larger data transfers. Other methods are Connect, Delete, Head, Options, Put, Trace, or Track. For more information on these options, look up XMLHttpRequest on the web. The function is based on XMLHttpRequest. See the ReadFile.nsx sample.&lt;br /&gt;
&lt;br /&gt;
It returns two values: .status = 0 or 200 if the file was read successfully and .responseText which has the entire contents of the file. If the file is not read successfully, a different status code is returned in .status.&lt;br /&gt;
&lt;br /&gt;
There is no equivilent WriteFile. Use [[sql|Sql]], [[localstorage|LocalStorage]] or the PhoneGap API to save data.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Returning the latest file&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can also pass a file location to ReadFile using this approach&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dim usrFile, req&lt;br /&gt;
usrFile = &amp;quot;users/12345.xml?&amp;amp;&amp;quot; &amp;amp; SysInfo(10)&lt;br /&gt;
req = ReadFile(usrFile)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This ?&amp;amp;&amp;quot; &amp;amp; SysInfo(10) at the end of the .xml ensures that the latest file on the server is returned. This is useful where you perhaps update the file and want to return the latest version later on within your application. Excluding this will only return the last cached file contents that you read.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rem ReadfileFile example&lt;br /&gt;
filename=&amp;quot;g.txt&amp;quot;&lt;br /&gt;
req=ReadFile(filename)&lt;br /&gt;
If req.status=200 Then&lt;br /&gt;
  MsgBox req.responseText&lt;br /&gt;
Else&lt;br /&gt;
  MsgBox &amp;quot;File could not be read&amp;quot;&lt;br /&gt;
End If&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Items ==&lt;br /&gt;
&lt;br /&gt;
[[ajax|Ajax]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Miscellaneous]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=ReadFile&amp;diff=6032</id>
		<title>ReadFile</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=ReadFile&amp;diff=6032"/>
		<updated>2014-05-22T16:40:13Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ReadFile (&#039;&#039;filename&#039;&#039;[,&#039;&#039;method&#039;&#039;])&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
Note: This function can be replaced by the [[Ajax]]() function.&lt;br /&gt;
&lt;br /&gt;
ReadFile will read &#039;&#039;filename&#039;&#039; which can either be deployed with the app or be on the same server as the app. If the file is to be deployed with the app, include it in the manifest. This function will only work when deployed to a website: it will not work when running in the local browser. &lt;br /&gt;
&lt;br /&gt;
Use &#039;&#039;method&#039;&#039; to define the access method. Usually this parameter can be left out: the default is Get. The next most common value for this is Post. Post responses are never cached, whereas Get responses can be. Post also allows larger data transfers. Other methods are Connect, Delete, Head, Options, Put, Trace, or Track. For more information on these options, look up XMLHttpRequest on the web. The function is based on XMLHttpRequest. See the ReadFile.nsx sample.&lt;br /&gt;
&lt;br /&gt;
It returns two values: .status = 0 or 200 if the file was read successfully and .responseText which has the entire contents of the file. If the file is not read successfully, a different status code is returned in .status.&lt;br /&gt;
&lt;br /&gt;
There is no equivilent WriteFile. Use [[sql|Sql]], [[localstorage|LocalStorage]] or the PhoneGap API to save data.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Returning the latest file&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can also pass a file location to ReadFile using this approach&lt;br /&gt;
&lt;br /&gt;
Dim usrFile, req&lt;br /&gt;
usrFile = &amp;quot;users/12345.xml?&amp;amp;&amp;quot; &amp;amp; SysInfo(10)&lt;br /&gt;
req = ReadFile(usrFile)&lt;br /&gt;
&lt;br /&gt;
This ?&amp;amp;&amp;quot; &amp;amp; SysInfo(10) at the end of the .xml ensures that the latest file on the server is returned. This is useful where you perhaps update the file and want to return the latest version later on within your application. Excluding this will only return the last cached file contents that you read.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rem ReadfileFile example&lt;br /&gt;
filename=&amp;quot;g.txt&amp;quot;&lt;br /&gt;
req=ReadFile(filename)&lt;br /&gt;
If req.status=200 Then&lt;br /&gt;
  MsgBox req.responseText&lt;br /&gt;
Else&lt;br /&gt;
  MsgBox &amp;quot;File could not be read&amp;quot;&lt;br /&gt;
End If&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Items ==&lt;br /&gt;
&lt;br /&gt;
[[ajax|Ajax]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Miscellaneous]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=ComboBox&amp;diff=4296</id>
		<title>ComboBox</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=ComboBox&amp;diff=4296"/>
		<updated>2013-11-21T23:17:51Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:ComboBox.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The ComboBox is used to display a picker with different values. The selected value is displayed. When the control is tapped on, a new window opens with a list of options. &lt;br /&gt;
&lt;br /&gt;
While a variety of different events are available, the usual response to clicking a ComboBox is to call the function ID_onchange(), where ID is the id of the control.&lt;br /&gt;
&lt;br /&gt;
To set up the items in the ComboBox, either add them to the &#039;&#039;items&#039;&#039; property in the IDE, or use the ID.AddItem function to add them at runtime. Each item can also have a &#039;&#039;value&#039;&#039;, which you can define in the IDE or at runtime. If you do not define a &#039;&#039;value&#039;&#039;, it defaults to the line number, starting at 1.&lt;br /&gt;
&lt;br /&gt;
To add a ComboBox to your app, choose the ComboBox icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the button: usually, just ID_onchange().&lt;br /&gt;
&lt;br /&gt;
To set the selection in code, use ID.setIndex(&#039;&#039;n&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
This control is part of iWebKit. The equivalent control in jQuery Mobile is [[Select]].&lt;br /&gt;
&lt;br /&gt;
== Methods and Properties ==&lt;br /&gt;
&lt;br /&gt;
Standard [[properties and methods|properties]] are supported, plus:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| addItem(item[,value]) || Add &#039;&#039;item&#039;&#039; to the list. You can also have an optional &#039;&#039;value&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| clear() || Clear the list&lt;br /&gt;
|-&lt;br /&gt;
| getItemCount() || The number of items on the list&lt;br /&gt;
|-&lt;br /&gt;
| List(n) || Get the text of item &#039;&#039;n&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| ListCount || The number of items. Same as getItemCount().&lt;br /&gt;
|-&lt;br /&gt;
| ListIndex || Gets or set the current selection number. If set, calls the control’s _onclick() and _onchange() functions.&lt;br /&gt;
|-&lt;br /&gt;
| removeItem(n) || Remove item &#039;&#039;n&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| selectedIndex() || The number of the current selection, starting from 0.&lt;br /&gt;
|-&lt;br /&gt;
| selectedItem() || The text of the currently selected item.&lt;br /&gt;
|-&lt;br /&gt;
| selectedValue() || The value of the currently selected item.&lt;br /&gt;
|-&lt;br /&gt;
| setIndex(n) || Set the current selection to &#039;&#039;n&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setText(value) || Set the text of the current selection to &#039;&#039;value&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setValue(value) || Set the value of the current selection to &#039;&#039;value&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| text || The text of the current selection. Same as selectedItem().&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Events&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Standard [[events|events]] are supported. For this control, the onchange event will be most useful.&lt;br /&gt;
&lt;br /&gt;
== Example (Basic) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Rem ComboBox is used to display a picker with different values&lt;br /&gt;
&lt;br /&gt;
For i=0 To 6&lt;br /&gt;
  ComboBox1.addItem(WeekdayName(i+1), WeekdayName(i+1))&lt;br /&gt;
Next&lt;br /&gt;
 &lt;br /&gt;
Function ComboBox1_onchange()&lt;br /&gt;
  MsgBox &amp;quot;selectedItem is &amp;quot; &amp;amp; ComboBox1.selectedItem()&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Disable a ComboBox (BASIC or JavaScript)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ComboBox1.children[0].disabled=true&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example (JavaScript) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//ComboBox is used to display a picker with different values&lt;br /&gt;
&lt;br /&gt;
for(i=0; i&amp;lt;=6; i++) {&lt;br /&gt;
  ComboBox1.addItem(WeekdayName[i+1], WeekdayName[i+1]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ComboBox1.onchange = function() {&lt;br /&gt;
  alert(&amp;quot;selectedItem is &amp;quot; + ComboBox1.selectedItem());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Output == &lt;br /&gt;
(on an iPhone – other devices may look different)&lt;br /&gt;
&lt;br /&gt;
[[file:ComboBoxOutput.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Controls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:iWebKit]]&lt;br /&gt;
&lt;br /&gt;
== Returning an Index for text (VB) == &lt;br /&gt;
Function ComboIndexOf(cboBox,cboSearch)&lt;br /&gt;
    Dim cboOut: cboOut = -1&lt;br /&gt;
    cboSearch = LCase(cboSearch)&lt;br /&gt;
    Dim cboTot: cboTot = cboBox.getItemCount()&lt;br /&gt;
    Dim xItem&lt;br /&gt;
    For i = 0 To cboTot - 1&lt;br /&gt;
      xItem = cboBox.List(i)&lt;br /&gt;
      xItem = LCase(xItem)&lt;br /&gt;
      If xItem = cboSearch Then return i&lt;br /&gt;
    Next&lt;br /&gt;
    return cboOut&lt;br /&gt;
End Function&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4223</id>
		<title>Grid</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4223"/>
		<updated>2013-11-03T03:09:44Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Useful Methods (Basic) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:Grid.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The Grid control is used to display data in a table. To add a Grid to your app, choose the Grid icon in the Toolbar. Use the Property Editor to set the properties. &lt;br /&gt;
&lt;br /&gt;
The onclick event can be used to check for clicks. Check event.target.id to find out which cell was clicked.&lt;br /&gt;
&lt;br /&gt;
The width of the grid is set to the total of the pixel widths of the columns, if supplied. Otherwise, it is full width.&lt;br /&gt;
&lt;br /&gt;
If you set the style of the grid to ‘table-layout:fixed;’ it will force the able to maintain cell widths. If the data is too big, it will overflow to the next cell, as in Excel.&lt;br /&gt;
&lt;br /&gt;
If you change the size of a control with scrolling enabled at runtime (by doing addCols or deleteRows, etc.), you need to recalulate the size of the scrolling area by doing &#039;&#039;controlname&#039;&#039;.refresh(). This also applies if you load a new form with a Grid on it.  The width may also need to be set. A good place to do this is in the onshow() function of the new form.&lt;br /&gt;
&lt;br /&gt;
  Grid1.refresh()&lt;br /&gt;
  Grid1.width=&amp;quot;90%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add a control to your app, choose the control’s icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the control: usually, just onclick.&lt;br /&gt;
&lt;br /&gt;
Each cell in the grid has its own id, in the form gridId_x_y. The id of the top left element of Grid1 is Grid1_0_0.&lt;br /&gt;
&lt;br /&gt;
To make a row column combination bold, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.fontWeight = &amp;quot;bold&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To align a row column combination, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.textAlign = &amp;quot;right&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To put an image in a grid cell, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.setValue(0,1,&amp;quot;&amp;lt;img src=&#039;mario.jpg&#039; id=&#039;Grid1_0_1&#039;&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
The 0_1 in the ID should have the same column and row as the first two arguments.&lt;br /&gt;
&lt;br /&gt;
To scroll to the top of the grid (row 1), do the following:&lt;br /&gt;
  &lt;br /&gt;
  Grid1_ref.scrollTo(0, 0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Useful Methods (Basic) ==&lt;br /&gt;
&#039; center align records in a grid&lt;br /&gt;
Function GridCenterAlign(grdName,startCol,endCol)&lt;br /&gt;
    Dim grdRows&lt;br /&gt;
    grdRows = grdName.getRowCount()&lt;br /&gt;
    For i = 1 To grdRows - 1&lt;br /&gt;
      For col = startCol To endCol&lt;br /&gt;
        grdName.cell(i,col).style.textAlign = &amp;quot;center&amp;quot;&lt;br /&gt;
      Next&lt;br /&gt;
    Next&lt;br /&gt;
End Function &lt;br /&gt;
&lt;br /&gt;
&#039; right align columns in a grid&lt;br /&gt;
Function GridRightAlign(grdName,startCol,endCol)&lt;br /&gt;
    Dim grdRows&lt;br /&gt;
    grdRows = grdName.getRowCount()&lt;br /&gt;
    For i = 1 To grdRows - 1&lt;br /&gt;
      For col = startCol To endCol&lt;br /&gt;
        grdName.cell(i,col).style.textAlign = &amp;quot;right&amp;quot;&lt;br /&gt;
      Next&lt;br /&gt;
    Next&lt;br /&gt;
End Function &lt;br /&gt;
&lt;br /&gt;
&#039; set the heigh of a grid row&lt;br /&gt;
Function SetGridHeight(grdName,grdRowHeight)&lt;br /&gt;
  Dim grdRows&lt;br /&gt;
  grdRows = grdName.getRowCount()&lt;br /&gt;
  For i = 1 To grdRows - 1&lt;br /&gt;
    grdName.setRowHeight(i, grdRowHeight)&lt;br /&gt;
  Next&lt;br /&gt;
End Function &lt;br /&gt;
&lt;br /&gt;
Function BoldGridRow(grdName,rowPos)&lt;br /&gt;
  Dim grdCols&lt;br /&gt;
  grdCols = grdName.getColCount()&lt;br /&gt;
  For i = 0 To grdCols - 1&lt;br /&gt;
    grdName.cell(rowPos,i).style.fontWeight = &amp;quot;bold&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
End Function &lt;br /&gt;
&lt;br /&gt;
&#039; draw alternate colors in the grid&lt;br /&gt;
Function AlternateGridColor(grdName)&lt;br /&gt;
  &#039;Paints Each row in alernating color.&lt;br /&gt;
  Dim grdRows, grdCols&lt;br /&gt;
  grdRows = grdName.getRowCount()&lt;br /&gt;
  grdCols = grdName.getColCount()&lt;br /&gt;
  For i = 1 To grdRows - 1&lt;br /&gt;
    For col = 0 To grdCols - 1&lt;br /&gt;
      If (Abs(i) % 2) = 1 Then&lt;br /&gt;
        grdName.cell(i,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
      Else&lt;br /&gt;
        grdName.cell(i,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
      End If&lt;br /&gt;
    Next&lt;br /&gt;
  Next&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
== Properties and Methods ==&lt;br /&gt;
&lt;br /&gt;
Standard [[properties and methods|properties]] are supported, plus:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| addCols(&#039;&#039;n&#039;&#039;) || Add &#039;&#039;n&#039;&#039; columns to the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| addRows(&#039;&#039;n&#039;&#039;) || Adds &#039;&#039;n&#039;&#039; rows to the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| alignments || The alignment of the data in each column. Can be left, right, center, justify or char=”.”. Optional. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| cell(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;) || Returns a reference to cell x,y.&lt;br /&gt;
|-&lt;br /&gt;
| cellstyle || The style of each cell in the grid. Use cell(x,y).style at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| cols || The number of columns in the table. (Design time only) &lt;br /&gt;
|-&lt;br /&gt;
| colwidths || The width of each column, in pixels (100px), comma separated. Design time only.&lt;br /&gt;
|-&lt;br /&gt;
| deleteCols(&#039;&#039;n&#039;&#039;) || Deletes &#039;&#039;n&#039;&#039; columns from the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| deleteRows(&#039;&#039;n&#039;&#039;) || Delete n rows from the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| getColCount() || Returns the number of columns.&lt;br /&gt;
|-&lt;br /&gt;
| getRowCount() || Returns the number of rows.&lt;br /&gt;
|-&lt;br /&gt;
| getValue(&#039;&#039;row&#039;&#039;,&#039;&#039;col&#039;&#039;) || Get the current value of a cell.&lt;br /&gt;
|-&lt;br /&gt;
| rowheights || The height of each row, in pixels (20px) or percentages (20%), comma separated. Read only at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| refresh() || Recalculate the scrolling area after additions or deletions. Used for scrolling grids only.&lt;br /&gt;
|-&lt;br /&gt;
| rows || The number of rows in the table. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| scroll_options || This control makes use of iScroll. It has a number of options, including:&lt;br /&gt;
&lt;br /&gt;
bounce: true/false. When the end of the scroll area is reached, should the image bounce?&lt;br /&gt;
&lt;br /&gt;
zoom: true/false. Allow two finger zoom in gesture?&lt;br /&gt;
&lt;br /&gt;
The full list of options is documented here: http://cubiq.org/iscroll-4&lt;br /&gt;
|-&lt;br /&gt;
| scrolling || Allow choices in the menu to scroll? On or off. (design time)&lt;br /&gt;
|-&lt;br /&gt;
| setColumnWidth(&#039;&#039;col&#039;&#039;, &#039;&#039;width&#039;&#039;)  || Sets the width of &#039;&#039;col&#039;&#039; to &#039;&#039;width&#039;&#039;. Needs to be done to all columns to be effective.&lt;br /&gt;
|-&lt;br /&gt;
| setRowHeight(&#039;&#039;row&#039;&#039;, &#039;&#039;height&#039;&#039;) || Sets the height of &#039;&#039;row&#039;&#039; to &#039;&#039;height&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setValue(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;, &#039;&#039;value&#039;&#039;) || Set the &#039;&#039;value&#039;&#039; of a cell. Can be string or HTML.&lt;br /&gt;
|-&lt;br /&gt;
| titles || The titles for each column, comma separated. Optional. (Design time only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
&lt;br /&gt;
Grid supports the standard [[events|events]].&lt;br /&gt;
&lt;br /&gt;
== Example 1 (Basic) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For row=0 to 3&lt;br /&gt;
  For col=0 to 3&lt;br /&gt;
    Grid1.setValue(row,col,row*col)&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
 &lt;br /&gt;
Function Button1_onclick()&lt;br /&gt;
  MsgBox &amp;quot;Grid(3,3)=&amp;quot; &amp;amp; Grid1.getValue(3,3)&lt;br /&gt;
End Function&lt;br /&gt;
 &lt;br /&gt;
Function Grid1_onclick()&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;)&lt;br /&gt;
  MsgBox &amp;quot;Click on &amp;quot; &amp;amp; s(0) &amp;amp; &amp;quot; at row &amp;quot; &amp;amp; s(1) &amp;amp; &amp;quot; and column &amp;quot; &amp;amp; s(2)&lt;br /&gt;
  MsgBox &amp;quot;Value is &amp;quot; &amp;amp; Grid1.getValue(s(1),s(2))&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell(1,1).style.backgroundColor=&amp;quot;red&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 1 (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for(row=0; row &amp;lt;= 3; row++) {&lt;br /&gt;
  for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
    Grid1.setValue(row,col,row*col);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Button1.onclick = function() {&lt;br /&gt;
  alert(&amp;quot;Grid[3,3]=&amp;quot; + Grid1.getValue(3,3));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Grid1.onclick = function() {&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;);&lt;br /&gt;
  alert(&amp;quot;Click on &amp;quot; + s[0] +  &amp;quot; at row &amp;quot; +  s[1] + &amp;quot; and column &amp;quot; +  s[2]);&lt;br /&gt;
  alert(&amp;quot;Value is &amp;quot; + Grid1.getValue(s[1] ,s[2]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell[1,1].style.backgroundColor=&amp;quot;red&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (Basic) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;)&lt;br /&gt;
 &#039;Add 100 rows with 4 cols to the grid.&lt;br /&gt;
 For row=1 To 100&lt;br /&gt;
   Grid1.addRows(1)&lt;br /&gt;
   Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;)&lt;br /&gt;
   For col=0 To 3&lt;br /&gt;
     If col = 0 Then&lt;br /&gt;
         Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row)&lt;br /&gt;
     Else&lt;br /&gt;
         Grid1.setValue(row,col,row*col)&lt;br /&gt;
     End If&lt;br /&gt;
     &#039;Paints each row in alernating color.&lt;br /&gt;
     If (Abs(row) % 2) = 1 Then&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
     Else&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
     End If&lt;br /&gt;
   Next&lt;br /&gt;
 Next&lt;br /&gt;
 Grid1.refresh()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (JavaScript) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
  Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;);&lt;br /&gt;
  //Add 100 rows with 4 cols to the grid.&lt;br /&gt;
  for(row=1; row &amp;lt;= 100; row++) {&lt;br /&gt;
    Grid1.addRows(1);&lt;br /&gt;
    Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;);&lt;br /&gt;
    for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
      if(col == 0) {&lt;br /&gt;
        Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.setValue(row,col,row*col);&lt;br /&gt;
      }&lt;br /&gt;
      //Paints each row in alernating color.&lt;br /&gt;
      if((Math.abs(row) % 2) == 1) {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  Grid1.refresh();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(&amp;quot;#Grid1 td&amp;quot;).css(&amp;quot;font-family&amp;quot;, &amp;quot;Courier New&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (BASIC) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For i = 0 To Grid1.children[0].children.length - 1&lt;br /&gt;
  For j = 0 To Grid1.children[0].children[i].children.length - 1&lt;br /&gt;
    Grid1.children[0].children[i].children[j].style.fontFamily=&amp;quot;Courier new&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Output ==&lt;br /&gt;
&lt;br /&gt;
[[file:GridOutput.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Controls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Common]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4222</id>
		<title>Grid</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4222"/>
		<updated>2013-11-03T03:08:21Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Useful Methods (Basic) = */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:Grid.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The Grid control is used to display data in a table. To add a Grid to your app, choose the Grid icon in the Toolbar. Use the Property Editor to set the properties. &lt;br /&gt;
&lt;br /&gt;
The onclick event can be used to check for clicks. Check event.target.id to find out which cell was clicked.&lt;br /&gt;
&lt;br /&gt;
The width of the grid is set to the total of the pixel widths of the columns, if supplied. Otherwise, it is full width.&lt;br /&gt;
&lt;br /&gt;
If you set the style of the grid to ‘table-layout:fixed;’ it will force the able to maintain cell widths. If the data is too big, it will overflow to the next cell, as in Excel.&lt;br /&gt;
&lt;br /&gt;
If you change the size of a control with scrolling enabled at runtime (by doing addCols or deleteRows, etc.), you need to recalulate the size of the scrolling area by doing &#039;&#039;controlname&#039;&#039;.refresh(). This also applies if you load a new form with a Grid on it.  The width may also need to be set. A good place to do this is in the onshow() function of the new form.&lt;br /&gt;
&lt;br /&gt;
  Grid1.refresh()&lt;br /&gt;
  Grid1.width=&amp;quot;90%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add a control to your app, choose the control’s icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the control: usually, just onclick.&lt;br /&gt;
&lt;br /&gt;
Each cell in the grid has its own id, in the form gridId_x_y. The id of the top left element of Grid1 is Grid1_0_0.&lt;br /&gt;
&lt;br /&gt;
To make a row column combination bold, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.fontWeight = &amp;quot;bold&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To align a row column combination, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.textAlign = &amp;quot;right&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To put an image in a grid cell, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.setValue(0,1,&amp;quot;&amp;lt;img src=&#039;mario.jpg&#039; id=&#039;Grid1_0_1&#039;&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
The 0_1 in the ID should have the same column and row as the first two arguments.&lt;br /&gt;
&lt;br /&gt;
To scroll to the top of the grid (row 1), do the following:&lt;br /&gt;
  &lt;br /&gt;
  Grid1_ref.scrollTo(0, 0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Useful Methods (Basic) ==&lt;br /&gt;
&#039; center align records in a grid&lt;br /&gt;
Sub GridCenterAlign(grdName,startCol,endCol)&lt;br /&gt;
    Dim grdRows&lt;br /&gt;
    grdRows = grdName.getRowCount()&lt;br /&gt;
    For i = 1 To grdRows - 1&lt;br /&gt;
      For col = startCol To endCol&lt;br /&gt;
        grdName.cell(i,col).style.textAlign = &amp;quot;center&amp;quot;&lt;br /&gt;
      Next&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
&#039; right align columns in a grid&lt;br /&gt;
Sub GridRightAlign(grdName,startCol,endCol)&lt;br /&gt;
    Dim grdRows&lt;br /&gt;
    grdRows = grdName.getRowCount()&lt;br /&gt;
    For i = 1 To grdRows - 1&lt;br /&gt;
      For col = startCol To endCol&lt;br /&gt;
        grdName.cell(i,col).style.textAlign = &amp;quot;right&amp;quot;&lt;br /&gt;
      Next&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
&#039; set the heigh of a grid row&lt;br /&gt;
Sub SetGridHeight(grdName,grdRowHeight)&lt;br /&gt;
  Dim grdRows&lt;br /&gt;
  grdRows = grdName.getRowCount()&lt;br /&gt;
  For i = 1 To grdRows - 1&lt;br /&gt;
    grdName.setRowHeight(i, grdRowHeight)&lt;br /&gt;
  Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
Sub BoldGridRow(grdName,rowPos)&lt;br /&gt;
  Dim grdCols&lt;br /&gt;
  grdCols = grdName.getColCount()&lt;br /&gt;
  For i = 0 To grdCols - 1&lt;br /&gt;
    grdName.cell(rowPos,i).style.fontWeight = &amp;quot;bold&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
&#039; draw alternate colors in the grid&lt;br /&gt;
Sub AlternateGridColor(grdName)&lt;br /&gt;
  &#039;Paints Each row in alernating color.&lt;br /&gt;
  Dim grdRows, grdCols&lt;br /&gt;
  grdRows = grdName.getRowCount()&lt;br /&gt;
  grdCols = grdName.getColCount()&lt;br /&gt;
  For i = 1 To grdRows - 1&lt;br /&gt;
    For col = 0 To grdCols - 1&lt;br /&gt;
      If (Abs(i) % 2) = 1 Then&lt;br /&gt;
        grdName.cell(i,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
      Else&lt;br /&gt;
        grdName.cell(i,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
      End If&lt;br /&gt;
    Next&lt;br /&gt;
  Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
== Properties and Methods ==&lt;br /&gt;
&lt;br /&gt;
Standard [[properties and methods|properties]] are supported, plus:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| addCols(&#039;&#039;n&#039;&#039;) || Add &#039;&#039;n&#039;&#039; columns to the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| addRows(&#039;&#039;n&#039;&#039;) || Adds &#039;&#039;n&#039;&#039; rows to the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| alignments || The alignment of the data in each column. Can be left, right, center, justify or char=”.”. Optional. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| cell(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;) || Returns a reference to cell x,y.&lt;br /&gt;
|-&lt;br /&gt;
| cellstyle || The style of each cell in the grid. Use cell(x,y).style at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| cols || The number of columns in the table. (Design time only) &lt;br /&gt;
|-&lt;br /&gt;
| colwidths || The width of each column, in pixels (100px), comma separated. Design time only.&lt;br /&gt;
|-&lt;br /&gt;
| deleteCols(&#039;&#039;n&#039;&#039;) || Deletes &#039;&#039;n&#039;&#039; columns from the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| deleteRows(&#039;&#039;n&#039;&#039;) || Delete n rows from the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| getColCount() || Returns the number of columns.&lt;br /&gt;
|-&lt;br /&gt;
| getRowCount() || Returns the number of rows.&lt;br /&gt;
|-&lt;br /&gt;
| getValue(&#039;&#039;row&#039;&#039;,&#039;&#039;col&#039;&#039;) || Get the current value of a cell.&lt;br /&gt;
|-&lt;br /&gt;
| rowheights || The height of each row, in pixels (20px) or percentages (20%), comma separated. Read only at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| refresh() || Recalculate the scrolling area after additions or deletions. Used for scrolling grids only.&lt;br /&gt;
|-&lt;br /&gt;
| rows || The number of rows in the table. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| scroll_options || This control makes use of iScroll. It has a number of options, including:&lt;br /&gt;
&lt;br /&gt;
bounce: true/false. When the end of the scroll area is reached, should the image bounce?&lt;br /&gt;
&lt;br /&gt;
zoom: true/false. Allow two finger zoom in gesture?&lt;br /&gt;
&lt;br /&gt;
The full list of options is documented here: http://cubiq.org/iscroll-4&lt;br /&gt;
|-&lt;br /&gt;
| scrolling || Allow choices in the menu to scroll? On or off. (design time)&lt;br /&gt;
|-&lt;br /&gt;
| setColumnWidth(&#039;&#039;col&#039;&#039;, &#039;&#039;width&#039;&#039;)  || Sets the width of &#039;&#039;col&#039;&#039; to &#039;&#039;width&#039;&#039;. Needs to be done to all columns to be effective.&lt;br /&gt;
|-&lt;br /&gt;
| setRowHeight(&#039;&#039;row&#039;&#039;, &#039;&#039;height&#039;&#039;) || Sets the height of &#039;&#039;row&#039;&#039; to &#039;&#039;height&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setValue(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;, &#039;&#039;value&#039;&#039;) || Set the &#039;&#039;value&#039;&#039; of a cell. Can be string or HTML.&lt;br /&gt;
|-&lt;br /&gt;
| titles || The titles for each column, comma separated. Optional. (Design time only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
&lt;br /&gt;
Grid supports the standard [[events|events]].&lt;br /&gt;
&lt;br /&gt;
== Example 1 (Basic) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For row=0 to 3&lt;br /&gt;
  For col=0 to 3&lt;br /&gt;
    Grid1.setValue(row,col,row*col)&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
 &lt;br /&gt;
Function Button1_onclick()&lt;br /&gt;
  MsgBox &amp;quot;Grid(3,3)=&amp;quot; &amp;amp; Grid1.getValue(3,3)&lt;br /&gt;
End Function&lt;br /&gt;
 &lt;br /&gt;
Function Grid1_onclick()&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;)&lt;br /&gt;
  MsgBox &amp;quot;Click on &amp;quot; &amp;amp; s(0) &amp;amp; &amp;quot; at row &amp;quot; &amp;amp; s(1) &amp;amp; &amp;quot; and column &amp;quot; &amp;amp; s(2)&lt;br /&gt;
  MsgBox &amp;quot;Value is &amp;quot; &amp;amp; Grid1.getValue(s(1),s(2))&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell(1,1).style.backgroundColor=&amp;quot;red&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 1 (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for(row=0; row &amp;lt;= 3; row++) {&lt;br /&gt;
  for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
    Grid1.setValue(row,col,row*col);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Button1.onclick = function() {&lt;br /&gt;
  alert(&amp;quot;Grid[3,3]=&amp;quot; + Grid1.getValue(3,3));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Grid1.onclick = function() {&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;);&lt;br /&gt;
  alert(&amp;quot;Click on &amp;quot; + s[0] +  &amp;quot; at row &amp;quot; +  s[1] + &amp;quot; and column &amp;quot; +  s[2]);&lt;br /&gt;
  alert(&amp;quot;Value is &amp;quot; + Grid1.getValue(s[1] ,s[2]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell[1,1].style.backgroundColor=&amp;quot;red&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (Basic) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;)&lt;br /&gt;
 &#039;Add 100 rows with 4 cols to the grid.&lt;br /&gt;
 For row=1 To 100&lt;br /&gt;
   Grid1.addRows(1)&lt;br /&gt;
   Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;)&lt;br /&gt;
   For col=0 To 3&lt;br /&gt;
     If col = 0 Then&lt;br /&gt;
         Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row)&lt;br /&gt;
     Else&lt;br /&gt;
         Grid1.setValue(row,col,row*col)&lt;br /&gt;
     End If&lt;br /&gt;
     &#039;Paints each row in alernating color.&lt;br /&gt;
     If (Abs(row) % 2) = 1 Then&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
     Else&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
     End If&lt;br /&gt;
   Next&lt;br /&gt;
 Next&lt;br /&gt;
 Grid1.refresh()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (JavaScript) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
  Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;);&lt;br /&gt;
  //Add 100 rows with 4 cols to the grid.&lt;br /&gt;
  for(row=1; row &amp;lt;= 100; row++) {&lt;br /&gt;
    Grid1.addRows(1);&lt;br /&gt;
    Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;);&lt;br /&gt;
    for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
      if(col == 0) {&lt;br /&gt;
        Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.setValue(row,col,row*col);&lt;br /&gt;
      }&lt;br /&gt;
      //Paints each row in alernating color.&lt;br /&gt;
      if((Math.abs(row) % 2) == 1) {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  Grid1.refresh();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(&amp;quot;#Grid1 td&amp;quot;).css(&amp;quot;font-family&amp;quot;, &amp;quot;Courier New&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (BASIC) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For i = 0 To Grid1.children[0].children.length - 1&lt;br /&gt;
  For j = 0 To Grid1.children[0].children[i].children.length - 1&lt;br /&gt;
    Grid1.children[0].children[i].children[j].style.fontFamily=&amp;quot;Courier new&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Output ==&lt;br /&gt;
&lt;br /&gt;
[[file:GridOutput.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Controls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Common]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4221</id>
		<title>Grid</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4221"/>
		<updated>2013-11-03T03:06:51Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:Grid.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The Grid control is used to display data in a table. To add a Grid to your app, choose the Grid icon in the Toolbar. Use the Property Editor to set the properties. &lt;br /&gt;
&lt;br /&gt;
The onclick event can be used to check for clicks. Check event.target.id to find out which cell was clicked.&lt;br /&gt;
&lt;br /&gt;
The width of the grid is set to the total of the pixel widths of the columns, if supplied. Otherwise, it is full width.&lt;br /&gt;
&lt;br /&gt;
If you set the style of the grid to ‘table-layout:fixed;’ it will force the able to maintain cell widths. If the data is too big, it will overflow to the next cell, as in Excel.&lt;br /&gt;
&lt;br /&gt;
If you change the size of a control with scrolling enabled at runtime (by doing addCols or deleteRows, etc.), you need to recalulate the size of the scrolling area by doing &#039;&#039;controlname&#039;&#039;.refresh(). This also applies if you load a new form with a Grid on it.  The width may also need to be set. A good place to do this is in the onshow() function of the new form.&lt;br /&gt;
&lt;br /&gt;
  Grid1.refresh()&lt;br /&gt;
  Grid1.width=&amp;quot;90%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add a control to your app, choose the control’s icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the control: usually, just onclick.&lt;br /&gt;
&lt;br /&gt;
Each cell in the grid has its own id, in the form gridId_x_y. The id of the top left element of Grid1 is Grid1_0_0.&lt;br /&gt;
&lt;br /&gt;
To make a row column combination bold, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.fontWeight = &amp;quot;bold&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To align a row column combination, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.textAlign = &amp;quot;right&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To put an image in a grid cell, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.setValue(0,1,&amp;quot;&amp;lt;img src=&#039;mario.jpg&#039; id=&#039;Grid1_0_1&#039;&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
The 0_1 in the ID should have the same column and row as the first two arguments.&lt;br /&gt;
&lt;br /&gt;
To scroll to the top of the grid (row 1), do the following:&lt;br /&gt;
  &lt;br /&gt;
  Grid1_ref.scrollTo(0, 0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Useful Methods (Basic) ===&lt;br /&gt;
&#039; center align records in a grid&lt;br /&gt;
Sub GridCenterAlign(grdName,startCol,endCol)&lt;br /&gt;
    Dim grdRows&lt;br /&gt;
    grdRows = grdName.getRowCount()&lt;br /&gt;
    For i = 1 To grdRows - 1&lt;br /&gt;
      For col = startCol To endCol&lt;br /&gt;
        grdName.cell(i,col).style.textAlign = &amp;quot;center&amp;quot;&lt;br /&gt;
      Next&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
&#039; right align columns in a grid&lt;br /&gt;
Sub GridRightAlign(grdName,startCol,endCol)&lt;br /&gt;
    Dim grdRows&lt;br /&gt;
    grdRows = grdName.getRowCount()&lt;br /&gt;
    For i = 1 To grdRows - 1&lt;br /&gt;
      For col = startCol To endCol&lt;br /&gt;
        grdName.cell(i,col).style.textAlign = &amp;quot;right&amp;quot;&lt;br /&gt;
      Next&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
&#039; set the heigh of a grid row&lt;br /&gt;
Sub SetGridHeight(grdName,grdRowHeight)&lt;br /&gt;
  Dim grdRows&lt;br /&gt;
  grdRows = grdName.getRowCount()&lt;br /&gt;
  For i = 1 To grdRows - 1&lt;br /&gt;
    grdName.setRowHeight(i, grdRowHeight)&lt;br /&gt;
  Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
Sub BoldGridRow(grdName,rowPos)&lt;br /&gt;
  Dim grdCols&lt;br /&gt;
  grdCols = grdName.getColCount()&lt;br /&gt;
  For i = 0 To grdCols - 1&lt;br /&gt;
    grdName.cell(rowPos,i).style.fontWeight = &amp;quot;bold&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
&#039; draw alternate colors in the grid&lt;br /&gt;
Sub AlternateGridColor(grdName)&lt;br /&gt;
  &#039;Paints Each row in alernating color.&lt;br /&gt;
  Dim grdRows, grdCols&lt;br /&gt;
  grdRows = grdName.getRowCount()&lt;br /&gt;
  grdCols = grdName.getColCount()&lt;br /&gt;
  For i = 1 To grdRows - 1&lt;br /&gt;
    For col = 0 To grdCols - 1&lt;br /&gt;
      If (Abs(i) % 2) = 1 Then&lt;br /&gt;
        grdName.cell(i,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
      Else&lt;br /&gt;
        grdName.cell(i,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
      End If&lt;br /&gt;
    Next&lt;br /&gt;
  Next&lt;br /&gt;
End Sub&lt;br /&gt;
&lt;br /&gt;
== Properties and Methods ==&lt;br /&gt;
&lt;br /&gt;
Standard [[properties and methods|properties]] are supported, plus:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| addCols(&#039;&#039;n&#039;&#039;) || Add &#039;&#039;n&#039;&#039; columns to the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| addRows(&#039;&#039;n&#039;&#039;) || Adds &#039;&#039;n&#039;&#039; rows to the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| alignments || The alignment of the data in each column. Can be left, right, center, justify or char=”.”. Optional. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| cell(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;) || Returns a reference to cell x,y.&lt;br /&gt;
|-&lt;br /&gt;
| cellstyle || The style of each cell in the grid. Use cell(x,y).style at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| cols || The number of columns in the table. (Design time only) &lt;br /&gt;
|-&lt;br /&gt;
| colwidths || The width of each column, in pixels (100px), comma separated. Design time only.&lt;br /&gt;
|-&lt;br /&gt;
| deleteCols(&#039;&#039;n&#039;&#039;) || Deletes &#039;&#039;n&#039;&#039; columns from the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| deleteRows(&#039;&#039;n&#039;&#039;) || Delete n rows from the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| getColCount() || Returns the number of columns.&lt;br /&gt;
|-&lt;br /&gt;
| getRowCount() || Returns the number of rows.&lt;br /&gt;
|-&lt;br /&gt;
| getValue(&#039;&#039;row&#039;&#039;,&#039;&#039;col&#039;&#039;) || Get the current value of a cell.&lt;br /&gt;
|-&lt;br /&gt;
| rowheights || The height of each row, in pixels (20px) or percentages (20%), comma separated. Read only at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| refresh() || Recalculate the scrolling area after additions or deletions. Used for scrolling grids only.&lt;br /&gt;
|-&lt;br /&gt;
| rows || The number of rows in the table. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| scroll_options || This control makes use of iScroll. It has a number of options, including:&lt;br /&gt;
&lt;br /&gt;
bounce: true/false. When the end of the scroll area is reached, should the image bounce?&lt;br /&gt;
&lt;br /&gt;
zoom: true/false. Allow two finger zoom in gesture?&lt;br /&gt;
&lt;br /&gt;
The full list of options is documented here: http://cubiq.org/iscroll-4&lt;br /&gt;
|-&lt;br /&gt;
| scrolling || Allow choices in the menu to scroll? On or off. (design time)&lt;br /&gt;
|-&lt;br /&gt;
| setColumnWidth(&#039;&#039;col&#039;&#039;, &#039;&#039;width&#039;&#039;)  || Sets the width of &#039;&#039;col&#039;&#039; to &#039;&#039;width&#039;&#039;. Needs to be done to all columns to be effective.&lt;br /&gt;
|-&lt;br /&gt;
| setRowHeight(&#039;&#039;row&#039;&#039;, &#039;&#039;height&#039;&#039;) || Sets the height of &#039;&#039;row&#039;&#039; to &#039;&#039;height&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setValue(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;, &#039;&#039;value&#039;&#039;) || Set the &#039;&#039;value&#039;&#039; of a cell. Can be string or HTML.&lt;br /&gt;
|-&lt;br /&gt;
| titles || The titles for each column, comma separated. Optional. (Design time only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
&lt;br /&gt;
Grid supports the standard [[events|events]].&lt;br /&gt;
&lt;br /&gt;
== Example 1 (Basic) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For row=0 to 3&lt;br /&gt;
  For col=0 to 3&lt;br /&gt;
    Grid1.setValue(row,col,row*col)&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
 &lt;br /&gt;
Function Button1_onclick()&lt;br /&gt;
  MsgBox &amp;quot;Grid(3,3)=&amp;quot; &amp;amp; Grid1.getValue(3,3)&lt;br /&gt;
End Function&lt;br /&gt;
 &lt;br /&gt;
Function Grid1_onclick()&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;)&lt;br /&gt;
  MsgBox &amp;quot;Click on &amp;quot; &amp;amp; s(0) &amp;amp; &amp;quot; at row &amp;quot; &amp;amp; s(1) &amp;amp; &amp;quot; and column &amp;quot; &amp;amp; s(2)&lt;br /&gt;
  MsgBox &amp;quot;Value is &amp;quot; &amp;amp; Grid1.getValue(s(1),s(2))&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell(1,1).style.backgroundColor=&amp;quot;red&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 1 (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for(row=0; row &amp;lt;= 3; row++) {&lt;br /&gt;
  for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
    Grid1.setValue(row,col,row*col);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Button1.onclick = function() {&lt;br /&gt;
  alert(&amp;quot;Grid[3,3]=&amp;quot; + Grid1.getValue(3,3));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Grid1.onclick = function() {&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;);&lt;br /&gt;
  alert(&amp;quot;Click on &amp;quot; + s[0] +  &amp;quot; at row &amp;quot; +  s[1] + &amp;quot; and column &amp;quot; +  s[2]);&lt;br /&gt;
  alert(&amp;quot;Value is &amp;quot; + Grid1.getValue(s[1] ,s[2]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell[1,1].style.backgroundColor=&amp;quot;red&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (Basic) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;)&lt;br /&gt;
 &#039;Add 100 rows with 4 cols to the grid.&lt;br /&gt;
 For row=1 To 100&lt;br /&gt;
   Grid1.addRows(1)&lt;br /&gt;
   Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;)&lt;br /&gt;
   For col=0 To 3&lt;br /&gt;
     If col = 0 Then&lt;br /&gt;
         Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row)&lt;br /&gt;
     Else&lt;br /&gt;
         Grid1.setValue(row,col,row*col)&lt;br /&gt;
     End If&lt;br /&gt;
     &#039;Paints each row in alernating color.&lt;br /&gt;
     If (Abs(row) % 2) = 1 Then&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
     Else&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
     End If&lt;br /&gt;
   Next&lt;br /&gt;
 Next&lt;br /&gt;
 Grid1.refresh()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (JavaScript) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
  Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;);&lt;br /&gt;
  //Add 100 rows with 4 cols to the grid.&lt;br /&gt;
  for(row=1; row &amp;lt;= 100; row++) {&lt;br /&gt;
    Grid1.addRows(1);&lt;br /&gt;
    Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;);&lt;br /&gt;
    for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
      if(col == 0) {&lt;br /&gt;
        Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.setValue(row,col,row*col);&lt;br /&gt;
      }&lt;br /&gt;
      //Paints each row in alernating color.&lt;br /&gt;
      if((Math.abs(row) % 2) == 1) {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  Grid1.refresh();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(&amp;quot;#Grid1 td&amp;quot;).css(&amp;quot;font-family&amp;quot;, &amp;quot;Courier New&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (BASIC) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For i = 0 To Grid1.children[0].children.length - 1&lt;br /&gt;
  For j = 0 To Grid1.children[0].children[i].children.length - 1&lt;br /&gt;
    Grid1.children[0].children[i].children[j].style.fontFamily=&amp;quot;Courier new&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Output ==&lt;br /&gt;
&lt;br /&gt;
[[file:GridOutput.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Controls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Common]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4220</id>
		<title>Grid</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4220"/>
		<updated>2013-11-03T03:03:03Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:Grid.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The Grid control is used to display data in a table. To add a Grid to your app, choose the Grid icon in the Toolbar. Use the Property Editor to set the properties. &lt;br /&gt;
&lt;br /&gt;
The onclick event can be used to check for clicks. Check event.target.id to find out which cell was clicked.&lt;br /&gt;
&lt;br /&gt;
The width of the grid is set to the total of the pixel widths of the columns, if supplied. Otherwise, it is full width.&lt;br /&gt;
&lt;br /&gt;
If you set the style of the grid to ‘table-layout:fixed;’ it will force the able to maintain cell widths. If the data is too big, it will overflow to the next cell, as in Excel.&lt;br /&gt;
&lt;br /&gt;
If you change the size of a control with scrolling enabled at runtime (by doing addCols or deleteRows, etc.), you need to recalulate the size of the scrolling area by doing &#039;&#039;controlname&#039;&#039;.refresh(). This also applies if you load a new form with a Grid on it.  The width may also need to be set. A good place to do this is in the onshow() function of the new form.&lt;br /&gt;
&lt;br /&gt;
  Grid1.refresh()&lt;br /&gt;
  Grid1.width=&amp;quot;90%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add a control to your app, choose the control’s icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the control: usually, just onclick.&lt;br /&gt;
&lt;br /&gt;
Each cell in the grid has its own id, in the form gridId_x_y. The id of the top left element of Grid1 is Grid1_0_0.&lt;br /&gt;
&lt;br /&gt;
To make a row column combination bold, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.fontWeight = &amp;quot;bold&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To align a row column combination, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.cell(1,0).style.textAlign = &amp;quot;right&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To put an image in a grid cell, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.setValue(0,1,&amp;quot;&amp;lt;img src=&#039;mario.jpg&#039; id=&#039;Grid1_0_1&#039;&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
The 0_1 in the ID should have the same column and row as the first two arguments.&lt;br /&gt;
&lt;br /&gt;
To scroll to the top of the grid (row 1), do the following:&lt;br /&gt;
  &lt;br /&gt;
  Grid1_ref.scrollTo(0, 0)&lt;br /&gt;
&lt;br /&gt;
== Properties and Methods ==&lt;br /&gt;
&lt;br /&gt;
Standard [[properties and methods|properties]] are supported, plus:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| addCols(&#039;&#039;n&#039;&#039;) || Add &#039;&#039;n&#039;&#039; columns to the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| addRows(&#039;&#039;n&#039;&#039;) || Adds &#039;&#039;n&#039;&#039; rows to the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| alignments || The alignment of the data in each column. Can be left, right, center, justify or char=”.”. Optional. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| cell(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;) || Returns a reference to cell x,y.&lt;br /&gt;
|-&lt;br /&gt;
| cellstyle || The style of each cell in the grid. Use cell(x,y).style at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| cols || The number of columns in the table. (Design time only) &lt;br /&gt;
|-&lt;br /&gt;
| colwidths || The width of each column, in pixels (100px), comma separated. Design time only.&lt;br /&gt;
|-&lt;br /&gt;
| deleteCols(&#039;&#039;n&#039;&#039;) || Deletes &#039;&#039;n&#039;&#039; columns from the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| deleteRows(&#039;&#039;n&#039;&#039;) || Delete n rows from the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| getColCount() || Returns the number of columns.&lt;br /&gt;
|-&lt;br /&gt;
| getRowCount() || Returns the number of rows.&lt;br /&gt;
|-&lt;br /&gt;
| getValue(&#039;&#039;row&#039;&#039;,&#039;&#039;col&#039;&#039;) || Get the current value of a cell.&lt;br /&gt;
|-&lt;br /&gt;
| rowheights || The height of each row, in pixels (20px) or percentages (20%), comma separated. Read only at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| refresh() || Recalculate the scrolling area after additions or deletions. Used for scrolling grids only.&lt;br /&gt;
|-&lt;br /&gt;
| rows || The number of rows in the table. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| scroll_options || This control makes use of iScroll. It has a number of options, including:&lt;br /&gt;
&lt;br /&gt;
bounce: true/false. When the end of the scroll area is reached, should the image bounce?&lt;br /&gt;
&lt;br /&gt;
zoom: true/false. Allow two finger zoom in gesture?&lt;br /&gt;
&lt;br /&gt;
The full list of options is documented here: http://cubiq.org/iscroll-4&lt;br /&gt;
|-&lt;br /&gt;
| scrolling || Allow choices in the menu to scroll? On or off. (design time)&lt;br /&gt;
|-&lt;br /&gt;
| setColumnWidth(&#039;&#039;col&#039;&#039;, &#039;&#039;width&#039;&#039;)  || Sets the width of &#039;&#039;col&#039;&#039; to &#039;&#039;width&#039;&#039;. Needs to be done to all columns to be effective.&lt;br /&gt;
|-&lt;br /&gt;
| setRowHeight(&#039;&#039;row&#039;&#039;, &#039;&#039;height&#039;&#039;) || Sets the height of &#039;&#039;row&#039;&#039; to &#039;&#039;height&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setValue(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;, &#039;&#039;value&#039;&#039;) || Set the &#039;&#039;value&#039;&#039; of a cell. Can be string or HTML.&lt;br /&gt;
|-&lt;br /&gt;
| titles || The titles for each column, comma separated. Optional. (Design time only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
&lt;br /&gt;
Grid supports the standard [[events|events]].&lt;br /&gt;
&lt;br /&gt;
== Example 1 (Basic) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For row=0 to 3&lt;br /&gt;
  For col=0 to 3&lt;br /&gt;
    Grid1.setValue(row,col,row*col)&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
 &lt;br /&gt;
Function Button1_onclick()&lt;br /&gt;
  MsgBox &amp;quot;Grid(3,3)=&amp;quot; &amp;amp; Grid1.getValue(3,3)&lt;br /&gt;
End Function&lt;br /&gt;
 &lt;br /&gt;
Function Grid1_onclick()&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;)&lt;br /&gt;
  MsgBox &amp;quot;Click on &amp;quot; &amp;amp; s(0) &amp;amp; &amp;quot; at row &amp;quot; &amp;amp; s(1) &amp;amp; &amp;quot; and column &amp;quot; &amp;amp; s(2)&lt;br /&gt;
  MsgBox &amp;quot;Value is &amp;quot; &amp;amp; Grid1.getValue(s(1),s(2))&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell(1,1).style.backgroundColor=&amp;quot;red&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 1 (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for(row=0; row &amp;lt;= 3; row++) {&lt;br /&gt;
  for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
    Grid1.setValue(row,col,row*col);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Button1.onclick = function() {&lt;br /&gt;
  alert(&amp;quot;Grid[3,3]=&amp;quot; + Grid1.getValue(3,3));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Grid1.onclick = function() {&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;);&lt;br /&gt;
  alert(&amp;quot;Click on &amp;quot; + s[0] +  &amp;quot; at row &amp;quot; +  s[1] + &amp;quot; and column &amp;quot; +  s[2]);&lt;br /&gt;
  alert(&amp;quot;Value is &amp;quot; + Grid1.getValue(s[1] ,s[2]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell[1,1].style.backgroundColor=&amp;quot;red&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (Basic) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;)&lt;br /&gt;
 &#039;Add 100 rows with 4 cols to the grid.&lt;br /&gt;
 For row=1 To 100&lt;br /&gt;
   Grid1.addRows(1)&lt;br /&gt;
   Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;)&lt;br /&gt;
   For col=0 To 3&lt;br /&gt;
     If col = 0 Then&lt;br /&gt;
         Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row)&lt;br /&gt;
     Else&lt;br /&gt;
         Grid1.setValue(row,col,row*col)&lt;br /&gt;
     End If&lt;br /&gt;
     &#039;Paints each row in alernating color.&lt;br /&gt;
     If (Abs(row) % 2) = 1 Then&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
     Else&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
     End If&lt;br /&gt;
   Next&lt;br /&gt;
 Next&lt;br /&gt;
 Grid1.refresh()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (JavaScript) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
  Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;);&lt;br /&gt;
  //Add 100 rows with 4 cols to the grid.&lt;br /&gt;
  for(row=1; row &amp;lt;= 100; row++) {&lt;br /&gt;
    Grid1.addRows(1);&lt;br /&gt;
    Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;);&lt;br /&gt;
    for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
      if(col == 0) {&lt;br /&gt;
        Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.setValue(row,col,row*col);&lt;br /&gt;
      }&lt;br /&gt;
      //Paints each row in alernating color.&lt;br /&gt;
      if((Math.abs(row) % 2) == 1) {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  Grid1.refresh();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(&amp;quot;#Grid1 td&amp;quot;).css(&amp;quot;font-family&amp;quot;, &amp;quot;Courier New&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (BASIC) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For i = 0 To Grid1.children[0].children.length - 1&lt;br /&gt;
  For j = 0 To Grid1.children[0].children[i].children.length - 1&lt;br /&gt;
    Grid1.children[0].children[i].children[j].style.fontFamily=&amp;quot;Courier new&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Output ==&lt;br /&gt;
&lt;br /&gt;
[[file:GridOutput.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Controls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Common]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4219</id>
		<title>Grid</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4219"/>
		<updated>2013-11-03T02:48:22Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Example 2 (Basic) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:Grid.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The Grid control is used to display data in a table. To add a Grid to your app, choose the Grid icon in the Toolbar. Use the Property Editor to set the properties. &lt;br /&gt;
&lt;br /&gt;
The onclick event can be used to check for clicks. Check event.target.id to find out which cell was clicked.&lt;br /&gt;
&lt;br /&gt;
The width of the grid is set to the total of the pixel widths of the columns, if supplied. Otherwise, it is full width.&lt;br /&gt;
&lt;br /&gt;
If you set the style of the grid to ‘table-layout:fixed;’ it will force the able to maintain cell widths. If the data is too big, it will overflow to the next cell, as in Excel.&lt;br /&gt;
&lt;br /&gt;
If you change the size of a control with scrolling enabled at runtime (by doing addCols or deleteRows, etc.), you need to recalulate the size of the scrolling area by doing &#039;&#039;controlname&#039;&#039;.refresh(). This also applies if you load a new form with a Grid on it.  The width may also need to be set. A good place to do this is in the onshow() function of the new form.&lt;br /&gt;
&lt;br /&gt;
  Grid1.refresh()&lt;br /&gt;
  Grid1.width=&amp;quot;90%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To add a control to your app, choose the control’s icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the control: usually, just onclick.&lt;br /&gt;
&lt;br /&gt;
Each cell in the grid has its own id, in the form gridId_x_y. The id of the top left element of Grid1 is Grid1_0_0.&lt;br /&gt;
&lt;br /&gt;
To put an image in a grid cell, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.setValue(0,1,&amp;quot;&amp;lt;img src=&#039;mario.jpg&#039; id=&#039;Grid1_0_1&#039;&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
The 0_1 in the ID should have the same column and row as the first two arguments.&lt;br /&gt;
&lt;br /&gt;
To scroll to the top of the grid (row 1), do the following:&lt;br /&gt;
  &lt;br /&gt;
  Grid1_ref.scrollTo(0, 0)&lt;br /&gt;
&lt;br /&gt;
== Properties and Methods ==&lt;br /&gt;
&lt;br /&gt;
Standard [[properties and methods|properties]] are supported, plus:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| addCols(&#039;&#039;n&#039;&#039;) || Add &#039;&#039;n&#039;&#039; columns to the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| addRows(&#039;&#039;n&#039;&#039;) || Adds &#039;&#039;n&#039;&#039; rows to the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| alignments || The alignment of the data in each column. Can be left, right, center, justify or char=”.”. Optional. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| cell(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;) || Returns a reference to cell x,y.&lt;br /&gt;
|-&lt;br /&gt;
| cellstyle || The style of each cell in the grid. Use cell(x,y).style at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| cols || The number of columns in the table. (Design time only) &lt;br /&gt;
|-&lt;br /&gt;
| colwidths || The width of each column, in pixels (100px), comma separated. Design time only.&lt;br /&gt;
|-&lt;br /&gt;
| deleteCols(&#039;&#039;n&#039;&#039;) || Deletes &#039;&#039;n&#039;&#039; columns from the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| deleteRows(&#039;&#039;n&#039;&#039;) || Delete n rows from the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| getColCount() || Returns the number of columns.&lt;br /&gt;
|-&lt;br /&gt;
| getRowCount() || Returns the number of rows.&lt;br /&gt;
|-&lt;br /&gt;
| getValue(&#039;&#039;row&#039;&#039;,&#039;&#039;col&#039;&#039;) || Get the current value of a cell.&lt;br /&gt;
|-&lt;br /&gt;
| rowheights || The height of each row, in pixels (20px) or percentages (20%), comma separated. Read only at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| refresh() || Recalculate the scrolling area after additions or deletions. Used for scrolling grids only.&lt;br /&gt;
|-&lt;br /&gt;
| rows || The number of rows in the table. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| scroll_options || This control makes use of iScroll. It has a number of options, including:&lt;br /&gt;
&lt;br /&gt;
bounce: true/false. When the end of the scroll area is reached, should the image bounce?&lt;br /&gt;
&lt;br /&gt;
zoom: true/false. Allow two finger zoom in gesture?&lt;br /&gt;
&lt;br /&gt;
The full list of options is documented here: http://cubiq.org/iscroll-4&lt;br /&gt;
|-&lt;br /&gt;
| scrolling || Allow choices in the menu to scroll? On or off. (design time)&lt;br /&gt;
|-&lt;br /&gt;
| setColumnWidth(&#039;&#039;col&#039;&#039;, &#039;&#039;width&#039;&#039;)  || Sets the width of &#039;&#039;col&#039;&#039; to &#039;&#039;width&#039;&#039;. Needs to be done to all columns to be effective.&lt;br /&gt;
|-&lt;br /&gt;
| setRowHeight(&#039;&#039;row&#039;&#039;, &#039;&#039;height&#039;&#039;) || Sets the height of &#039;&#039;row&#039;&#039; to &#039;&#039;height&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setValue(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;, &#039;&#039;value&#039;&#039;) || Set the &#039;&#039;value&#039;&#039; of a cell. Can be string or HTML.&lt;br /&gt;
|-&lt;br /&gt;
| titles || The titles for each column, comma separated. Optional. (Design time only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
&lt;br /&gt;
Grid supports the standard [[events|events]].&lt;br /&gt;
&lt;br /&gt;
== Example 1 (Basic) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For row=0 to 3&lt;br /&gt;
  For col=0 to 3&lt;br /&gt;
    Grid1.setValue(row,col,row*col)&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
 &lt;br /&gt;
Function Button1_onclick()&lt;br /&gt;
  MsgBox &amp;quot;Grid(3,3)=&amp;quot; &amp;amp; Grid1.getValue(3,3)&lt;br /&gt;
End Function&lt;br /&gt;
 &lt;br /&gt;
Function Grid1_onclick()&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;)&lt;br /&gt;
  MsgBox &amp;quot;Click on &amp;quot; &amp;amp; s(0) &amp;amp; &amp;quot; at row &amp;quot; &amp;amp; s(1) &amp;amp; &amp;quot; and column &amp;quot; &amp;amp; s(2)&lt;br /&gt;
  MsgBox &amp;quot;Value is &amp;quot; &amp;amp; Grid1.getValue(s(1),s(2))&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell(1,1).style.backgroundColor=&amp;quot;red&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 1 (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for(row=0; row &amp;lt;= 3; row++) {&lt;br /&gt;
  for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
    Grid1.setValue(row,col,row*col);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Button1.onclick = function() {&lt;br /&gt;
  alert(&amp;quot;Grid[3,3]=&amp;quot; + Grid1.getValue(3,3));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Grid1.onclick = function() {&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;);&lt;br /&gt;
  alert(&amp;quot;Click on &amp;quot; + s[0] +  &amp;quot; at row &amp;quot; +  s[1] + &amp;quot; and column &amp;quot; +  s[2]);&lt;br /&gt;
  alert(&amp;quot;Value is &amp;quot; + Grid1.getValue(s[1] ,s[2]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell[1,1].style.backgroundColor=&amp;quot;red&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (Basic) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;)&lt;br /&gt;
 &#039;Add 100 rows with 4 cols to the grid.&lt;br /&gt;
 For row=1 To 100&lt;br /&gt;
   Grid1.addRows(1)&lt;br /&gt;
   Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;)&lt;br /&gt;
   For col=0 To 3&lt;br /&gt;
     If col = 0 Then&lt;br /&gt;
         Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row)&lt;br /&gt;
     Else&lt;br /&gt;
         Grid1.setValue(row,col,row*col)&lt;br /&gt;
     End If&lt;br /&gt;
     &#039;Paints each row in alernating color.&lt;br /&gt;
     If (Abs(row) % 2) = 1 Then&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
     Else&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
     End If&lt;br /&gt;
   Next&lt;br /&gt;
 Next&lt;br /&gt;
 Grid1.refresh()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (JavaScript) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
  Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;);&lt;br /&gt;
  //Add 100 rows with 4 cols to the grid.&lt;br /&gt;
  for(row=1; row &amp;lt;= 100; row++) {&lt;br /&gt;
    Grid1.addRows(1);&lt;br /&gt;
    Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;);&lt;br /&gt;
    for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
      if(col == 0) {&lt;br /&gt;
        Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.setValue(row,col,row*col);&lt;br /&gt;
      }&lt;br /&gt;
      //Paints each row in alernating color.&lt;br /&gt;
      if((Math.abs(row) % 2) == 1) {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  Grid1.refresh();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(&amp;quot;#Grid1 td&amp;quot;).css(&amp;quot;font-family&amp;quot;, &amp;quot;Courier New&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (BASIC) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For i = 0 To Grid1.children[0].children.length - 1&lt;br /&gt;
  For j = 0 To Grid1.children[0].children[i].children.length - 1&lt;br /&gt;
    Grid1.children[0].children[i].children[j].style.fontFamily=&amp;quot;Courier new&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Output ==&lt;br /&gt;
&lt;br /&gt;
[[file:GridOutput.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Controls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Common]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4218</id>
		<title>Grid</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Grid&amp;diff=4218"/>
		<updated>2013-11-03T02:47:05Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Example 2 (JavaScript) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:Grid.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The Grid control is used to display data in a table. To add a Grid to your app, choose the Grid icon in the Toolbar. Use the Property Editor to set the properties. &lt;br /&gt;
&lt;br /&gt;
The onclick event can be used to check for clicks. Check event.target.id to find out which cell was clicked.&lt;br /&gt;
&lt;br /&gt;
The width of the grid is set to the total of the pixel widths of the columns, if supplied. Otherwise, it is full width.&lt;br /&gt;
&lt;br /&gt;
If you set the style of the grid to ‘table-layout:fixed;’ it will force the able to maintain cell widths. If the data is too big, it will overflow to the next cell, as in Excel.&lt;br /&gt;
&lt;br /&gt;
If you change the size of a control with scrolling enabled at runtime (by doing addCols or deleteRows, etc.), you need to recalulate the size of the scrolling area by doing &#039;&#039;controlname&#039;&#039;.refresh(). This also applies if you load a new form with a Grid on it.  The width may also need to be set. A good place to do this is in the onshow() function of the new form.&lt;br /&gt;
&lt;br /&gt;
  Grid1.refresh()&lt;br /&gt;
  Grid1.width=&amp;quot;90%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
To add a control to your app, choose the control’s icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the control: usually, just onclick.&lt;br /&gt;
&lt;br /&gt;
Each cell in the grid has its own id, in the form gridId_x_y. The id of the top left element of Grid1 is Grid1_0_0.&lt;br /&gt;
&lt;br /&gt;
To put an image in a grid cell, do the following:&lt;br /&gt;
&lt;br /&gt;
  Grid1.setValue(0,1,&amp;quot;&amp;lt;img src=&#039;mario.jpg&#039; id=&#039;Grid1_0_1&#039;&amp;gt;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
The 0_1 in the ID should have the same column and row as the first two arguments.&lt;br /&gt;
&lt;br /&gt;
To scroll to the top of the grid (row 1), do the following:&lt;br /&gt;
  &lt;br /&gt;
  Grid1_ref.scrollTo(0, 0)&lt;br /&gt;
&lt;br /&gt;
== Properties and Methods ==&lt;br /&gt;
&lt;br /&gt;
Standard [[properties and methods|properties]] are supported, plus:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| addCols(&#039;&#039;n&#039;&#039;) || Add &#039;&#039;n&#039;&#039; columns to the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| addRows(&#039;&#039;n&#039;&#039;) || Adds &#039;&#039;n&#039;&#039; rows to the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| alignments || The alignment of the data in each column. Can be left, right, center, justify or char=”.”. Optional. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| cell(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;) || Returns a reference to cell x,y.&lt;br /&gt;
|-&lt;br /&gt;
| cellstyle || The style of each cell in the grid. Use cell(x,y).style at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| cols || The number of columns in the table. (Design time only) &lt;br /&gt;
|-&lt;br /&gt;
| colwidths || The width of each column, in pixels (100px), comma separated. Design time only.&lt;br /&gt;
|-&lt;br /&gt;
| deleteCols(&#039;&#039;n&#039;&#039;) || Deletes &#039;&#039;n&#039;&#039; columns from the right of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| deleteRows(&#039;&#039;n&#039;&#039;) || Delete n rows from the end of the table. Default is 1.&lt;br /&gt;
|-&lt;br /&gt;
| getColCount() || Returns the number of columns.&lt;br /&gt;
|-&lt;br /&gt;
| getRowCount() || Returns the number of rows.&lt;br /&gt;
|-&lt;br /&gt;
| getValue(&#039;&#039;row&#039;&#039;,&#039;&#039;col&#039;&#039;) || Get the current value of a cell.&lt;br /&gt;
|-&lt;br /&gt;
| rowheights || The height of each row, in pixels (20px) or percentages (20%), comma separated. Read only at runtime.&lt;br /&gt;
|-&lt;br /&gt;
| refresh() || Recalculate the scrolling area after additions or deletions. Used for scrolling grids only.&lt;br /&gt;
|-&lt;br /&gt;
| rows || The number of rows in the table. (Design time only)&lt;br /&gt;
|-&lt;br /&gt;
| scroll_options || This control makes use of iScroll. It has a number of options, including:&lt;br /&gt;
&lt;br /&gt;
bounce: true/false. When the end of the scroll area is reached, should the image bounce?&lt;br /&gt;
&lt;br /&gt;
zoom: true/false. Allow two finger zoom in gesture?&lt;br /&gt;
&lt;br /&gt;
The full list of options is documented here: http://cubiq.org/iscroll-4&lt;br /&gt;
|-&lt;br /&gt;
| scrolling || Allow choices in the menu to scroll? On or off. (design time)&lt;br /&gt;
|-&lt;br /&gt;
| setColumnWidth(&#039;&#039;col&#039;&#039;, &#039;&#039;width&#039;&#039;)  || Sets the width of &#039;&#039;col&#039;&#039; to &#039;&#039;width&#039;&#039;. Needs to be done to all columns to be effective.&lt;br /&gt;
|-&lt;br /&gt;
| setRowHeight(&#039;&#039;row&#039;&#039;, &#039;&#039;height&#039;&#039;) || Sets the height of &#039;&#039;row&#039;&#039; to &#039;&#039;height&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| setValue(&#039;&#039;row&#039;&#039;, &#039;&#039;col&#039;&#039;, &#039;&#039;value&#039;&#039;) || Set the &#039;&#039;value&#039;&#039; of a cell. Can be string or HTML.&lt;br /&gt;
|-&lt;br /&gt;
| titles || The titles for each column, comma separated. Optional. (Design time only)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Events ==&lt;br /&gt;
&lt;br /&gt;
Grid supports the standard [[events|events]].&lt;br /&gt;
&lt;br /&gt;
== Example 1 (Basic) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For row=0 to 3&lt;br /&gt;
  For col=0 to 3&lt;br /&gt;
    Grid1.setValue(row,col,row*col)&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
 &lt;br /&gt;
Function Button1_onclick()&lt;br /&gt;
  MsgBox &amp;quot;Grid(3,3)=&amp;quot; &amp;amp; Grid1.getValue(3,3)&lt;br /&gt;
End Function&lt;br /&gt;
 &lt;br /&gt;
Function Grid1_onclick()&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;)&lt;br /&gt;
  MsgBox &amp;quot;Click on &amp;quot; &amp;amp; s(0) &amp;amp; &amp;quot; at row &amp;quot; &amp;amp; s(1) &amp;amp; &amp;quot; and column &amp;quot; &amp;amp; s(2)&lt;br /&gt;
  MsgBox &amp;quot;Value is &amp;quot; &amp;amp; Grid1.getValue(s(1),s(2))&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell(1,1).style.backgroundColor=&amp;quot;red&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 1 (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for(row=0; row &amp;lt;= 3; row++) {&lt;br /&gt;
  for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
    Grid1.setValue(row,col,row*col);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Button1.onclick = function() {&lt;br /&gt;
  alert(&amp;quot;Grid[3,3]=&amp;quot; + Grid1.getValue(3,3));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Grid1.onclick = function() {&lt;br /&gt;
  s=Split(event.target.id, &amp;quot;_&amp;quot;);&lt;br /&gt;
  alert(&amp;quot;Click on &amp;quot; + s[0] +  &amp;quot; at row &amp;quot; +  s[1] + &amp;quot; and column &amp;quot; +  s[2]);&lt;br /&gt;
  alert(&amp;quot;Value is &amp;quot; + Grid1.getValue(s[1] ,s[2]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the color of a cell:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Grid1.cell[1,1].style.backgroundColor=&amp;quot;red&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (Basic) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Grid1.setRowHeight(0, &amp;quot;18px&amp;quot;)&lt;br /&gt;
 &#039;Add 100 rows with 4 cols to the grid.&lt;br /&gt;
 For row=1 To 100&lt;br /&gt;
   Grid1.addRows(1)&lt;br /&gt;
   Grid1.setRowHeight(0, &amp;quot;14px&amp;quot;)&lt;br /&gt;
   For col=0 To 3&lt;br /&gt;
     If col = 0 Then&lt;br /&gt;
         Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row)&lt;br /&gt;
     Else&lt;br /&gt;
         Grid1.setValue(row,col,row*col)&lt;br /&gt;
     End If&lt;br /&gt;
     &#039;Paints each row in alernating color.&lt;br /&gt;
     If (Abs(row) % 2) = 1 Then&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240)&lt;br /&gt;
     Else&lt;br /&gt;
       Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255)&lt;br /&gt;
     End If&lt;br /&gt;
   Next&lt;br /&gt;
 Next&lt;br /&gt;
 Grid1.refresh()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example 2 (JavaScript) ==&lt;br /&gt;
This sample code will add 100 rows to a grid with 4 columns and it will alternate the row colors.&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
  Grid1.setRowHeight(0, &amp;quot;40px&amp;quot;);&lt;br /&gt;
  //Add 100 rows with 4 cols to the grid.&lt;br /&gt;
  for(row=1; row &amp;lt;= 100; row++) {&lt;br /&gt;
    Grid1.addRows(1);&lt;br /&gt;
    Grid1.setRowHeight(row, &amp;quot;32px&amp;quot;);&lt;br /&gt;
    for(col=0; col &amp;lt;= 3; col++) {&lt;br /&gt;
      if(col == 0) {&lt;br /&gt;
        Grid1.setValue(row,col,&amp;quot;Row &amp;quot; + row);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.setValue(row,col,row*col);&lt;br /&gt;
      }&lt;br /&gt;
      //Paints each row in alernating color.&lt;br /&gt;
      if((Math.abs(row) % 2) == 1) {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(255,255,240);&lt;br /&gt;
      } else {&lt;br /&gt;
        Grid1.cell(row,col).style.backgroundColor = RGB(240,248,255);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  Grid1.refresh();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (JavaScript) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(&amp;quot;#Grid1 td&amp;quot;).css(&amp;quot;font-family&amp;quot;, &amp;quot;Courier New&amp;quot;) &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Grid Font (BASIC) ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
For i = 0 To Grid1.children[0].children.length - 1&lt;br /&gt;
  For j = 0 To Grid1.children[0].children[i].children.length - 1&lt;br /&gt;
    Grid1.children[0].children[i].children[j].style.fontFamily=&amp;quot;Courier new&amp;quot;&lt;br /&gt;
  Next&lt;br /&gt;
Next&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Output ==&lt;br /&gt;
&lt;br /&gt;
[[file:GridOutput.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Language Reference]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Controls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Common]]&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Using_SQLite&amp;diff=4209</id>
		<title>Using SQLite</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Using_SQLite&amp;diff=4209"/>
		<updated>2013-10-30T22:38:08Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: /* Persisting Updates to the Database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SQLite is a fast, popular and easy to use database. Its speed and easy of use make it a practical choice for use when you need an indexed file system for an app. Databases you create can be accessed, without change, on any platform SQLite supports. It is built into mobile devices that AppStudio supports.&lt;br /&gt;
&lt;br /&gt;
If you just need to save some simple data, without needing an index, have a look at using [[localStorage]].&lt;br /&gt;
&lt;br /&gt;
SQLite is a zero-configuration, in-process, SQL database engine. But don&#039;t let this description scare you: SQLite is an easy way for your app to store and retrieve data.&lt;br /&gt;
&lt;br /&gt;
Your app can create, update and delete SQLite databases. The databases are kept in your app&#039;s private directory. Generally, an app is not allowed to access databases belonging to other apps for security reasons. However, apps deployed from the same server can share databases. This allows you to create a family of apps which share data, so long as they all come from the same server. The security protects apps from changing or stealing information from other app&#039;s databases.&lt;br /&gt;
&lt;br /&gt;
Databases cannot be directly imported or exported, once again, for security reasons. However, it is possible to [[Distributing_your_App#The_Manifest_File|include an SQLite database]] with your application. Add the name of the database to the manifest in [[Properties Window]] and it will be automatically converted in to a format that can be exported from the server. The app will then import the database automatically when the application starts for the first time. To do this, the [[SqlExport|SQLExport]] and [[SqlImport|SQLImport]] methods are called internally. These methods are also available for use at any time.&lt;br /&gt;
&lt;br /&gt;
There are two sets of commands: the ones AppStudio uses to call SQLite and the SQLite commands themselves. Documentation on AppStudio&#039;s commands are in this Tech Note; documentation on SQLite itself is in the [[SQLite Reference]].&lt;br /&gt;
&lt;br /&gt;
=== Persisting Updates to the Database ===&lt;br /&gt;
&lt;br /&gt;
If you have an already defined database that you want to include with your application, to ensure that updates to your database are persisted, one needs to ensure that the &amp;quot;manifest&amp;quot; property of the project is properly set. When the database is specified in the manifest property, its uploaded to the application when the application is first run just like the SQLImport statement.&lt;br /&gt;
&lt;br /&gt;
The SQLImport function uses this statement for example, SQLImport(JSON, [DB], [callback], [overwrite]), and your &amp;quot;manifest&amp;quot; property should be in line with this for your updates to be considered when your application is run, an example would be &#039;mydb.db,dbObj,callBackMethod,NSB.overwriteIfVersionDifferent&#039;. &lt;br /&gt;
&lt;br /&gt;
NB: If on this property only the database name is specified that should be included with the application, any changes made during the application run, whilst they will be reflected in your application, the problem is that the next time you start the application, all your updates will not exist.&lt;br /&gt;
&lt;br /&gt;
=== Asynchronous Results ===&lt;br /&gt;
&lt;br /&gt;
The results of calls to the database are returned asynchronously. That means that after a statement involving the database is executed, the next statement in the program is executed - even though the database operation may not be complete. The database operation continues on its own. When it finishes, it will call a function you specify in your program, depending on the success or failure of the operation. In the meantime, you can do other processing: update controls on the screen or do calculations. You cannot do a [[MsgBox]] statement while you are waiting for an SQL call to finish - you will lose the callback.&lt;br /&gt;
&lt;br /&gt;
Consider the following code:&lt;br /&gt;
&lt;br /&gt;
    MsgBox &amp;quot;Before doing call&amp;quot;&lt;br /&gt;
    sqlList=&amp;quot;CREATE TABLE myData(&#039;name&#039;, &#039;age&#039;)&amp;quot;&lt;br /&gt;
    sql(DB, [sqlList, Success_Function, Fail_Function])&lt;br /&gt;
    Msgbox &amp;quot;After doing call&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    Function Success_Function(transaction, result)&lt;br /&gt;
      Msgbox &amp;quot;Success - result received&amp;quot;&lt;br /&gt;
    End function&lt;br /&gt;
 &lt;br /&gt;
    Function Fail_Function(transaction, result)&lt;br /&gt;
      Msgbox &amp;quot;Fail&amp;quot;&lt;br /&gt;
    End function&lt;br /&gt;
&lt;br /&gt;
The result will be 3 messages, in this order:&lt;br /&gt;
&lt;br /&gt;
    &amp;quot;Before doing call&amp;quot;&lt;br /&gt;
    &amp;quot;After doing call&amp;quot;&lt;br /&gt;
    &amp;quot;Success - result received&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Transactions ===&lt;br /&gt;
&lt;br /&gt;
When doing multiple operations on a database, for example, adding a number of new records, it is much faster to group them into a transaction. A transaction is a list of database operations that are performed as a set: each of the operations on the list has to successful. If any one step fails, the entire transaction can be aborted without change to the database.&lt;br /&gt;
&lt;br /&gt;
A transaction is implemented as an array, with one operation in each element of the array.&lt;br /&gt;
&lt;br /&gt;
Example: Add 3 new records into customerData&lt;br /&gt;
&lt;br /&gt;
    sqlList = []&lt;br /&gt;
    sqlList[0]=&amp;quot;INSERT INTO customerData (name,age,sales) VALUES (&#039;Haley&#039;,16,121)&amp;quot;&lt;br /&gt;
    sqlList[1]=&amp;quot;INSERT INTO customerData (name,age,sales) VALUES (&#039;Alex&#039;,12,80)&amp;quot;&lt;br /&gt;
    sqlList[2]=&amp;quot;INSERT INTO customerData (name,age,sales) VALUES (&#039;Luke&#039;,7,65)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Each operation in a transaction can have optional success and fail callbacks. In this case, the element in transaction array is itself an array:&lt;br /&gt;
&lt;br /&gt;
[&#039;&#039;operation&#039;&#039;, &#039;&#039;success&#039;&#039;, &#039;&#039;fail&#039;&#039;] , where &#039;&#039;operation&#039;&#039; is a string. &#039;&#039;success&#039;&#039; and &#039;&#039;fail&#039;&#039; are functions in the program. You are required to have at least a &#039;&#039;success&#039;&#039; function defined in your program.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 &lt;br /&gt;
   sqlList[3]=array(&amp;quot;Select * from customerData&amp;quot;, Success_Function, Fail_Function)&lt;br /&gt;
&lt;br /&gt;
==== Opening the database file using SqlOpenDatabase() ====&lt;br /&gt;
&lt;br /&gt;
SQLite keeps the entire database in a single physical file. Use the [[SqlOpenDatabase]] method to open the file. If it does not exist, it is created:&lt;br /&gt;
 &lt;br /&gt;
    DB = SqlOpenDatabase(&amp;quot;customers.db&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;My Customer Database&amp;quot;)&lt;br /&gt;
    If DB.version&amp;lt;&amp;gt;&amp;quot;&amp;quot; Then Print &amp;quot;Database Opened&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The return value, DB, will be used to identify the database in subsequent calls. If the database does not exist, it is created. Here is the full syntax of SqlOpenDatabase:&lt;br /&gt;
&lt;br /&gt;
res = &#039;&#039;&#039;SqlOpenDatabase(&#039;&#039;&#039;&#039;&#039;filename, version, fullname, maxsize&#039;&#039;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;filename&#039;&#039; is the actual name of the file&lt;br /&gt;
* &#039;&#039;version&#039;&#039; is the version number (optional). Used on file creation. Set to &amp;quot;1.0&amp;quot; if no value supplied.&lt;br /&gt;
* &#039;&#039;fullname&#039;&#039; is a long description of the file. (optional). Used on file creation. Set to &#039;&#039;filename&#039;&#039; if no value supplied.&lt;br /&gt;
* &#039;&#039;maxsize&#039;&#039; is the maximum number of records (optional). Used on file creation. Set to 1,000,000 if no value supplied.&lt;br /&gt;
&lt;br /&gt;
====  Create a table in the database ====&lt;br /&gt;
&lt;br /&gt;
After step 1 creates a new database file, it is empty. A database is made up of tables. A table is simply a collection of records with a defined format. Let&#039;s create the table, but first, let&#039;s get rid of any existing table with the same name.&lt;br /&gt;
 &lt;br /&gt;
   sqlList=[]&lt;br /&gt;
   sqlList[0]=[&amp;quot;DROP TABLE customerData;&amp;quot;,,skipError]&lt;br /&gt;
   sqlList[1]=[&amp;quot;CREATE TABLE customerData(&#039;name&#039;, &#039;age&#039;, &#039;sales&#039;, PRIMARY KEY(&#039;name&#039;) );&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
   Sql(DB, sqlList)&lt;br /&gt;
&lt;br /&gt;
We&#039;re creating a table with three columns, indexed by the first name: each record therefore has 3 fields. The [[Sql]] statement is used to send a transaction (a list of SQL commands) to SQLite. The syntax of Sql is:&lt;br /&gt;
&lt;br /&gt;
  &#039;&#039;&#039;Sql&#039;&#039;&#039;(&#039;&#039;db, sqlList&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;db&#039;&#039; is the reference to the database returned by SqlOpenDatabase&lt;br /&gt;
* &#039;&#039;sqList&#039;&#039; is an SQLite command or an array of SQLite commands.&lt;br /&gt;
&lt;br /&gt;
====  Add records to the database and select them ====&lt;br /&gt;
 &lt;br /&gt;
   For j = 0 to databaseSize-1&lt;br /&gt;
     sqlList[j]=&amp;quot;INSERT INTO customerData (name, age, sales) VALUES ( &amp;quot; &amp;amp;amp; &amp;quot;&#039;cust&amp;quot; &amp;amp;amp; j &amp;amp;amp; &amp;quot;&#039;, &amp;quot; &amp;amp;amp; j &amp;amp;amp; &amp;quot;, &amp;quot; &amp;amp;amp; j*10 &amp;amp;amp; &amp;quot;);&amp;quot;&lt;br /&gt;
   Next&lt;br /&gt;
   sqlList[databaseSize]=[&amp;quot;SELECT * from customerData ORDER BY name;&amp;quot;, dataHandler]&lt;br /&gt;
 &lt;br /&gt;
   Sql(DB, sqlList)&lt;br /&gt;
&lt;br /&gt;
The SELECT command is very powerful - you can use it to collect all kinds of different sets of records. Read more about it in the [SQLite.htm SQL Documentation].&lt;br /&gt;
&lt;br /&gt;
In the SELECT command, we&#039;re specifying that we want to run a special function when the SELECT completes. The function &amp;lt;code&amp;gt;datahandler&amp;lt;/code&amp;gt; will be called. It gives the result of the SELECT:&lt;br /&gt;
&lt;br /&gt;
   Function dataHandler(transaction, results)&lt;br /&gt;
     // Called on completion of SQL command&lt;br /&gt;
     DBRecords = results&lt;br /&gt;
     message.innerHTML = &amp;quot;Records created: &amp;quot; &amp;amp;amp; DBRecords.rows.length &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; (Sysinfo(10)-startTime) &amp;amp;amp; &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
   End Function&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;dataHandler&amp;lt;/code&amp;gt;, transaction contains information about the last transaction. Results is an array, with one row for each record of the table that is returned.&lt;br /&gt;
&lt;br /&gt;
====  Replace a record in the table ====&lt;br /&gt;
&lt;br /&gt;
   cmd=&amp;quot;INSERT OR REPLACE INTO &amp;quot;&amp;quot;customerData&amp;quot;&amp;quot; VALUES (&amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; tbFirstName.text &amp;amp;amp; &amp;quot;&amp;quot;&amp;quot;,&amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; _&lt;br /&gt;
     tbLastName.text &amp;amp;amp;&amp;quot;&amp;quot;&amp;quot;,&amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; tbAge.text &amp;amp;amp; &amp;quot;&amp;quot;&amp;quot;)&amp;quot;&lt;br /&gt;
   Sql(DB, cmd)&lt;br /&gt;
&lt;br /&gt;
Once again, all the quotes get resolved in the command. The actual command sent to SQLite is:&lt;br /&gt;
&lt;br /&gt;
   INSERT OR REPLACE INTO &amp;quot;customerData&amp;quot; VALUES(&amp;quot;John&amp;quot;,&amp;quot;Kemeny&amp;quot;,&amp;quot;80&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Using the last name as the key, the record is added or replaced. Once again, there are many more options on this command: we&#039;re just trying to get you started here. Once you have added the record, you&#039;ll need to do your selection again. It won&#039;t be automatically added to the existing selection.&lt;br /&gt;
&lt;br /&gt;
==== Update a record ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the simplest case:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Function HeaderBar1_onclick(button)&lt;br /&gt;
  s=Array([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo&#039; WHERE CustomerID=&#039;ALFKI&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
  Sql(DB,s)&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You need to extend it in two ways: update more fields, and update more rows.&lt;br /&gt;
&lt;br /&gt;
To update more fields, add more to the SET clause:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
s=Array([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo&#039;, City=&#039;Toronto&#039; WHERE CustomerID=&#039;ALFKI&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To update more rows, add a new array element for each row:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
s=Array([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo&#039;, City=&#039;Toronto&#039; WHERE CustomerID=&#039;ALFKI&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
s.push([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo2&#039;, City=&#039;New York&#039; WHERE CustomerID=&#039;ANATR&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Delete a record ====&lt;br /&gt;
&lt;br /&gt;
This is pretty easy. Do not use success or fail routine with DELETE.&lt;br /&gt;
&lt;br /&gt;
   cmd=&amp;quot;DELETE FROM customerData WHERE lastname = &amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; tbLastName.Text &amp;amp;amp; &amp;quot;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Sql(DB, cmd)&lt;br /&gt;
&lt;br /&gt;
The command sent to SQLite resolves to:&lt;br /&gt;
&lt;br /&gt;
   DELETE FROM customerData WHERE lastname = &amp;quot;Kemeny&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Closing the Database ====&lt;br /&gt;
&lt;br /&gt;
When you are done using a database, you can close it.&lt;br /&gt;
&lt;br /&gt;
   DB.close&lt;br /&gt;
&lt;br /&gt;
==== Complete Sample ====&lt;br /&gt;
&lt;br /&gt;
&#039;This sample shows how to access SQLite from AppStudio. It can also be found in the Samples folder 2: it is SQLSample1.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dim databaseSize  &#039;number of records in the database&lt;br /&gt;
Dim DB            &#039;the database itself&lt;br /&gt;
Dim startTime     &#039;used for timer&lt;br /&gt;
Dim lastSQL       &#039;the last SQL statement. Useful for debugging.&lt;br /&gt;
Dim total         &#039;use to total sales from customers&lt;br /&gt;
Dim DBRecords     &#039;the last set of records selected from DB&lt;br /&gt;
&lt;br /&gt;
databaseSize=1000&lt;br /&gt;
&lt;br /&gt;
Function btnCreate_onclick()&lt;br /&gt;
  total=0&lt;br /&gt;
  initDB&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function btnCount_onclick()&lt;br /&gt;
  total=0&lt;br /&gt;
  startTime=SysInfo(10)&lt;br /&gt;
  For i=0 To DBRecords.rows.length-1&lt;br /&gt;
    total=total +  DBRecords.rows.item(i)[&amp;quot;sales&amp;quot;]&lt;br /&gt;
  Next&lt;br /&gt;
  txtMessage.value = &amp;quot;Total of &amp;quot; &amp;amp;amp; DBRecords.rows.length &amp;amp;amp; &amp;quot; recs is &amp;quot; &amp;amp;amp; total &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; _&lt;br /&gt;
    (Sysinfo(10)-startTime) &amp;amp;amp; &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function btnRandom_onclick()&lt;br /&gt;
  Dim sqlList&lt;br /&gt;
  startTime=SysInfo(10)&lt;br /&gt;
  total=0&lt;br /&gt;
  sqlList = []&lt;br /&gt;
  For j=0 To databaseSize-1&lt;br /&gt;
    sqlList[j]=[&amp;quot;SELECT * FROM customerData WHERE name=&#039;cust&amp;quot; &amp;amp;amp; Fix(Rnd * databaseSize) &amp;amp;  &amp;quot;&#039;&amp;quot;,Random_Total]&lt;br /&gt;
  Next&lt;br /&gt;
&lt;br /&gt;
  sqlList[databaseSize-1][1]=Random_Complete&lt;br /&gt;
  Sql(DB, sqlList)&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function Random_Total(transaction, results)&lt;br /&gt;
  total=total +  results.rows.item(0)[&amp;quot;sales&amp;quot;]&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function Random_Complete(transaction, results)&lt;br /&gt;
  txtMessage.value =  &amp;quot;Total of &amp;quot; &amp;amp;amp; databaseSize &amp;amp;amp; &amp;quot; random recs is &amp;quot; &amp;amp;amp; total &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; _&lt;br /&gt;
    (Sysinfo(10)-startTime) &amp;amp;amp; &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function initDB()&lt;br /&gt;
  Dim sqlList&lt;br /&gt;
  DB = SqlOpenDatabase(&amp;quot;customerdb.db&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;My Customer Database&amp;quot;)&lt;br /&gt;
  If DB&amp;lt;&amp;gt;0 Then&lt;br /&gt;
    startTime=SysInfo(10)&lt;br /&gt;
    nTables = -1&lt;br /&gt;
    sqlList=[]&lt;br /&gt;
    sqlList[0]=[&amp;quot;SELECT COUNT(*) AS tabCount FROM sqlite_master WHERE type=&#039;table&#039; AND name=&#039;customerData&#039;;&amp;quot;,tableExistCheck,masterErr]&lt;br /&gt;
    Sql(DB, sqlList)&lt;br /&gt;
  End If&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function dataHandler(transaction, results)&lt;br /&gt;
  // Called On completion of Sql command&lt;br /&gt;
  DBRecords = results&lt;br /&gt;
  txtMessage.value = &amp;quot;Recs created: &amp;quot; &amp;amp;amp; DBRecords.rows.length &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; (Sysinfo(10)-startTime) &amp;amp;amp; _&lt;br /&gt;
    &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function skipError(transaction, error)&lt;br /&gt;
  //Called On failure of Sql command&lt;br /&gt;
  MsgBox &amp;quot;SQL Error: &amp;quot; &amp;amp; error.message &amp;amp; &amp;quot; (&amp;quot; &amp;amp; error.code &amp;amp; &amp;quot;)&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function btnDelete_onclick()&lt;br /&gt;
  Dim SQList&lt;br /&gt;
  SQList=[]&lt;br /&gt;
  &#039;Note no success or fail callbacks!&lt;br /&gt;
  SQList[0]=[&amp;quot;DELETE FROM customerData&amp;quot;]&lt;br /&gt;
  SQList[1]=[&amp;quot;SELECT * from customerData ORDER BY name;&amp;quot;, dataHandler]&lt;br /&gt;
  Sql(DB, SQList)&lt;br /&gt;
  txtMessage.value = &amp;quot;All rows deleted.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using the Chrome Debugger to examine databases ===&lt;br /&gt;
&lt;br /&gt;
By opening the Chrome Debugger and using the Resource Tab, you can examine the database. The following example shows a database named customers with a single record containing John Doe&#039;s name, age and sales:&lt;br /&gt;
&lt;br /&gt;
[[File:Sqldebugger.png]]&lt;br /&gt;
&lt;br /&gt;
=== Clearing a Locally-Deployed App Incorporating an SQLite Database From a PC ===&lt;br /&gt;
&lt;br /&gt;
Clearing a remotely-deployed app&#039;s data and SQLite DB from a browser simply involves clearing the browser&#039;s cached app data or content for that app&#039;s domain via the settings panel. However, for a locally-deployed app the process is more involved because the various pieces are stored in multiple locations on the PC. &lt;br /&gt;
&lt;br /&gt;
Here&#039;s a way to eliminate all traces of a locally-deployed app so that it will behave as a freshly installed app on the next deploy:&lt;br /&gt;
&lt;br /&gt;
1. In Chrome Debugger&#039;s console, with the app currently deployed locally, delete all localStorage variables with the localStorage.clear() command. Use the Resources tab, Local Storage, file:// to confirm success.&lt;br /&gt;
&lt;br /&gt;
2. Find the special location where Windows stores SQLite (and other) databases and delete that folder with its contents:&lt;br /&gt;
&lt;br /&gt;
* Windows Vista or 7: \Users\_username_\AppData\Local\Google\Chrome\User Data\Default\databases&lt;br /&gt;
* Windows XP: \Documents and Settings\_username_\Local Settings\Application Data\Google\Chrome\User Data\Default\databases&lt;br /&gt;
* Mac OS X: ~/Library/Application Support/Google/Chrome/Default/databases&lt;br /&gt;
* Linux: ~/.config/google-chrome/Default/databases&lt;br /&gt;
&lt;br /&gt;
3. Delete the app files themselves (html, /nsb folder, etc.) from the Windows system. The location for these is found in the URL/Address window of the Chrome browser itself.  Just drill down using the file explorer and delete the temp folder being used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Contributed by c185driver&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
	<entry>
		<id>https://wiki.appstudio.dev/index.php?title=Using_SQLite&amp;diff=4208</id>
		<title>Using SQLite</title>
		<link rel="alternate" type="text/html" href="https://wiki.appstudio.dev/index.php?title=Using_SQLite&amp;diff=4208"/>
		<updated>2013-10-30T22:33:58Z</updated>

		<summary type="html">&lt;p&gt;Mashiane: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SQLite is a fast, popular and easy to use database. Its speed and easy of use make it a practical choice for use when you need an indexed file system for an app. Databases you create can be accessed, without change, on any platform SQLite supports. It is built into mobile devices that AppStudio supports.&lt;br /&gt;
&lt;br /&gt;
If you just need to save some simple data, without needing an index, have a look at using [[localStorage]].&lt;br /&gt;
&lt;br /&gt;
SQLite is a zero-configuration, in-process, SQL database engine. But don&#039;t let this description scare you: SQLite is an easy way for your app to store and retrieve data.&lt;br /&gt;
&lt;br /&gt;
Your app can create, update and delete SQLite databases. The databases are kept in your app&#039;s private directory. Generally, an app is not allowed to access databases belonging to other apps for security reasons. However, apps deployed from the same server can share databases. This allows you to create a family of apps which share data, so long as they all come from the same server. The security protects apps from changing or stealing information from other app&#039;s databases.&lt;br /&gt;
&lt;br /&gt;
Databases cannot be directly imported or exported, once again, for security reasons. However, it is possible to [[Distributing_your_App#The_Manifest_File|include an SQLite database]] with your application. Add the name of the database to the manifest in [[Properties Window]] and it will be automatically converted in to a format that can be exported from the server. The app will then import the database automatically when the application starts for the first time. To do this, the [[SqlExport|SQLExport]] and [[SqlImport|SQLImport]] methods are called internally. These methods are also available for use at any time.&lt;br /&gt;
&lt;br /&gt;
There are two sets of commands: the ones AppStudio uses to call SQLite and the SQLite commands themselves. Documentation on AppStudio&#039;s commands are in this Tech Note; documentation on SQLite itself is in the [[SQLite Reference]].&lt;br /&gt;
&lt;br /&gt;
=== Persisting Updates to the Database ===&lt;br /&gt;
&lt;br /&gt;
To ensure that updates to your database are persisted to the database, one needs to ensure that the &amp;quot;manifest&amp;quot; property of the project is properly set. When the database is specified in the manifest property, its uploaded to the application when the application is first run just like the SQLImport statement.&lt;br /&gt;
&lt;br /&gt;
The SQLImport function uses this statement for example, SQLImport(JSON, [DB], [callback], [overwrite]), and your &amp;quot;manifest&amp;quot; property should be in line with this for your updates to be considered when your application is run, an example would be &#039;mydb.db,dbObj,callBackMethod,NSB.overwriteIfVersionDifferent&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asynchronous Results ===&lt;br /&gt;
&lt;br /&gt;
The results of calls to the database are returned asynchronously. That means that after a statement involving the database is executed, the next statement in the program is executed - even though the database operation may not be complete. The database operation continues on its own. When it finishes, it will call a function you specify in your program, depending on the success or failure of the operation. In the meantime, you can do other processing: update controls on the screen or do calculations. You cannot do a [[MsgBox]] statement while you are waiting for an SQL call to finish - you will lose the callback.&lt;br /&gt;
&lt;br /&gt;
Consider the following code:&lt;br /&gt;
&lt;br /&gt;
    MsgBox &amp;quot;Before doing call&amp;quot;&lt;br /&gt;
    sqlList=&amp;quot;CREATE TABLE myData(&#039;name&#039;, &#039;age&#039;)&amp;quot;&lt;br /&gt;
    sql(DB, [sqlList, Success_Function, Fail_Function])&lt;br /&gt;
    Msgbox &amp;quot;After doing call&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    Function Success_Function(transaction, result)&lt;br /&gt;
      Msgbox &amp;quot;Success - result received&amp;quot;&lt;br /&gt;
    End function&lt;br /&gt;
 &lt;br /&gt;
    Function Fail_Function(transaction, result)&lt;br /&gt;
      Msgbox &amp;quot;Fail&amp;quot;&lt;br /&gt;
    End function&lt;br /&gt;
&lt;br /&gt;
The result will be 3 messages, in this order:&lt;br /&gt;
&lt;br /&gt;
    &amp;quot;Before doing call&amp;quot;&lt;br /&gt;
    &amp;quot;After doing call&amp;quot;&lt;br /&gt;
    &amp;quot;Success - result received&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Transactions ===&lt;br /&gt;
&lt;br /&gt;
When doing multiple operations on a database, for example, adding a number of new records, it is much faster to group them into a transaction. A transaction is a list of database operations that are performed as a set: each of the operations on the list has to successful. If any one step fails, the entire transaction can be aborted without change to the database.&lt;br /&gt;
&lt;br /&gt;
A transaction is implemented as an array, with one operation in each element of the array.&lt;br /&gt;
&lt;br /&gt;
Example: Add 3 new records into customerData&lt;br /&gt;
&lt;br /&gt;
    sqlList = []&lt;br /&gt;
    sqlList[0]=&amp;quot;INSERT INTO customerData (name,age,sales) VALUES (&#039;Haley&#039;,16,121)&amp;quot;&lt;br /&gt;
    sqlList[1]=&amp;quot;INSERT INTO customerData (name,age,sales) VALUES (&#039;Alex&#039;,12,80)&amp;quot;&lt;br /&gt;
    sqlList[2]=&amp;quot;INSERT INTO customerData (name,age,sales) VALUES (&#039;Luke&#039;,7,65)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Each operation in a transaction can have optional success and fail callbacks. In this case, the element in transaction array is itself an array:&lt;br /&gt;
&lt;br /&gt;
[&#039;&#039;operation&#039;&#039;, &#039;&#039;success&#039;&#039;, &#039;&#039;fail&#039;&#039;] , where &#039;&#039;operation&#039;&#039; is a string. &#039;&#039;success&#039;&#039; and &#039;&#039;fail&#039;&#039; are functions in the program. You are required to have at least a &#039;&#039;success&#039;&#039; function defined in your program.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 &lt;br /&gt;
   sqlList[3]=array(&amp;quot;Select * from customerData&amp;quot;, Success_Function, Fail_Function)&lt;br /&gt;
&lt;br /&gt;
==== Opening the database file using SqlOpenDatabase() ====&lt;br /&gt;
&lt;br /&gt;
SQLite keeps the entire database in a single physical file. Use the [[SqlOpenDatabase]] method to open the file. If it does not exist, it is created:&lt;br /&gt;
 &lt;br /&gt;
    DB = SqlOpenDatabase(&amp;quot;customers.db&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;My Customer Database&amp;quot;)&lt;br /&gt;
    If DB.version&amp;lt;&amp;gt;&amp;quot;&amp;quot; Then Print &amp;quot;Database Opened&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The return value, DB, will be used to identify the database in subsequent calls. If the database does not exist, it is created. Here is the full syntax of SqlOpenDatabase:&lt;br /&gt;
&lt;br /&gt;
res = &#039;&#039;&#039;SqlOpenDatabase(&#039;&#039;&#039;&#039;&#039;filename, version, fullname, maxsize&#039;&#039;&#039;&#039;&#039;)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;filename&#039;&#039; is the actual name of the file&lt;br /&gt;
* &#039;&#039;version&#039;&#039; is the version number (optional). Used on file creation. Set to &amp;quot;1.0&amp;quot; if no value supplied.&lt;br /&gt;
* &#039;&#039;fullname&#039;&#039; is a long description of the file. (optional). Used on file creation. Set to &#039;&#039;filename&#039;&#039; if no value supplied.&lt;br /&gt;
* &#039;&#039;maxsize&#039;&#039; is the maximum number of records (optional). Used on file creation. Set to 1,000,000 if no value supplied.&lt;br /&gt;
&lt;br /&gt;
====  Create a table in the database ====&lt;br /&gt;
&lt;br /&gt;
After step 1 creates a new database file, it is empty. A database is made up of tables. A table is simply a collection of records with a defined format. Let&#039;s create the table, but first, let&#039;s get rid of any existing table with the same name.&lt;br /&gt;
 &lt;br /&gt;
   sqlList=[]&lt;br /&gt;
   sqlList[0]=[&amp;quot;DROP TABLE customerData;&amp;quot;,,skipError]&lt;br /&gt;
   sqlList[1]=[&amp;quot;CREATE TABLE customerData(&#039;name&#039;, &#039;age&#039;, &#039;sales&#039;, PRIMARY KEY(&#039;name&#039;) );&amp;quot;]&lt;br /&gt;
 &lt;br /&gt;
   Sql(DB, sqlList)&lt;br /&gt;
&lt;br /&gt;
We&#039;re creating a table with three columns, indexed by the first name: each record therefore has 3 fields. The [[Sql]] statement is used to send a transaction (a list of SQL commands) to SQLite. The syntax of Sql is:&lt;br /&gt;
&lt;br /&gt;
  &#039;&#039;&#039;Sql&#039;&#039;&#039;(&#039;&#039;db, sqlList&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;db&#039;&#039; is the reference to the database returned by SqlOpenDatabase&lt;br /&gt;
* &#039;&#039;sqList&#039;&#039; is an SQLite command or an array of SQLite commands.&lt;br /&gt;
&lt;br /&gt;
====  Add records to the database and select them ====&lt;br /&gt;
 &lt;br /&gt;
   For j = 0 to databaseSize-1&lt;br /&gt;
     sqlList[j]=&amp;quot;INSERT INTO customerData (name, age, sales) VALUES ( &amp;quot; &amp;amp;amp; &amp;quot;&#039;cust&amp;quot; &amp;amp;amp; j &amp;amp;amp; &amp;quot;&#039;, &amp;quot; &amp;amp;amp; j &amp;amp;amp; &amp;quot;, &amp;quot; &amp;amp;amp; j*10 &amp;amp;amp; &amp;quot;);&amp;quot;&lt;br /&gt;
   Next&lt;br /&gt;
   sqlList[databaseSize]=[&amp;quot;SELECT * from customerData ORDER BY name;&amp;quot;, dataHandler]&lt;br /&gt;
 &lt;br /&gt;
   Sql(DB, sqlList)&lt;br /&gt;
&lt;br /&gt;
The SELECT command is very powerful - you can use it to collect all kinds of different sets of records. Read more about it in the [SQLite.htm SQL Documentation].&lt;br /&gt;
&lt;br /&gt;
In the SELECT command, we&#039;re specifying that we want to run a special function when the SELECT completes. The function &amp;lt;code&amp;gt;datahandler&amp;lt;/code&amp;gt; will be called. It gives the result of the SELECT:&lt;br /&gt;
&lt;br /&gt;
   Function dataHandler(transaction, results)&lt;br /&gt;
     // Called on completion of SQL command&lt;br /&gt;
     DBRecords = results&lt;br /&gt;
     message.innerHTML = &amp;quot;Records created: &amp;quot; &amp;amp;amp; DBRecords.rows.length &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; (Sysinfo(10)-startTime) &amp;amp;amp; &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
   End Function&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;dataHandler&amp;lt;/code&amp;gt;, transaction contains information about the last transaction. Results is an array, with one row for each record of the table that is returned.&lt;br /&gt;
&lt;br /&gt;
====  Replace a record in the table ====&lt;br /&gt;
&lt;br /&gt;
   cmd=&amp;quot;INSERT OR REPLACE INTO &amp;quot;&amp;quot;customerData&amp;quot;&amp;quot; VALUES (&amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; tbFirstName.text &amp;amp;amp; &amp;quot;&amp;quot;&amp;quot;,&amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; _&lt;br /&gt;
     tbLastName.text &amp;amp;amp;&amp;quot;&amp;quot;&amp;quot;,&amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; tbAge.text &amp;amp;amp; &amp;quot;&amp;quot;&amp;quot;)&amp;quot;&lt;br /&gt;
   Sql(DB, cmd)&lt;br /&gt;
&lt;br /&gt;
Once again, all the quotes get resolved in the command. The actual command sent to SQLite is:&lt;br /&gt;
&lt;br /&gt;
   INSERT OR REPLACE INTO &amp;quot;customerData&amp;quot; VALUES(&amp;quot;John&amp;quot;,&amp;quot;Kemeny&amp;quot;,&amp;quot;80&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Using the last name as the key, the record is added or replaced. Once again, there are many more options on this command: we&#039;re just trying to get you started here. Once you have added the record, you&#039;ll need to do your selection again. It won&#039;t be automatically added to the existing selection.&lt;br /&gt;
&lt;br /&gt;
==== Update a record ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the simplest case:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Function HeaderBar1_onclick(button)&lt;br /&gt;
  s=Array([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo&#039; WHERE CustomerID=&#039;ALFKI&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
  Sql(DB,s)&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You need to extend it in two ways: update more fields, and update more rows.&lt;br /&gt;
&lt;br /&gt;
To update more fields, add more to the SET clause:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
s=Array([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo&#039;, City=&#039;Toronto&#039; WHERE CustomerID=&#039;ALFKI&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To update more rows, add a new array element for each row:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
s=Array([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo&#039;, City=&#039;Toronto&#039; WHERE CustomerID=&#039;ALFKI&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
s.push([&amp;quot;UPDATE Customers SET CompanyName=&#039;NewCo2&#039;, City=&#039;New York&#039; WHERE CustomerID=&#039;ANATR&#039;;&amp;quot;, loadGrid])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Delete a record ====&lt;br /&gt;
&lt;br /&gt;
This is pretty easy. Do not use success or fail routine with DELETE.&lt;br /&gt;
&lt;br /&gt;
   cmd=&amp;quot;DELETE FROM customerData WHERE lastname = &amp;quot;&amp;quot;&amp;quot; &amp;amp;amp; tbLastName.Text &amp;amp;amp; &amp;quot;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
   Sql(DB, cmd)&lt;br /&gt;
&lt;br /&gt;
The command sent to SQLite resolves to:&lt;br /&gt;
&lt;br /&gt;
   DELETE FROM customerData WHERE lastname = &amp;quot;Kemeny&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Closing the Database ====&lt;br /&gt;
&lt;br /&gt;
When you are done using a database, you can close it.&lt;br /&gt;
&lt;br /&gt;
   DB.close&lt;br /&gt;
&lt;br /&gt;
==== Complete Sample ====&lt;br /&gt;
&lt;br /&gt;
&#039;This sample shows how to access SQLite from AppStudio. It can also be found in the Samples folder 2: it is SQLSample1.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dim databaseSize  &#039;number of records in the database&lt;br /&gt;
Dim DB            &#039;the database itself&lt;br /&gt;
Dim startTime     &#039;used for timer&lt;br /&gt;
Dim lastSQL       &#039;the last SQL statement. Useful for debugging.&lt;br /&gt;
Dim total         &#039;use to total sales from customers&lt;br /&gt;
Dim DBRecords     &#039;the last set of records selected from DB&lt;br /&gt;
&lt;br /&gt;
databaseSize=1000&lt;br /&gt;
&lt;br /&gt;
Function btnCreate_onclick()&lt;br /&gt;
  total=0&lt;br /&gt;
  initDB&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function btnCount_onclick()&lt;br /&gt;
  total=0&lt;br /&gt;
  startTime=SysInfo(10)&lt;br /&gt;
  For i=0 To DBRecords.rows.length-1&lt;br /&gt;
    total=total +  DBRecords.rows.item(i)[&amp;quot;sales&amp;quot;]&lt;br /&gt;
  Next&lt;br /&gt;
  txtMessage.value = &amp;quot;Total of &amp;quot; &amp;amp;amp; DBRecords.rows.length &amp;amp;amp; &amp;quot; recs is &amp;quot; &amp;amp;amp; total &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; _&lt;br /&gt;
    (Sysinfo(10)-startTime) &amp;amp;amp; &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function btnRandom_onclick()&lt;br /&gt;
  Dim sqlList&lt;br /&gt;
  startTime=SysInfo(10)&lt;br /&gt;
  total=0&lt;br /&gt;
  sqlList = []&lt;br /&gt;
  For j=0 To databaseSize-1&lt;br /&gt;
    sqlList[j]=[&amp;quot;SELECT * FROM customerData WHERE name=&#039;cust&amp;quot; &amp;amp;amp; Fix(Rnd * databaseSize) &amp;amp;  &amp;quot;&#039;&amp;quot;,Random_Total]&lt;br /&gt;
  Next&lt;br /&gt;
&lt;br /&gt;
  sqlList[databaseSize-1][1]=Random_Complete&lt;br /&gt;
  Sql(DB, sqlList)&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function Random_Total(transaction, results)&lt;br /&gt;
  total=total +  results.rows.item(0)[&amp;quot;sales&amp;quot;]&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function Random_Complete(transaction, results)&lt;br /&gt;
  txtMessage.value =  &amp;quot;Total of &amp;quot; &amp;amp;amp; databaseSize &amp;amp;amp; &amp;quot; random recs is &amp;quot; &amp;amp;amp; total &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; _&lt;br /&gt;
    (Sysinfo(10)-startTime) &amp;amp;amp; &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function initDB()&lt;br /&gt;
  Dim sqlList&lt;br /&gt;
  DB = SqlOpenDatabase(&amp;quot;customerdb.db&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;My Customer Database&amp;quot;)&lt;br /&gt;
  If DB&amp;lt;&amp;gt;0 Then&lt;br /&gt;
    startTime=SysInfo(10)&lt;br /&gt;
    nTables = -1&lt;br /&gt;
    sqlList=[]&lt;br /&gt;
    sqlList[0]=[&amp;quot;SELECT COUNT(*) AS tabCount FROM sqlite_master WHERE type=&#039;table&#039; AND name=&#039;customerData&#039;;&amp;quot;,tableExistCheck,masterErr]&lt;br /&gt;
    Sql(DB, sqlList)&lt;br /&gt;
  End If&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function dataHandler(transaction, results)&lt;br /&gt;
  // Called On completion of Sql command&lt;br /&gt;
  DBRecords = results&lt;br /&gt;
  txtMessage.value = &amp;quot;Recs created: &amp;quot; &amp;amp;amp; DBRecords.rows.length &amp;amp;amp; &amp;quot; in &amp;quot; &amp;amp;amp; (Sysinfo(10)-startTime) &amp;amp;amp; _&lt;br /&gt;
    &amp;quot; milliseconds.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function skipError(transaction, error)&lt;br /&gt;
  //Called On failure of Sql command&lt;br /&gt;
  MsgBox &amp;quot;SQL Error: &amp;quot; &amp;amp; error.message &amp;amp; &amp;quot; (&amp;quot; &amp;amp; error.code &amp;amp; &amp;quot;)&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&lt;br /&gt;
Function btnDelete_onclick()&lt;br /&gt;
  Dim SQList&lt;br /&gt;
  SQList=[]&lt;br /&gt;
  &#039;Note no success or fail callbacks!&lt;br /&gt;
  SQList[0]=[&amp;quot;DELETE FROM customerData&amp;quot;]&lt;br /&gt;
  SQList[1]=[&amp;quot;SELECT * from customerData ORDER BY name;&amp;quot;, dataHandler]&lt;br /&gt;
  Sql(DB, SQList)&lt;br /&gt;
  txtMessage.value = &amp;quot;All rows deleted.&amp;quot;&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using the Chrome Debugger to examine databases ===&lt;br /&gt;
&lt;br /&gt;
By opening the Chrome Debugger and using the Resource Tab, you can examine the database. The following example shows a database named customers with a single record containing John Doe&#039;s name, age and sales:&lt;br /&gt;
&lt;br /&gt;
[[File:Sqldebugger.png]]&lt;br /&gt;
&lt;br /&gt;
=== Clearing a Locally-Deployed App Incorporating an SQLite Database From a PC ===&lt;br /&gt;
&lt;br /&gt;
Clearing a remotely-deployed app&#039;s data and SQLite DB from a browser simply involves clearing the browser&#039;s cached app data or content for that app&#039;s domain via the settings panel. However, for a locally-deployed app the process is more involved because the various pieces are stored in multiple locations on the PC. &lt;br /&gt;
&lt;br /&gt;
Here&#039;s a way to eliminate all traces of a locally-deployed app so that it will behave as a freshly installed app on the next deploy:&lt;br /&gt;
&lt;br /&gt;
1. In Chrome Debugger&#039;s console, with the app currently deployed locally, delete all localStorage variables with the localStorage.clear() command. Use the Resources tab, Local Storage, file:// to confirm success.&lt;br /&gt;
&lt;br /&gt;
2. Find the special location where Windows stores SQLite (and other) databases and delete that folder with its contents:&lt;br /&gt;
&lt;br /&gt;
* Windows Vista or 7: \Users\_username_\AppData\Local\Google\Chrome\User Data\Default\databases&lt;br /&gt;
* Windows XP: \Documents and Settings\_username_\Local Settings\Application Data\Google\Chrome\User Data\Default\databases&lt;br /&gt;
* Mac OS X: ~/Library/Application Support/Google/Chrome/Default/databases&lt;br /&gt;
* Linux: ~/.config/google-chrome/Default/databases&lt;br /&gt;
&lt;br /&gt;
3. Delete the app files themselves (html, /nsb folder, etc.) from the Windows system. The location for these is found in the URL/Address window of the Chrome browser itself.  Just drill down using the file explorer and delete the temp folder being used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Contributed by c185driver&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Mashiane</name></author>
	</entry>
</feed>