Android Date Script - Titanium Mobile App - android

I have a form on my app that I am trying to force a particular format on the text field (ex. dob 11/33/1944). The following code works great on iPhone but on Android the app stops working once I enter the first number. Can someone please help me modify the code so that it works for both iPhone and Android. Thanks for the help.
I have a file called global.js where I have the code that forces the format. This is what I am using:
Mask =
{
mask: function(_field, _function)
{
_field.value = _function(_field.value);
},
dob: function(v)
{
v = v.replace(/\D/g,"");
v = v.replace(/^(\d\d)(\d)/g,"$1/$2");
v = v.replace(/(\d{2})(\d)/,"$1/$2");
return v.slice(0, 10);
},
phone: function(v)
{
v = v.replace(/\D/g,"");
v = v.replace(/^(\d\d)(\d)/g,"($1) $2");
v = v.replace(/(\d{4})(\d)/,"$1-$2");
return v.slice(0, 14);
}
};
On my form i added the following on the top of the of the view for the global.js:
var styles = require('global').Styles;
Then my field is as follows:
// Create a TextField.
var aTextField_dob = Ti.UI.createTextField(
{
top : "10%",
width : '80%',
height:'8%',
color: styles.textfield.color,
font :
{
fontSize : font_text
},
hintText : 'Date of Birth (Ex.01/01/1999)',
paddingLeft : styles.textfield.paddingLeft,
backgroundImage : styles.textfielda.backgroundImage,
});
// Listen for return events.
aTextField_dob.addEventListener('change', function(e)
{
Mask.mask(aTextField_dob, Mask.dob);
});
Here is the issue I get on the Android device, it just keeps repeating itself and the app has to be forced to stop:
[WARN] : IInputConnectionWrapper: getCursorCapsMode on inactive InputConnection

First of all, I’d avoid the issue altogether by using a date picker control. That’d be a better UI/UX anyway.
It’s probable that you are creating infinite recursion in the change event. That could be avoided by using the blur (lost focus) event, or the keypressed event if it can’t wait until focus is lost.
I’m not sure if the regular expression engines are different. Try putting the regex output into another control or just log it – separate it from any possible change event infinite loop to test that out.

Related

Javascript using regexp instead of keyCodes to capture Android soft keyboard characters?

I know Android, and many users, say not to use $event.keyCode || $event.charCode because the returned characters can't be trusted. And its true, it can't. But what about using a regexp to test for the presence of certain characters?
As a case example, US zip codes can be in several formats: 12345, 12345-6789 or 12345 6789. These three formats allow numbers, space and minus sign. But the minus sign could also be the dash sign. So with a physical keyboard you can test for $event.keyCode to match keyCodes [32,109,189] (ie: space, minus, keypad-minus).
But on a softkey board, particularly android soft keyboard, the returned key for almost ALL keys is never correct. On top of which, on android keypress isn't supported, only keydown and keyup - and those present their own challenges. So instead of capturing the keycodes, why not just evaluate the last pressed key and test that character against a regexp?
In my code I have changed things to:
<input id="zip" ng-model="userInfo.zip" ng-keyup="checkKeyCode($event)" ng-blur="setInfo($event,'zip')" >
$scope.checkKeyCode = function() {
var lastChar = $scope.userInfo.zip.slice(-1) ;
var regex1 = /^[\n]*$/ ; // enter key
var regex2 = /^[\d\s-]*$/ ; // numbers, space and minus
if (regex1.test(lastChar)) {
$event.target.blur($event,'zip') ; //force to blur, process data
return ;
}
if (regex2.test(lastChar) == false) {
$scope.errMsg = "Only numbers, space and dash/minus characters are permitted" ;
$scope.errColor = "red" ;
var sLen = $scope.userInfo.zip.length - 1 ;
$scope.userInfo.zip = $scope.userInfo.zip.substring(0,sLen) ; //remove invalid char
return ;
}
if ($scope.userInfo.zip.length > 10) {
$scope.errMsg = "Max length is 10 characters" ;
$scope.errColor = "red" ;
$scope.userInfo.zip = $scope.userInfo.zip.substring(0,10) ;
return ;
}
}
Even though my code works, I have a feeling there are some pitfalls to this method. For example keyCode 109 and 189 are both the minus sign, but does the above regex2 capture both of those or do I need to account a minus sign and a dash - does the regexp treat them differently?
What are the pitfalls and reasons to not do it this way? And last, if this isn't a solid method, then how does one account for keyCodes for Android soft keyboards?

