When do databases get overwritten?

Recently, Thomas Gruber raised the question about when databases get overwritten on an iOS 6 device. We looked into and found it was indeed a good question. First, there were some bugs in the SQLImport() function that needed to be fixed. Second, we found that a couple more options were needed to make it really useful. Make sure you are running at least version 2.6.0.2 of App Studio to get these features.

We made changes to the 4th parameter of SQLImport():

   SQLImport(Json, DB, callback, overwrite)

The fourth parameter, overwrite, now has 4 possible values. It can be used in the function and in the manifest.

NSB.overwriteAlways overwrite the existing database (default).
NSB.overwriteNever only write out database if it does not exist yet.
NSB.overwriteIfVersionDifferent overwrite if the version number of the database has changed.
NSB.overwriteIfVersionSame overwrite if the version number of the database is the same.

The old True/False options for the overwrite parameter will continue to work as before.

Also, SQLImport now returns a string with the status of the callback function.

Here are some use cases. (You’re welcome to rerun the tests on other devices or versions of the OS – let me know if you get different results!)
Continue reading “When do databases get overwritten?”

Running your app in Kiosk mode

iOS 6 brings a nice new feature to both iPads and iPhones: the ability to run your app in kiosk mode. Your app becomes the only one running on the device and the home button is disabled. Turn the device off, turn it on again – your app is still running. This is ideal for single purpose apps: order taking, inventory, surveys; where the device is used for one thing only.

Here’s how to enable it:
Continue reading “Running your app in Kiosk mode”

Creating your own jQuery Mobile Themes (updated)

Update Oct 6, 2014: The latest version of this is here.

This blog post has been updated with additional findings by Leslie Peaker.

jQuery Mobile comes with three themes: a, b and c. To use different colors, fonts, etc. in your jQuery Mobile controls, you can create your own theme using the ThemeRoller Mobile tool. You can have a different theme for each control, or set up a theme to use on all your controls, giving you a consistent look and feel.

Here’s how to use it:
Continue reading “Creating your own jQuery Mobile Themes (updated)”

Creating runtime buttons. Plus: One event for all your buttons!

While it’s much nicer to create buttons in the IDE, sometimes you need to create them at runtime. It’s not that hard to do. Keep in mind, though, that you will have to do some of the work that the IDE takes care of.

Here’s some sample code to create 9 buttons in a row. Each will be 20×20 and have their number displayed on them:

Function btnMake10Buttons_onclick()
  'To make 9 text boxes, change type=button to type=text
  Dim i, btn, s
  For i=1 To 9
    btn=document.createElement("div")
    s="<input id='btn" & i & "' type=button "
    s+="style='position:absolute; "
    s+="width:24px; height:24px; top:360px; "
    s+="left:" & (243+i*30) & "px;' "
    s+="value=" & i & ">"
    btn.innerHTML=s
    Form1.appendChild(btn)
  Next
End Function

What we’re doing is defining the buttons using HTML, then adding them to your running app within a DIV. Here is how it looks:

You can do fancier formatting on the buttons by changing the HTML definition of the button.

This technique can be used for much more than buttons. If you change the type=button to type=text, you will create a group of input boxes.

Plus: One event for all your buttons!

Now that you have n buttons on your form, do you really want to add n _onclick() functions? Here’s a single onclick function you can use for all your buttons:

Function Form1_onclick(event)
  MsgBox event.target.id
End Function  

This function will display the id of the button (or any other control on your form) that is clicked. It will handle buttons you created dynamically as well as the ones you set up in the IDE.

Deleting Buttons

You can delete the buttons once you create them as follows:

btn1.parentNode.removeChild(btn1)

Edited 3/28/16: corrected variable name

iOS 6 getter/setter Bug

UPDATE: This is no longer a problem in AppStudio 3. See AppStudio 3: Moving, resizing and hiding controls.

In App Studio 2.5.0, we introduced some functions which made it easier to resize controls. They worked nicely on all versions of iOS and Android, both on the desktop and on device. This is broken in iOS 6.

Here’s the workaround:

Button1.width = 100            'works up to iOS 6

Button1.style.width = "100px"  'works for all versions of iOS

