jQuery Mobile and TYPO3

This article describes an easy way to create websites targeted at mobile devices with TYPO3. The demo website I describe here is available on:  http://xavier.perseguers.ch/?id=133.

Updates:

  • [08.12.2011] Links to jQuery Mobile beta1 have been updated to point to final 1.0 instead
  • [21.10.2011] Tutorial adapted to work with TYPO3 4.6
  • [26.06.2011] Links to jQuery Mobile alpha4 have been updated to point to beta1 instead

Introduction

A while ago, I made some prototyping with  jQTouch along with a TemplaVoilà-based website. This time, I’m using  jQuery Mobile to create my website. It does not basically differ but I used a completely different strategy this time as I wanted my mobile website to be as much “plain TYPO3” as possible.

In short, when I used jQTouch with TemplaVoilà, I had flexible content elements (FCE) to create the mobile “pages”, meaning a single physical TYPO3 page (in the page tree) could lead to multiple mobile pages because in the end those frameworks use DIVs with special classes to identify the “pages” and only show a single page at a time. This works and makes sense sometimes but it often makes life harder than wanted by having a virtual page structure within the physical TYPO3 page structure. This time, I made sure 1 page in TYPO3 is 1 page on my mobile device.

Create a basic page structure

First of all, you need a basic website structure. Here is mine for the sake of this tutorial:

General configuration

What is a TYPO3 website without some TypoScript? Not that much! According to the jQuery Mobile documentation, the anatomy of a page is as follows:

<!DOCTYPE html> 
<html> 
	<head> 
	<title>Page Title</title> 
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
	<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
</head> 
<body> 
 
<div data-role="page">
 
	<div data-role="header">
		<h1>Page Title</h1>
	</div><!-- /header -->
 
	<div data-role="content">	
		<p>Page content goes here.</p>		
	</div><!-- /content -->
 
	<div data-role="footer">
		<h4>Page Footer</h4>
	</div><!-- /footer -->
</div><!-- /page -->
 
</body>
</html>

This is done with a few lines of TypoScript (the \~ marker is used to tell you setup flows over next line):

Basic page TS

config {
    renderCharset = utf-8
    doctype = html5
    xmlprologue = none
}
 
page = PAGE
 
page.includeJSlibs {
    jquery = http://code.jquery.com/jquery-1.6.4.min.js
    jquery.external = 1
    jquery.disableCompression = 1
    jquery.excludeFromConcatenation = 1
 
    jquerymobile = http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js
    jquerymobile.external = 1
    jquerymobile.disableCompression = 1
    jquerymobile.excludeFromConcatenation = 1
}
 
page.includeCSS {
    jquerymobile = http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css
    jquerymobile.external = 1
    jquerymobile.disableCompression = 1
    jquerymobile.excludeFromConcatenation = 1
}
 
page {
    10 = TEXT
    10 {
        data = page:title
        wrap = <h1>|</h1>
        wrap2 = <div data-role="header" data-position="fixed" data-theme="b">|
        dataWrap = <div data-role="page" id="page_{page:uid}" data-add-back-btn="true">|
    }
 
    20 = TEXT
    20 {
        value = Home
        typolink.parameter = {$website.links.homepage}
        typolink.ATagParams = data-icon="home" data-iconpos="notext" data-direction="reverse" \~
                                                       class="ui-btn-right jqm-home"
        wrap = |</div><!-- /header -->
    }
 
    30 < styles.content.get
    30.wrap = <div data-role="content">|</div>
 
    40 = TEXT
    40 {
        value = Copyright 2011
        wrap = <h1>|</h1>
        wrap2 = <div data-role="footer" data-position="fixed" data-theme="a">|</div>
    }
 
    1000 = TEXT
    1000.value = </div><!-- /page -->
}
 
# Remove the home icon on homepage
[globalVar = TSFE:id = {$website.links.homepage}]
page.20.value >
page.20.typolink >
[global]

We used a constant for linking to the homepage of your website. So add

website.links.homepage = <uid>

to your TS constants. Now to make the website usable, we need to:

  1. Include the CSS Styled Content static template (Includes / Include static on our TS template)
  2. Add a sitemap showing our page structure on the homepage (Special elements / Sitemap / Menu type = Menu of subpages of selected pages)

Show your website either in a browser or on your mobile phone and that’s it already. A “back” button is automatically added to the toolbar when you leave the homepage and as defined in our TypoScript, each page except the homepage itself gets the pretty tiny home button top right :-)

One note regarding the back button added automatically.While updating this article to work with beta1 instead of alpha4, I slightly changed the template to include an additional property for the page:

<div data-role="page" id="page_{page:uid}" data-add-back-btn="true">

However, the preferred way of enabling the back button feature would be to use JavaScript snippet below as this will work for generated pages (e.g., for nested UL-lists) too:

(function($) {
    $(document).bind('mobileinit',function(){
      $.mobile.page.prototype.options.addBackBtn = true;
    });
})(jQuery);

Further tuning

