Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit b88368c510ddf8b91e1febcf231f6b0eb7eb5ead @matthew-andrews committed Aug 28, 2012
@@ -0,0 +1,23 @@
+<?php
+// Convert RSS feed to JSON, stripping out all but basic HTML
+// Using Guardian Technology feed as it contains the full content
+$rss = new SimpleXMLElement(file_get_contents('http://www.guardian.co.uk/technology/mobilephones/rss'));
+$xpath = '/rss/channel/item';
+$items = $rss->xpath($xpath);
+
+if ($items) {
+ $output = array();
+ foreach ($items as $id => $item) {
+
+ // This will be encoded as an object, not an array, by json_encode
+ $output[] = array(
+ 'id' => $id + 1,
+ 'headline' => strval($item->title),
+ 'date' => strval($item->pubDate),
+ 'body' => strval(strip_tags($item->description,'<p><br>')),
+ 'author' => strval($item->children('http://purl.org/dc/elements/1.1/')->creator)
+ );
+ }
+}
+
+echo json_encode($output);
@@ -0,0 +1,24 @@
+<?php
+// Concatenate the files in the /source/ directory
+// This would be a sensible point to compress your Javascript.
+$js = '';
+$js .= file_get_contents('../../libraries/client/fastclick.js');
+$js = $js . 'var APP={}; (function (APP) {';
+$js = $js . file_get_contents('../../source/application/applicationcontroller.js');
+$js = $js . file_get_contents('../../source/articles/articlescontroller.js');
+$js = $js . file_get_contents('../../source/articles/article.js');
+$js = $js . file_get_contents('../../source/datastores/network.js');
+$js = $js . file_get_contents('../../source/datastores/indexeddb.js');
+$js = $js . file_get_contents('../../source/datastores/websql.js');
+$js = $js . file_get_contents('../../source/templates.js');
+$js = $js . '}(APP));';
+$output['js'] = $js;
+
+// Concatenate the files in the /css/ directory
+// This would be a sensible point to compress your css
+$css = '';
+$css = $css . file_get_contents('../../css/global.css');
+$output['css'] = $css;
+
+// Encode with JSON (PHP 5.2.0+) & output the resources
+echo json_encode($output);
@@ -0,0 +1,3 @@
+body {
+ background: #d6fab2; /* garish green */
+}
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en" manifest="offline.manifest.php">
+ <head>
+ <script type="text/javascript" src="jquery.min.js"></script>
+ <script type="text/javascript">
+ $(document).ready(function () {
+ var APP_START_FAILED = "I'm sorry, the app can't start right now.";
+ function startWithResources(resources, storeResources) {
+
+ // Try to execute the Javascript
+ try {
+ eval(resources.js);
+ APP.applicationController.start(resources, storeResources);
+
+ // If the Javascript fails to launch, stop execution!
+ } catch (e) {
+ console.log(e);
+ alert(APP_START_FAILED);
+ }
+ }
+ function startWithOnlineResources(resources) {
+ startWithResources(resources, true);
+ }
+
+ function startWithOfflineResources(e) {
+ var resources;
+
+ // If we have resources saved from a previous visit, use them
+ if (localStorage && localStorage.resources) {
+ resources = JSON.parse(localStorage.resources);
+ startWithResources(resources, false);
+
+ // Otherwise, apologize and let the user know
+ } else {
+ alert("Cannot find" + JSON.stringify(e));
+ alert(APP_START_FAILED);
+ }
+ }
+
+ // If we know the device is offline, don't try to load new resources
+ if (navigator && navigator.onLine === false) {
+ startWithOfflineResources();
+
+ // Otherwise, download resources, eval them, if successful push them into local storage.
+ } else {
+ $.ajax({
+ url: 'api/resources/',
+ success: startWithOnlineResources,
+ error: startWithOfflineResources,
+ dataType: 'json'
+ });
+ }
+
+ });
+ </script>
+ <title>News</title>
+ </head>
+<body>
+ <div id="loading">Loading&hellip;</div>
+</body>
+</html>

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,251 @@
+/**
+ * @preserve
+ *
+ * FastClick: polyfill to remove click delays on browsers with touch UIs.
+ *
+ * @copyright The Financial Times Limited [All Rights Reserved]
+ * @licence MIT License (see LICENCE.txt)
+ * @codingstandard ftlabs-jslint
+ */
+
+/*jslint browser:true*/
+/*global Node*/
+
+self.FastClick = (function() {
+ 'use strict';
+
+ var
+
+ scrollBoundary = navigator.userAgent.indexOf('PlayBook') === -1 ? 5 : 20;
+
+
+ /**
+ * Determine whether a given element requires a native click.
+ *
+ * @param {Element} target DOM element
+ * @returns {boolean} Returns true if the element needs a native click
+ */
+ function needsClick(target) {
+ return (/\bneedsclick\b/).test(target.className) || ({
+ 'select': true,
+ 'input' : true,
+ 'label' : true,
+ 'video' : true
+ })[target.nodeName.toLowerCase()];
+ }
+
+
+ /**
+ * Instantiate fast-clicking listeners on the specificed layer.
+ *
+ * @constructor
+ * @param {Element} layer The layer to listen on
+ */
+ function FastClick(layer) {
+ var
+
+
+ /**
+ * The position and page scroll amount when click had started to be tracked.
+ *
+ * @type Object
+ */
+ clickStart = { x: 0, y: 0, scrollX: 0, scrollY: 0 },
+
+
+ /**
+ * Whether a click is currently being tracked.
+ *
+ * @type boolean
+ */
+ trackingClick = false,
+
+
+ /**
+ * Maximum distance (37 pixels) to the power of two.
+ *
+ * @type number
+ */
+ bound = Math.pow(37, 2),
+
+
+ /**
+ * On touch start, record the position and scroll offset.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ onTouchStart = function(event) {
+ trackingClick = true;
+
+ clickStart.x = event.targetTouches[0].pageX;
+ clickStart.y = event.targetTouches[0].pageY;
+ if (clickStart.x === event.targetTouches[0].clientX) {
+ clickStart.x += window.pageXOffset;
+ }
+ if (clickStart.y === event.targetTouches[0].clientY) {
+ clickStart.y += window.pageYOffset;
+ }
+ clickStart.scrollX = window.pageXOffset;
+ clickStart.scrollY = window.pageYOffset;
+
+ return true;
+ },
+
+
+ /**
+ * Update the last position.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ onTouchMove = function(event) {
+ if (!trackingClick) {
+ return true;
+ }
+
+ // Detect whether a click has left the bounds of would be defined as a click, defined as a circle of radius sqrt(bound) around the start point.
+ if ((Math.pow(event.targetTouches[0].pageX - clickStart.x, 2) + Math.pow(event.targetTouches[0].pageY - clickStart.y, 2)) > bound) {
+ trackingClick = false;
+ }
+
+ // If the touch has moved, cancel the click tracking
+ if (Math.abs(window.pageXOffset - clickStart.scrollX) > scrollBoundary || Math.abs(window.pageYOffset - clickStart.scrollY) > scrollBoundary) {
+ trackingClick = false;
+ }
+
+ return true;
+ },
+
+
+ /**
+ * On touch end, determine whether to send a click event at once.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ onTouchEnd = function(event) {
+ var targetElement, targetCoordinates, clickEvent;
+
+ if (!trackingClick) {
+ return true;
+ }
+
+ trackingClick = false;
+
+ // Set up the coordinates to match
+ targetCoordinates = {
+ x: clickStart.x - clickStart.scrollX,
+ y: clickStart.y - clickStart.scrollY
+ };
+
+ // Derive the element to click as a result of the touch.
+ targetElement = document.elementFromPoint(targetCoordinates.x, targetCoordinates.y);
+
+ // If we're not clicking anything exit early
+ if (!targetElement) {
+ return false;
+ }
+
+ // If the targetted node is a text node, target the parent instead
+ if (targetElement.nodeType === Node.TEXT_NODE) {
+ targetElement = targetElement.parentElement;
+ }
+
+ // Prevent the actual click from going though - unless the target node is marked as requiring
+ // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted
+ // to open the options list and so the original event is required.
+ if (needsClick(targetElement)) {
+ return false;
+ }
+
+ // Synthesise a click event, with an extra attribute so it can be tracked
+ clickEvent = document.createEvent('MouseEvents');
+ clickEvent.initMouseEvent('click', true, true, window, 1, 0, 0, targetCoordinates.x, targetCoordinates.y, false, false, false, false, 0, null);
+ clickEvent.forwardedTouchEvent = true;
+ targetElement.dispatchEvent(clickEvent);
+
+ event.preventDefault();
+ return false;
+ },
+
+
+ /**
+ * On touch cancel, stop tracking the click.
+ */
+ onTouchCancel = function() {
+ trackingClick = false;
+ },
+
+
+ /**
+ * On actual clicks, determine whether this is a touch-generated click, a click action occurring
+ * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
+ * an actual click which should be permitted.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+ onClick = function(event) {
+ var targetElement;
+
+ if (event.forwardedTouchEvent) {
+ return true;
+ }
+
+ // Programmatically generated events targeting a specific element should be permitted
+ if (!event.cancelable) {
+ return true;
+ }
+
+ targetElement = document.elementFromPoint(clickStart.x - clickStart.scrollX, clickStart.y - clickStart.scrollY);
+
+ // Derive and check the target element to see whether the
+ // click needs to be permitted; unless explicitly enabled, prevent non-touch click events
+ // from triggering actions, to prevent ghost/doubleclicks.
+ if (!targetElement || !needsClick(targetElement)) {
+
+ // Cancel the event
+ event.stopPropagation();
+ event.preventDefault();
+
+ // Prevent any user-added listeners declared on FastClick element from being fired.
+ if (event.stopImmediatePropagation) {
+ event.stopImmediatePropagation();
+ }
+
+ return false;
+ }
+
+ // If clicks are permitted, return true for the action to go through.
+ return true;
+ };
+
+ if (!layer || !layer.nodeType) {
+ throw new TypeError('Layer must be a document node');
+ }
+
+ // Devices that don't support touch don't need FastClick
+ if (typeof window.ontouchstart === 'undefined') {
+ return;
+ }
+
+ // Set up event handlers as required
+ layer.addEventListener('click', onClick, true);
+ layer.addEventListener('touchstart', onTouchStart, true);
+ layer.addEventListener('touchmove', onTouchMove, true);
+ layer.addEventListener('touchend', onTouchEnd, true);
+ layer.addEventListener('touchcancel', onTouchCancel, true);
+
+ // If a handler is already declared in the element's onclick attribute, it will be fired before
+ // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
+ // adding it as listener.
+ if (typeof layer.onclick === 'function') {
+ layer.addEventListener('click', layer.onclick, false);
+ layer.onclick = null;
+ }
+ }
+
+ return FastClick;
+
+}());
@@ -0,0 +1,9 @@
+<?php
+header("Content-Type: text/cache-manifest");
+?>
+CACHE MANIFEST
+# 2012-07-14 v3
+jquery.min.js
+
+NETWORK:
+*
Oops, something went wrong.

0 comments on commit b88368c

Please sign in to comment.