AS3/AIR Load/Save Username progress

I am creating an Android application created using Flash AS3. The user will input his/her name(instance namenameField), click the previous (btnPrev) and next (btnNext) button and press save (btnPrev). After restarting the application, the last frame saved was loaded (with the name). However if I want to input 2nd user with different name and save it in different frame, will the 2nd user's save progress be retained (without deleting the progress of the 1st user?). The problem, when I type the previous user name progress and press load (btnLoad), his saved progress doesn't load. Please help.
I am a newbie in programming. Here is my code so far:
*import flash.events.MouseEvent;
var savedstuff:SharedObject = SharedObject.getLocal("myStuff");
btnSave.addEventListener(MouseEvent.CLICK, SaveData);
btnLoad.addEventListener(MouseEvent.CLICK, LoadData);
btnNext.addEventListener(MouseEvent.CLICK, pageNext);
btnPrev.addEventListener(MouseEvent.CLICK, pagePrev);
function pageNext (e:MouseEvent){
nextFrame();
}
function pagePrev (e:MouseEvent){
prevFrame();
}
function SaveData(MouseEvent){
savedstuff.data.username = nameField.text
savedstuff.flush();
}
function LoadData(MouseEvent){
if(savedstuff.size>0){
nameField.text = savedstuff.data.username}
gotoAndStop(savedstuff.data.saveData);
}
if(savedstuff.size>0){
nameField.text = savedstuff.data.username}*
If I understood it correctly you want to save and load savedstuff for two different users, right ?
Since you always saving everything with the name "myStuff" data will be overwritten every time you save. If you want that per user you might want to add the username to the SharedObject name:
var savedstuff:SharedObject;
function SaveData(e:MouseEvent)
{
var userName:String = nameField.text;
savedstuff = SharedObject.getLocal(userName + "myStuff");
savedstuff.data.username = userName;
savedstuff.flush();
}
function LoadData(e:MouseEvent)
{
var userName:String = nameField.text;
savedstuff = SharedObject.getLocal(userName + "myStuff");
if(savedstuff.size > 0)
{
nameField.text = savedstuff.data.username}
gotoAndStop(savedstuff.data.saveData);
}
}

Android Chrome - Keypress event is not returning any key data (jQuery)?