Great! But our sitemap could certainly look much better with those lists of items we are used to see on our mobile devices. Furthermore, we should ensure titles of standard “Text” or “Text & Images” content elements are rendered with h2 tags and not h1. OK, let’s enhance our setup:

# Remove useless classes (h1 class="csc-firstHeader" and so on)
lib.stdheader.3.headerClass >
 
lib.stdheader.stdWrap.dataWrap >
tt_content.stdWrap.innerWrap.cObject.default >
 
# Remove class="bodytext" to paragraphs
lib.parseFunc_RTE.nonTypoTagStdWrap.encapsLines.addAttributes.P.class >
 
# Change header levels: h1 -> h2, h2 -> h3, h3 -> h4
lib.stdheader.10.1 < lib.stdheader.10.2
lib.stdheader.10.2 < lib.stdheader.10.3
lib.stdheader.10.3 < lib.stdheader.10.4
 
temp.listHeader = COA
temp.listHeader.1 = TEXT
temp.listHeader.1 {
  field = header
  if {
    equals.field = header_layout
    value = 100
    negate = 1
  }
  wrap = <li data-role="list-divider" role="heading">|</li>
}
temp.listHeader.wrap = <ul data-role="listview" data-inset="true">|
 
# Sitemap tuning
tt_content.menu.10 > 
tt_content.menu.10 < temp.listHeader
tt_content.menu.20.1.wrap = |</ul>

Website ready!

And voilà! Your website is ready to be used:

Application toolbar

Having the copyright as footer was easy but you would certainly prefer having a nice looking toolbar with big icons to switch to the different part of your website, wouldn’t you? This is very easy and I’ll show you how to do that using the icon set from  Glyphish.

The idea is as follows:

  • Provide a data-id attribute to your toolbar, this allows the toolbar to stay “in-place” during page transition if both source and target pages contain this toolbar.
  • Create a menu with special type “list” in TypoScript to put exactly the pages we want to show
  • Use a dedicated id for each page link, this lets us skinning the links in CSS (adding the corresponding icon)
page.40 = HMENU
page.40 {
    stdWrap.wrap = <ul>|</ul>
    stdWrap.wrap2 = <div data-role="navbar" data-grid="d">|</div>
    stdWrap.wrap3 = <div data-role="footer" data-position="fixed" data-theme="a" data-id="menu">|</div>
 
    special = list
    # uid of the pages to show, these values are used again in CASE below
    special.value = 10,12,13
 
    1 = TMENU
    1 {
        NO {
            wrapItemAndSub = <li>|</li>
 
            ATagParams.cObject = CASE
            ATagParams.cObject {
                key.field = uid
                10 = TEXT
                10.value = toolbar-page1
 
                12 = TEXT
                12.value = toolbar-page2
 
                13 = TEXT
                13.value = toolbar-page3
 
                stdWrap.wrap = id="|" data-icon="custom"
            }
        }
        ACT < .NO
        ACT = 1
        ACT.ATagParams.cObject.stdWrap.wrap = id="|" data-icon="custom" class="ui-btn-active"
    }
}

Now just add this to your own CSS and you’re done:

.ui-footer .ui-icon {
    top                : 5px;
    height             : 24px;
    width              : 24px;
    background-size    : 24px 24px;
    background-position: 50% 50%;
    background-repeat  : no-repeat;
    border-radius      : 0;
    margin-left        : -11px;
}
 
.ui-footer .ui-btn-text {
    font-size          : 9px;
}
 
#toolbar-page1 .ui-icon {
    background         : url(glyphish-icons/08-chat.png);
}
 
#toolbar-page2 .ui-icon {
    background         : url(glyphish-icons/23-bird.png);
}
 
#toolbar-page3 .ui-icon {
    background         : url(glyphish-icons/117-todo.png);
}

iPhone home screen bookmark

The final touch if you own an iPhone is to provide a nice icon that shows up when bookmarking your website to your home screen. In addition, you should provide a startup image that will be shown while the iPhone is loading your website in full screen mode. Just try with my  demo website.

Resources

page.headerData.10 = COA
page.headerData.10 {
    1 = TEXT
    1.value = fileadmin/iphone_icon.png
    1.wrap = <link rel="apple-touch-icon" href="|" />
    # rel="apple-touch-icon-precomposed" to remove glossy effect
 
    2 = TEXT
    2.value = fileadmin/startup.png
    2.wrap = <link rel="apple-touch-startup-image" href="|" />
 
    3 = TEXT
    3.value = <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, \~
                                                             user-scalable=0;" name="viewport" />
 
    4 = TEXT
    4.value = <meta content="yes" name="apple-mobile-web-app-capable" />
 
    5 = TEXT
    5.value = <meta content="black" name="apple-mobile-web-app-status-bar-style">
}

Conclusion

There is a lot more you can do with jQuery Mobile and it matured a lot since my first tests with alpha4.

This article only gives you the initial input you may need to create your website. Of course, you should fine tune further the way standard content elements and plugins are rendered and the best way is to read the official documentation that is available as mobile web pages:

 http://jquerymobile.com/demos/1.0/

Browse to your favorite section, show page source and… be inspired!

Flattr