Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery mobile calendar with 3-state day colours

I am looking at creating an event and reservation system.

I found the Stack Overflow question jQuery - Mobile date picker control which shows jquery-mobile-datebox and jQuery-Mobile-Themed-DatePicker.

I want to display a calendar where certain dates I get from the server are

  1. available
  2. not available
  3. reserved

When a reserved or available date is touched, I want to show times - there can be more than one time per day. The user can then click on a time to reserve it which would hit off an Ajax request.

jQuery UI datepicker, for example, has

 onSelect: function(date, inst) {

From what I can see in the above pickers, what I need is not readily available. Before I start hacking them myself:

  1. Which one would lend itself best to what I want?
  2. Are there perhaps better ones out there that already serve my needs?

UPDATE:

Firebug gave me

<div class="ui-datebox-griddate ui-corner-all ui-btn-up-e" data-date="25" data-theme="e">25</div>

where ui-btn-up-e can be changed from a - e.

Now I need to find out if data-theme also needs to be changed

 $('.ui-datebox-griddate').click(function () {
   alert($(this).attr("class"));
 }

What is the nicest way to toggle through three of the classes and save the state each time?

 $('.ui-datebox-griddate').toggle(
   function () {
     $(this).????? // change ui-btn-up-? to ui-btn-up-a
     $.get(...)
  },
   function () {
     $(this).????? // change ui-btn-up-a to ui-btn-up-b
     $.get(...)
  },
   function () {
     $(this).????? // change ui-btn-up-b to ui-btn-up-c
     $.get(...)
  }
);

UPDATE: NOTE: When I click, the calendar change the date, reloading the calendar completely. Perhaps I need to stop that :(

like image 984
mplungjan Avatar asked Jun 15 '11 13:06

mplungjan


2 Answers

What is the nicest way to toggle through three of the classes and save the state each time?

Something like:

$('.ui-datebox-griddate').click(function (e) {
  var $this = $(this);
  var cycle = ["ui-btn-up-a", "ui-btn-up-b", "ui-btn-up-c"];

  if (typeof $this.data("ui-btn-cycle") == "undefined" ) {
    this.className = this.className.replace(/ui-btn-up-./, cycle[0]);
    $this.data("ui-btn-cycle", cycle[0]);
  }

  for (var i=0; i<cycle.length; i++) {
    if ( $this.hasClass(cycle[i]) ) {
      $this.removeClass(cycle[i]).addClass(cycle[i % cycle.length]);
      $this.data("ui-btn-cycle", [i % cycle.length]);
      break;
    }
  }
  $.get( ... );

  e.preventDefault() // stop default click behaviour
});

This can cycle though an arbitrary amount of classes. The current state would be available through calling .data("ui-btn-cycle") on the respective element.

This is even nicer:

$('.ui-datebox-griddate')
.each(function () {
  var cycle = ["ui-btn-up-a", "ui-btn-up-b", "ui-btn-up-c"];
  $(this).data("ui-btn-cycle", cycle);
  this.className = this.className.replace(/ui-btn-up-./, cycle[0]);
})
.click(function (e) {
  var cycle = $(this).data("ui-btn-cycle");
  $(this).removeClass(cycle[0]).addClass(cycle[1]);
  cycle.push(cycle.shift());
  e.preventDefault();
});

The current state would always be .data("ui-btn-cycle")[0] on the respective element. See it working here: http://jsfiddle.net/Tomalak/mAH4n/

like image 106
Tomalak Avatar answered Sep 28 '22 11:09

Tomalak


Based on what J.T.Sage said I thought I would have a play with jQuery Mobile Calendar. I think I have something which could potentially be extended to fulfil your requirements. I am not sure to what extent multi-colour themeing would be possible (without extensive modifications).

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>jQueryMobile - DateBox Demos</title>
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css" />
    <link type="text/css" href="http://dev.jtsage.com/cdn/datebox/latest/jquery.mobile.datebox.min.css" rel="stylesheet" />
    <!-- NOTE: Script load order is significant! -->
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
    <script type="text/javascript">
        $( document ).bind( "mobileinit", function(){ $.mobile.page.prototype.options.degradeInputs.date = 'text'; });
    </script>
    <script type="text/javascript" src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script>
    <script type="text/javascript" src="http://dev.jtsage.com/cdn/datebox/latest/jquery.mobile.datebox.min.js"></script>
    <script type="text/javascript">
    $('#page').live('pagecreate', function(event) {
        $('#mydate').bind('change', function () {
            alert($(this).val());
        });
    });
    </script>
</head>
<body>
<div id="page" data-role="page">
<div data-role="content">
<input name="mydate" id="mydate" type="date" data-role="datebox" data-options='{"mode": "calbox", "calHighToday": false, "calHighPicked": false, "useInline": true, "useInlineHideInput": true, "highDates": ["2011-06-25", "2011-06-27", "2011-07-04"]}'></input>
</div>
</div>
</html>

UPDATE

I suppose the highDates mechanism could be bypassed completely and the individual days uniquely targeted. The plugin maintains a JavaScript Date object of the last date selected (or today if nothing has been selected) - so it should be possible to get the current month and iterate through all your matching data updating the matching days in the current month as appropriate (e.g. replacing the setColours method below with something that is data/state aware).

<script type="text/javascript">
$('#page').live('pagecreate', function(event) {

    $('#mydate').bind('change', function () {
        //alert($(this).val());
        alert($('#mydate').data('datebox').theDate);
    });
    setColours();

    $('#mydate').bind('datebox', function (e, pressed) {
        setColours();
    });

    $('.ui-datebox-gridplus, .ui-datebox-gridminus').bind('vclick', function(){
         // To handle changing months
          setColours();
         //alert($('#mydate').data('datebox').theDate);
    });

    function setColours(){
        $('div.ui-datebox-griddate[data-date=25][data-theme]').css({"background-color":"red", "background-image":"none", "color" : "white"});
        $('div.ui-datebox-griddate[data-date=26][data-theme]').css({"background-color":"green", "background-image":"none", "color" : "white"});
        $('div.ui-datebox-griddate[data-date=27][data-theme]').css({"background-color":"blue", "background-image":"none", "color" : "white"});
    }

});
</script>
like image 27
Mark McLaren Avatar answered Sep 28 '22 11:09

Mark McLaren