/*! * FireHint plugin for jQuery * https://github.com/nikolay-zakharov/jquery-fireHint * * Copyright 2012, Nikolay Zakharov * Date: Thu June 28 21:44:17 2012 +0400 */ (function($) { $.fn.fireHint = function(custom_config) { // Default configuration var default_config = { elements: { header: [],// DOM elements list that will be placed inside `strong.firehint-header` element of the hint body: []// DOM elements list that will be placed inside `div.firehint-content-body` element of the hint }, timeouts: { hide: 5000,// Hint will disapper after (ms) slide: 300,// Hint will get animation for (ms) fade: 70// Hint will disappear during (ms) /starts animation is finished/ }, rows: { count: 2, position: 'bl',// `tr` means Top-Right. Also available: `tl` (top-left), `br` (bottom-right), `bl` (bottom-left) minTop: 20,// Vertical limits of set of hints maxTop: 20// Vertical limits of set of hints }, cells: { margins: {// Gap between hints vertical: 30,// ...vertical horizontal: 20// ,.,horizontal }, width: 352 }, additionalClasses: { '.firehint-msg-box': [],// You can assign custom css classes for messagebox '.firehint-header': [],// ...or just header '.firehint-content-body': []// ...or just content body }, bindings: {// Here you can configure custom events. Object mask as a Key and object as a Value. // This object (Value) has event name as a Key and `function(Event){...}` as a Value. // You are able to bind any behaviour to any DOM Object inside main message-box (`.firehint-msg-box`) or to its own '.firehint-msg-box': { selectstart: function(evt){ evt.preventDefault(); }, mouseenter: function(evt){ $(evt.target).animate(config.css_states.hover, config.timeouts.fade); }, mouseleave: function(evt){ $(evt.target).animate(config.css_states.general, config.timeouts.fade); } }, '.firehint-infadable': { mouseenter: function(evt){ $(evt.target).parents('.firehint-msg-box:first').trigger('mouseleave'); }, mouseleave: function(evt){ $(evt.target).parents('.firehint-msg-box:first').trigger('mouseenter'); } } }, css_states: { general: { opacity: 0.85 }, hover: { opacity: 1 } } }; var config = $.extend(true, null, default_config, custom_config); // Running plugin return this.each(function(ind, msg_box_blank_element){ var msg_box_unique_id = (new Date()).getTime()+'_'+(Math.round(Math.random()*8999-(-1000))); var msg_box_element = $(msg_box_blank_element).clone().appendTo(document.body).data('uid', msg_box_unique_id); // Setting timeout for message box to hide var current_box_interval = window.setTimeout(function(){ var current_message_box_height = $(msg_box_element).height(); // Tells about freed space document.fireHint.rows[row_ind].free -= -(config.cells.margins.vertical - (- current_message_box_height)); document.fireHint.rows[row_ind].occupied -= (current_message_box_height - (- config.cells.margins.vertical)); document.fireHint.rows[$(msg_box_element).data('row_index')].message_boxes[msg_box_unique_id] = undefined; // Slide top (or bottom) other message boxes inside current row if(typeof config.timeouts.slide == 'number' && config.timeouts.slide > 0){ for(var uid in document.fireHint.rows[$(msg_box_element).data('row_index')].message_boxes){ var some_message_box = document.fireHint.rows[$(msg_box_element).data('row_index')].message_boxes[uid]; if(typeof some_message_box != 'undefined'){ some_message_box.animate({ top: $(some_message_box).position().top + (config.cells.margins.vertical - (- current_message_box_height)) }, config.timeouts.slide); } } } $(msg_box_element).fadeOut().remove(); }, config.timeouts.hide); // Technical data, being used by timeout callback function if(typeof document.fireHint == 'undefined'){ document.fireHint = { active_timeouts: {}, rows: {} }; } if(typeof document.fireHint.active_timeouts[msg_box_unique_id] != 'undefined'){ window.clearTimeout(document.fireHint.active_timeouts[msg_box_unique_id]); document.fireHint.active_timeouts[msg_box_unique_id] = undefined; } document.fireHint.active_timeouts[msg_box_unique_id] = current_box_interval; // Technical data, being used on looking for place for a message boxes for(var row_ind=1; row_ind<=config.rows.count; row_ind++){ if(typeof document.fireHint.rows[row_ind] == 'undefined'){ document.fireHint.rows[row_ind] = { free: $(window).height() - config.rows.minTop, occupied: 0, message_boxes: {} }; } } // Applies additional classes and appends header and body elements $.each(config.elements.header, function(header_ind, header_item){ $('.firehint-header', msg_box_element).append(header_item); }); $.each(config.elements.body, function(body_ind, body_item){ $('.firehint-content-body', msg_box_element).append(body_item); }); $.each(config.additionalClasses, function(element_mask, classes_list){ $(msg_box_element) .filter(element_mask).addClass( classes_list.join(' ')).end() .find(element_mask).addClass( classes_list.join(' ') ); }); // Applying general style for a message box $(msg_box_element).css(config.css_states.general) // Binding callbacks $.each(config.bindings, function(element_mask, bindings_list){ $.each(bindings_list, function(event_name, callback_func){ $(msg_box_element) .filter(element_mask).bind(event_name, callback_func).end() .find(element_mask).bind(event_name, callback_func); }); }); // Looking for a place for current message box var current_message_box_height = $(msg_box_element).height(); for(var row_ind=1; row_ind<=config.rows.count; row_ind++){ if(document.fireHint.rows[row_ind].free >= current_message_box_height - (- config.cells.margins.vertical)){ $(msg_box_element).data('row_index', row_ind); $(msg_box_element).css({ //top: ($(window).height() - config.cells.margins.vertical - current_message_box_height - 30 - document.fireHint.rows[row_ind].occupied) +'px', top: ($(window).height() - config.cells.margins.vertical - current_message_box_height - 30 - document.fireHint.rows[row_ind].occupied) +'px', left: ((row_ind)*config.cells.width - config.cells.width + 10) +'px' }).show(); document.fireHint.rows[row_ind].free -= current_message_box_height - (- config.cells.margins.vertical); document.fireHint.rows[row_ind].occupied -= - config.cells.margins.vertical - current_message_box_height; document.fireHint.rows[row_ind].message_boxes[msg_box_unique_id] = msg_box_element; break; } } if($(msg_box_element).filter(':visible').length == 0){ console.log('NO_SPACE_FOR_A_MESSAGE_BOX') } }); } })(jQuery);