summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorAlib <aliboba@free.fr>2010-03-15 17:56:22 +0100
committerAlib <aliboba@free.fr>2010-03-15 17:56:22 +0100
commit438912c0c4a4075a5cd74cf9689451c9df4bbe34 (patch)
tree334e03bbba01b002a34d3cbf81ee7e600ec7bff6 /js
parenta8012963c23e7e5eaf487ee9e192ae5c4d4ccff2 (diff)
downloadistreamdev-438912c0c4a4075a5cd74cf9689451c9df4bbe34.tar.gz
istreamdev-438912c0c4a4075a5cd74cf9689451c9df4bbe34.tar.bz2
New Jquery branch. Initial development version for istreamdev 1.0
Diffstat (limited to 'js')
-rw-r--r--js/functions.js112
-rw-r--r--js/istreamdev.js676
-rw-r--r--js/spinningwheel-min.js1
-rw-r--r--js/spinningwheel.js492
4 files changed, 1281 insertions, 0 deletions
diff --git a/js/functions.js b/js/functions.js
new file mode 100644
index 0000000..5db31a3
--- /dev/null
+++ b/js/functions.js
@@ -0,0 +1,112 @@
+function openSelectDate(timer_year,timer_month,timer_day) {
+ var now = new Date();
+ if ( timer_year == null ) {
+ var now_year = now.getFullYear();
+ var now_month = now.getMonth()+1;
+ var now_day = now.getDate();
+ }
+ else
+ {
+ var now_year = timer_year;
+ var now_month = timer_month;
+ var now_day = timer_day;
+ }
+ var layer = 'layer_date';
+ var days = { };
+ var years = { };
+ var months = { '01': '01', '02': '02', '03': '03', '04': '04', '05': '05','06': '06', '07': '07', '08': '08', '09': '09', '10': '10', '11': '11', '12': '12' };
+
+ for( var i = 1; i < 32; i += 1 ) {
+ days[i] = str_pad(i, 2, '0', 'STR_PAD_LEFT');
+ }
+
+ for( i = now.getFullYear(); i < now.getFullYear()+5; i += 1 ) {
+ years[i] = i;
+ }
+
+ SpinningWheel.addSlot(years, 'right', now_year );
+ SpinningWheel.addSlot(months, '', now_month);
+ SpinningWheel.addSlot(days, 'right', now_day);
+ SpinningWheel.setCancelAction(cancel_date);
+ SpinningWheel.setDoneAction(done_date);
+
+ SpinningWheel.open();
+}
+
+function done_date() {
+ var results = SpinningWheel.getSelectedValues();
+
+ document.getElementById('layer_date').innerHTML = results.values.join('-');
+ document.timer.timer_date.value = results.values.join('-');
+ $('a').removeClass('active');
+}
+
+function cancel_date() {
+$('a').removeClass('active');
+}
+function openSelectTime(layer,timer_hour,timer_minute) {
+ if ( timer_hour == null ) {
+ var now = new Date();
+ var now_hour = now.getHours();
+ var now_minute = now.getMinutes()+1;
+ }
+ else
+ {
+ var now_hour = timer_hour;
+ var now_minute = timer_minute;
+ }
+ var hours = { };
+ var minutes = { };
+
+ for( var i = 0; i < 24; i += 1 ) {
+ hours[i] = str_pad(i,2,'0','STR_PAD_LEFT');
+ }
+
+ for( var i = 0; i < 60; i += 1 ) {
+ minutes[i] = str_pad(i,2,'0','STR_PAD_LEFT');
+ }
+
+ SpinningWheel.addSlot(hours, 'right', now_hour);
+ //SpinningWheel.addSlot({ separator: 'h' }, 'readonly shrink');
+ SpinningWheel.addSlot(minutes, '', now_minute);
+
+ SpinningWheel.setCancelAction( function() { $('a').removeClass('active');} );
+ SpinningWheel.setDoneAction(function () {var results = SpinningWheel.getSelectedValues(); document.getElementById(layer).innerHTML = results.values.join('h');if ( layer == 'layer_starttime' ) { var forminput = 'timer_starttime'; } else { var forminput = 'timer_endtime'; }; eval ("document.timer." + forminput + ".value = results.values.join('')");$('a').removeClass('active'); });
+ SpinningWheel.open();
+}
+
+function str_pad (input, pad_length, pad_string, pad_type) {
+ // Returns input string padded on the left or right to specified length with pad_string
+ //
+ // version: 909.322
+ // discuss at: http://phpjs.org/functions/str_pad // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + namespaced by: Michael White (http://getsprink.com)
+ // + input by: Marco van Oort
+ // + bugfixed by: Brett Zamir (http://brett-zamir.me)
+ // * example 1: str_pad('Kevin van Zonneveld', 30, '-=', 'STR_PAD_LEFT'); // * returns 1: '-=-=-=-=-=-Kevin van Zonneveld'
+ // * example 2: str_pad('Kevin van Zonneveld', 30, '-', 'STR_PAD_BOTH');
+ // * returns 2: '------Kevin van Zonneveld-----'
+ var half = '', pad_to_go;
+ var str_pad_repeater = function (s, len) {
+ var collect = '', i;
+
+ while (collect.length < len) {collect += s;}
+ collect = collect.substr(0,len);
+ return collect;
+ };
+
+ input += ''; pad_string = pad_string !== undefined ? pad_string : ' ';
+
+ if (pad_type != 'STR_PAD_LEFT' && pad_type != 'STR_PAD_RIGHT' && pad_type != 'STR_PAD_BOTH') { pad_type = 'STR_PAD_RIGHT'; }
+ if ((pad_to_go = pad_length - input.length) > 0) {
+ if (pad_type == 'STR_PAD_LEFT') { input = str_pad_repeater(pad_string, pad_to_go) + input; } else if (pad_type == 'STR_PAD_RIGHT') { input = input + str_pad_repeater(pad_string, pad_to_go); }
+ else if (pad_type == 'STR_PAD_BOTH') {
+ half = str_pad_repeater(pad_string, Math.ceil(pad_to_go/2));
+ input = half + input + half;
+ input = input.substr(0, pad_length); }
+ }
+
+ return input;
+}
+
+
diff --git a/js/istreamdev.js b/js/istreamdev.js
new file mode 100644
index 0000000..fc9247b
--- /dev/null
+++ b/js/istreamdev.js
@@ -0,0 +1,676 @@
+//INIT
+jQT = new $.jQTouch({
+ icon: 'img/istreamdev.png',
+ addGlossToIcon: true,
+ useFastTouch: true,
+ startupScreen: 'img/startup.png',
+ statusBar: 'black',
+ iconIsGlossy: true,
+ fullscreen: true,
+ preloadImages: [
+ 'themes/jqt/img/chevron.png',
+ 'themes/jqt/img/back_button.png',
+ 'themes/jqt/img/back_button_clicked.png',
+ 'themes/jqt/img/button_clicked.png',
+ 'themes/jqt/img/button.png',
+ 'themes/jqt/img/button_clicked.png',
+ 'themes/jqt/img/loading.gif',
+ 'themes/jqt/img/toolbar.png',
+ 'themes/jqt/img/on_off.png',
+ 'img/loading.gif',
+ 'img/audio.png',
+ 'img/epg.png',
+ 'img/media.png',
+ 'img/record.png',
+ 'img/timers.png',
+ 'img/timeron.png',
+ 'img/timeroff.png',
+ 'img/timerrec.png',
+ 'img/tv.png',
+ 'img/video.png',
+ 'img/stream.png',
+ 'img/stream_clicked.png',
+ 'img/istreamdev.png',
+ 'img/mask.png',
+ 'img/nologoTV.png',
+ 'img/nologoREC.png',
+ 'img/nologoMEDIA.png',
+ 'img/rec.png',
+ 'img/rec_clicked.png',
+ 'img/sw-alpha.png',
+ 'img/sw-button-cancel.png',
+ 'img/sw-button-done.png',
+ 'img/sw-header.png',
+ 'img/sw-slot-border.png'
+ ]
+});
+
+// [GENERIC STUFF]
+// Global variable
+
+dataString = "action=getGlobals";
+$.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ streamdev_server = data.streamdev_server;
+ rec_path = data.rec_path;
+ video_path = data.video_path;
+ audio_path = data.audio_path;
+ }
+ );
+//streamdev_server = "http://127.0.0.1:3000/TS/";
+//rec_path = "/video/";
+//video_path = "/mnt/media/Video/";
+//audio_path = "/mnt/media/Music/";
+
+
+
+//Goto home
+$('#home_but').tap(function(event) {
+ event.preventDefault();
+ jQT.goTo('#home','flip');
+});
+
+//JSON query loading handler
+function json_start(button) {
+ $(button).addClass('active');
+ $('#loader').addClass("loader");
+
+}
+function json_complete(destination,effect) {
+ $('#loader').removeClass("loader");
+ $('a').removeClass('active');
+ jQT.goTo(destination,effect);
+}
+function hide_loader() {
+ $('#loader').removeClass("loader");
+ $('a').removeClass('active');
+}
+
+// [/GENERIC STUFF]
+
+// [HOME SECTION]
+//buttons
+$('#categories_but').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ gen_categories();
+ return false;
+});
+
+$('#recording_but').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ browser = 1;
+ gen_browser(rec_path,browser,"Recordings","rec");
+ return false;
+});
+
+$('#timers_but').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ gen_timers();
+ return false;
+});
+
+$('#video_but').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ browser = 1;
+ gen_browser(video_path,browser,"Videos","vid");
+ return false;
+});
+// [/HOME SECTION]
+
+// [TV SECTION]
+//buttons
+$('#categories ul#cat_menu a').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ var category = $(this).html();
+ gen_channels(category);
+ return false;
+});
+
+$('#channels ul#chan_menu a').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ var channame = $(this).find('span[class="name"]').html();
+ var channumber = $(this).find('small[class="counter"]').html();
+ gen_streamchannel(channame,channumber);
+ return false;
+});
+
+//Gen Categories
+function gen_categories() {
+ $("#cat_menu").html('');
+ var dataString = "action=getTvCat";
+ //Json call to get category array
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ $.each(data.categories, function(i,categories){
+ $("#cat_menu").append('<li class="arrow"><a class="cat_but" href="#">' + categories.name + '</a><small class="counter">' + categories.channels + '</small></li>');
+ });
+ json_complete('#categories','cube');
+ })
+}
+
+//Gen Channels
+function gen_channels(category) {
+ $("#chan_menu").html('');
+ var dataString = "action=getTvChan&cat=" + category;
+ //Json call to get category array
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ $.each(data.channel,function(i,channel){
+ $("#chan_menu").append('<li class="channellist"><a class="chan_but" href="#"><img src="logos/' + channel.name + '.png"/><small class="counter">' + channel.number + '</small><span class="name">' + channel.name + '</span><span class="comment">' + channel.now_title + '</span></a></li>');
+ });
+ json_complete('#channels','cube');
+ })
+}
+
+
+// [/TV SECTION]
+// [STREAM SECTION]
+//buttons
+$('#streamchannel span.streamButton a').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ var type = $("#streamchannel").find('span[rel="type"]').html();
+ var url = $("#streamchannel").find('span[rel="url"]').html();
+ var mode = $(this).attr('rel');
+ start_broadcast(type,url,mode);
+ return false;
+});
+$('#streamrec span.streamButton a').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ var type = $("#streamrec").find('span[rel="type"]').html();
+ var url = $("#streamrec").find('span[rel="url"]').html();
+ var mode = $(this).attr('rel');
+ start_broadcast(type,url,mode);
+ return false;
+});
+$('#streamvid span.streamButton a').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ var type = $("#streamvid").find('span[rel="type"]').html();
+ var url = $("#streamvid").find('span[rel="url"]').html();
+ var mode = $(this).attr('rel');
+ start_broadcast(type,url,mode);
+ return false;
+});
+$('#streaming span.streamButton a[rel="stopbroadcast"]').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ var session = $("#streaming").find('span[rel="session"]').html();
+ stop_broadcast(session);
+ return false;
+});
+//Gen tv start stream
+function gen_streamchannel(channame,channumber) {
+ $('#streamchannel').find('h1').html( '<img class="menuicon" src="img/tv.png" /> ' +channame);
+ $('#streamchannel').find('#thumbnail').attr('src','logos/' + channame + ".png");
+ var dataString = "action=getChanInfo&chan=" + channumber;
+ //Json call to get tv program info
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ var program = data.program;
+ $("#streamchannel").find('span[class="name_now"]').html( 'Now: ' + program.now_title );
+ $("#streamchannel").find('span[class="epgtime_now"]').html( program.now_time );
+ $("#streamchannel").find('span[class="desc_now"]').html( program.now_desc );
+ $("#streamchannel").find('span[class="name_next"]').html( 'Next: ' + program.next_title );
+ $("#streamchannel").find('span[class="epgtime_next"]').html( program.next_time );
+ $("#streamchannel").find('span[rel="url"]').html(streamdev_server + channumber);
+ $("#streamchannel").find('span[rel="type"]').html('tv');
+ json_complete('#streamchannel','cube');
+ });
+}
+
+function gen_streamrec(folder,path) {
+ var dataString = "action=getRecInfo&rec=" + path + folder;
+ //Json call to get rec info
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ var program = data.program;
+ $('#streamrec').find('h1').html('<img class="menuicon" src="img/record.png" /> ' + program.name);
+ $('#streamrec').find('#thumbnail').attr('src','logos/' + program.channel + ".png");
+ $("#streamrec").find('span[class="name_now"]').html( program.name );
+ $("#streamrec").find('span[class="epgtime_now"]').html( 'Recorded: ' + program.recorded );
+ $("#streamrec").find('span[class="desc_now"]').html( program.desc );
+ $("#streamrec").find('span[rel="url"]').html( path + folder );
+ $("#streamrec").find('span[rel="type"]').html('rec');
+ json_complete('#streamrec','cube');
+ });
+}
+
+function gen_streamvid(filename,path) {
+ var dataString = "action=getVidInfo&file=" + path + filename;
+ //Json call to get rec info
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ var program = data.program;
+ $('#streamvid').find('h1').html('<img class="menuicon" src="img/video.png" /> ' + program.name);
+ $('#streamvid').find('#thumbnail').attr('src','ram/temp-logo.png');
+ $("#streamvid").find('span[class="name_now"]').html( program.name );
+ $("#streamvid").find('span[class="epgtime_now"]').html( 'Duration: ' + program.duration );
+ desc='<b>format: </b>' + program.format + '<br><b>video: </b>' + program.video + '<br><b>audio: </b>' + program.audio + '<br><b>resolution: </b>' + program.resolution;
+ $("#streamvid").find('span[class="desc_now"]').html( desc );
+ $("#streamvid").find('span[rel="url"]').html( path + filename );
+ $("#streamvid").find('span[rel="type"]').html('vid');
+ json_complete('#streamvid','cube');
+ });
+}
+//Gen streaming page
+function gen_streaming(session) {
+ $("#streaming").find('span[rel="session"]').html(session);
+ var dataString = "action=getStreamInfo&session=" + session;
+ //Json call to start streaming
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ var stream = data.stream;
+ $('#streaming').find('#thumbnail').attr('src','ram/session' + stream.session + '/thumb.png');
+ $("#streaming").find('span[rel="thumbwidth"]').html(stream.thumbwidth);
+ $("#streaming").find('span[rel="thumbheight"]').html(stream.thumbheight);
+ if (stream.type == "tv")
+ {
+ $('#streaming').find('h1').html('<img class="menuicon" src="img/tv.png" /> ' + stream.name );
+ $('#streaming').find('#player').css('width', '90px');
+ var streaminfo = '<li><span class="name_now">Now: ' + stream.now_title + '</span>';
+ streaminfo += '<span class="epgtime_now">' + stream.now_time + '</span>';
+ streaminfo += '<span class="desc_now">' + stream.now_desc + '</span></li>';
+ streaminfo += '<li><span class="name_next">Next: ' + stream.next_title + '</span>';
+ streaminfo += '<span class="epgtime_next">' + stream.next_time + '</span></li>';
+ $("#streaming").find('ul[class="streaminfo"]').html(streaminfo);
+ }
+ else if (stream.type == "rec")
+ {
+ $('#streaming').find('h1').html('<img class="menuicon" src="img/record.png" /> ' + stream.name );
+ $('#streaming').find('#player').css('width', '90px');
+ var streaminfo = '<li><span class="name_now">' + stream.name + '</span>';
+ streaminfo += '<span class="epgtime_now">Recorded: ' + stream.recorded + '</span>';
+ streaminfo += '<span class="desc_now">' + stream.desc + '</span></li>';
+ $("#streaming").find('ul[class="streaminfo"]').html(streaminfo);
+ }
+ else if (stream.type == "vid")
+ {
+ $('#streaming').find('h1').html('<img class="menuicon" src="img/video.png" /> ' + stream.name );
+ $('#streaming').find('#player').css('width', '190px');
+ var streaminfo = '<li><span class="name_now">' + stream.name + '</span>';
+ streaminfo += '<span class="epgtime_now">Duration: ' + stream.duration + '</span>';
+ desc='<b>format: </b>' + stream.format + '<br><b>video: </b>' + stream.video + '<br><b>audio: </b>' + stream.audio + '<br><b>resolution: </b>' + stream.resolution;
+ streaminfo += '<span class="desc_now">' + desc + '</span></li>';
+ $("#streaming").find('ul[class="streaminfo"]').html(streaminfo);
+ }
+ $('ul[class="streamstatus"]').find('span[class="mode"]').html('Please wait.');
+ $("#streaming").find('span[rel="name"]').html(stream.name);
+ json_complete('#streaming','cube');
+ });
+}
+
+//Start broadcast
+function start_broadcast(type,url,mode) {
+ var dataString = 'action=startBroadcast&type='+type+'&url='+url;
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ var session = data.session;
+ gen_streaming(session);
+ });
+
+}
+//Stop broadcast
+
+function stop_broadcast(session) {
+ var dataString = 'action=stopBroadcast&session='+session;
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data) {
+ var status = data.status;
+ var message = data.message;
+ hide_loader();
+ jQT.goBack();
+ });
+}
+
+//trick to prevent animation bug with object.
+$(document).ready(function(e){
+$('#streaming').bind('pageAnimationEnd', function(event, info){
+ if (info.direction == 'in') {
+ var session = $("#streaming").find('span[rel="session"]').html();
+ var name = $("#streaming").find('span[rel="name"]').html();
+ playvideo(session,name);
+ }
+})
+
+$('#streaming').bind('pageAnimationStart', function(event, info){
+ var session = $("#streaming").find('span[rel="session"]').html();
+ if (info.direction == 'out') {
+ $('#player').html('<img class="thumbnail" id="thumbnail" src="ram/session' + session + '/thumb.png"></img>');
+ }
+ })
+});
+
+//Get server status & Play video
+function playvideo(session,name) {
+ var prevmsg="";
+ var status_OnComplete = function(data) {
+ var status = data.status;
+ var message = data.message;
+ var url = data.url;
+ var thumbwidth = $('#streaming span[rel="thumbwidth"]').html();
+ var thumbheight = $('#streaming span[rel="thumbheight"]').html();
+ $('#streaming ul[class="streamstatus"]').find('span[class="mode"]').html(message);
+ if ( status == "ready" ) {
+ $('#player').html('<video id="videofeed" width="' + thumbwidth + '" height="' + thumbheight + '" poster="ram/session' + session + '/thumb.png" src="' + url + '" ></video><span rel="ready"></span>');
+ return false;
+ }
+ prevmsg = message;
+ status_Start(session,prevmsg);
+ }
+
+ var status_Start = function(session,prevmsg) {
+ dataString = "action=getStreamStatus&session=" + session + "&msg=" + prevmsg;
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data){
+ status_OnComplete(data)
+ });
+ }
+ status_Start(session,prevmsg);
+}
+// [/STREAM SECTION]
+
+// [BROWSER SECTION]
+//buttons
+$('ul[rel="filelist"] li.arrow a').tap(function(event) {
+ event.preventDefault();
+ json_start(this);
+ var type = $(this).attr('rel');
+ var name = $(this).find('span[class="menuname"]').html();
+ var path = $(this).parents('div').find('span[rel="path"]').html();
+ var browser = $(this).parents('div').find('span[rel="currentbrowser"]').html();
+ var foldertype = $(this).parents('div').find('span[rel="foldertype"]').html();
+ browser = parseInt(browser);
+ browser++;
+ if ( type == "folder" )
+ {
+ newpath=path+name;
+ gen_browser(newpath,browser,name,foldertype);
+ }
+ else if ( type == "rec" )
+ {
+ gen_streamrec(name,path);
+ }
+ else if ( type == "video" )
+ {
+ gen_streamvid(name,path);
+ }
+ return false;
+});
+
+$('div[rel="browser"] a[class="back"]').tap(function(event) {
+ event.preventDefault();
+ $(this).parents('div[rel="browser"]').remove();
+});
+
+$('div[rel="browser"] #home_but').tap(function(event) {
+ event.preventDefault();
+ $('#home').bind('pageAnimationEnd', function(event, info){
+ $('#jqt div[rel="browser"]').remove();
+ $('#home').unbind('pageAnimationEnd');
+
+ });
+});
+
+//functions
+function gen_browser(path,browser,name,foldertype) {
+ browser_template = '<div class="toolbar"></div>';
+ browser_template += '<ul rel="filelist" class="rounded"></ul>';
+ browser_template += '<div rel="dataholder" style="visibility:hidden">'
+ browser_template += '<span rel="path"></span>';
+ browser_template += '<span rel="currentbrowser"></span>';
+ browser_template += '<span rel="foldertype">' + foldertype + '</span>';
+ browser_template += '</div>';
+ $('#jqt').append('<div id="browser' + browser + '" rel="browser"></div>'),
+ $('#browser'+browser).html(browser_template);
+ if ( path == rec_path || path == video_path ) {
+ toolbar = '<a href="#" class="back">Home</a>';
+ if ( foldertype == 'rec' ){
+ toolbar += '<h1><img class="menuicon" src="img/record.png" /> ' + name + '</h1>';
+ }
+ else {
+ toolbar += '<h1><img class="menuicon" src="img/video.png" /> ' + name + '</h1>';
+ }
+ $('#browser' + browser + ' div[class="toolbar"]').html(toolbar);
+ }
+ else {
+ toolbar = '<a href="#" class="back">Back</a>';
+ toolbar += '<a href="#home" id="home_but" class="button">Home</a>';
+ if ( foldertype == 'rec' ){
+ toolbar += '<h1><img class="menuicon" src="img/record.png" /> ' + name + '</h1>';
+ }
+ else {
+ toolbar += '<h1><img class="menuicon" src="img/video.png" /> ' + name + '</h1>';
+ }
+ $('#browser' + browser + ' div[class="toolbar"]').html(toolbar);
+ }
+ var dataString = 'action=browseFolder&path='+path+'&browser=' + browser;
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data) {
+ $("#browser" + browser).find('ul').html('');
+ $("#browser" + browser).find('span[rel="path"]').html(path);
+ $("#browser" + browser).find('span[rel="currentbrowser"]').html(browser);
+ $.each(data.list, function(i,list){
+ if (list.type == "folder") {
+ $("#browser" + browser).find('ul').append('<li class="arrow"><a href="#" rel="folder"><span class="menuname">' + list.name + '</span></a></li>');
+ }
+ else if (list.type == "rec") {
+ $("#browser" + browser).find('ul').append('<li class="arrow"><a href="#" rel="rec"><img class="menuicon" src="img/record.png" /><span class="menuname">' + list.name + '</span></a></li>');
+ }
+ else if ( list.type == "video" ) {
+ $("#browser" + browser).find('ul').append('<li class="arrow"><a href="#" rel="video"><img class="menuicon" src="img/video.png" /><span class="menuname">' + list.name + '</span></a></li>');
+ }
+ });
+ json_complete('#browser' + browser,'cube');
+ });
+}
+
+
+// [/BROWSER SECTION]
+
+// [TIMER SECTION]
+//get fullchannel list onload
+
+$(document).ready(function(e){
+gen_formchanlist();
+});
+
+// buttons
+$('#timers li[class="arrow"] a').tap(function(event) {
+ event.preventDefault();
+ $(this).addClass('active');
+ if ( $(this).attr('rel') == "new" ) {
+ gen_edittimer();
+ } else {
+ timerid = $(this).attr('rel');
+ timerdata = $('#timers ul[rel="timers"] li a[rel="' + timerid + '"]').data("timerdata");
+ id = timerdata.id;
+ name = timerdata.name;
+ active = timerdata.active;
+ channumber = timerdata.channumber;
+ channame = timerdata.channame;
+ date = timerdata.date;
+ starttime = timerdata.starttime;
+ endtime = timerdata.endtime;
+ gen_edittimer(id,name,active,channumber,channame,date,starttime,endtime);
+ }
+});
+
+// gen Timers
+function gen_timers(edit) {
+ $('#timers ul[rel="timers"]').html('');
+ var dataString = 'action=getTimers';
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data) {
+ $('#timers ul[rel="timers"]').append('<li><span class="menutitle">Current timers</span></li>');
+ $.each(data.timer, function(i,timer){
+ if ( timer.running == "1" ) {
+ timerli = '<li class="arrow"><a rel="' + timer.id + '" href="#"><img class="menuicon" src="img/timerrec.png" /><span class="menuname">' + timer.date + ' ' + timer.name + '</span></a></li>';
+ }
+ else
+ {
+ if ( timer.active == "1" ) {
+ timerli = '<li class="arrow"><a rel="' + timer.id + '" href="#"><img class="menuicon" src="img/timeron.png" /><span class="menuname">' + timer.date + ' ' + timer.name + '</span></a></li>';
+ } else {
+ timerli = '<li class="arrow"><a rel="' + timer.id + '" href="#"><img class="menuicon" src="img/timeroff.png" /><span class="menuname">' + timer.date + ' ' + timer.name + '</span></a></li>';
+ }
+ }
+ $('#timers ul[rel="timers"]').append(timerli);
+ $('#timers ul[rel="timers"] li a[rel="' + timer.id + '"]').data("timerdata", timer);
+ });
+ if ( edit ) {
+ hide_loader();
+ jQT.goBack();
+ }
+ else {
+ json_complete('#timers','cube');
+ }
+ });
+}
+
+function gen_edittimer(id,name,active,channumber,channame,date,starttime,endtime) {
+ $('ul[ref="submitbut"]').remove();
+ if (id) {
+ $('#edittimer h1').html('<img class="menuicon" src="img/timers.png" / > EDIT TIMER');
+ if (active = 1)
+ {
+ $('#timer_active').attr("checked", "checked");
+ }
+ $('#timer_id').val(id);
+ $('#timer_name').val(name);
+ $('#timer_chan option[value="' + channumber + '"]').attr("selected", "selected");
+ $('#timer_date').val(date);
+ var wheeldate = date;
+ while (wheeldate.indexOf("-") > -1)
+ wheeldate = wheeldate.replace("-", ",");
+ $('#a_date').attr('href', "javascript:openSelectDate(" + wheeldate + ");");
+ $('#layer_date').html(date);
+ $('#timer_starttime').val(starttime);
+ $('#timer_endtime').val(endtime);
+ wheelstart_h = starttime.substring(0,2);
+ wheelstart_m = starttime.substring(2,4);
+ $('#layer_starttime').html(wheelstart_h + 'h' + wheelstart_m);
+ $('#a_starttime').attr('href', "javascript:openSelectTime('layer_starttime','" + wheelstart_h + "','" + wheelstart_m + "')");
+ wheelend_h = endtime.substring(0,2);
+ wheelend_m = endtime.substring(2,4);
+ $('#layer_endtime').html(wheelend_h + 'h' + wheelend_m);
+ $('#a_endtime').attr('href', "javascript:openSelectTime('layer_endtime','" + wheelend_h + "','" + wheelend_m + "')");
+ submitbuttons = '<ul ref="submitbut" class="individual">';
+ submitbuttons += '<li><a class="submit_form" href="#">Edit</a></li>';
+ submitbuttons += '<li><a class="abutton" href="javascript:deletetimer(\'id\');">Delete</a></li></ul>';
+ $('#timer').append(submitbuttons);
+ }
+ else {
+ $('#edittimer h1').html('<img class="menuicon" src="img/timers.png" / > NEW TIMER');
+ $('#timer_active').attr("checked", "checked");
+ $('#timer_id').val(null);
+ $('#timer_name').val(null);
+ $('#timer_chan option').removeAttr("selected");
+ $('#timer_chan option[value="1"]').attr("selected", "selected");
+ $('#a_date').attr('href', "javascript:openSelectDate();");
+ $('#layer_date').html("Select date");
+ $('#timer_date').val(null);
+ $('#timer_starttime').val(null);
+ $('#timer_endtime').val(null);
+ $('#a_starttime').attr('href', "javascript:openSelectTime('layer_starttime')");
+ $('#layer_starttime').html('Select start time');
+ $('#a_endtime').attr('href', "javascript:openSelectTime('layer_endtime')");
+ $('#layer_endtime').html('select end time');
+ submitbutton = '<ul ref="submitbut" class="rounded">';
+ submitbutton += '<li><center><a class="submit_form" href="#">Create</a></center></li></ul>';
+ $('#timer').append(submitbutton);
+ }
+ $('.formerror').hide();
+ json_complete('#edittimer','cube');
+}
+//get full chanlist for timer page ( doing it one time on document load ).
+function gen_formchanlist() {
+ var dataString = 'action=getFullChanList';
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data) {
+ $.each(data.category, function(i,category){
+ $('#timer_chan').append('<optgroup label="' + category.name + '">');
+ var catname = category.name;
+ $.each(category.channel, function(j, channel){
+ $('#timer_chan optgroup[label="' + catname +'"]').append('<option value="' + channel.number + '">' + channel.name +'</option>');
+ });
+ $('#timer_chan').append('</optgroup>');
+ });
+ });
+}
+
+// TIMER FORM VALIDATION & SUBMIT
+$('.submit_form').tap(function(event) {
+ event.preventDefault();
+ $('.formerror').hide();
+ $(this).removeClass('active');
+ var timer_name = $("input#timer_name").val();
+ if (timer_name == "") {
+ $("li#timer_name_error").show();
+ $.scrollTo('#edittimer #ul[rel="name"]');
+ return false;
+ }
+ var timer_date = $("input#timer_date").val();
+ if (timer_date == "") {
+ $("li#timer_date_error").show();
+ $.scrollTo('#edittimer #timer_date_error');
+ return false;
+ }
+ var timer_starttime = $("input#timer_starttime").val();
+ if (timer_starttime == "") {
+ $("li#timer_starttime_error").show();
+ $.scrollTo('#edittimer #timer_starttime_error');
+ return false;
+ }
+ var timer_endtime = $("input#timer_endtime").val();
+ if (timer_endtime == "") {
+ $("li#timer_endtime_error").show();
+ $.scrollTo('#edittimer #timer_endtime_error');
+ return false;
+ }
+ var timer_id = $("input#timer_id").val();
+ var timer_chan = $("select#timer_chan").val();
+ var timer_active = $("input#timer_active").val();
+ var dataString = 'action=editTimer&id=' + timer_id + '&active=' + timer_active + '&channumber=' + timer_chan + '&date=' + timer_date + '&starttime=' + timer_starttime + '&endtime=' + timer_endtime;
+ $.getJSON("bin/backend.php",
+ dataString,
+ function(data) {
+ message = data.status + ": " + data.message;
+ gen_timers("true");
+ json_start(this);
+ showStatus( 0,message );
+ return false;
+ });
+ return false;
+});
+
+function showStatus( timeout, message ) {
+ if( timeout == 0 ) {
+ $('#timer_status').html(message);
+ $('#timer_status').show();
+ setTimeout( function() { showStatus( 1, message ); }, 4000 );
+ } else if( timeout == 1 ) {
+ $('#timer_status').hide();
+ }
+}
+// [/TIMER SECTION] \ No newline at end of file
diff --git a/js/spinningwheel-min.js b/js/spinningwheel-min.js
new file mode 100644
index 0000000..a2b68dd
--- /dev/null
+++ b/js/spinningwheel-min.js
@@ -0,0 +1 @@
+var SpinningWheel={cellHeight:44,friction:0.003,slotData:[],handleEvent:function(e){if(e.type=="touchstart"){this.lockScreen(e);if(e.currentTarget.id=="sw-cancel"||e.currentTarget.id=="sw-done"){this.tapDown(e)}else{if(e.currentTarget.id=="sw-frame"){this.scrollStart(e)}}}else{if(e.type=="touchmove"){this.lockScreen(e);if(e.currentTarget.id=="sw-cancel"||e.currentTarget.id=="sw-done"){this.tapCancel(e)}else{if(e.currentTarget.id=="sw-frame"){this.scrollMove(e)}}}else{if(e.type=="touchend"){if(e.currentTarget.id=="sw-cancel"||e.currentTarget.id=="sw-done"){this.tapUp(e)}else{if(e.currentTarget.id=="sw-frame"){this.scrollEnd(e)}}}else{if(e.type=="webkitTransitionEnd"){if(e.target.id=="sw-wrapper"){this.destroy()}else{this.backWithinBoundaries(e)}}else{if(e.type=="orientationchange"){this.onOrientationChange(e)}else{if(e.type=="scroll"){this.onScroll(e)}}}}}}},onOrientationChange:function(e){window.scrollTo(0,0);this.swWrapper.style.top=window.innerHeight+window.pageYOffset+"px";this.calculateSlotsWidth()},onScroll:function(e){this.swWrapper.style.top=window.innerHeight+window.pageYOffset+"px"},lockScreen:function(e){e.preventDefault();e.stopPropagation()},reset:function(){this.slotEl=[];this.activeSlot=null;this.swWrapper=undefined;this.swSlotWrapper=undefined;this.swSlots=undefined;this.swFrame=undefined},calculateSlotsWidth:function(){var div=this.swSlots.getElementsByTagName("div");for(var i=0;i<div.length;i+=1){this.slotEl[i].slotWidth=div[i].offsetWidth}},create:function(){var i,l,out,ul,div;this.reset();div=document.createElement("div");div.id="sw-wrapper";div.style.top=window.innerHeight+window.pageYOffset+"px";div.style.webkitTransitionProperty="-webkit-transform";div.innerHTML='<div id="sw-header"><div id="sw-cancel">Cancel</div><div id="sw-done">Done</div></div><div id="sw-slots-wrapper"><div id="sw-slots"></div></div><div id="sw-frame"></div>';document.body.appendChild(div);this.swWrapper=div;this.swSlotWrapper=document.getElementById("sw-slots-wrapper");this.swSlots=document.getElementById("sw-slots");this.swFrame=document.getElementById("sw-frame");for(l=0;l<this.slotData.length;l+=1){ul=document.createElement("ul");out="";for(i in this.slotData[l].values){out+="<li>"+this.slotData[l].values[i]+"</li>"}ul.innerHTML=out;div=document.createElement("div");div.className=this.slotData[l].style;div.appendChild(ul);this.swSlots.appendChild(div);ul.slotPosition=l;ul.slotYPosition=0;ul.slotWidth=0;ul.slotMaxScroll=this.swSlotWrapper.clientHeight-ul.clientHeight-86;ul.style.webkitTransitionTimingFunction="cubic-bezier(0, 0, 0.2, 1)";this.slotEl.push(ul);if(this.slotData[l].defaultValue){this.scrollToValue(l,this.slotData[l].defaultValue)}}this.calculateSlotsWidth();document.addEventListener("touchstart",this,false);document.addEventListener("touchmove",this,false);window.addEventListener("orientationchange",this,true);window.addEventListener("scroll",this,true);document.getElementById("sw-cancel").addEventListener("touchstart",this,false);document.getElementById("sw-done").addEventListener("touchstart",this,false);this.swFrame.addEventListener("touchstart",this,false)},open:function(){this.create();this.swWrapper.style.webkitTransitionTimingFunction="ease-out";this.swWrapper.style.webkitTransitionDuration="400ms";this.swWrapper.style.webkitTransform="translate3d(0, -260px, 0)"},destroy:function(){this.swWrapper.removeEventListener("webkitTransitionEnd",this,false);this.swFrame.removeEventListener("touchstart",this,false);document.getElementById("sw-cancel").removeEventListener("touchstart",this,false);document.getElementById("sw-done").removeEventListener("touchstart",this,false);document.removeEventListener("touchstart",this,false);document.removeEventListener("touchmove",this,false);window.removeEventListener("orientationchange",this,true);window.removeEventListener("scroll",this,true);this.slotData=[];this.cancelAction=function(){return false};this.cancelDone=function(){return true};this.reset();document.body.removeChild(document.getElementById("sw-wrapper"))},close:function(){this.swWrapper.style.webkitTransitionTimingFunction="ease-in";this.swWrapper.style.webkitTransitionDuration="400ms";this.swWrapper.style.webkitTransform="translate3d(0, 0, 0)";this.swWrapper.addEventListener("webkitTransitionEnd",this,false)},addSlot:function(values,style,defaultValue){if(!style){style=""}style=style.split(" ");for(var i=0;i<style.length;i+=1){style[i]="sw-"+style[i]}style=style.join(" ");var obj={values:values,style:style,defaultValue:defaultValue};this.slotData.push(obj)},getSelectedValues:function(){var index,count,i,l,keys=[],values=[];for(i in this.slotEl){this.slotEl[i].removeEventListener("webkitTransitionEnd",this,false);this.slotEl[i].style.webkitTransitionDuration="0";if(this.slotEl[i].slotYPosition>0){this.setPosition(i,0)}else{if(this.slotEl[i].slotYPosition<this.slotEl[i].slotMaxScroll){this.setPosition(i,this.slotEl[i].slotMaxScroll)}}index=-Math.round(this.slotEl[i].slotYPosition/this.cellHeight);count=0;for(l in this.slotData[i].values){if(count==index){keys.push(l);values.push(this.slotData[i].values[l]);break}count+=1}}return{keys:keys,values:values}},setPosition:function(slot,pos){this.slotEl[slot].slotYPosition=pos;this.slotEl[slot].style.webkitTransform="translate3d(0, "+pos+"px, 0)"},scrollStart:function(e){var xPos=e.targetTouches[0].clientX-this.swSlots.offsetLeft;var slot=0;for(var i=0;i<this.slotEl.length;i+=1){slot+=this.slotEl[i].slotWidth;if(xPos<slot){this.activeSlot=i;break}}if(this.slotData[this.activeSlot].style.match("readonly")){this.swFrame.removeEventListener("touchmove",this,false);this.swFrame.removeEventListener("touchend",this,false);return false}this.slotEl[this.activeSlot].removeEventListener("webkitTransitionEnd",this,false);this.slotEl[this.activeSlot].style.webkitTransitionDuration="0";var theTransform=window.getComputedStyle(this.slotEl[this.activeSlot]).webkitTransform;theTransform=new WebKitCSSMatrix(theTransform).m42;if(theTransform!=this.slotEl[this.activeSlot].slotYPosition){this.setPosition(this.activeSlot,theTransform)}this.startY=e.targetTouches[0].clientY;this.scrollStartY=this.slotEl[this.activeSlot].slotYPosition;this.scrollStartTime=e.timeStamp;this.swFrame.addEventListener("touchmove",this,false);this.swFrame.addEventListener("touchend",this,false);return true},scrollMove:function(e){var topDelta=e.targetTouches[0].clientY-this.startY;if(this.slotEl[this.activeSlot].slotYPosition>0||this.slotEl[this.activeSlot].slotYPosition<this.slotEl[this.activeSlot].slotMaxScroll){topDelta/=2}this.setPosition(this.activeSlot,this.slotEl[this.activeSlot].slotYPosition+topDelta);this.startY=e.targetTouches[0].clientY;if(e.timeStamp-this.scrollStartTime>80){this.scrollStartY=this.slotEl[this.activeSlot].slotYPosition;this.scrollStartTime=e.timeStamp}},scrollEnd:function(e){this.swFrame.removeEventListener("touchmove",this,false);this.swFrame.removeEventListener("touchend",this,false);if(this.slotEl[this.activeSlot].slotYPosition>0||this.slotEl[this.activeSlot].slotYPosition<this.slotEl[this.activeSlot].slotMaxScroll){this.scrollTo(this.activeSlot,this.slotEl[this.activeSlot].slotYPosition>0?0:this.slotEl[this.activeSlot].slotMaxScroll);return false}var scrollDistance=this.slotEl[this.activeSlot].slotYPosition-this.scrollStartY;if(scrollDistance<this.cellHeight/1.5&&scrollDistance>-this.cellHeight/1.5){if(this.slotEl[this.activeSlot].slotYPosition%this.cellHeight){this.scrollTo(this.activeSlot,Math.round(this.slotEl[this.activeSlot].slotYPosition/this.cellHeight)*this.cellHeight,"100ms")}return false}var scrollDuration=e.timeStamp-this.scrollStartTime;var newDuration=(2*scrollDistance/scrollDuration)/this.friction;var newScrollDistance=(this.friction/2)*(newDuration*newDuration);if(newDuration<0){newDuration=-newDuration;newScrollDistance=-newScrollDistance}var newPosition=this.slotEl[this.activeSlot].slotYPosition+newScrollDistance;if(newPosition>0){newPosition/=2;newDuration/=3;if(newPosition>this.swSlotWrapper.clientHeight/4){newPosition=this.swSlotWrapper.clientHeight/4}}else{if(newPosition<this.slotEl[this.activeSlot].slotMaxScroll){newPosition=(newPosition-this.slotEl[this.activeSlot].slotMaxScroll)/2+this.slotEl[this.activeSlot].slotMaxScroll;newDuration/=3;if(newPosition<this.slotEl[this.activeSlot].slotMaxScroll-this.swSlotWrapper.clientHeight/4){newPosition=this.slotEl[this.activeSlot].slotMaxScroll-this.swSlotWrapper.clientHeight/4}}else{newPosition=Math.round(newPosition/this.cellHeight)*this.cellHeight}}this.scrollTo(this.activeSlot,Math.round(newPosition),Math.round(newDuration)+"ms");return true},scrollTo:function(slotNum,dest,runtime){this.slotEl[slotNum].style.webkitTransitionDuration=runtime?runtime:"100ms";this.setPosition(slotNum,dest?dest:0);if(this.slotEl[slotNum].slotYPosition>0||this.slotEl[slotNum].slotYPosition<this.slotEl[slotNum].slotMaxScroll){this.slotEl[slotNum].addEventListener("webkitTransitionEnd",this,false)}},scrollToValue:function(slot,value){var yPos,count,i;this.slotEl[slot].removeEventListener("webkitTransitionEnd",this,false);this.slotEl[slot].style.webkitTransitionDuration="0";count=0;for(i in this.slotData[slot].values){if(i==value){yPos=count*this.cellHeight;this.setPosition(slot,yPos);break}count-=1}},backWithinBoundaries:function(e){e.target.removeEventListener("webkitTransitionEnd",this,false);this.scrollTo(e.target.slotPosition,e.target.slotYPosition>0?0:e.target.slotMaxScroll,"150ms");return false},tapDown:function(e){e.currentTarget.addEventListener("touchmove",this,false);e.currentTarget.addEventListener("touchend",this,false);e.currentTarget.className="sw-pressed"},tapCancel:function(e){e.currentTarget.removeEventListener("touchmove",this,false);e.currentTarget.removeEventListener("touchend",this,false);e.currentTarget.className=""},tapUp:function(e){this.tapCancel(e);if(e.currentTarget.id=="sw-cancel"){this.cancelAction()}else{this.doneAction()}this.close()},setCancelAction:function(action){this.cancelAction=action},setDoneAction:function(action){this.doneAction=action},cancelAction:function(){return false},cancelDone:function(){return true}}; \ No newline at end of file
diff --git a/js/spinningwheel.js b/js/spinningwheel.js
new file mode 100644
index 0000000..79f8ab6
--- /dev/null
+++ b/js/spinningwheel.js
@@ -0,0 +1,492 @@
+/**
+ *
+ * Find more about the Spinning Wheel function at
+ * http://cubiq.org/spinning-wheel-on-webkit-for-iphone-ipod-touch/11
+ *
+ * Copyright (c) 2009 Matteo Spinelli, http://cubiq.org/
+ * Released under MIT license
+ * http://cubiq.org/dropbox/mit-license.txt
+ *
+ * Version 1.4 - Last updated: 2009.07.09
+ *
+ */
+
+var SpinningWheel = {
+ cellHeight: 44,
+ friction: 0.003,
+ slotData: [],
+
+
+ /**
+ *
+ * Event handler
+ *
+ */
+
+ handleEvent: function (e) {
+ if (e.type == 'touchstart') {
+ this.lockScreen(e);
+ if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') {
+ this.tapDown(e);
+ } else if (e.currentTarget.id == 'sw-frame') {
+ this.scrollStart(e);
+ }
+ } else if (e.type == 'touchmove') {
+ this.lockScreen(e);
+
+ if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') {
+ this.tapCancel(e);
+ } else if (e.currentTarget.id == 'sw-frame') {
+ this.scrollMove(e);
+ }
+ } else if (e.type == 'touchend') {
+ if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') {
+ this.tapUp(e);
+ } else if (e.currentTarget.id == 'sw-frame') {
+ this.scrollEnd(e);
+ }
+ } else if (e.type == 'webkitTransitionEnd') {
+ if (e.target.id == 'sw-wrapper') {
+ this.destroy();
+ } else {
+ this.backWithinBoundaries(e);
+ }
+ } else if (e.type == 'orientationchange') {
+ this.onOrientationChange(e);
+ } else if (e.type == 'scroll') {
+ this.onScroll(e);
+ }
+ },
+
+
+ /**
+ *
+ * Global events
+ *
+ */
+
+ onOrientationChange: function (e) {
+ window.scrollTo(0, 0);
+ this.swWrapper.style.top = window.innerHeight + window.pageYOffset + 'px';
+ this.calculateSlotsWidth();
+ },
+
+ onScroll: function (e) {
+ this.swWrapper.style.top = window.innerHeight + window.pageYOffset + 'px';
+ },
+
+ lockScreen: function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ },
+
+
+ /**
+ *
+ * Initialization
+ *
+ */
+
+ reset: function () {
+ this.slotEl = [];
+
+ this.activeSlot = null;
+
+ this.swWrapper = undefined;
+ this.swSlotWrapper = undefined;
+ this.swSlots = undefined;
+ this.swFrame = undefined;
+ },
+
+ calculateSlotsWidth: function () {
+ var div = this.swSlots.getElementsByTagName('div');
+ for (var i = 0; i < div.length; i += 1) {
+ this.slotEl[i].slotWidth = div[i].offsetWidth;
+ }
+ },
+
+ create: function () {
+ var i, l, out, ul, div;
+
+ this.reset(); // Initialize object variables
+
+ // Create the Spinning Wheel main wrapper
+ div = document.createElement('div');
+ div.id = 'sw-wrapper';
+ div.style.top = window.innerHeight + window.pageYOffset + 'px'; // Place the SW down the actual viewing screen
+ div.style.webkitTransitionProperty = '-webkit-transform';
+ div.innerHTML = '<div id="sw-header"><div id="sw-cancel">Cancel</' + 'div><div id="sw-done">Done</' + 'div></' + 'div><div id="sw-slots-wrapper"><div id="sw-slots"></' + 'div></' + 'div><div id="sw-frame"></' + 'div>';
+
+ document.body.appendChild(div);
+
+ this.swWrapper = div; // The SW wrapper
+ this.swSlotWrapper = document.getElementById('sw-slots-wrapper'); // Slots visible area
+ this.swSlots = document.getElementById('sw-slots'); // Pseudo table element (inner wrapper)
+ this.swFrame = document.getElementById('sw-frame'); // The scrolling controller
+
+ // Create HTML slot elements
+ for (l = 0; l < this.slotData.length; l += 1) {
+ // Create the slot
+ ul = document.createElement('ul');
+ out = '';
+ for (i in this.slotData[l].values) {
+ out += '<li>' + this.slotData[l].values[i] + '<' + '/li>';
+ }
+ ul.innerHTML = out;
+
+ div = document.createElement('div'); // Create slot container
+ div.className = this.slotData[l].style; // Add styles to the container
+ div.appendChild(ul);
+
+ // Append the slot to the wrapper
+ this.swSlots.appendChild(div);
+
+ ul.slotPosition = l; // Save the slot position inside the wrapper
+ ul.slotYPosition = 0;
+ ul.slotWidth = 0;
+ ul.slotMaxScroll = this.swSlotWrapper.clientHeight - ul.clientHeight - 86;
+ ul.style.webkitTransitionTimingFunction = 'cubic-bezier(0, 0, 0.2, 1)'; // Add default transition
+
+ this.slotEl.push(ul); // Save the slot for later use
+
+ // Place the slot to its default position (if other than 0)
+ if (this.slotData[l].defaultValue) {
+ this.scrollToValue(l, this.slotData[l].defaultValue);
+ }
+ }
+
+ this.calculateSlotsWidth();
+
+ // Global events
+ document.addEventListener('touchstart', this, false); // Prevent page scrolling
+ document.addEventListener('touchmove', this, false); // Prevent page scrolling
+ window.addEventListener('orientationchange', this, true); // Optimize SW on orientation change
+ window.addEventListener('scroll', this, true); // Reposition SW on page scroll
+
+ // Cancel/Done buttons events
+ document.getElementById('sw-cancel').addEventListener('touchstart', this, false);
+ document.getElementById('sw-done').addEventListener('touchstart', this, false);
+
+ // Add scrolling to the slots
+ this.swFrame.addEventListener('touchstart', this, false);
+ },
+
+ open: function () {
+ this.create();
+
+ this.swWrapper.style.webkitTransitionTimingFunction = 'ease-out';
+ this.swWrapper.style.webkitTransitionDuration = '400ms';
+ this.swWrapper.style.webkitTransform = 'translate3d(0, -260px, 0)';
+ },
+
+
+ /**
+ *
+ * Unload
+ *
+ */
+
+ destroy: function () {
+ this.swWrapper.removeEventListener('webkitTransitionEnd', this, false);
+
+ this.swFrame.removeEventListener('touchstart', this, false);
+
+ document.getElementById('sw-cancel').removeEventListener('touchstart', this, false);
+ document.getElementById('sw-done').removeEventListener('touchstart', this, false);
+
+ document.removeEventListener('touchstart', this, false);
+ document.removeEventListener('touchmove', this, false);
+ window.removeEventListener('orientationchange', this, true);
+ window.removeEventListener('scroll', this, true);
+
+ this.slotData = [];
+ this.cancelAction = function () {
+ return false;
+ };
+
+ this.cancelDone = function () {
+ return true;
+ };
+
+ this.reset();
+
+ document.body.removeChild(document.getElementById('sw-wrapper'));
+ },
+
+ close: function () {
+ this.swWrapper.style.webkitTransitionTimingFunction = 'ease-in';
+ this.swWrapper.style.webkitTransitionDuration = '400ms';
+ this.swWrapper.style.webkitTransform = 'translate3d(0, 0, 0)';
+
+ this.swWrapper.addEventListener('webkitTransitionEnd', this, false);
+ },
+
+
+ /**
+ *
+ * Generic methods
+ *
+ */
+
+ addSlot: function (values, style, defaultValue) {
+ if (!style) {
+ style = '';
+ }
+
+ style = style.split(' ');
+
+ for (var i = 0; i < style.length; i += 1) {
+ style[i] = 'sw-' + style[i];
+ }
+
+ style = style.join(' ');
+
+ var obj = { 'values': values, 'style': style, 'defaultValue': defaultValue };
+ this.slotData.push(obj);
+ },
+
+ getSelectedValues: function () {
+ var index, count,
+ i, l,
+ keys = [], values = [];
+
+ for (i in this.slotEl) {
+ // Remove any residual animation
+ this.slotEl[i].removeEventListener('webkitTransitionEnd', this, false);
+ this.slotEl[i].style.webkitTransitionDuration = '0';
+
+ if (this.slotEl[i].slotYPosition > 0) {
+ this.setPosition(i, 0);
+ } else if (this.slotEl[i].slotYPosition < this.slotEl[i].slotMaxScroll) {
+ this.setPosition(i, this.slotEl[i].slotMaxScroll);
+ }
+
+ index = -Math.round(this.slotEl[i].slotYPosition / this.cellHeight);
+
+ count = 0;
+ for (l in this.slotData[i].values) {
+ if (count == index) {
+ keys.push(l);
+ values.push(this.slotData[i].values[l]);
+ break;
+ }
+
+ count += 1;
+ }
+ }
+
+ return { 'keys': keys, 'values': values };
+ },
+
+
+ /**
+ *
+ * Rolling slots
+ *
+ */
+
+ setPosition: function (slot, pos) {
+ this.slotEl[slot].slotYPosition = pos;
+ this.slotEl[slot].style.webkitTransform = 'translate3d(0, ' + pos + 'px, 0)';
+ },
+
+ scrollStart: function (e) {
+ // Find the clicked slot
+ var xPos = e.targetTouches[0].clientX - this.swSlots.offsetLeft; // Clicked position minus left offset (should be 11px)
+
+ // Find tapped slot
+ var slot = 0;
+ for (var i = 0; i < this.slotEl.length; i += 1) {
+ slot += this.slotEl[i].slotWidth;
+
+ if (xPos < slot) {
+ this.activeSlot = i;
+ break;
+ }
+ }
+
+ // If slot is readonly do nothing
+ if (this.slotData[this.activeSlot].style.match('readonly')) {
+ this.swFrame.removeEventListener('touchmove', this, false);
+ this.swFrame.removeEventListener('touchend', this, false);
+ return false;
+ }
+
+ this.slotEl[this.activeSlot].removeEventListener('webkitTransitionEnd', this, false); // Remove transition event (if any)
+ this.slotEl[this.activeSlot].style.webkitTransitionDuration = '0'; // Remove any residual transition
+
+ // Stop and hold slot position
+ var theTransform = window.getComputedStyle(this.slotEl[this.activeSlot]).webkitTransform;
+ theTransform = new WebKitCSSMatrix(theTransform).m42;
+ if (theTransform != this.slotEl[this.activeSlot].slotYPosition) {
+ this.setPosition(this.activeSlot, theTransform);
+ }
+
+ this.startY = e.targetTouches[0].clientY;
+ this.scrollStartY = this.slotEl[this.activeSlot].slotYPosition;
+ this.scrollStartTime = e.timeStamp;
+
+ this.swFrame.addEventListener('touchmove', this, false);
+ this.swFrame.addEventListener('touchend', this, false);
+
+ return true;
+ },
+
+ scrollMove: function (e) {
+ var topDelta = e.targetTouches[0].clientY - this.startY;
+
+ if (this.slotEl[this.activeSlot].slotYPosition > 0 || this.slotEl[this.activeSlot].slotYPosition < this.slotEl[this.activeSlot].slotMaxScroll) {
+ topDelta /= 2;
+ }
+
+ this.setPosition(this.activeSlot, this.slotEl[this.activeSlot].slotYPosition + topDelta);
+ this.startY = e.targetTouches[0].clientY;
+
+ // Prevent slingshot effect
+ if (e.timeStamp - this.scrollStartTime > 80) {
+ this.scrollStartY = this.slotEl[this.activeSlot].slotYPosition;
+ this.scrollStartTime = e.timeStamp;
+ }
+ },
+
+ scrollEnd: function (e) {
+ this.swFrame.removeEventListener('touchmove', this, false);
+ this.swFrame.removeEventListener('touchend', this, false);
+
+ // If we are outside of the boundaries, let's go back to the sheepfold
+ if (this.slotEl[this.activeSlot].slotYPosition > 0 || this.slotEl[this.activeSlot].slotYPosition < this.slotEl[this.activeSlot].slotMaxScroll) {
+ this.scrollTo(this.activeSlot, this.slotEl[this.activeSlot].slotYPosition > 0 ? 0 : this.slotEl[this.activeSlot].slotMaxScroll);
+ return false;
+ }
+
+ // Lame formula to calculate a fake deceleration
+ var scrollDistance = this.slotEl[this.activeSlot].slotYPosition - this.scrollStartY;
+
+ // The drag session was too short
+ if (scrollDistance < this.cellHeight / 1.5 && scrollDistance > -this.cellHeight / 1.5) {
+ if (this.slotEl[this.activeSlot].slotYPosition % this.cellHeight) {
+ this.scrollTo(this.activeSlot, Math.round(this.slotEl[this.activeSlot].slotYPosition / this.cellHeight) * this.cellHeight, '100ms');
+ }
+
+ return false;
+ }
+
+ var scrollDuration = e.timeStamp - this.scrollStartTime;
+
+ var newDuration = (2 * scrollDistance / scrollDuration) / this.friction;
+ var newScrollDistance = (this.friction / 2) * (newDuration * newDuration);
+
+ if (newDuration < 0) {
+ newDuration = -newDuration;
+ newScrollDistance = -newScrollDistance;
+ }
+
+ var newPosition = this.slotEl[this.activeSlot].slotYPosition + newScrollDistance;
+
+ if (newPosition > 0) {
+ // Prevent the slot to be dragged outside the visible area (top margin)
+ newPosition /= 2;
+ newDuration /= 3;
+
+ if (newPosition > this.swSlotWrapper.clientHeight / 4) {
+ newPosition = this.swSlotWrapper.clientHeight / 4;
+ }
+ } else if (newPosition < this.slotEl[this.activeSlot].slotMaxScroll) {
+ // Prevent the slot to be dragged outside the visible area (bottom margin)
+ newPosition = (newPosition - this.slotEl[this.activeSlot].slotMaxScroll) / 2 + this.slotEl[this.activeSlot].slotMaxScroll;
+ newDuration /= 3;
+
+ if (newPosition < this.slotEl[this.activeSlot].slotMaxScroll - this.swSlotWrapper.clientHeight / 4) {
+ newPosition = this.slotEl[this.activeSlot].slotMaxScroll - this.swSlotWrapper.clientHeight / 4;
+ }
+ } else {
+ newPosition = Math.round(newPosition / this.cellHeight) * this.cellHeight;
+ }
+
+ this.scrollTo(this.activeSlot, Math.round(newPosition), Math.round(newDuration) + 'ms');
+
+ return true;
+ },
+
+ scrollTo: function (slotNum, dest, runtime) {
+ this.slotEl[slotNum].style.webkitTransitionDuration = runtime ? runtime : '100ms';
+ this.setPosition(slotNum, dest ? dest : 0);
+
+ // If we are outside of the boundaries go back to the sheepfold
+ if (this.slotEl[slotNum].slotYPosition > 0 || this.slotEl[slotNum].slotYPosition < this.slotEl[slotNum].slotMaxScroll) {
+ this.slotEl[slotNum].addEventListener('webkitTransitionEnd', this, false);
+ }
+ },
+
+ scrollToValue: function (slot, value) {
+ var yPos, count, i;
+
+ this.slotEl[slot].removeEventListener('webkitTransitionEnd', this, false);
+ this.slotEl[slot].style.webkitTransitionDuration = '0';
+
+ count = 0;
+ for (i in this.slotData[slot].values) {
+ if (i == value) {
+ yPos = count * this.cellHeight;
+ this.setPosition(slot, yPos);
+ break;
+ }
+
+ count -= 1;
+ }
+ },
+
+ backWithinBoundaries: function (e) {
+ e.target.removeEventListener('webkitTransitionEnd', this, false);
+
+ this.scrollTo(e.target.slotPosition, e.target.slotYPosition > 0 ? 0 : e.target.slotMaxScroll, '150ms');
+ return false;
+ },
+
+
+ /**
+ *
+ * Buttons
+ *
+ */
+
+ tapDown: function (e) {
+ e.currentTarget.addEventListener('touchmove', this, false);
+ e.currentTarget.addEventListener('touchend', this, false);
+ e.currentTarget.className = 'sw-pressed';
+ },
+
+ tapCancel: function (e) {
+ e.currentTarget.removeEventListener('touchmove', this, false);
+ e.currentTarget.removeEventListener('touchend', this, false);
+ e.currentTarget.className = '';
+ },
+
+ tapUp: function (e) {
+ this.tapCancel(e);
+
+ if (e.currentTarget.id == 'sw-cancel') {
+ this.cancelAction();
+ } else {
+ this.doneAction();
+ }
+
+ this.close();
+ },
+
+ setCancelAction: function (action) {
+ this.cancelAction = action;
+ },
+
+ setDoneAction: function (action) {
+ this.doneAction = action;
+ },
+
+ cancelAction: function () {
+ return false;
+ },
+
+ cancelDone: function () {
+ return true;
+ }
+}; \ No newline at end of file