// $Id:$ (function ($) { /** * Attach the slider behavior to each checkbox with the 'slider' class. */ Drupal.behaviors.slider = { attach: function (context) { $('input:checkbox.slider:not(.slider-processed)').addClass('slider-processed').each(function() { Drupal.slider[$(this).attr('id')] = new Drupal.slider($(this)); }); } }; /** * Converts a checkbox into a slider. * * @param options (object) * - The jQuery checkbox element on which to apply the slider behavior. * * @param options (object) * - An optional object with which you can alter some default behaviors. * * direction (string): 'vertical' or 'horizontal' (defualt). * disable_styles (bool): Whether or not to disable the slider's default CSS. * id_prefix (string): The prefix used for the slider's ID. By default the id of the checkbox is used. * slider_width (int): The width of the slider. By default this is 30. * slider_height (int): The height of the slider. By default this is 15. * container_width (int): The width of the slider's bounding box. By default this is twice the width of the slider. * container_height (int): The height of the slider's bounding box. By default this equals the slider's height. */ Drupal.slider = function(checkbox, options) { // Reference variables var ref = {}; ref.obj = checkbox; ref.options = (options) || {}; // Configuration variables ref.direction = 'horizontal'; ref.disable_styles = false; ref.id_prefix = ref.obj.attr('id'); ref.slider_width = 30; ref.slider_height = 15; ref.container_width = (ref.slider_width * 2); ref.container_height = ref.slider_height; // Global records ref.last_mouse_pos = {x:0, y:0}; ref.last_slider_pos = {x:0, y:0}; ref.mouse_down = false; ref.init = true; ref.drag_status = {}; ref.slider_id; ref.slider; ref.slider_container; ref.slider_status; ref.slider_last_status; // Event callbacks ref.start; // Use to perform validation before proceeding e.g. start: function(ref.obj) {return false} ref.stop; // Called after releasing the slider. Also used for validation. e.g. stop: function(ref.obj, changed) { return (statement)}} ref.change; // Called if the slider's value has been changed after releasing e.g. change: function(status, ref.obj) { alert(ref.obj.attr('name') + ' has been changed!') } /** * Initializes the slider function. */ ref.init = function() { ref.obj.hide(); ref.setConfigurationOptions(); ref.createSlider(); ref.sliderAddEventListeners(); ref.init = false; }; /** * This function checks for all passed arguments in the options object. * If a configuration option is given, the default values is overwritten. */ ref.setConfigurationOptions = function() { // Here we check wheter a required setting is set in the arguments options. If not, we'll set the default value for(var option in ref.options) if(ref.options[option] !== undefined && ref.options[option] !== '') ref[option] = ref.options[option]; }; /** * Attaches all required event listeners to the slider DOM elements. */ ref.sliderAddEventListeners = function() { // When the mouse is moved while the mouse button is pressed $(document).mousemove(function(e) { // Trigger the onstart callback, if defined // Stop if the callback returns false if(ref.start && ref['start'](ref.obj) == false) return false; if(ref.mouse_down && ref.drag_status[ref.slider_id] == 'on') { // update the position and call the registered function ref.updatePosition(e); return false; }; }); // When the mouse button is released $(document).mouseup(function(e) { if (ref.mouse_down && ref.drag_status[ref.slider_id] == 'on') { // update track variables ref.mouse_down = false; ref.slider_last_status = ref.slider_status; // Get the position status var released_status = ref.getNearestStatus(e); var changed = (ref.slider_last_status != released_status); // Trigger the onstop callback, if defined // Stop if the callback returns false if (ref.stop && ref['stop'](ref.obj, changed) === false || ref.obj.attr('disabled')) { ref.sliderSetStatus(ref.slider_last_status); } else { ref.slider_last_status = released_status; ref.sliderSetStatus(ref.slider_last_status); }; return false; }; }); // When an element receives a mouse press ref.slider.mousedown(function(e) { if (ref.start && ref['start'](ref.obj) == false) return false; // update track variables ref.mouse_down = true; // retrieve positioning properties var pos = ref.getMousePos(e); ref.last_mouse_pos.x = pos.x; ref.last_mouse_pos.y = pos.y; ref.last_slider_pos.y = this.offsetTop; ref.last_slider_pos.x = this.offsetLeft; ref.updatePosition(e); return false; }); ref.obj.click(function() { ref.slider_last_status = (ref.obj.attr('checked')) ? true : false; ref.sliderSetStatus(ref.slider_last_status); }); ref.slider_container.mousedown(function() { // Trigger the onstart callback, if defined // Stop if the callback returns false if(ref.start && ref['start'](ref.obj) == false) return false; // Trigger the onstop callback, if defined // Stop if the callback returns false if(ref.stop && ref['stop'](ref.obj) !== false && !ref.obj.attr('disabled')) { ref.slider_last_status = (ref.obj.attr('checked')) ? true : false; ref.slider_status = !ref.slider_last_status; ref.sliderSetStatus(ref.slider_status); }; }); }; /** * Sets the value of the checkbox * * @param on Boolean TRUE if the checkbox should be checked, FALSE if it should be unchecked */ ref.updateCheckbox = function(on) { ref.obj.attr({'checked':(on) ? 'checked' : ''}); }; /** * Places the Slider DOM object after the checkbox object */ ref.createSlider = function() { ref.slider_id = ref.id_prefix + (new Date().getTime()); ref.slider_container = $('
').addClass('slider_container').prependTo(ref.obj.parent()); ref.slider = $('
').attr({'id':ref.slider_id}).addClass('slider').appendTo(ref.slider_container); ref.slider_container.css({ 'width' : ref.container_width + 'px', 'height' : ref.container_height + 'px', 'position' : 'relative', }); ref.slider.css({ 'width' : ref.slider_width + 'px', 'height' : ref.slider_height + 'px', 'position' : 'absolute', 'top' : '0px', 'left' : '0px', 'cursor' : 'pointer' }); if(ref.disable_styles == false) { ref.slider_container.css({ 'border' : 'solid gray 1px' }); ref.slider.css({ 'background' : '#ccc', }); }; if(ref.obj.attr('disabled')) ref.slider_container.css({'opacity':0.5}).addClass('disabled'); ref.slider_container.addClass((ref.obj.attr('checked')) ? 'on' : 'off'); ref.drag_status[ref.slider_id] = "on"; ref.sliderSetStatus(ref.obj.attr('checked')); }; /** * Get the current slider status by checking it's position */ //ref.sliderGetStatus = function() { // var dir = (ref.direction == 'vertical') ? 'top' : 'left'; // return (parseInt(ref.slider.css(dir)) == 0); //}; /** * Sets the slider's position * If the status has been changed, the callback function is triggered * * @param on Boolean TRUE if the slider should be toggled to the 'on' position, FALSE if the slider has to be toogled to the 'off' position. */ ref.sliderSetStatus = function(on) { // Set the position, depending on the direction if(ref.direction == 'vertical') { ref.slider.css('top', (on) ? ref.container_height - ref.slider_height : 0); } else { ref.slider.css('left', (on) ? ref.container_width - ref.slider_width : 0); }; // Check wether the status has been changed // Then trigger the 'on change' callback function, if one is specified, and toggle the classes of the slider container if((ref.slider_last_status !== ref.slider_status) && ref.change) { ref.slider_container.toggleClass('on').toggleClass('off'); ref['change'](on, ref.obj); }; // Update the checkbox value ref.updateCheckbox(on); // Update the slider status ref.slider_status = on; }; /** * Updates the sliders position after mousemovement */ ref.updatePosition = function(e) { var pos = ref.getMousePos(e); if(ref.direction == 'vertical') { var y = (ref.last_slider_pos.y + (pos.y - ref.last_mouse_pos.y)); var max_y = (ref.container_height - ref.slider_height); if(y >= max_y) y = max_y; if(y <= 0) y = 0; ref.slider.css("top", y); } else { var x = (ref.last_slider_pos.x + (pos.x - ref.last_mouse_pos.x)); var max_x = (ref.container_width - ref.slider_width); if(x >= max_x) x = max_x; if(x <= 0) x = 0; ref.slider.css("left", x); }; }; /** * If the button is released, the slider will move to the nearest side of the bounding box */ ref.getNearestStatus = function(e) { var pos = ref.getMousePos(e); var container_offset = ref.slider_container.offset(); if(ref.direction == 'vertical') { return ((pos.y - container_offset.top) > (ref.container_height / 2)); } else { return ((pos.x - container_offset.left) > (ref.container_width / 2)); }; }; /** * */ ref.getMousePos = function(e) { var x = 0; var y = 0; if (!e) var e = window.event; if (e.pageX || e.pageY) { posx = e.pageX; posy = e.pageY; } else if (e.clientX || e.clientY) { posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; }; return { 'x': posx, 'y': posy }; }; ref.init(); return ref.slider_container; }; })(jQuery);