﻿/* Room selector plugin for jQuery
 * Author: E-Travel
 *
 * This plugin creates room selector boxes inside the selected element:
 * Example:
 * $('#mydivforrooms').roomselector({
            rooms: 4,
            adults: 4,
            children: 4,
            age: 12
        });
 * This will create a room selector for 4 rooms, maximum 4 adults and 4 
 * children per room. And the maximum children age will be 12 years.
 */

/* Start jQuery alias $ */
(function ($) {
    var defaultSettings = {
        /* Maximum number of rooms */
        rooms: 2,
        /* Maximum number of adults per room */
        adults: 2,
        /* Maximum number of children per room */
        children: 2,
        /* Maximum age per child */
        age: 12,
        /* cookie to store the state of the selector */
        cookiename: "roomselector",
        regional : 
            typeof(roomselectorregionalsettings) != "undefined"?roomselectorregionalsettings:{
            rooms: "Rooms",
            numroom: "Number of Rooms",
            room: "Room",
            adults: "Adults",
            children: "Children",
            child: "Child",
            age: "Age"
        }
    };
    
    /* Template for the the main area: number of rooms */
    var mainTemplate = {
        header: "<fieldset class=\"{selector} roomlistselector\">\n\
    <legend>"+defaultSettings.regional.rooms+"</legend>\n\
    <label for=\"{selector}numrooms\">"+defaultSettings.regional.numroom+"</label>\n\
    <select title=\""+defaultSettings.regional.numroom+"\" name=\"numrooms\" id=\"{selector}numrooms\" >\n",
        item: "\t\t<option {selected} value=\"{value}\">{value}</option>\n",
        footer: "\t</select><div class=\"roomsarea\"></div>\n</fieldset>"
    };
    
    /* Template per room:
     * - Number of adults.
     * - Number of children.
     */
    var roomTemplate = {
        headerAdults: "<fieldset class=\"room{roomid} isroom\">\n\
            <legend>"+defaultSettings.regional.room+" {roomid}</legend>\n\
            <label for=\"sel{selector}room{roomid}numadults\">"+defaultSettings.regional.adults+"</label>\
                <select title=\""+defaultSettings.regional.adults+"\" name=\"room{roomid}numadults\" id=\"sel{selector}room{roomid}numadults\" class=\"adultselect\" onchange=\"$.roomselector._adultchange({selector},{roomid},this)\">",
        item: "\t\t<option {selected} value=\"{value}\">{value}</option>\n",
        footerAdults: "</select>",
        headerChildren: "<label for=\"sel{selector}room{roomid}numchildren\">"+defaultSettings.regional.children+"</label>\n\
                 <select title=\""+defaultSettings.regional.children+"\" id=\"sel{selector}room{roomid}numchildren\" name=\"room{roomid}numchildren\" onchange=\"$.roomselector._childrenchange({selector},{roomid},this)\">",
        footerChildren: "</select><div class=\"childrenarea\"><hr /></div>",
        footer: "</fieldset>"
            
    };
    
    var childTemplate = {
        header: "<div class=\"childage\">\n\
        <label for=\"sel{selector}room{roomid}child{childid}\">"+defaultSettings.regional.child+"&nbsp;{childid}</label>\n\
        <select name=\"room{roomid}child{childid}\" id=\"sel{selector}room{roomid}child{childid}\" title=\"Select Child {childid} age\" onchange=\"$.roomselector._agechange({selector},{roomid},{childid},this)\">\n",
        item: "\t\t<option {selected} value=\"{value}\">{value}</option>\n",
        /* If there are children, this content will be added to the beginning */
        content: "<hr />",
        footer: "\t</select></div>\n"
    };


    function changeRoomNumber(event) {
        this.selector.rooms = parseInt(this.value);
        drawRooms(this);
    }

    
    function drawChildren(id,room,place) {
        /* Before doing anything, do we have children to paint?
         * if not, we hide the div because in IE it draws an empty box and eats space
         */
        var selector = $.roomselector.selectors[id-1];
        var numchildren = selector.roomsdata[room-1].children;
        if (numchildren == 0) 
        {
            $(place).hide();
            return;
        }
        else $(place).show();
        
        
         
        var buffer = childTemplate.content;
        
        /* For each children we add an age box */
        for(var i=0;i<numchildren;i++) {
            var childnum = i+1;
            buffer += childTemplate.header
                .replace(new RegExp('{roomid}','g'),room)
                .replace(new RegExp('{selector}','g'),id)
                .replace(new RegExp('{childid}','g'),childnum);
            
            /* Add each age value */    
            for(var j=0;j<=selector.settings.age;j++) {
                var value = j;
                var line = childTemplate.item.replace(new RegExp('{value}','g'),value);
                var selected = "";
                
                if (value == selector.roomsdata[room-1].childrendata[i]) selected="selected=\"selected\"";
                buffer += line.replace(new RegExp('{selected}','g'),selected);
            }
            buffer+= childTemplate.footer;
        }
        place.innerHTML = buffer;
    }
    
    function drawRooms(element) {
        var place = element.nextSibling;
        var selector = element.selector;
        var buffer = "";

        place.innerHTML = "";
        for(var i=0;i<selector.rooms;i++) {
            var roomnum = i+1;
            buffer = roomTemplate.headerAdults
                .replace(new RegExp('{roomid}','g'),roomnum)
                .replace(new RegExp('{selector}','g'),selector.id);
                
            for(var j=0;j<selector.settings.adults;j++) {
                var value = j+1;
                var line = roomTemplate.item.replace(new RegExp('{value}','g'),value);
                var selected = "";
                if (value == selector.roomsdata[i].adults) selected="selected=\"selected\"";
                buffer += line.replace(new RegExp('{selected}','g'),selected);
            }
            buffer += roomTemplate.footerAdults;
            
            /* Now the same for children 
             * - 1st header for children. Parameters: roomid, selector
             * - 2nd per child. Parameters: value
             * - 3rd footer children.
            */
            buffer += roomTemplate.headerChildren
                .replace(new RegExp('{roomid}','g'),roomnum)
                .replace(new RegExp('{selector}','g'),selector.id);
            for(var j=0,childitem=roomTemplate.item;j<=selector.settings.children;j++) {
                var value = j;
                var line = childitem.replace(new RegExp('{value}','g'),value);
                var selected = "";
                if (value == selector.roomsdata[i].children) selected="selected=\"selected\"";
                buffer += line.replace(new RegExp('{selected}','g'),selected);
            }
            buffer += roomTemplate.footerChildren;
            
            buffer += roomTemplate.footer;
            place.innerHTML += buffer;
            
        }
       
        
        /* Draw children */
        for(var i=0;i<selector.rooms;i++) {
            var value =i+1;
            //var element = $('#room'+value+'numchildren');
            //element.bind('change',changeChildrenNumber);
            /* we set the room number in the area (div) */
            var select = document.getElementById('sel'+selector.id+'room'+value+'numchildren');
            var div = $(select).siblings('div.childrenarea');
            drawChildren(selector.id,value,div[0]);
        }
        
        place.innerHTML += '<div class="clearer"></div>';
    }
    
    /* create
     * Creates a new RoomSelector for the DOM element given with the settings given
     */
    function create(element,settings) {
        /* Create a new roomselector */
        var selector = $.roomselector.NewSelector(settings),
            mycookie = $.cookie(selector.settings.cookiename);
        
        /* Do we have previous data in a cookie? */
        if(typeof(mycookie) == "string")
            selector.setState(mycookie);
        
        /* Build the rooms */
        var buffer = mainTemplate.header.replace(new RegExp('{selector}','g'), 'sel'+selector.id);
        for(var i = 0; i <selector.settings.rooms; i++) {
            var value = i + 1;
            var line = mainTemplate.item.replace(new RegExp('{value}','g'),value);
            var selected = "";
            if (value == selector.rooms) selected = "selected=\"selected\"";
            buffer += line.replace(new RegExp('{selected}','g'),selected);
        }
        buffer +=mainTemplate.footer;
        
        element.innerHTML = buffer;
        
        /* On exit, we store our state */
        $(window).bind("unload",function () {
            $.cookie(selector.settings.cookiename,selector.getState());
        });
        /* perhaps this is better/faster to put it in the template */
        var theselect = $(element).find('select');
        theselect.bind('change',changeRoomNumber);
        
        theselect[0].selector = selector;
        drawRooms(theselect[0]);
    }
    
    /* Room
     * This class serves as a model to store information about rooms
     */
    function Room(selector) {
        this.parent = selector;
        this.id = 1;
        this.adults = 1;
        this.children = 0;
        
        this.childrendata = []
        for(var i=0;i<selector.settings.children;i++) 
            this.childrendata[i] = 0;
            
    };
    /* Room::toJSON
     * export the current room to JSON data 
     *
     * In fact the returned string is not real JSON, but can be inserted in a JSON 
     * representation. A real JSON should be [value,value,...], and here
     * we return value,value,...
     */
    Room.prototype.toJSON = function () {
        return this.adults + "r" + this.children + "r"+this.childrendata.join("r");
    }
    
    Room.prototype.fromJSON = function(state) {
        var values = state.split("r");
        this.adults = parseInt(values[0]);
        this.children = parseInt(values[1]);
        for(var i=2;i<values.length;i++) {
            this.childrendata[i-2] = values[i];
        }
    }
    
    
    function RoomSelector(settings) {
        this.id = 0;
        this.settings = $.extend({}, defaultSettings, settings);
        this.rooms = 1;
        
        /* Initialize with empty data for ALL rooms
         * This is useful because we will keep the data even if the user hides
         * an option.
         */
        this.roomsdata = [];
        for(var i=0;i<this.settings.rooms;i++) 
        {
            this.roomsdata[i] = new Room(this);
        }
    }
   
   /* getValues
    * Export the internal state of the room selector.
    * Useful when storing the state in a cookie.
    */
   RoomSelector.prototype.getState = function () {
        var output = this.rooms+"D",
            hadprevious = false;
        for (var i=0;i<this.roomsdata.length;i++) {
            if (hadprevious) output += "R";
            output += this.roomsdata[i].toJSON();
            hadprevious = true;
        }
        
        return output;
    };
    
    RoomSelector.prototype.setState = function (state) {
        /* Just in case. the string will be longer */
        if (state.length < 5) return;
        
        /* Number of rooms and room data */
        var tmp = state.split("D");
        this.rooms = parseInt(tmp[0]);
        
        /* Rooms */
        tmp = tmp[1].split("R");
        for (var i=0;i<tmp.length && i<this.roomsdata.length;i++) {
            this.roomsdata[i].fromJSON(tmp[i]);
        }
    };
    
    /* Stores the configuration or all room selectors */
    function RoomselectorHolder() {
        /* Keep the configuration of each selector */
        this.selectors = [];
        
        this.setLanguage = function (regionalSettings) {
            $.extend(defaultSettings.regional, regionalSettings);
        };
        
        this.NewSelector = function(settings) {
            var selector = new RoomSelector(settings);
            this.selectors[this.selectors.length] = selector;
            selector.id = this.selectors.length;
            return selector;
        }
        
        this._adultchange = function (id,room,select) {
            this.selectors[id-1].roomsdata[room-1].adults = select.value;
        }
        
        this._childrenchange = function (id,room,select) {
            this.selectors[id-1].roomsdata[room-1].children = select.value;
            drawChildren(id,room,$(select).siblings('div.childrenarea')[0]);
        }
        
        this._agechange = function (id,room,child,select) {
            this.selectors[id-1].roomsdata[room-1].childrendata[child-1] = select.value;
        }
    }
    
    /* Assign the extra function */
    $.roomselector = new RoomselectorHolder();
    $.fn.extend({
        roomselector: function(settings) {
            /* For each element selected */
            this.each(function () {
                create(this,settings);
            });
            return this;
        }
    });


/* End jQuery alias $ */
})(jQuery)


