Skip to content

Instantly share code, notes, and snippets.

@cantecim
Forked from premiumFrye/pf-mobilePolyForm.js
Last active January 16, 2016 16:28
Show Gist options
  • Save cantecim/735c51f4167074b283a0 to your computer and use it in GitHub Desktop.
Save cantecim/735c51f4167074b283a0 to your computer and use it in GitHub Desktop.
A directive for making Android behave a bit more like iOS when filling out forms using the ionic framework. Directive will automatically advance cursor to next field when user taps return, and if the next field is a select input, automatically pop open options. Additionally, this directive solves an issue where angularjs won't update ng-model an…
angular.module('foxitcl-mobilePolyform', [])
.directive('mobileFormPolyfill', function($timeout, $parse) {
return {
compile: function(tElement, tAttrs) {
tAttrs.inputs = [];
tAttrs.keydownFns = [];
var formElements = tElement[0].elements,
k = -1;
Object.keys(formElements).forEach(function(elm) {
//
if (/^[0-9]+$/.test(elm) === false)
return;
if (formElements[elm].nodeName === 'INPUT' || formElements[elm].nodeName === 'SELECT') {
k++;
var thisInput = angular.element(formElements[elm]);
// if an input field doesn't already has a ng-keydown directive, add it and call 'nextInput'
if (!thisInput.attr('ng-keydown')) {
thisInput.attr('ng-keydown', 'nextInput($event,' + k + ');');
}
// if ng-keydown registers some other events, save them to call them back later
if (thisInput.attr('ng-keydown').indexOf('nextInput') === -1) {
tAttrs.keydownFns[k] = $parse(thisInput.attr('ng-keydown'));
thisInput.attr('ng-keydown', 'nextInput($event,' + k + ');');
}
}
if (formElements[elm].nodeName === 'SELECT') {
var thisSelect = angular.element(formElements[elm])[0];
// ng-model doesn't always update (browser discrepancies) and selected option doesn't always show as selected with certain browsers - throw a shim in there.
thisSelect.onchange = function() {
thisSelect.blur();
};
// make android act like iOS - when user hits 'return' and focuses on a select field, emulate a mouse click and open up options
if (ionic.Platform.isAndroid()) {
thisSelect.onfocus = function() {
if (document.createEvent) {
var e = document.createEvent("MouseEvents");
e.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
thisSelect.dispatchEvent(e);
}
else if (thisSelect.fireEvent) {
thisSelect.fireEvent("onmousedown");
}
};
}
}
});
return {
post: function(scope, tElement, tAttrs) {
var formElements = tElement[0].elements,
inputs = (tAttrs.inputs),
keydownFns = (tAttrs.keydownFns);
Object.keys(formElements).forEach(function(elm) {
if (/^[0-9]+$/.test(elm) === false)
return;
if (formElements[elm].nodeName === 'INPUT' || formElements[elm].nodeName === 'SELECT') {
var thisInput = angular.element(formElements[elm]);
inputs.push(thisInput);
}
});
scope.nextInput = function(e, num) {
// apply any functions user had attached to ng-keydown on input
if (keydownFns[num]) {
keydownFns[num](scope, {
$event: e
});
}
// event trigers $digest, but focus event wants to trigger $digest too: wrap in a $timeout and tell angular not to $digest (false option)
if (e.keyCode === 13) {
if (inputs[num + 1]) {
$timeout(function() {
inputs[num + 1][0].focus();
}, 100, false);
}
else {
$timeout(function() {
tElement.triggerHandler('submit');
}, 500, false);
}
e.preventDefault();
}
};
}
};
}
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment