/** NRE Live Boards for IE9/HTML5 @authour edwin.webb @ fortune cookie **/ var xm = { firstVisit : false, firstPinnedVisit: false, storage : ls, pin : pinJS, ajax : lt, timer : "", el : { win : $(window), content : $("#content"), settings : $("#settings_"), search : $("#search_"), sections : $("section"), results : $("#results_"), arrivals : $("#arrivals"), departures : $("#departures"), calling : $("#calling_"), status : $("#status"), station : $("#station"), filter : $("#filter"), tooltip : $("#tooltip"), resultsNav : $("#results_ nav"), favIcon : $("#fav-me") }, opt : { slideWidth : 600, hGap : 0, vGap : 0, departing : true, pagination : 0, refreshTime : 180000, currentTime : "00:00", firstRun : true } } var xv = { picker : stationPicker, positionContent : function() { xm.opt.vGap = xm.el.win.height() * .2; xm.opt.hGap = (xm.el.win.width() - xm.opt.slideWidth) / 2; xv.hideTip(); xm.el.content.css({"left":xm.opt.hGap,"padding-right" : xm.opt.hGap}); $("#f1").css("width",xm.opt.hGap); $("#f2").css("width",xm.opt.hGap); //xv.showSection(0); }, showSection : function(i) { /* xm.el.sections.hide(); xm.el.sections.eq(i).show(); xv.positionContent(); */ var el = $("html:not(:animated),body:not(:animated)"); var t = 500; var e = "swing"; var q = true; switch(i) { case 0 : el.animate({ scrollLeft: 0},{"duration" : t, "easing" : e , "queue": q}); //Hide any open calling points details. xm.el.calling.children("div").hide(); break; case 1 : el.animate({ scrollLeft: 600},{"duration" : t, "easing" : e , "queue": q}); break; case 2 : el.animate({ scrollLeft: 1100},{"duration" : t, "easing" : e , "queue": q}); break; case 3 : el.animate({ scrollLeft: 1600},{"duration" : t, "easing" : e , "queue": q}); //Hide any open calling points details. xm.el.calling.children("div").hide(); break; } }, showTip : function(element,msg,offset) { var $element = $(element); xm.el.tooltip.css({ "top" : $element.offset().top + $element.height() + 5 + offset.top, "left" : $element.offset().left + offset.left, "display" : "block" }).html(msg); }, hideTip : function() { xm.el.tooltip.empty().hide(); }, shake : function(el) { el.animate({"left":"-10px"},33) .animate({"left":"10px"},33) .animate({"left":"-9px"},33) .animate({"left":"9px"},33) .animate({"left":"0px"},33); }, renderResults : function(target,json) { var i; var resultsHTML; var station = xm.el.station.val(); xm.el.results.find("h1").text(xm.el.station.val()).attr("title",station); if(station == xm.storage.FC.workStn || station == xm.storage.FC.homeStn || $.inArray(station,xm.storage.FC.favorites) > -1) { $("#fav-me").addClass("active"); } else { $("#fav-me").removeClass("active"); } if(json.trains.length === 0) { if(json.buses.length === 0 && json.ferries.length === 0 && json.trains.length === 0) { resultsHTML = "

Sorry, no results found

"; } else { resultsHTML = "

Sorry, no trains found.

"; resultsHTML += '

However we did find buses ('+ json.buses.length +') or ferries ('+ json.ferries.length +') which can be seen at the national rail website

'; } } else { resultsHTML = xm.ajax.buildTableRows(json.trains); } target.find(".results").html(resultsHTML); target.find("thead tr th:last-child").text("@" + json.time); xm.el.resultsNav.find("a").removeClass("selected"); xm.el.resultsNav.find("a:contains('"+target[0].id+"')").addClass("selected"); xv.renderPagination(target,json.time); }, renderDetails : function(id,json) { xm.el.calling.find("tbody").empty().html(xm.ajax.buildDetailsTableRows(json.trains)); window.location.hash = "calling"; var target = xm.el.results.find(".results > div:[data-service-id='"+id+"']"); var calling = xm.el.calling.children("div"); var callingDIV = calling.children("div"); calling.show(); callingDIV.css({"height":"auto","overflow-y":"auto","max-height":"auto","top":"auto"}); calling.css("top","auto"); if(xm.el.calling.height() > parseInt(xm.el.win.height()) - 250) { callingDIV.css({"height":parseInt(xm.el.win.height()) - 250, "overflow-y" : "auto", "top":"0px"}); } else { calling.css({"top": (target.offset().top - (calling.height() / 2)) - 135}); if(calling.offset().top + calling.outerHeight() > parseInt(xm.el.win.height()) - 50) { callingDIV.css({"height":parseInt(xm.el.win.height()) - 250, "overflow-y" : "auto"}); calling.css("top","auto"); } } }, renderPagination : function(target,time) { var html = ""; var results = target.find(".results").children(); var length = results.length; if(length <= 10) { target.find(".pagination").hide(); return false; } for(var i = 0; i < length ; i++) { var page = i%10 == 0; var range = i >= xm.opt.pagination*10 && i < (xm.opt.pagination*10)+10; if(page && range) { html += '' + (i/10+1) + ''; } else if(page) { html += '' + (i/10+1) + ''; } if(range) { results[i].style.display = "block"; if(xm.opt.pagination == 0) { xv.animateRow(results[i],i - (xm.opt.pagination*10)); } else { xv.animateRowQuick(results[i],i - (xm.opt.pagination*10)); } } else { results[i].style.display = "none"; } } if(time) { html += ""; xm.currentTime = time; } else { html += ""; } target.find(".pagination").html(html); }, renderFaves : function() { var f = xm.storage.FC.favorites; var c = xm.el.settings; var tablerow = 'Y'; if(f.length > 2) { c.find("tbody tr").eq(0).hide(); } else { c.find("tbody tr").eq(0).show(); } xm.el.settings.find("tbody tr").not("tr:first-child").remove(); for(var i = 0; i < f.length; i++) { c.find("tbody").append(tablerow.replace(/Y/,f[i])); } }, showResults : function(departing) { var current; if(departing) { xm.el.departures.show(); xm.el.arrivals.hide(); current = xm.el.departures; } else { xm.el.arrivals.show(); xm.el.departures.hide(); current = xm.el.arrivals; } }, showStatus : function(html) { xm.el.status.show(); xm.el.status.find("div").html(html); xm.pin.pushIconToList("http://ie9.nationalrail.co.uk/img/warning_16.ico","There is a status update for " + xm.el.station.val()); }, hideStatus : function() { xm.el.status.hide(); xm.pin.clearIcon(); }, animateRowQuick : function(el,i) { var time = 500; $(el).css("left",-xm.opt.hGap - $(el).width() - 100).delay((i+1)*time/2).animate({"left":0},time,"easeOutQuad"); $(el).hover(xc.rowOver,xc.rowOut); }, animateRow : function(el,i) { var time = 500; $(el).hide().delay(1200).css("left",-xm.opt.hGap - $(el).width() - 600).delay((i+1)*time/2).show().animate({"left":0},time,"easeOutQuad"); $(el).hover(xc.rowOver,xc.rowOut); } } var xc = { init : function() { xv.picker.init(); xm.storage.init(); xm.pin.clearIcon(); xv.positionContent(); xv.picker.addInputSet({ from: xm.el.station }); xv.picker.addInputSet({ from: xm.el.filter }); xc.initSettings(); xc.hashChangeHandler({},true); xm.opt.firstRun = false; $(".picker button").click(xc.buttonHandler); $(".picker input").focus(xc.inputHandler); xm.el.win.bind("LDBJSONLoaded",xc.LDBJSONHandler); xm.el.win.bind("detailsJSONLoaded",xc.detailsJSONHandler); $("#results_ nav a").click(xc.navHandler); $(".pagination").click(xc.paginationClickhandler); xm.el.results.find("#fav-me").click(xc.stationHoverHandler); xm.el.win.bind("click",xc.windowClickHandler); xm.el.tooltip.click(xc.toolTipClickHanlder); xm.el.win.bind("resize",xv.positionContent); $(".results").click(xc.resultsClickHandler); xm.el.win.bind("hashchange",xc.hashChangeHandler); xm.el.settings.click(xc.settingsClickHandler); $(".fade").click(xc.fadeClickHandler); //xv.showSection(0); $("#loading-splash").fadeOut(); }, initSettings : function() { xv.picker.addInputSet({ from: $("#work") }); xv.picker.addInputSet({ from: $("#home") }); xv.picker.addInputSet({ from: $("#addStation") }); xv.renderFaves(); }, buttonHandler : function(e) { var input = $(this).siblings("input"); var station = input.val(); if($.trim(station).length && input.attr("data-stationok") == "true"){ switch(input[0].id) { case "station" : xm.storage.addSave("recents",station); xm.el.filter.val(" "); xm.opt.pagination = 0; xm.ajax.callLDB(station," ", true, xc.stationJSONHanlder); break; case "filter" : xm.storage.addSave("recents",station); xm.ajax.callLDB(xm.el.station.val(), station, xm.opt.departing, xc.stationJSONHanlder); xm.opt.pagination = 0; break; case "addStation" : xm.storage.addSave("favorites",station); break; default : xm.storage.setStation(this.id.slice(3),input.val()); input.css("background-color","#598527").animate({"backgroundColor" : "rgb(255,255,255)"},1000); break; } } else { xv.shake(input.parent(".picker")); xv.showTip(input.parent(".picker")[0], "Sorry, please start typing and choose from the list",{"top":0,"left":0}) } }, inputHandler : function(e) { xv.hideTip(); this.value = ""; }, LDBJSONHandler : function(e,departing,json) { if(json.updates.length) { xv.showStatus(xm.ajax.writeStatusUpdates(json.updates)); } else { xv.hideStatus(); } xv.renderResults(departing ? xm.el.departures : xm.el.arrivals , json); xv.showResults(departing); window.location.hash = "results"; xm.opt.pagination = 0; xc.startTimer(); }, detailsJSONHandler : function(e,json,id) { xv.renderDetails(id,json); if(window.location.hash = "calling") { xv.showSection(2); } else { window.location.hash = "calling" } }, navHandler : function(e) { e.preventDefault(); xm.opt.departing = this.innerText == "departures"; xm.ajax.callLDB(xm.el.station.val(),xm.el.filter.val(), xm.opt.departing, xc.stationJSONHanlder); }, paginationClickhandler : function(e) { var i = parseInt(e.target.innerHTML) - 1; if(i >= 0) { xm.opt.pagination = i; xv.renderPagination(xm.opt.departing ? xm.el.departures : xm.el.arrivals, false); } }, stationHoverHandler : function(e) { var s = xm.storage.FC; var v = xm.el.station.val(); var star = false; var content = 'Close'; xv.showTip($(this),content,{top:-5,left:-35}); xm.el.tooltip.find("li").show(); if($.inArray(v,s.favorites) > -1) { xm.el.tooltip.find(".fav").hide(); } if(v == s.workStn) { xm.el.tooltip.find(".work").hide(); } if(v == s.homeStn) { xm.el.tooltip.find(".home").hide(); } }, toolTipClickHanlder : function(e) { e.stopPropagation(); switch(e.target.className) { case "work" : xm.storage.setStation("workStn", xm.el.station.val()); xm.el.favIcon.addClass("active"); break; case "home" : xm.storage.setStation("homeStn", xm.el.station.val()); xm.el.favIcon.addClass("active"); break; case "fav" : xm.storage.addSave("favorites",xm.el.station.val()); xm.el.favIcon.addClass("active"); break; case "settings" : xv.showSection(3); break; } xm.storage.setStationPicker(); xv.hideTip(); }, resultsClickHandler : function(e) { var id = $(e.target).parent("div").attr("data-service-id"); if(!id) { id = $(e.target).attr("data-service-id") } if(id.length == 0) { return false; } xm.ajax.callCallingPoints(id); }, hashChangeHandler : function(e,i) { if(!i) { e.preventDefault(); e.stopPropagation(); } var loc = window.location.hash.slice(1); switch(loc) { case "" : case "search" : xv.showSection(0); break; case "results" : if(xm.opt.firstRun) { window.location.hash = "search"; } else { xv.showSection(1); } break; case "calling" : if(xm.opt.firstRun) { window.location.hash = "search"; } else { xv.showSection(2); } break; case "settings" : xv.showSection(3); break; default : if(loc.indexOf("-") > -1) { var station = $.URLDecode(loc.slice(loc.indexOf("-") + 1)); xm.el.station.val(station); xm.ajax.callLDB(station," ", true, xc.stationJSONHanlder); } break; } return false; }, settingsClickHandler : function(e) { var input; if(e.target.nodeName.toLowerCase() == "button") { input = $(e.target).siblings("input"); if(input.length) { switch(input[0].id) { case "work" : xm.storage.setStation("workStn", input.val()) break; case "home" : xm.storage.setStation("homeStn", input.val()) break; case "fav" : xm.storage.addSave("favorites",input.val()); break; } } else { input = $(e.target).closest("tr"); xm.storage.removeSave("favorites",input.find("td").eq(0).text()); } } xm.storage.setStationPicker(); xv.renderFaves(); }, timerHandler : function(e) { xm.ajax.callLDB(xm.el.station.val(),xm.el.filter.val(), xm.opt.departing, xc.stationJSONHanlder); }, startTimer : function() { xc.stopTimer(); xm.timer = setInterval(xc.timerHandler, xm.opt.refreshTime); }, stopTimer : function() { clearInterval(xm.timer); xm.timer = ""; }, rowOver : function() { $(this).animate({"left" : 30},250,"swing"); }, rowOut : function() { $(this).animate({"left" : 0},250,"swing"); }, windowClickHandler : function(e) { //reset the timer if(xm.el.station.val().length > 1) { xc.startTimer(); } //hide tool tips if(e.target.nodeName.toLowerCase() === "body") xv.hideTip(); }, fadeClickHandler : function(e) { var back = e.clientX < window.innerWidth / 2; var callingShown = xm.el.calling.children("div").css("display") === "block"; e.preventDefault(); switch(window.location.hash) { case ("#search"): if(!back) { window.location.hash = "results" } else { window.location.hash = "settings" } break; case ("#results"): if(back) { window.location.hash = "search" } else { if(callingShown) { window.location.hash = "calling" } else { window.location.hash = "settings" } } break; case ("#calling"): if(back) { window.location.hash = "results" } else { window.location.hash = "settings" } break; case ("#settings"): if(back) { if(callingShown) { window.location.hash = "calling" } else { window.location.hash = "results" } } else { window.location.hash = "search" } break; default: window.location.hash = "results" break; } } } /** Start plugins **/ $.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/; while(x1 && m[1]!=''){o+=m[1];x+=m[1].length; }else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16); o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;}, URLDecode:function(s){var o=s;var binVal,t;var r=/(%[^%]{2})/; while((m=r.exec(o))!=null && m.length>1 && m[1]!=''){b=parseInt(m[1].substr(1),16); t=String.fromCharCode(b);o=o.replace(m[1],t);}return o;} }); jQuery.easing['jswing'] = jQuery.easing['swing']; jQuery.extend( jQuery.easing, { def: 'easeOutQuad', swing: function (x, t, b, c, d) { //alert(jQuery.easing.default); return jQuery.easing[jQuery.easing.def](x, t, b, c, d); }, easeInQuad: function (x, t, b, c, d) { return c*(t/=d)*t + b; }, easeOutQuad: function (x, t, b, c, d) { return -c *(t/=d)*(t-2) + b; } }); /* * jQuery Color Animations * Copyright 2007 John Resig * Released under the MIT and GPL licenses. */ (function(jQuery){ // We override the animation for all of these color styles //jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){ jQuery.fx.step['backgroundColor'] = function(fx){ if ( fx.state == 0 ) { fx.start = getColor( fx.elem, 'backgroundColor' ); fx.end = getRGB( fx.end ); } fx.elem.style['backgroundColor'] = "rgb(" + [ Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0), Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0), Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0) ].join(",") + ")"; } //}); // Color Conversion functions from highlightFade // By Blair Mitchelmore // http://jquery.offput.ca/highlightFade/ // Parse strings looking for color tuples [255,255,255] function getRGB(color) { var result; // Check if we're already dealing with an array of colors if ( color && color.constructor == Array && color.length == 3 ) return color; // Look for rgb(num,num,num) if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])]; // Look for rgb(num%,num%,num%) if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; // Look for #a0b1c2 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; // Look for #fff if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; // Otherwise, we're most likely dealing with a named color return colors[jQuery.trim(color).toLowerCase()]; } function getColor(elem, attr) { var color; do { color = jQuery.curCSS(elem, attr); // Keep going until we find an element that has color, or we hit the body if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") ) break; attr = "backgroundColor"; } while ( elem = elem.parentNode ); return getRGB(color); }; // Some named colors to work with // From Interface by Stefan Petre // http://interface.eyecon.ro/ var colors = { green:[0,128,0] }; })(jQuery);