/**
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);