Skip to content

Instantly share code, notes, and snippets.

@vlucas
Last active December 30, 2015 09:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vlucas/7810041 to your computer and use it in GitHub Desktop.
Save vlucas/7810041 to your computer and use it in GitHub Desktop.
// "Constants"
exports.STYLE_HINT = 'hint';
exports.STYLE_LABEL = 'label';
exports.TYPE_DATE = 'date';
exports.TYPE_DATETIME = 'datetime';
exports.TYPE_EMAIL = 'email';
exports.TYPE_URL = 'url';
exports.TYPE_NUMBER = 'number';
exports.TYPE_PASSWORD = 'password';
exports.TYPE_PHONE = 'phone';
exports.TYPE_BOOLEAN = 'boolean';
exports.TYPE_PICKER = 'select';
exports.TYPE_STRING = 'string';
exports.TYPE_TEXT = 'text';
exports.TYPE_FILE = 'file';
exports.TYPE_SUBMIT = 'submit';
var isAndroid = Ti.Platform.osname === 'android';
var textFieldDefaults = {
height: '40dp',
top: '10dp',
color: '#222',
right : 0,
left : 0
};
var keyboardMap = {};
keyboardMap[exports.TYPE_EMAIL] = Ti.UI.KEYBOARD_EMAIL;
keyboardMap[exports.TYPE_URL] = Ti.UI.KEYBOARD_URL;
keyboardMap[exports.TYPE_NUMBER] = Ti.UI.KEYBOARD_NUMBER_PAD;
keyboardMap[exports.TYPE_PASSWORD] = Ti.UI.KEYBOARD_DEFAULT;
keyboardMap[exports.TYPE_PHONE] = Ti.UI.KEYBOARD_NUMBER_PAD;
keyboardMap[exports.TYPE_TEXT] = Ti.UI.KEYBOARD_DEFAULT;
var handleStyle = function(form, field, textField, title) {
if (form.fieldStyle === exports.STYLE_HINT && textField) {
textField.hintText = title;
var noTouchFields = ['username', 'email', 'password', 'password_confirm', 'url', 'link_url'];
var autocorrectTypes = [exports.TYPE_STRING, exports.TYPE_TEXT];
if(noTouchFields.indexOf(field.name) !== -1 || autocorrectTypes.indexOf(field.type) === -1) {
textField.autocorrect = false;
textField.autocapitalization = Titanium.UI.TEXT_AUTOCAPITALIZATION_NONE;
}
if(field.hasOwnProperty('length')) {
textField.maxLength = field.length;
}
} else {
form.container.add(Ti.UI.createLabel({
text: title,
top: '10dp',
left: '35dp',
color: '#222',
font: {
fontSize: '16dp',
fontWeight: 'bold'
},
height: 'auto',
width: 'auto'
}));
if (textField) {
textField.top = '5dp';
}
}
};
var setupPickerTextField = function(textField, pickerType, data) {
textField.editable = false;
textField.rightButton = Ti.UI.createButton({
style: Ti.UI.iPhone.SystemButton.DISCLOSURE,
transform: Ti.UI.create2DMatrix().rotate(90)
});
textField.rightButtonMode = Ti.UI.INPUT_BUTTONMODE_ALWAYS;
textField.addEventListener('click', function(e) {
e.source.blur();
var semiModalPicker = require('/tin/semiModalPicker').createSemiModalPicker({
textField: textField,
value: textField.value,
type: pickerType,
data: data
});
if(isAndroid) {
semiModalPicker.open({ modal: true });
} else {
semiModalPicker.open({ animated: false });
}
});
};
var ctr = 1;
var addField = function(field, fieldRefs) {
var title = field.title || ('field' + ctr++);
var id = field.name || field.id || title;
var type = field.type || exports.TYPE_TEXT;
var form = this;
var fieldObject = undefined;
textFieldDefaults.value = field.value || null;
if (
type === exports.TYPE_STRING ||
type === exports.TYPE_URL ||
type === exports.TYPE_EMAIL ||
type === exports.TYPE_NUMBER ||
type === exports.TYPE_PHONE ||
type === exports.TYPE_PASSWORD) {
fieldObject = Ti.UI.createTextField(textFieldDefaults);
fieldObject._type = type;
fieldObject.keyboardType = keyboardMap[type];
fieldObject.passwordMask = type === exports.TYPE_PASSWORD;
handleStyle(form, field, fieldObject, title);
} else if (type === exports.TYPE_TEXT) {
fieldObject = Ti.UI.createTextArea(textFieldDefaults);
fieldObject.height = '120dp';
handleStyle(form, field, fieldObject, title);
} else if (type === exports.TYPE_BOOLEAN) {
fieldObject = Ti.UI.createSwitch({value:0});
handleStyle(form, field, undefined, title);
} else if (type === exports.TYPE_DATE) {
if (isAndroid) {
// Titanium android does not support date picker, so we have to just display as a text field... (sigh)
fieldObject = Ti.UI.createTextField(textFieldDefaults);
handleStyle(form, field, fieldObject, title);
setupPickerTextField(fieldObject, Ti.UI.PICKER_TYPE_DATE);
} else {
fieldObject = Ti.UI.createTextField(textFieldDefaults);
handleStyle(form, field, fieldObject, title);
setupPickerTextField(fieldObject, Ti.UI.PICKER_TYPE_DATE);
}
} else if (type === exports.TYPE_DATETIME) {
if (isAndroid) {
// Titanium android does not support date+time picker, so we have to just display as a text field... (mega sigh)
fieldObject = Ti.UI.createTextField(textFieldDefaults);
handleStyle(form, field, fieldObject, title);
setupPickerTextField(fieldObject, Ti.UI.PICKER_TYPE_DATE);
} else {
fieldObject = Ti.UI.createTextField(textFieldDefaults);
handleStyle(form, field, fieldObject, title);
setupPickerTextField(fieldObject, Ti.UI.PICKER_TYPE_DATE_AND_TIME);
}
} else if (type === exports.TYPE_PICKER) {
if (isAndroid) {
// fieldObject = Ti.UI.createPicker({
// type: Ti.UI.PICKER_TYPE_PLAIN,
// value: field.value
// });
// handleStyle(form, field, undefined, title);
// for (var i in field.options) {
// var value = tin.isNumber(i) ? field.options[i] : i;
// fieldObject.add(Ti.UI.createPickerRow({ title:field.options[i], value: value }));
// }
fieldObject = Ti.UI.createTextField(textFieldDefaults);
handleStyle(form, field, fieldObject, title);
setupPickerTextField(fieldObject, Ti.UI.PICKER_TYPE_PLAIN, field.options);
} else {
fieldObject = Ti.UI.createTextField(textFieldDefaults);
handleStyle(form, field, fieldObject, title);
setupPickerTextField(fieldObject, Ti.UI.PICKER_TYPE_PLAIN, field.options);
}
} else if (type === exports.TYPE_FILE) {
var fieldObject = Ti.UI.createButton({
title: 'Select Photo...',
top:'10dp'
});
fieldObject.addEventListener('click', function(e) {
Ti.Media.openPhotoGallery({
mediaTypes:[Ti.Media.MEDIA_TYPE_PHOTO],
success:function(e) {
fieldObject.value = e.media;
fieldObject.title = '[ Photo Selected ]';
},
cancel:function() {
fieldObject.value = null;
fieldObject.title = 'Select Photo...';
},
error:function(err) {
Ti.API.error(err);
fieldObject.value = null;
fieldObject.title = 'Select Photo...';
}
});
});
} else if (type === exports.TYPE_SUBMIT) {
var button = Ti.UI.createButton({
title: title,
top:'10dp'
});
button.addEventListener('click', function(e) {
var values = {};
for (var i in fieldRefs) {
values[i] = fieldRefs[i].value;
}
form.fireEvent(id, {values:values});
});
form.container.add(button);
}
// Add our prepared UI component to the form
if (fieldObject) {
form.container.add(fieldObject);
fieldRefs[id] = fieldObject;
}
};
var addFields = function(fields, fieldRefs) {
for (var i in fields) {
this.addField(fields[i], fieldRefs);
}
};
exports.createForm = function(o) {
var container = Ti.UI.createView({
layout: 'vertical',
height: 'auto'
});
var fieldRefs = {};
var form = Ti.UI.createScrollView({
contentHeight: 'auto',
contentWidth: 'auto',
showVerticalScrollIndicator:true,
showHorizontalScrollIndicator:true,
// new stuff
container: container,
fieldStyle: o.style || exports.STYLE_HINT,
addField: addField,
addFields: addFields
});
form.addFields(o.fields, fieldRefs);
form.add(container);
// Add this so each field can be accessed directly, if necessary
form.fieldRefs = fieldRefs;
return form;
}
var isAndroid = Ti.Platform.osname === 'android';
// Helpers
var stringToDate = function(dateString) {
dateString = dateString || '';
var matches = /(\d+)\/(\d+)\/(\d+)/.exec(dateString);
if (matches && matches.length >= 4) {
return new Date(matches[3], matches[1] - 1, matches[2]);
}
return new Date();
};
var stringToDateTime = function(dateString) {
dateString = dateString || '';
var matches = /(\d+)\/(\d+)\/(\d+) (\d+):(\d+)/.exec(dateString);
if (matches && matches.length >= 4) {
return new Date(matches[3], matches[1] - 1, matches[2], matches[4], matches[5]);
}
return new Date();
};
var dateToString = function(date) {
return (date.getMonth()+1) + '/' + date.getDate() + '/' + date.getFullYear();
};
var dateTimeToString = function(date) {
return (date.getMonth()+1) + '/' + date.getDate() + '/' + date.getFullYear() + ' ' + date.getHours() + ':' + date.getMinutes();
};
var toType = function(me) {
return Object.prototype.toString.call(me).split(/\W/)[2].toLowerCase();
};
// Main method
exports.createSemiModalPicker = function(o) {
var type = o.type === undefined ? Ti.UI.PICKER_TYPE_PLAIN : o.type;
var modalWin = Ti.UI.createWindow({
backgroundColor:'transparent'
});
var overlay = Ti.UI.createView({
backgroundColor: '#000',
opacity: 0.6
});
var container = Ti.UI.createView({
bottom: 0,
layout: 'vertical',
height: '251dp'
});
var picker = Ti.UI.createPicker({
type: type,
height: 'auto',
selectionIndicator: true
});
if (type === Ti.UI.PICKER_TYPE_DATE) {
picker.value = stringToDate(o.value);
} else if (type === Ti.UI.PICKER_TYPE_DATE_AND_TIME) {
picker.value = stringToDateTime(o.value);
} else if (o.data) {
for (var i in o.data) {
if(toType(o.data) === 'array') {
var value = o.data[i];
} else {
var value = toType(i) === 'string' ? i : o.data[i];
}
picker.add(Ti.UI.createPickerRow({ title: o.data[i], value: value }));
}
}
picker.addEventListener('change', function(e) {});
// Toolbar UI
if(isAndroid) {
container.backgroundColor = '#ccc';
var cancel = Ti.UI.createButton({
title:'Cancel',
width: '80dp',
left: '10dp',
top: '3dp'
});
var done = Ti.UI.createButton({
title:'Done',
width: '80dp',
right: '10dp',
top: '3dp'
});
var toolbar = Ti.UI.createView({
height: '48dp',
backgroundColor: '#bbb'
});
toolbar.add(cancel);
toolbar.add(done);
} else {
var cancel = Ti.UI.createButton({
title:'Cancel',
style: Ti.UI.iPhone.SystemButtonStyle.BORDERED
});
var done = Ti.UI.createButton({
title:'Done',
style: Ti.UI.iPhone.SystemButtonStyle.DONE
});
var spacer = Ti.UI.createButton({
systemButton: Ti.UI.iPhone.SystemButton.FLEXIBLE_SPACE
});
var toolbar = Ti.UI.iOS.createToolbar({
top:0,
items: [cancel, spacer, done]
});
}
// Events
cancel.addEventListener('click', function(e) {
modalWin.close();
});
done.addEventListener('click', function(e) {
if (type === Ti.UI.PICKER_TYPE_DATE) {
o.textField.value = dateToString(picker.value);
} else if (type === Ti.UI.PICKER_TYPE_DATE_AND_TIME) {
o.textField.value = dateTimeToString(picker.value);
} else {
o.textField.value = picker.getSelectedRow(0).value || picker.getSelectedRow(0).title;
}
modalWin.close();
});
container.add(toolbar);
container.add(picker);
modalWin.add(overlay);
modalWin.add(container);
return modalWin;
};
var forms = require('/lib/forms');
fields = [];
fields.push({title: 'Name', type: 'text', id: 'name' });
fields.push({title: 'Submit', type: 'submit', id: 'submit' });
var formWin = Ti.UI.createWindow();
// Setup form
var form = forms.createForm({
style: forms.STYLE_HINT,
fields: fields,
window: formWin
});
formWin.addEventListener('open', function(e) {
// Focus on first form field
var firstField = _.first(fields);
var firstFieldObj = form.fieldRefs[firstField.name || firstField.id];
if(firstFieldObj) {
firstFieldObj.focus();
}
});
form.addEventListener('submit', function(e) {
// Handle form submit
});
// Add form to window
formWin.add(form);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment