-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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