27. UserAgent Sniffing
//
// Find the current device
// @return {{DomString}} 'blackberryX', 'android', 'webkit', 'desktop'
//
findDevice: function() {
var userAgent = navigator.userAgent;
if (userAgent.match(/browzr/i)) return 'blackberry4';
if (userAgent.match(/blackberryd*/4..*/i)) return 'blackberry4';
if (userAgent.match(/blackberryd*/5..*/i)) return 'blackberry5';
if (userAgent.match(/android/i)) return 'android';
if (userAgent.match(/blackberryd*/6..*/i)) return 'webkit';
if (userAgent.match(/webkit/i)) return 'webkit';
return 'desktop';
}
28. //
// Preload Images Preloading Images
//
// The images are preloaded into the DOM and then removed.
//
// @param {DOMString} imgSources is an array of image URLs to preload
//
Application.help.preloadImages = function(imgSources, callback) {
var img = null;
var preloadNextImage = function() {
if (img !== null) delete img;
if (imgSources.length <= 0) { Application.dispatch(callback); return; }
img = new Image();
img.onload = preloadNextImage;
img.src = imgSources.pop();
}
preloadNextImage();
};
29. External Link Quirks
// BlackBerry child browser
if (Application.supports.browser.widget) {
blackberry.invoke.invoke(
blackberry.invoke.APP_BROWSER,
new blackberry.invoke.BrowserArguments(href)
);
}
// Android child browser
else if (Application.supports.browser.android) {
window.android.loadExternalUrl(href);
}
// Everyone else
else {
document.location = href;
}
30. // @blackberry4 workaround for render issues that display a white
// block that proportional in height to the amount scrolled vertically.
if (!Application.is('blackberry4')) {
x$(element).addClass('selected'); Page Target Quirks
}
hash = hash[0].replace('#', '');
if (hash !== '') {
if (Application.events[hash]) {
Application.trigger(hash, element);
}
else if (Application.is('android') || Application.is('blackberry4')) {
document.location.hash = '#' + hash;
}
else {
var $element = x$('a[name=' + hash + ']');
$element = ($element.length > 0) ? $element : x$('#' + hash);
if ($element.length > 0) { $element[0].scrollIntoView(true); }
}
}
31. Ellipsis Support
//
// Ellipsis Support
//
// @param {DOMElement} DOM element to apply ellipsis to
//
Application.help.ellipsis = function(element) {
if (Application.supports.ellipsis) return;
// ... manually create ellipsis
};
// ...
Application.supports.ellipsis = (typeof e.style.textOverflow !== 'undefined');
34. //
// Search records using the PhoneGap plugin or JavaScript Feature Detection
//
if (Application.supports.store.search) {
window.plugins.store.search(query, function(response) {
jsonResponse.data = response.message.data;
jsonResponse.error = response.message.error;
renderResults();
});
}
else {
Application.database.all(function(records) {
for(var i = 0; i < records.length; i++) {
matchRecord(records[i]);
}
renderResults();
});
}
35. Application.help.getStoragePath = function() {
var storagePath = ''; PhoneGap File API Quirks
if (typeof navigator !== 'undefined' && navigator.fileMgr) {
var rootPaths = navigator.fileMgr.getRootPaths();
for (var i = 0; i < rootPaths.length; i++) {
// iOS workaround. For some reason it returns an invalid path on the simulator.
if (rootPaths[i].match(/document/i)) {
storagePath = './../Documents/';
break;
}
// BlackBerry / Android
else if (rootPaths[i].match(/sdcard/i)) {
storagePath = rootPaths[i];
break;
}
}
}
return storagePath;
};
36. Performance
//
// Dispatch a function asynchronously
//
// This will push the process onto a new
// execution stack and allocate a new memory
// heap. This is very useful for BlackBerry5,
// which runs into memory issues on deep
// callback stacks. It is important to understand
// that dispatch will only fire after the current
// execution thread ends.
//
// @param {Function} function to dispatch. Accepts no args.
//
dispatch: function(fn) {
setTimeout(fn, 10);
}
42. Summary
• Decouple view from model
• Test model programmatically
• Test view through QA
• Test on real devices
• Create a simple build chain
• Generate static content to avoid runtime penalties