I decided to start working on an iGoogle replacement since iGoogle is going to die.
Here's some early code. Its far from done, and on the backburner at the moment, but, here's a link
https://github.com/bren1818/iGoogle_Static
Bren's Blog
A web developer's rant, a place for resources and topics of interest.
Wednesday, January 23, 2013
Saturday, January 5, 2013
Dynamically configure Viewport (ios/android) meta tag
In the head of your page include this:
//jquery
<meta name="HandheldFriendly" content="True" />
<meta id="Viewport" name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
$(function(){
var minSiteWidth = 480; /*Anything Less than or Equal to this will be in 'phone' view*/
var maxSiteWidth = 1024; /*Anything between this and min width will be tablet, anything greater will be Desktop*/
var previousOrientation = 0;
var checkOrientation = function(){
if(window.orientation !== previousOrientation && window.orentation != undefined){
previousOrientation = window.orientation;
$(function(){
//get proper width
var ww = ( $(window).width() < window.screen.width ) ? $(window).width() : window.screen.width;
//get proper width
var wh = ( $(window).height() < window.screen.height ) ? $(window).height() : window.screen.height;
var o = ( ww > wh) ? "Landscape" : "Portait";
$('body').removeClass('Landscape');
$('body').removeClass('Portait');
$('body').addClass(o);
});
}
};
function isMobile(){
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
return true;
}else{
return false;
}
}
/*Add on the resize and orientation events for Mobile*/
if( isMobile() ) {
window.addEventListener("resize", checkOrientation, false);
window.addEventListener("orientationchange", checkOrientation, false);
}
function setViewPort(mw){
if( isMobile() ) { //Only care about setting the view ports on mobile devices
$('body').addClass('mobileDevice');
if( mw == undefined ){
mw = minSiteWidth;
}
var ww = ( $(window).width() < window.screen.width ) ? $(window).width() : window.screen.width; //get proper width
var ratio = ww / mw; //calculate ratio
if( ww <= mw){ /*Phone Layout*/
$('body').addClass('phone');
$('body').removeClass('tablet');
$('.siteSection').width( mw );
$('#Viewport').attr('content', 'initial-scale=' + ratio + ', maximum-scale=' + ratio + ', minimum-scale=' + ratio + ', user-scalable=no, width=' + ww);
}else{ /*Tablet / Desktop Layout */
$('body').addClass('tablet');
$('body').removeClass('phone');
$('.siteSection').width( ww );
$('#Viewport').attr('content', 'initial-scale=1.0, maximum-scale=2, minimum-scale=1.0, user-scalable=no, width=' + ww);
if( ww >= maxSiteWidth ){
$('body').addClass('desktopDevice'); /*Optional */
}
}
}else{
$('body').addClass('desktopDevice');
}
}
/*Function to allow a delayed re-size trigger event*/
var waitForFinalEvent = (function () {
var timers = {};
return function (callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout (timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();
if( !isMobile() ) { /*This is for desktops, don't need it done on both*/
$(window).resize(function () { /*so that we don't have to coninuously call functions on a resize*/
waitForFinalEvent(function(){
var w = ( $(window).width() < window.screen.width ) ? $(window).width() : window.screen.width;
if( w <= minSiteWidth ){
$('body').addClass('phone');
$('body').removeClass('desktopDevice');
$('body').removeClass('tablet');
log( "Gone to phone View");
}else if( w > minSiteWidth && w < maxSiteWidth ){
$('body').addClass('tablet');
$('body').removeClass('phone');
$('body').removeClass('desktopDevice');
log("Gone to Tablet View");
}else{
$('body').removeClass('phone');
$('body').removeClass('tablet');
$('body').addClass('desktopDevice');
log("Gone to Desktop View");
}
}, 500, "WindowResize");
});
}
setViewPort(minSiteWidth); //viewport for mobile devices
});
Saturday, September 8, 2012
Simple Web-App for Android and iOS
So as of late, I have been working on websites which function on mobile devices. Its often easier to make code changes and updates when creating applications out of html,css and javascript. If you want a really easy jumping off point, I have created a super simple little web app which will play nicely on Android and iOS devices including tablets.
To create this package I use the following libraries:
-jQuery - to abbreviate javascript
-iScroll - to help with cross device scrolling
-less.js - cause its a nifty way of styling with css
-touchSwipe - help with swipes
This web app (at the present time) is one screen with scroll-able content and swipe zones, along with scroll-able and inner scroll-able zones. I wrote some javascript to tie the libraries all together and create a nice and responsive application.
At the bottom of this page I'll have a link to the files, He're is a brief over view of the html, js and css/less.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="theme/touch-icon-iphone.png" />
<link rel="apple-touch-icon" sizes="72x72" href="theme/touch-icon-ipad.png" />
<link rel="apple-touch-icon" sizes="114x114" href="theme/touch-icon-iphone4.png" />
<link rel="apple-touch-startup-image" href="theme/startup.jpg" media="screen and (min-device-width: 200px) and (max-device-width: 480) and (orientation:portrait)"> <!-- iPod/Phone 320 x 460 image -->
<link rel="apple-touch-startup-image" href="theme/startup-iPad-portrait.jpg" media="(device-width: 768px) and (orientation: portrait)" /> <!--iPad Portrait 768 x 1004 -->
<link rel="apple-touch-startup-image" href="theme/startup-iPad-landscape.jpg" media="(device-width: 768px) and (orientation: landscape)" /> <!--iPad LandScape 1024 x 748-->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="HandheldFriendly" content="true" />
<title>Cross Device Example</title>
<link rel="stylesheet/less" type="text/css" href="css/styles.less" />
<link rel="stylesheet" href="css/style.css" />
<link rel="stylesheet" href="css/iscroll.css" />
<script type="text/javascript" src="js/jquery-1.8.0.min.js"></script>
<script type="text/javascript" src="js/jquery.touchwipe.min.js"></script>
<script type="text/javascript" src="js/iscroll.js"></script>
<script type="text/javascript" src="js/less-1.3.0.min.js"></script>
<script type="text/javascript" src="js/brenFunctions.js"></script>
</head>
<body>
<div id="wrap">
<div id="main" class="clearfix"> <div id="header">
<h1>Bren's App</h1>
</div><!--End Header-->
<div id="displayRegion">
<div id="displayContent">
<div id="swipeRegionLeft">
<div id="leftContentScroller" class="iScrollWrapper">
<div class="iScrollScroller">
<div style="padding:5px 10px;">
<ul>
<li><a href="#">Option 1</a></li>
<li><a href="#">Option 2</a></li>
<li><a href="#">Option 3</a></li>
<li><a href="#">Option 4</a></li>
</ul>
<ul>
<li><a href="#">Option 1</a></li>
<li><a href="#">Option 2</a></li>
<li><a href="#">Option 3</a></li>
<li><a href="#">Option 4</a></li>
</ul>
</div>
</div>
</div>
</div>
<div id="iScrollWrapper" class="iScrollWrapper">
<div class="iScrollScroller">
<div style="padding:15px 30px;">
<!-- nested! -->
<div class="smallContentBlockRight">
<div id="wrapperNestedRight" class="iScrollWrapper inneriScroll">
<div class="iScrollScroller">
<div style="padding:5px 10px;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nisi nulla, molestie nec vestibulum et, molestie eget lectus. Nam imperdiet gravida sapien eu tincidunt. Curabitur pellentesque nibh orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi rhoncus nunc vel massa pharetra rutrum. Donec pellentesque augue eget tortor pellentesque consequat. Nam molestie consectetur metus, non tristique neque pretium venenatis. Mauris id massa eu ligula sagittis facilisis consectetur et augue. Cras ullamcorper blandit massa, quis vestibulum felis ornare et. Sed quis lorem a mauris tristique ullamcorper. Etiam ultricies gravida dolor, non imperdiet ligula dapibus nec. Nulla lacinia bibendum massa eget porttitor.</p>
<p>Vivamus eros massa, varius sit amet venenatis at, malesuada sit amet quam. Praesent massa nunc, suscipit nec ullamcorper a, ullamcorper et nibh. Morbi vel sapien quis turpis mattis volutpat et vitae velit. Suspendisse imperdiet nisi ac augue ullamcorper vehicula. Morbi vel diam eget risus faucibus pharetra. Phasellus posuere mauris ut diam tristique id aliquet lacus condimentum. Fusce pharetra tempus felis, in sollicitudin velit ullamcorper sed.</p>
</div>
</div>
</div>
</div>
<h1>Chapter Bren</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nisi nulla, molestie nec vestibulum et, molestie eget lectus. Nam imperdiet gravida sapien eu tincidunt. Curabitur pellentesque nibh orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi rhoncus nunc vel massa pharetra rutrum. Donec pellentesque augue eget tortor pellentesque consequat. Nam molestie consectetur metus, non tristique neque pretium venenatis. Mauris id massa eu ligula sagittis facilisis consectetur et augue. Cras ullamcorper blandit massa, quis vestibulum felis ornare et. Sed quis lorem a mauris tristique ullamcorper. Etiam ultricies gravida dolor, non imperdiet ligula dapibus nec. Nulla lacinia bibendum massa eget porttitor.</p>
...
<div class="smallContentBlockLeft">
<div id="wrapperNestedLeft" class="iScrollWrapper inneriScroll">
<div class="iScrollScroller">
<div style="padding:5px 10px;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nisi nulla, molestie nec vestibulum et, molestie eget lectus. Nam imperdiet gravida sapien eu tincidunt. Curabitur pellentesque nibh orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi rhoncus nunc vel massa pharetra rutrum. Donec pellentesque augue eget tortor pellentesque consequat. Nam molestie consectetur metus, non tristique neque pretium venenatis. Mauris id massa eu ligula sagittis facilisis consectetur et augue. Cras ullamcorper blandit massa, quis vestibulum felis ornare et. Sed quis lorem a mauris tristique ullamcorper. Etiam ultricies gravida dolor, non imperdiet ligula dapibus nec. Nulla lacinia bibendum massa eget porttitor.</p>
<p>Vivamus eros massa, varius sit amet venenatis at, malesuada sit amet quam. Praesent massa nunc, suscipit nec ullamcorper a, ullamcorper et nibh. Morbi vel sapien quis turpis mattis volutpat et vitae velit. Suspendisse imperdiet nisi ac augue ullamcorper vehicula. Morbi vel diam eget risus faucibus pharetra. Phasellus posuere mauris ut diam tristique id aliquet lacus condimentum. Fusce pharetra tempus felis, in sollicitudin velit ullamcorper sed.</p>
</div>
</div>
</div>
</div>
.... <p>Proin auctor feugiat quam at tempor. Duis est nulla, interdum porta laoreet non, faucibus vitae sem. Suspendisse in semper lorem. Ut ante arcu, varius ac rutrum in, faucibus in mauris. Etiam condimentum diam eu nisi porttitor a varius mauris eleifend. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis vel quam odio, sit amet facilisis nulla. Nullam faucibus ipsum eget leo mattis non volutpat odio vehicula. Mauris vestibulum, enim vel eleifend aliquam, est neque commodo nibh, nec dignissim arcu dolor a mi. Integer non odio quis ipsum pulvinar venenatis. Cras ac nibh at tellus ornare consequat. Etiam cursus libero vitae ante venenatis non auctor libero gravida.</p>
</div> <!--pdding -->
</div> <!--iScrollScroller-->
</div> <!--iScrollWrapper-->
</div><!--End Display Content -->
</div> <!--End DisplayRegion -->
</div>
</div>
<div id="footer">
</div><!--End Footer-->
</body>
</html>
* { margin:0; padding:0; }
html, body, #wrap { height: 100%; }
body > #wrap {height: auto; min-height: 100%;}
body,ul,li {
padding:0;
margin:0;
border:0;
}
body {
font-size:12px;
-webkit-user-select:none;
-webkit-text-size-adjust:none;
display: none;
overflow: hidden;
height: 100%;
width: 100%;
background-color: #ddd; /* Background color */
color: #222; /* Foreground color used for text */
font-family: Helvetica;
font-size: 14px;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
}
@headerHeight: 43px;
@footerHeight: 43px;
@borderlistRadius: 10px;
.boxModel{ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
#main { padding-bottom: @footerHeight; .boxModel; } /* must be same height as the footer */
#displayRegion{
position: relative;
height: 100%;
width: 100%;
display:block;
overflow: hidden;
.boxModel;
}
#displayContent{
position: relative;
background-color: #fff;
display:block;
clear: both;
overflow: hidden;
width: 100%;
height: 100%;
.boxModel;
}
#swipeRegionLeft{
max-width: 100%;
width: 0%;
display: none;
position: absolute;
z-index: 1000;
height: 100%;
top: 0px;
left: 0px;
overflow: hidden;
border-right: 1px solid #000;
background-image: url('../images/pinstripes.png');
background-repeat: repeat;
background-color: #C5CCD4;
.boxModel;
}
#header{
position: relative;
clear: both;
height: @headerHeight;
width: 100%;
display:block;
}
#header h1{
width: 100%;
color: #fff;
line-height: @headerHeight;
font-size: @headerHeight - 18px;
font-weight: normak;
margin: 0px;
height: @headerHeight;
text-align: center;
text-decoration: none;
display:inline-block;
}
#leftContentScroller ul li{
margin: 0px;
padding: 0px;
min-height: 42px;
}
.border-radius-top (@radius) {
-webkit-border-top-left-radius: @radius;
-webkit-border-top-right-radius: @radius;
-moz-border-radius-topleft: @radius;
-moz-border-radius-topright: @radius;
border-top-left-radius: @radius;
border-top-right-radius: @radius;
}
.border-radius-bottom (@radius) {
-webkit-border-bottom-right-radius: @radius;
-webkit-border-bottom-left-radius: @radius;
-moz-border-radius-bottomright: @radius;
-moz-border-radius-bottomleft: @radius;
border-bottom-right-radius: @radius;
border-bottom-left-radius: @radius;
}
#swipeRegionLeft ul { margin:5px 0 15px 0; padding:0; list-style:none; -webkit-border-radius:0; border-width:0; background-color:transparent; }
#swipeRegionLeft ul > li { margin:0; padding:0; border-width:0; }
#swipeRegionLeft ul > li a { text-align:left; padding:11px 0 9px 10px; background:url('../images/listArrow.png') center right no-repeat;
display:block; text-decoration:none; overflow:hidden; text-overflow:ellipsis; color:#000; font-weight:bold; font-size:17px;
margin:0; border:1px solid #aaa; border-bottom-width:0 !important; margin-top:-1px; background-color:#fff; }
#swipeRegionLeft ul > li:first-child a { .border-radius-top (10px); }
#swipeRegionLeft ul > li:last-child a { .border-radius-bottom (10px); border-bottom-width:1px !important; }
p{
margin: 0 8px;
font-size: 15px;
line-height: 20px;
font-family: Helvetica, arial;
}
#footer {
position: relative;
margin-top: -@footerHeight; /* negative value of footer height */
height: @footerHeight;
clear:both;
}
/* CLEAR FIX*/
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix {
display: inline-block;
}
/* Hides from IE-mac \*/
* html .clearfix {
height: 1%;
}
.clearfix {
display: block;
}
/* End hide from IE-mac */
.gradient{
background: #4c4c4c; /* Old browsers */
background: -moz-linear-gradient(top, #4c4c4c 0%, #595959 12%, #666666 25%, #474747 39%, #2c2c2c 50%, #000000 51%, #111111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#4c4c4c), color-stop(12%,#595959), color-stop(25%,#666666), color-stop(39%,#474747), color-stop(50%,#2c2c2c), color-stop(51%,#000000), color-stop(60%,#111111), color-stop(76%,#2b2b2b), color-stop(91%,#1c1c1c), color-stop(100%,#131313)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* IE10+ */
background: linear-gradient(to bottom, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313',GradientType=0 ); /* IE6-9 */
}
#footer,
#header{
.gradient;
.boxModel;
width: 100%;
display:block;
position: relative;
border: 1px solid #000;
}
.defaultSmallBlockContent{
position:relative;
width: 40%;
height: 200px;
margin-top: 20px;
margin-bottom: 20px;
border: 1px solid #ccc;
padding: 10px;
}
var viewportWidth = 0;
var viewportHeight = 0;
var portrait = 0;
var landscape = 0;
var previousOrientation = 0;
var minMove = 50; //minimum swipe movement to trigger event
var minSize = 480;
var headerFooterHeight = 43; //header + footer height
var iScrolls = new Array(); //array of iscrolls
var scrollInit = 0; //flag for scroll bar initilization
var sideBarOpen = 0; //flag for if side bar is open
var firstRun = 1;
//function to refresh each iscroller on change
function refreshiScrolls(){
if( !firstRun ){ //flag for when body will be visible
for( var s = 0; s < iScrolls.length; s++){
iScrolls[s].refresh();
}
}
}
//function called after screen rotation, used for applying necessary classes and resetting sizes
function updateScreen(){
viewportWidth = $(window).width();
viewportHeight = $(window).height();
if( viewportWidth < minSize ){
$('body').addClass('smallView');
}else{
$('body').removeClass('smallView');
}
if( window.orientation != undefined){
if( window.orientation == 0 || window.orientation == 180){
portrait = 1; landscape = 0;
$('body').addClass('portrait'); $('body').removeClass('landscape');
}else{ //90 || -90
portrait = 0; landscape = 1;
$('body').removeClass('portrait'); $('body').addClass('landscape');
}
}
$('#displayRegion').css({'width' : viewportWidth + 'px', 'height' : viewportHeight - (headerFooterHeight * 2) + 'px'});
console.log( 'width ' + viewportWidth + 'px ' + 'height ' + viewportHeight + 'px');
console.log( 'landscape : ' + landscape + ' portrait : ' + portrait );
refreshiScrolls();
}
//function to open the 'options' side bar
function animateSideBar(){
var slideDuration = 50;
if( sideBarOpen ){
$('#swipeRegionLeft').css({'display' : 'none', 'width' : '0%'});
if( ! viewportWidth < minSize){
$('#iScrollWrapper').animate({
left: '0%',
width: '100%'
}, slideDuration, function() {
// Animation complete.
refreshiScrolls();
});
}
sideBarOpen = 0;
$('#displayContent').removeClass('optionsOpen');
}else{
sideBarOpen = 1;
$('#displayContent').addClass('optionsOpen');
$('#swipeRegionLeft').css('display', 'block');
if( viewportWidth < minSize){
$('#swipeRegionLeft').animate({
width: '100%'
}, slideDuration, function() {
// Animation complete.
refreshiScrolls();
});
}else{
$('#swipeRegionLeft').animate({
width: '300px'
}, slideDuration, function() {
// Animation complete.
refreshiScrolls();
});
$('#iScrollWrapper').animate({
width:(viewportWidth - 300) + 'px',
left: '300px'
}, slideDuration, function() {
refreshiScrolls();
});
}
}
}
//just for triggering the rotation event
var checkOrientation = function(){
if(window.orientation !== previousOrientation){
previousOrientation = window.orientation;
updateScreen();
}
};
function loaded()
{
$(function(){
$('.iScrollWrapper').each(function(index){ //get collection of iScrolls
if( $(this).hasClass('inneriScroll') ){
iScrolls[index] = new iScroll( $(this).attr('id').toString() ,{
onBeforeScrollMove: function (e) {
e.preventDefault();
e.stopPropagation();
}
});
}else{
iScrolls[index] = new iScroll( $(this).attr('id').toString() );
}
if( index = $('.iScrollWrapper').length -1){
scrollInit = 1;
}
});
updateScreen();
//Add Swipe Handlers for the various regions of the screen
$("#iScrollWrapper").touchwipe({
wipeLeft: function() { animateSideBar() },
wipeRight: function() { animateSideBar() },
min_move_x: minMove,
preventDefaultEvents: false
});
$('#swipeRegionLeft').touchwipe({
wipeLeft: function() { animateSideBar() },
min_move_x: minMove,
preventDefaultEvents: false
});
$("#footer").touchwipe({
wipeUp: function() { alert("down"); },
wipeDown: function() { alert("up"); },
preventDefaultEvents: false
});
/*fix for internal links on iOS*/
$.expr[':'].external = function(obj){ return !obj.href.match(/^mailto\:/) && (obj.hostname != location.hostname) && (obj.hostname != ''); };
$('a').not('a:external').each(function(){ //grab all the local links
if( typeof $(this).attr('href') !== 'undefined' && $(this).attr('href') !== false){ //check that there is a href
if( $(this).attr('href') != "#"){ //check the href is not an anchor
$(this).addClass('internalAppLink');
}
}
});
/*Check if IOS*/
$('a.internalAppLink').click(function(event){
event.preventDefault();
window.location.href = $(this).attr('href');
});
if( scrollInit == 1 ){
$('body').css('display', 'block');
firstRun = 0;
refreshiScrolls(); //body must be displayed to work
}
});
}//end loaded
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
//Use this for high compatibility (iDevice + Android)
document.addEventListener('DOMContentLoaded', function () { setTimeout(loaded, 200); }, false);
//Use this for iDevice only
//document.addEventListener('DOMContentLoaded', loaded, false);
//Use this if nothing else works
//window.addEventListener('load', setTimeout(function () { loaded(); }, 200), false);
window.addEventListener("resize", updateScreen, false);
window.addEventListener("orientationchange", checkOrientation, false);
if(/Android/i.test(navigator.userAgent) ){ //Android Doesnt seem to always pick up on it, so force a check. This can affect battery performance only use if people experience issues
// setInterval(checkOrientation, 1000);
}
*Note swipe right to trigger side menu
Here are the files. mobileApp v1.zip
Hope it helps someone - I'll extend on this further and post updates!
To create this package I use the following libraries:
-jQuery - to abbreviate javascript
-iScroll - to help with cross device scrolling
-less.js - cause its a nifty way of styling with css
-touchSwipe - help with swipes
This web app (at the present time) is one screen with scroll-able content and swipe zones, along with scroll-able and inner scroll-able zones. I wrote some javascript to tie the libraries all together and create a nice and responsive application.
At the bottom of this page I'll have a link to the files, He're is a brief over view of the html, js and css/less.
HTML Template:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="theme/touch-icon-iphone.png" />
<link rel="apple-touch-icon" sizes="72x72" href="theme/touch-icon-ipad.png" />
<link rel="apple-touch-icon" sizes="114x114" href="theme/touch-icon-iphone4.png" />
<link rel="apple-touch-startup-image" href="theme/startup.jpg" media="screen and (min-device-width: 200px) and (max-device-width: 480) and (orientation:portrait)"> <!-- iPod/Phone 320 x 460 image -->
<link rel="apple-touch-startup-image" href="theme/startup-iPad-portrait.jpg" media="(device-width: 768px) and (orientation: portrait)" /> <!--iPad Portrait 768 x 1004 -->
<link rel="apple-touch-startup-image" href="theme/startup-iPad-landscape.jpg" media="(device-width: 768px) and (orientation: landscape)" /> <!--iPad LandScape 1024 x 748-->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="HandheldFriendly" content="true" />
<title>Cross Device Example</title>
<link rel="stylesheet/less" type="text/css" href="css/styles.less" />
<link rel="stylesheet" href="css/style.css" />
<link rel="stylesheet" href="css/iscroll.css" />
<script type="text/javascript" src="js/jquery-1.8.0.min.js"></script>
<script type="text/javascript" src="js/jquery.touchwipe.min.js"></script>
<script type="text/javascript" src="js/iscroll.js"></script>
<script type="text/javascript" src="js/less-1.3.0.min.js"></script>
<script type="text/javascript" src="js/brenFunctions.js"></script>
</head>
<body>
<div id="wrap">
<div id="main" class="clearfix"> <div id="header">
<h1>Bren's App</h1>
</div><!--End Header-->
<div id="displayRegion">
<div id="displayContent">
<div id="swipeRegionLeft">
<div id="leftContentScroller" class="iScrollWrapper">
<div class="iScrollScroller">
<div style="padding:5px 10px;">
<ul>
<li><a href="#">Option 1</a></li>
<li><a href="#">Option 2</a></li>
<li><a href="#">Option 3</a></li>
<li><a href="#">Option 4</a></li>
</ul>
<ul>
<li><a href="#">Option 1</a></li>
<li><a href="#">Option 2</a></li>
<li><a href="#">Option 3</a></li>
<li><a href="#">Option 4</a></li>
</ul>
</div>
</div>
</div>
</div>
<div id="iScrollWrapper" class="iScrollWrapper">
<div class="iScrollScroller">
<div style="padding:15px 30px;">
<!-- nested! -->
<div class="smallContentBlockRight">
<div id="wrapperNestedRight" class="iScrollWrapper inneriScroll">
<div class="iScrollScroller">
<div style="padding:5px 10px;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nisi nulla, molestie nec vestibulum et, molestie eget lectus. Nam imperdiet gravida sapien eu tincidunt. Curabitur pellentesque nibh orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi rhoncus nunc vel massa pharetra rutrum. Donec pellentesque augue eget tortor pellentesque consequat. Nam molestie consectetur metus, non tristique neque pretium venenatis. Mauris id massa eu ligula sagittis facilisis consectetur et augue. Cras ullamcorper blandit massa, quis vestibulum felis ornare et. Sed quis lorem a mauris tristique ullamcorper. Etiam ultricies gravida dolor, non imperdiet ligula dapibus nec. Nulla lacinia bibendum massa eget porttitor.</p>
<p>Vivamus eros massa, varius sit amet venenatis at, malesuada sit amet quam. Praesent massa nunc, suscipit nec ullamcorper a, ullamcorper et nibh. Morbi vel sapien quis turpis mattis volutpat et vitae velit. Suspendisse imperdiet nisi ac augue ullamcorper vehicula. Morbi vel diam eget risus faucibus pharetra. Phasellus posuere mauris ut diam tristique id aliquet lacus condimentum. Fusce pharetra tempus felis, in sollicitudin velit ullamcorper sed.</p>
</div>
</div>
</div>
</div>
<h1>Chapter Bren</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nisi nulla, molestie nec vestibulum et, molestie eget lectus. Nam imperdiet gravida sapien eu tincidunt. Curabitur pellentesque nibh orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi rhoncus nunc vel massa pharetra rutrum. Donec pellentesque augue eget tortor pellentesque consequat. Nam molestie consectetur metus, non tristique neque pretium venenatis. Mauris id massa eu ligula sagittis facilisis consectetur et augue. Cras ullamcorper blandit massa, quis vestibulum felis ornare et. Sed quis lorem a mauris tristique ullamcorper. Etiam ultricies gravida dolor, non imperdiet ligula dapibus nec. Nulla lacinia bibendum massa eget porttitor.</p>
...
<div class="smallContentBlockLeft">
<div id="wrapperNestedLeft" class="iScrollWrapper inneriScroll">
<div class="iScrollScroller">
<div style="padding:5px 10px;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nisi nulla, molestie nec vestibulum et, molestie eget lectus. Nam imperdiet gravida sapien eu tincidunt. Curabitur pellentesque nibh orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi rhoncus nunc vel massa pharetra rutrum. Donec pellentesque augue eget tortor pellentesque consequat. Nam molestie consectetur metus, non tristique neque pretium venenatis. Mauris id massa eu ligula sagittis facilisis consectetur et augue. Cras ullamcorper blandit massa, quis vestibulum felis ornare et. Sed quis lorem a mauris tristique ullamcorper. Etiam ultricies gravida dolor, non imperdiet ligula dapibus nec. Nulla lacinia bibendum massa eget porttitor.</p>
<p>Vivamus eros massa, varius sit amet venenatis at, malesuada sit amet quam. Praesent massa nunc, suscipit nec ullamcorper a, ullamcorper et nibh. Morbi vel sapien quis turpis mattis volutpat et vitae velit. Suspendisse imperdiet nisi ac augue ullamcorper vehicula. Morbi vel diam eget risus faucibus pharetra. Phasellus posuere mauris ut diam tristique id aliquet lacus condimentum. Fusce pharetra tempus felis, in sollicitudin velit ullamcorper sed.</p>
</div>
</div>
</div>
</div>
.... <p>Proin auctor feugiat quam at tempor. Duis est nulla, interdum porta laoreet non, faucibus vitae sem. Suspendisse in semper lorem. Ut ante arcu, varius ac rutrum in, faucibus in mauris. Etiam condimentum diam eu nisi porttitor a varius mauris eleifend. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis vel quam odio, sit amet facilisis nulla. Nullam faucibus ipsum eget leo mattis non volutpat odio vehicula. Mauris vestibulum, enim vel eleifend aliquam, est neque commodo nibh, nec dignissim arcu dolor a mi. Integer non odio quis ipsum pulvinar venenatis. Cras ac nibh at tellus ornare consequat. Etiam cursus libero vitae ante venenatis non auctor libero gravida.</p>
</div> <!--pdding -->
</div> <!--iScrollScroller-->
</div> <!--iScrollWrapper-->
</div><!--End Display Content -->
</div> <!--End DisplayRegion -->
</div>
</div>
<div id="footer">
</div><!--End Footer-->
</body>
</html>
style.css
* { margin:0; padding:0; }
html, body, #wrap { height: 100%; }
body > #wrap {height: auto; min-height: 100%;}
body,ul,li {
padding:0;
margin:0;
border:0;
}
body {
font-size:12px;
-webkit-user-select:none;
-webkit-text-size-adjust:none;
display: none;
overflow: hidden;
height: 100%;
width: 100%;
background-color: #ddd; /* Background color */
color: #222; /* Foreground color used for text */
font-family: Helvetica;
font-size: 14px;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
}
Style.less
@headerHeight: 43px;
@footerHeight: 43px;
@borderlistRadius: 10px;
.boxModel{ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
#main { padding-bottom: @footerHeight; .boxModel; } /* must be same height as the footer */
#displayRegion{
position: relative;
height: 100%;
width: 100%;
display:block;
overflow: hidden;
.boxModel;
}
#displayContent{
position: relative;
background-color: #fff;
display:block;
clear: both;
overflow: hidden;
width: 100%;
height: 100%;
.boxModel;
}
#swipeRegionLeft{
max-width: 100%;
width: 0%;
display: none;
position: absolute;
z-index: 1000;
height: 100%;
top: 0px;
left: 0px;
overflow: hidden;
border-right: 1px solid #000;
background-image: url('../images/pinstripes.png');
background-repeat: repeat;
background-color: #C5CCD4;
.boxModel;
}
#header{
position: relative;
clear: both;
height: @headerHeight;
width: 100%;
display:block;
}
#header h1{
width: 100%;
color: #fff;
line-height: @headerHeight;
font-size: @headerHeight - 18px;
font-weight: normak;
margin: 0px;
height: @headerHeight;
text-align: center;
text-decoration: none;
display:inline-block;
}
#leftContentScroller ul li{
margin: 0px;
padding: 0px;
min-height: 42px;
}
.border-radius-top (@radius) {
-webkit-border-top-left-radius: @radius;
-webkit-border-top-right-radius: @radius;
-moz-border-radius-topleft: @radius;
-moz-border-radius-topright: @radius;
border-top-left-radius: @radius;
border-top-right-radius: @radius;
}
.border-radius-bottom (@radius) {
-webkit-border-bottom-right-radius: @radius;
-webkit-border-bottom-left-radius: @radius;
-moz-border-radius-bottomright: @radius;
-moz-border-radius-bottomleft: @radius;
border-bottom-right-radius: @radius;
border-bottom-left-radius: @radius;
}
#swipeRegionLeft ul { margin:5px 0 15px 0; padding:0; list-style:none; -webkit-border-radius:0; border-width:0; background-color:transparent; }
#swipeRegionLeft ul > li { margin:0; padding:0; border-width:0; }
#swipeRegionLeft ul > li a { text-align:left; padding:11px 0 9px 10px; background:url('../images/listArrow.png') center right no-repeat;
display:block; text-decoration:none; overflow:hidden; text-overflow:ellipsis; color:#000; font-weight:bold; font-size:17px;
margin:0; border:1px solid #aaa; border-bottom-width:0 !important; margin-top:-1px; background-color:#fff; }
#swipeRegionLeft ul > li:first-child a { .border-radius-top (10px); }
#swipeRegionLeft ul > li:last-child a { .border-radius-bottom (10px); border-bottom-width:1px !important; }
p{
margin: 0 8px;
font-size: 15px;
line-height: 20px;
font-family: Helvetica, arial;
}
#footer {
position: relative;
margin-top: -@footerHeight; /* negative value of footer height */
height: @footerHeight;
clear:both;
}
/* CLEAR FIX*/
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix {
display: inline-block;
}
/* Hides from IE-mac \*/
* html .clearfix {
height: 1%;
}
.clearfix {
display: block;
}
/* End hide from IE-mac */
.gradient{
background: #4c4c4c; /* Old browsers */
background: -moz-linear-gradient(top, #4c4c4c 0%, #595959 12%, #666666 25%, #474747 39%, #2c2c2c 50%, #000000 51%, #111111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#4c4c4c), color-stop(12%,#595959), color-stop(25%,#666666), color-stop(39%,#474747), color-stop(50%,#2c2c2c), color-stop(51%,#000000), color-stop(60%,#111111), color-stop(76%,#2b2b2b), color-stop(91%,#1c1c1c), color-stop(100%,#131313)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* IE10+ */
background: linear-gradient(to bottom, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313',GradientType=0 ); /* IE6-9 */
}
#footer,
#header{
.gradient;
.boxModel;
width: 100%;
display:block;
position: relative;
border: 1px solid #000;
}
.defaultSmallBlockContent{
position:relative;
width: 40%;
height: 200px;
margin-top: 20px;
margin-bottom: 20px;
border: 1px solid #ccc;
padding: 10px;
}
brenFunctions.js
var viewportWidth = 0;
var viewportHeight = 0;
var portrait = 0;
var landscape = 0;
var previousOrientation = 0;
var minMove = 50; //minimum swipe movement to trigger event
var minSize = 480;
var headerFooterHeight = 43; //header + footer height
var iScrolls = new Array(); //array of iscrolls
var scrollInit = 0; //flag for scroll bar initilization
var sideBarOpen = 0; //flag for if side bar is open
var firstRun = 1;
//function to refresh each iscroller on change
function refreshiScrolls(){
if( !firstRun ){ //flag for when body will be visible
for( var s = 0; s < iScrolls.length; s++){
iScrolls[s].refresh();
}
}
}
//function called after screen rotation, used for applying necessary classes and resetting sizes
function updateScreen(){
viewportWidth = $(window).width();
viewportHeight = $(window).height();
if( viewportWidth < minSize ){
$('body').addClass('smallView');
}else{
$('body').removeClass('smallView');
}
if( window.orientation != undefined){
if( window.orientation == 0 || window.orientation == 180){
portrait = 1; landscape = 0;
$('body').addClass('portrait'); $('body').removeClass('landscape');
}else{ //90 || -90
portrait = 0; landscape = 1;
$('body').removeClass('portrait'); $('body').addClass('landscape');
}
}
$('#displayRegion').css({'width' : viewportWidth + 'px', 'height' : viewportHeight - (headerFooterHeight * 2) + 'px'});
console.log( 'width ' + viewportWidth + 'px ' + 'height ' + viewportHeight + 'px');
console.log( 'landscape : ' + landscape + ' portrait : ' + portrait );
refreshiScrolls();
}
//function to open the 'options' side bar
function animateSideBar(){
var slideDuration = 50;
if( sideBarOpen ){
$('#swipeRegionLeft').css({'display' : 'none', 'width' : '0%'});
if( ! viewportWidth < minSize){
$('#iScrollWrapper').animate({
left: '0%',
width: '100%'
}, slideDuration, function() {
// Animation complete.
refreshiScrolls();
});
}
sideBarOpen = 0;
$('#displayContent').removeClass('optionsOpen');
}else{
sideBarOpen = 1;
$('#displayContent').addClass('optionsOpen');
$('#swipeRegionLeft').css('display', 'block');
if( viewportWidth < minSize){
$('#swipeRegionLeft').animate({
width: '100%'
}, slideDuration, function() {
// Animation complete.
refreshiScrolls();
});
}else{
$('#swipeRegionLeft').animate({
width: '300px'
}, slideDuration, function() {
// Animation complete.
refreshiScrolls();
});
$('#iScrollWrapper').animate({
width:(viewportWidth - 300) + 'px',
left: '300px'
}, slideDuration, function() {
refreshiScrolls();
});
}
}
}
//just for triggering the rotation event
var checkOrientation = function(){
if(window.orientation !== previousOrientation){
previousOrientation = window.orientation;
updateScreen();
}
};
function loaded()
{
$(function(){
$('.iScrollWrapper').each(function(index){ //get collection of iScrolls
if( $(this).hasClass('inneriScroll') ){
iScrolls[index] = new iScroll( $(this).attr('id').toString() ,{
onBeforeScrollMove: function (e) {
e.preventDefault();
e.stopPropagation();
}
});
}else{
iScrolls[index] = new iScroll( $(this).attr('id').toString() );
}
if( index = $('.iScrollWrapper').length -1){
scrollInit = 1;
}
});
updateScreen();
//Add Swipe Handlers for the various regions of the screen
$("#iScrollWrapper").touchwipe({
wipeLeft: function() { animateSideBar() },
wipeRight: function() { animateSideBar() },
min_move_x: minMove,
preventDefaultEvents: false
});
$('#swipeRegionLeft').touchwipe({
wipeLeft: function() { animateSideBar() },
min_move_x: minMove,
preventDefaultEvents: false
});
$("#footer").touchwipe({
wipeUp: function() { alert("down"); },
wipeDown: function() { alert("up"); },
preventDefaultEvents: false
});
/*fix for internal links on iOS*/
$.expr[':'].external = function(obj){ return !obj.href.match(/^mailto\:/) && (obj.hostname != location.hostname) && (obj.hostname != ''); };
$('a').not('a:external').each(function(){ //grab all the local links
if( typeof $(this).attr('href') !== 'undefined' && $(this).attr('href') !== false){ //check that there is a href
if( $(this).attr('href') != "#"){ //check the href is not an anchor
$(this).addClass('internalAppLink');
}
}
});
/*Check if IOS*/
$('a.internalAppLink').click(function(event){
event.preventDefault();
window.location.href = $(this).attr('href');
});
if( scrollInit == 1 ){
$('body').css('display', 'block');
firstRun = 0;
refreshiScrolls(); //body must be displayed to work
}
});
}//end loaded
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
//Use this for high compatibility (iDevice + Android)
document.addEventListener('DOMContentLoaded', function () { setTimeout(loaded, 200); }, false);
//Use this for iDevice only
//document.addEventListener('DOMContentLoaded', loaded, false);
//Use this if nothing else works
//window.addEventListener('load', setTimeout(function () { loaded(); }, 200), false);
window.addEventListener("resize", updateScreen, false);
window.addEventListener("orientationchange", checkOrientation, false);
if(/Android/i.test(navigator.userAgent) ){ //Android Doesnt seem to always pick up on it, so force a check. This can affect battery performance only use if people experience issues
// setInterval(checkOrientation, 1000);
}
*Note swipe right to trigger side menu
Here are the files. mobileApp v1.zip
Hope it helps someone - I'll extend on this further and post updates!
Tuesday, July 31, 2012
Some Powerful Object Oriented Javacript
So here is some code I wrote to 'make' javascript classes a little bit easier. In essence what the code below does is, you create an object like so:
var aPerson = myObjWrap("Name, Age, Gender");
from there, my code creates the 'aPerson' object so you can perform functions on it like so:
aPerson.setName("Brendon");
aPerson.setAge("24");
aPerson.setGender("Male");
And then if you want to see what the object contains you can do something like this:
console.log("Name: " + aPerson.getName() + " Age:" + aPerson.getAge() + " Gender: " + aPerson.getGender() );
Which would spit out: Name: Brendon Age:24 Gender: Male
So here's the code
var aPerson = myObjWrap("Name, Age, Gender");
from there, my code creates the 'aPerson' object so you can perform functions on it like so:
aPerson.setName("Brendon");
aPerson.setAge("24");
aPerson.setGender("Male");
And then if you want to see what the object contains you can do something like this:
console.log("Name: " + aPerson.getName() + " Age:" + aPerson.getAge() + " Gender: " + aPerson.getGender() );
Which would spit out: Name: Brendon Age:24 Gender: Male
So here's the code
//code for trim if (!String.prototype.trim) { String.prototype.trim = function () { return this.replace(/^\s+|\s+$/g,''); }; } $(document).ready(function() { function AddGettersAndSetters(object) { for (var field in object) { if (typeof(object[field]) != 'function') { if (typeof(object[field]) == 'object') { for (var f = 0; f < object[field][0].length; f++) { AssignFunctions(object, object[field][0][f].trim() ); } } else { AssignFunctions(object, field); } } } function AssignFunctions(object, field) { object['get' + field] = function() { return this[field]; }; object['set' + field] = function(value) { this[field] = value; }; } } var myObjWrap = function(fields) { var functions = new Array(fields.split(",")); var theObj = { fields: functions }; var gs = new AddGettersAndSetters(theObj); return theObj; } var aPerson = myObjWrap("Name, Age, Gender"); console.log( aPerson ); aPerson.setName("Brendon"); aPerson.setAge("24"); aPerson.setGender("Male"); console.log( aPerson ); console.log("Name: " + aPerson.getName() + " Age:" + aPerson.getAge()
+ " Gender: " + aPerson.getGender() ); });
Thursday, May 17, 2012
Getting started with creating Mobile App like websites, quickly and Easily
So, I am assuming if you have come across this posting, you're looking to create a mobile friendly website of your current website or from scratch. Well, you've come to the right place. I am going to assume you have at least some familiarity with things like CSS, HTML, jQuery & Javascript, and we'll go from there.
So how do we begin? Step one. Have a design, well at-least in mind. To create something mobile friendly, your content is going to have to be presented in a mobile friendly fashion. In alot of cases, these changes can be made very easily and I'll outline a few examples. So without further ado, Lets start.
Step 1.
Start with the correct html structure and doctype.
In this case, there are two doctypes you should look into using, the mobile doctype like so:
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN"
"http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
or the standard HTML5 doctype like so:
Using one of theses doctypes will help your application render better in Mobile devices.
Step 2.
Add in the appropriate "meta tags"
<meta name="HandheldFriendly" content="true" /> <meta name="viewport" content="user-scalable=no" /> <meta name="viewport" content="width=480" />
The meta tags above are going to give you much better cross device look and consistency. As you can see, in my example, I am assuming the viewport should be 480px wide (I have found this yields nice results on most devices).
Add in the optional "Meta tags"
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
These are i-Device specific meta tags (see apple documenation
And lastly, add some polish (note file paths will be unique and you'll have to change).
<link rel="shortcut icon" href="/GetSiteFile/favicon.ico" />
These are all Apple specific items
<link rel="apple-touch-icon" href="/GetSiteFile/touch-icon-iphone.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/GetSiteFile/touch-icon-ipad.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/GetSiteFile/touch-icon-iphone4.png" />
<link rel="apple-touch-startup-image" href="/GetSiteFile/startup.png">
Step 3.
We have our doctype, we have our meta tags and other tid bits setup, now how about actually displaying content. This goes back to having a design in mind, and designing in mind for mobile.
Mobile Layouts have to be tuned to work with less real-estate, which means, cut the crap, and only show what is relevant. This can be a bit challenging when scaling from a Desktop website to a Mobile site, but its not impossible.
A typical Menu on a website may look something like this:
[Option 1][Option2][Option3][Option4][Option5]
but in a mobile site, that should be re-structured to something like this:
[Option 1]
[Option 2]
[Option 3]
[Option 4]
etc...
Step 4.
Consider implementing touch gestures (where applicable). Not everything, or everyone will require swipe gestures for items, but in some instances it makes sense to include it. To keep this posting short, I'll leave you with a nice little jQuery plugin which I have found most useful and easy to use.
http://www.netcu.de/jquery-touchwipe-iphone-ipad-library
Step 5.
The rest is for you, this is very quick list of things to create a mobile website quickly.
Other things to investigate if you haven't
-Using a mobile framework like Sencha Touch
-Using a framework like Less.js to make styling changes easier
I will post more relevant items when I think of them.
View this: http://bren1818.blogspot.ca/2012/09/simple-web-app-for-android-and-ios.html (A newer post)
So how do we begin? Step one. Have a design, well at-least in mind. To create something mobile friendly, your content is going to have to be presented in a mobile friendly fashion. In alot of cases, these changes can be made very easily and I'll outline a few examples. So without further ado, Lets start.
Step 1.
Start with the correct html structure and doctype.
In this case, there are two doctypes you should look into using, the mobile doctype like so:
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN"
"http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
or the standard HTML5 doctype like so:
<!DOCTYPE html>
Using one of theses doctypes will help your application render better in Mobile devices.
Step 2.
Add in the appropriate "meta tags"
<meta name="HandheldFriendly" content="true" /> <meta name="viewport" content="user-scalable=no" /> <meta name="viewport" content="width=480" />
The meta tags above are going to give you much better cross device look and consistency. As you can see, in my example, I am assuming the viewport should be 480px wide (I have found this yields nice results on most devices).
Add in the optional "Meta tags"
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
These are i-Device specific meta tags (see apple documenation
And lastly, add some polish (note file paths will be unique and you'll have to change).
<link rel="shortcut icon" href="/GetSiteFile/favicon.ico" />
These are all Apple specific items
<link rel="apple-touch-icon" href="/GetSiteFile/touch-icon-iphone.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/GetSiteFile/touch-icon-ipad.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/GetSiteFile/touch-icon-iphone4.png" />
<link rel="apple-touch-startup-image" href="/GetSiteFile/startup.png">
Step 3.
We have our doctype, we have our meta tags and other tid bits setup, now how about actually displaying content. This goes back to having a design in mind, and designing in mind for mobile.
Mobile Layouts have to be tuned to work with less real-estate, which means, cut the crap, and only show what is relevant. This can be a bit challenging when scaling from a Desktop website to a Mobile site, but its not impossible.
A typical Menu on a website may look something like this:
[Option 1][Option2][Option3][Option4][Option5]
but in a mobile site, that should be re-structured to something like this:
[Option 1]
[Option 2]
[Option 3]
[Option 4]
etc...
Step 4.
Consider implementing touch gestures (where applicable). Not everything, or everyone will require swipe gestures for items, but in some instances it makes sense to include it. To keep this posting short, I'll leave you with a nice little jQuery plugin which I have found most useful and easy to use.
http://www.netcu.de/jquery-touchwipe-iphone-ipad-library
Step 5.
The rest is for you, this is very quick list of things to create a mobile website quickly.
Other things to investigate if you haven't
-Using a mobile framework like Sencha Touch
-Using a framework like Less.js to make styling changes easier
I will post more relevant items when I think of them.
View this: http://bren1818.blogspot.ca/2012/09/simple-web-app-for-android-and-ios.html (A newer post)
Subscribe to:
Posts (Atom)