2 Copyright (c) 2007-9, iUI Project Members
3 See LICENSE.txt for licensing terms
10 var slideInterval = 0;
12 var currentPage = null;
13 var currentDialog = null;
15 var currentHash = location.hash;
16 var hashPrefix = "#_";
20 var hasOrientationEvent = false;
21 var portraitVal = "portrait";
22 var landscapeVal = "landscape";
24 // *************************************************************************************************
28 animOn: true, // Slide animation with CSS transition is now enabled by default where supported
30 showPage: function(page, backwards)
36 currentDialog.removeAttribute("selected");
40 if (hasClass(page, "dialog"))
44 var fromPage = currentPage;
48 setTimeout(slidePages, 0, fromPage, page, backwards);
50 updatePage(page, fromPage);
55 showPageById: function(pageId)
60 var index = pageHistory.indexOf(pageId);
61 var backwards = index != -1;
63 pageHistory.splice(index, pageHistory.length);
65 iui.showPage(page, backwards);
69 showPageByHref: function(href, args, method, replace, cb, backwards)
71 var req = new XMLHttpRequest();
72 req.onerror = function()
78 req.onreadystatechange = function()
80 if (req.readyState == 4)
83 replaceElementWithSource(replace, req.responseText);
86 var frag = document.createElement("div");
87 frag.innerHTML = req.responseText;
88 iui.insertPages(frag.childNodes, backwards);
91 setTimeout(cb, 1000, true);
97 req.open(method || "GET", href, true);
98 req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
99 req.setRequestHeader("Content-Length", args.length);
100 req.send(args.join("&"));
104 req.open(method || "GET", href, true);
109 insertPages: function(nodes, backwards)
112 for (var i = 0; i < nodes.length; ++i)
114 var child = nodes[i];
115 if (child.nodeType == 1)
118 child.id = "__" + (++newPageCount) + "__";
120 var clone = $(child.id);
122 clone.parentNode.replaceChild(child, clone);
124 document.body.appendChild(child);
126 if (child.getAttribute("selected") == "true" || !targetPage)
134 iui.showPage(targetPage, backwards);
137 getSelectedPage: function()
139 for (var child = document.body.firstChild; child; child = child.nextSibling)
141 if (child.nodeType == 1 && child.getAttribute("selected") == "true")
145 isNativeUrl: function(href)
147 for(var i = 0; i < iui.nativeUrlPatterns.length; i++)
149 if(href.match(iui.nativeUrlPatterns[i])) return true;
154 new RegExp("^http:\/\/maps.google.com\/maps\?"),
155 new RegExp("^mailto:"),
157 new RegExp("^http:\/\/www.youtube.com\/watch\\?v="),
158 new RegExp("^http:\/\/www.youtube.com\/v\/"),
159 new RegExp("^javascript:"),
164 // *************************************************************************************************
166 addEventListener("load", function(event)
168 var page = iui.getSelectedPage();
169 var locPage = getPageFromLoc();
174 if (locPage && (locPage != page))
175 iui.showPage(locPage);
177 setTimeout(preloadImages, 0);
178 if (typeof window.onorientationchange == "object")
180 window.onorientationchange=orientChangeHandler;
181 hasOrientationEvent = true;
182 setTimeout(orientChangeHandler, 0);
184 setTimeout(checkOrientAndLocation, 0);
185 checkTimer = setInterval(checkOrientAndLocation, 300);
188 addEventListener("unload", function(event)
193 addEventListener("click", function(event)
195 var link = findParent(event.target, "a");
198 function unselect() { link.removeAttribute("selected"); }
200 if (link.href && link.hash && link.hash != "#" && !link.target)
202 link.setAttribute("selected", "true");
203 iui.showPage($(link.hash.substr(1)));
204 setTimeout(unselect, 500);
206 if (link == $("backButton")) {
208 } else if (link.getAttribute("type") == "submit")
210 var form = findParent(link, "form");
211 if (form.target == "_self")
214 return; // return so we don't preventDefault
218 else if (link.getAttribute("type") == "cancel")
219 cancelDialog(findParent(link, "form"));
220 else if (link.target == "_replace")
222 link.setAttribute("selected", "progress");
223 iui.showPageByHref(link.href, null, null, link, unselect);
225 else if (iui.isNativeUrl(link.href))
229 else if (link.target == "_webapp")
231 location.href = link.href;
233 else if (!link.target)
235 link.setAttribute("selected", "progress");
237 var backwards = link.getAttribute("backwards");
239 iui.showPageByHref(link.href, null, null, null, unselect, backwards);
244 event.preventDefault();
248 addEventListener("click", function(event)
250 var div = findParent(event.target, "div");
251 if (div && hasClass(div, "toggle"))
253 div.setAttribute("toggled", div.getAttribute("toggled") != "true");
254 event.preventDefault();
258 function getPageFromLoc()
261 var result = location.hash.match(/#_([^\?_]+)/);
269 function orientChangeHandler()
271 var orientation=window.orientation;
275 setOrientation(portraitVal);
280 setOrientation(landscapeVal);
286 function checkOrientAndLocation()
288 if (!hasOrientationEvent)
290 if (window.innerWidth != currentWidth)
292 currentWidth = window.innerWidth;
293 var orient = currentWidth == 320 ? portraitVal : landscapeVal;
294 setOrientation(orient);
298 if (location.hash != currentHash)
300 var pageId = location.hash.substr(hashPrefix.length);
301 iui.showPageById(pageId);
305 function setOrientation(orient)
307 document.body.setAttribute("orient", orient);
308 setTimeout(scrollTo, 100, 0, 1);
311 function showDialog(page)
313 currentDialog = page;
314 page.setAttribute("selected", "true");
316 if (hasClass(page, "dialog") && !page.target)
320 function showForm(form)
322 form.onsubmit = function(event)
324 event.preventDefault();
328 form.onclick = function(event)
330 if (event.target == form && hasClass(form, "dialog"))
335 function cancelDialog(form)
337 form.removeAttribute("selected");
340 function updatePage(page, fromPage)
343 page.id = "__" + (++newPageCount) + "__";
345 location.hash = currentHash = hashPrefix + page.id;
346 pageHistory.push(page.id);
348 var pageTitle = $("pageTitle");
350 pageTitle.innerHTML = page.title;
352 if (page.localName.toLowerCase() == "form" && !page.target)
355 var backButton = $("backButton");
358 var prevPage = $(pageHistory[pageHistory.length-2]);
359 if (prevPage && !page.getAttribute("hideBackButton"))
361 backButton.style.display = "inline";
362 backButton.innerHTML = prevPage.title ? prevPage.title : "Back";
365 backButton.style.display = "none";
369 var backButton = $("myBackButton");
372 var label = page.getAttribute("myBackLabel");
376 backButton.style.display = "inline";
377 backButton.innerHTML = label;
378 backButton.href = page.getAttribute("myBackHref");
379 backButton.target = page.getAttribute("myBackTarget");
380 backButton.setAttribute("backwards", "true");
383 backButton.style.display = "none";
388 function slidePages(fromPage, toPage, backwards)
390 var axis = (backwards ? fromPage : toPage).getAttribute("axis");
392 clearInterval(checkTimer);
394 if (canDoSlideAnim() && axis != 'y')
396 slide2(fromPage, toPage, backwards, slideDone);
400 slide1(fromPage, toPage, backwards, axis, slideDone);
405 if (!hasClass(toPage, "dialog"))
406 fromPage.removeAttribute("selected");
407 checkTimer = setInterval(checkOrientAndLocation, 300);
408 setTimeout(updatePage, 0, toPage, fromPage);
409 fromPage.removeEventListener('webkitTransitionEnd', slideDone, false);
413 function canDoSlideAnim()
415 return (iui.animOn) && (typeof WebKitCSSMatrix == "object");
418 function slide1(fromPage, toPage, backwards, axis, cb)
421 (backwards ? fromPage : toPage).style.top = "100%";
423 toPage.style.left = "100%";
426 toPage.setAttribute("selected", "true");
429 var timer = setInterval(slide, slideInterval);
433 percent -= slideSpeed;
437 clearInterval(timer);
444 ? fromPage.style.top = (100-percent) + "%"
445 : toPage.style.top = percent + "%";
449 fromPage.style.left = (backwards ? (100-percent) : (percent-100)) + "%";
450 toPage.style.left = (backwards ? -percent : percent) + "%";
456 function slide2(fromPage, toPage, backwards, cb)
458 toPage.style.webkitTransitionDuration = '0ms'; // Turn off transitions to set toPage start offset
459 // fromStart is always 0% and toEnd is always 0%
460 // iPhone won't take % width on toPage
461 var toStart = 'translateX(' + (backwards ? '-' : '') + window.innerWidth + 'px)';
462 var fromEnd = 'translateX(' + (backwards ? '100%' : '-100%') + ')';
463 toPage.style.webkitTransform = toStart;
464 toPage.setAttribute("selected", "true");
465 toPage.style.webkitTransitionDuration = ''; // Turn transitions back on
466 function startTrans()
468 fromPage.style.webkitTransform = fromEnd;
469 toPage.style.webkitTransform = 'translateX(0%)'; //toEnd
471 fromPage.addEventListener('webkitTransitionEnd', cb, false);
472 setTimeout(startTrans, 0);
475 function preloadImages()
477 var preloader = document.createElement("div");
478 preloader.id = "preloader";
479 document.body.appendChild(preloader);
482 function submitForm(form)
484 iui.showPageByHref(form.action || "POST", encodeForm(form), form.method);
487 function encodeForm(form)
489 function encode(inputs)
491 for (var i = 0; i < inputs.length; ++i)
494 args.push(inputs[i].name + "=" + escape(inputs[i].value));
499 encode(form.getElementsByTagName("input"));
500 encode(form.getElementsByTagName("textarea"));
501 encode(form.getElementsByTagName("select"));
505 function findParent(node, localName)
507 while (node && (node.nodeType != 1 || node.localName.toLowerCase() != localName))
508 node = node.parentNode;
512 function hasClass(self, name)
514 var re = new RegExp("(^|\\s)"+name+"($|\\s)");
515 return re.exec(self.getAttribute("class")) != null;
518 function replaceElementWithSource(replace, source)
520 var page = replace.parentNode;
521 var parent = replace;
522 while (page.parentNode != document.body)
524 page = page.parentNode;
525 parent = parent.parentNode;
528 var frag = document.createElement(parent.localName);
529 frag.innerHTML = source;
531 page.removeChild(parent);
533 while (frag.firstChild)
534 page.appendChild(frag.firstChild);
537 function $(id) { return document.getElementById(id); }
538 function ddd() { console.log.apply(console, arguments); }