This affects the following App Studio properties: .width, .height, .top, .left, .Visible and the .resize function.

Beneath the covers, we use JavaScript’s __defineGetter__ and __defineSetter__ functions. While they still exist in iOS6 JavaScript, they no longer change the values in html elements. Here’s a simplified version of what we’re doing in JavaScript:

Button1.__defineSetter__('width', function(x){
	Button1.style.width=x
	});

Before, this code would change the value of Button1.style.width. It does not anymore.

We have reported this to Apple.

iOS 6 AJAX Caching Bug: Solution

It seems iOS6 has introduced a ‘bug’ in Ajax calls – specifically it caches any Ajax “POST” call so that subsequent reads access the cached file instead of the original on your website which you may have changed.  The solution is to change the Ajax call just slightly so it is unique.

Here is a workaround that forces the Ajax call to access the original. The original code:

  res=Ajax(filename,"POST")

The corrected code:

  res=Ajax(filename,"POST","/no-cache?" & Date)

Thanks to Helen Sandoz for this tip!

PhoneGap Build comes out of beta!

The day we have been wondering about it is finally here. PhoneGap Build is coming out of beta.

It looks like the service will continue to be free if you have a single project and do less than 100 builds a month. For $9.95 a month, you can have up to 25 projects and 1000 builds a month.

You will have to sign up with your own account to do this. It’s not clear how much longer the free PhoneGap Build that is in App Studio will continue to work.

Other than that, it looks like the procedure to use App Studio will be unchanged. Put your PhoneGap Build Email and Password into Deploy Options and it will work as before. (You’ll need the full version to enter these options).

Building apps using the PhoneGap API will continue to be free.

We will keep you updated as this develops.

Here’s the announcement:
http://phonegap.com/blog/2012/09/24/phonegap-build-is-launched

Ajax Made Simple Part 11: MySQL/SQLite on the server

PHP has built in support for MySQL and SQLite. If you have a database on your server, it’s easy to query it and return the result to your app. Here’s a very simple example of accessing MySQL:

<?php

$host = "localhost";
$databasename = "myDatabaseName";
$username ="myUsername";
$password = "myPassword";

$con = mysql_connect($host,$username,$password) or die(mysql_error());
mysql_select_db($databasename) or die(mysql_error());
$query = file_get_contents("php://input"); 
$results = mysql_query($query);

if (mysql_errno()) { 
  header("HTTP/1.1 500 Internal Server Error");
  echo $query.'n';
  echo mysql_error(); 
}
else
{
  $rows = array();
  while($r = mysql_fetch_assoc($results)) {
    $rows[] = $r;
  }
  echo json_encode($rows);
}
?>

You’ll want to address security with this. There is no parsing of the incoming query string, so someone could conceivably put some malicious code in there and you may want to determine that the person requesting the info is authorized to do so.

Ajax Made Simple Part 10: Using AJAX to send an email

Contributed by Graham Barlow, New Zealand

The App Studio Code:

  EmailText = EmailText & vbCRLF & "Date: " & FormatDateTime(Date,"dd/mm/yy")
  Url = "/ajaxEmailRegister.php/?EmailTo=gotnomates@farmmates.com"
  req=Ajax(Url,"POST",EmailText)
  If req.status=200 Then 'success
    MsgBox("Confirmation email sent.")
  Else 'failure
    MsgBox("Error sending email " & req.err)
  End If

…and the PHP script that gets called (“ajaxEmailRegister.php”):

<?php
  // Get the data from the client.
  $myText = file_get_contents('php://input');
  $to = $_GET['EmailTo'];
  $subject = "New Mate registration confirmation";
  $body = $myText;
  $headers = "From: gotnomates@farmmates.com";
  mail($to, $subject, $body, $headers);
?>

Ajax Made Simple Part 9: Cross Origin Resource Sharing

A lot of the discussion in this Tech Note has been ways to get around Same Origin Policies. Can we get rid of this restriction? We can, but there’s a catch.

To allow a PHP script on your server to give its results to apps which were not loaded from your server, add this line as the first line of your script.

header('Access-Control-Allow-Origin: *');

The catch is that now anyone with an internet connection can run your PHP script, even if their browser is compliant with access control.