It's been well documented that Chrome in Android doesn't support keydown and keyup events. I'm using jQuery to attach an event listener to a text area like this:
$textarea.on('keyup', function(e) {
alert(e.key);
}
also tried:
$textarea.on('keydown', function(e) {
alert(e.key);
}
$this is the text area. The event doesn't return anything useful. Check out the event object:
Object
altKey: false
bubbles: true
cancelable: true
char: undefined
charCode: 0
ctrlKey: false
currentTarget: HTMLTextAreaElement
data: undefined
delegateTarget: HTMLTextAreaElement
eventPhase: 2
handleObj: Object
isDefaultPrevented: function returnFalse() {
jQuery21102996875715907663: true
key: undefined
keyCode: 0
metaKey: false
originalEvent: KeyboardEvent
relatedTarget: undefined
shiftKey: false
target: HTMLTextAreaElement
timeStamp: 1412092745055
type: "keydown"
view: Window
which: 0
__proto__: —
Notice how any of the key values are not defined. This was for simply tapping the letter "A". Is there something I'm doing wrong?
Does anyone know if there is a work around for this? I'm using jQuery Mobile 1.4.2 to style the textarea. Does that have anything to do with that?
I'm open to non-jQuery options as well, if there are any...
So I figured out a solution I was hoping to avoid. Basically I'm going to have to grab the value out of the input and evaluate the last character to determine what was input. It's going to add some overhead to the text input, but I don't see any other way around it.
Check it out:
var currentCursorPos;
$this.on('keyup', function(e) {
currentCursorPos = $this[0].selectionStart; // grab the cursor position
var val = $this.val(); // grab the input value
console.log('Current Val: ' + val);
var firstPrevious = val.charAt(currentCursorPos - 1); // grab the character that was just entered
console.log('Entered Character: ' + firstPrevious);
});

Titanium Change event not firing the first time with picker

I am making an iOS and Android app using Titanium Classic. I am fairly new to Titanium but I have some experience using Javascript. The app will have a window where the user and select from a picker an amount of time in hours and minutes. The selection will be saved and be used later to send a notification to the user that the time they selected is up. I am currently using Titanium's picker function with the type of "count down timer." However, I am having trouble getting the change event to work when the user selects a different time. It also will show the last selected time when I try going to a different window and entering the timer window again.
My question is how can I get the change event to fire the first time the user selects a different number?
In follow up to my question, is there a better way to save the picker selection for later use?
Here is the code for the picker:
var hours = 0;
var minutes = 1;
var win = Ti.UI.createWindow({
backgroundColor: '#A6B97B',
layout: 'horizontal'
});
var picker = Ti.UI.createPicker({
type:Ti.UI.PICKER_TYPE_COUNT_DOWN_TIMER,
top:2,
width: '50%',
height: '20%'
});
picker.addEventListener("change", function(e) {
Ti.App.Properties.setInt('countDownDuration', e.countDownDuration);
if (e.countDownDuration >= 3600000)
{
hours = Math.floor(Ti.App.Properties.getInt('countDownDuration')/3600000);
minutes = Math.floor(Ti.App.Properties.getInt('countDownDuration')/60000 - (hours*60));
}
else {
minutes = Math.floor(Ti.App.Properties.getInt('countDownDuration')/60000);
hours = 0;
}
});
var doneBtn = Ti.UI.createButton({
title : 'Get Value',
height : '15%',
width : '30%'
});
doneBtn.addEventListener('click', function() {
// get value
if(hours > 0){
alert('You set the time estimate to ' + hours + ' hours and ' + minutes+ ' minutes');
}
else {
alert('You set the time estimate to ' + minutes + ' minutes');
}
});
If anyone has any advice on how to get the change event to fire the first time, I would really appreciate it. Also, if you know a better way to accomplish saving data from the picker for use later, that would be helpful as well.
Thanks!
Jessica

Previous scene doesn't get removed

I'm pretty new to corona and I can't seem to find a solution for my problem:
I have levels in my game and I am using storyboards, when the player clicks on the nextlevelbutton they get sent to the level2 scene, the scene starts with storyboard.removeALL() but that doesn't remove the previous scene and my background is messed up.
function nextlevel(event)
storyboard.gotoScene( "level2" )
end
function win ()
nextlevelbutton = display.newRoundedRect( display.contentCenterX, 285, 120, 30, 3 )
nextlevelbutton:setFillColor( 61/255,61/255,61/255 )
nextleveltxt = display.newText( { text = "Next Level", font = native.systemFontBold, fontsize = 20, x= display.contentCenterX, y = 285 } )
nextlevelbutton:addEventListener( "tap", nextlevel )
end
This is all inside the scene:enterScene function.
This is the start of the level2 scene:
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
storyboard.removeAll( )
I tried putting the nextlevel event inside the win function but nothing happened.
Thanks
This should help you:
http://www.coronalabs.com/blog/2013/04/02/cleaning-up-display-objects-andlisteners/
If your loading a menu and you want to remove EVERYTHING from all other classes then use:
storyboard.purgeAll()
that should stop all the listeners and remove all the objects.
Another thing you could do is add this code:
function scene:didExitScene( event )
storyboard.purgeScene( "sceneyouareleaving" )
end
scene:addEventListener( "didExitScene" )
All you need to do is call that function and your done :)
Hope this helps!
Also, as your 'messed up' background might suggest, please remember to add all the objects you create to view group:
function scene:createScene(event)
local group = self.view
local params = event.params
And then when you create objects, eg:
background = display.newImageRect("gfx/bg.png", 1425, 900)
background:setReferencePoint(display.TopLeftReferencePoint)
background.x = 0
background.y = 0
background:setFillColor(0, 255, 255)
Remember to add it to group:
group:insert(background)
I somehow managed to solve it. I think I did something wrong with the positions of the functions and groups. Anyway thanks for helping!

Categories

Resources