/** * Js Framework for my.haodf.com * @author enigma * @date 2010.05.07 * @version 1.0.1.3 * * history: * 2010.05.07 增加气泡框大小变化时, 可调整位置的方法 * 增加固定气泡位置的功能(如右下角不动), IE无效 * 2010.04.28 修复bubble全局弹出初始位置不正确. * 增加绿色bubble. * 改进bubble resize, scroll事件处理机制. 改为只有弹出bubble时才会触发. * 2010.04.24 增加mask效果, bubble modal功能. * 2010.04.23 解决气泡手动弹出与气泡队列自动弹出的冲突. * 2010.04.22 initial release. * * current modules: * hdf: cookie * hdf_ui: ajaxMsg, mask * $().bubble * bubble_queue * $.cross_domain_ajax * $().defaultText */ if (typeof(hdf) == "undefined") { //page load functions $(function() { // add submit button mouse events $("input[type=submit],input[type=button]").addClass("my_submit_button").mouseover(function(){$(this).addClass("my_submit_button_mouseover");}).mouseout(function(){$(this).removeClass('my_submit_button_mouseover');}); /* 在haodf.com范围内设置任何AJAX请求都不缓存, 以避免出现页面不更新的情况 */ $.ajaxSetup({cache: false}); }); hdf = { version: '1.0.1.2', /* cookie */ cookie_default_domain: { domain:'haodf.com', path:'/'}, set_cookie: function(name, value, expires, path, domain, secure) { var cookie_string = name + "=" + encodeURI(value); if (expires) { now = new Date(); now.setTime(now.getTime() + expires * 1000); cookie_string += "; expires=" + now.toGMTString(); } if (!path || !domain) { path = this.cookie_default_domain.path; domain = this.cookie_default_domain.domain; } cookie_string += "; path=" + encodeURI(path) + "; domain=" + escape(domain); if (secure) cookie_string += "; secure"; document.cookie = cookie_string; return true; }, get_cookie: function(name) { if (typeof(name) != 'string') return null; name = name.replace('[', '\\[').replace(']', '\\]'); var results = document.cookie.match ('(^|; )' + name + '=([^;]*)(;|$)'); return results ? results[2] : null; }, del_cookie: function(name) { if (this.get_cookie(name) != null) this.set_cookie(name, null, -86400); return true; } }; hdf_ui = { /* msg */ ajaxMsg: function(url, option) { if (!option) option = {}; /* id */ if (option.id && option.id[0] == '#') option.id = option.id.substr(1, option.id.length - 1); if ($(option.id).size() == 0) option.id = false; if (!option.id) option.id = 'hdf_ajax_msg_' + Math.floor(Math.random()*100000000); if ($('#' + option.id).size() == 0) { $(document.body).append('
'); } dialog_option = { autoOpen: false, open: function() { $('#' + option.id).load(url); } }; if (option.width) dialog_option.width = option.width; if (option.height) dialog_option.height = option.height; $('#' + option.id).dialog(dialog_option); $('#' + option.id).dialog('open'); }, /* mask for modal dialog */ mask: { opacity: 0.2, duration: 500, layers: {}, count: 0, /* 根据窗口尺寸调整mask尺寸 */ refreshSize: function() { var h = $(document).height(); var wh = $(window).height(); if (wh > h) h = wh; var w = $(document).width(); var ww = $(window).width(); if (ww > w) w = ww; mh = $('#hdf_ui_mask').height(); mw = $('#hdf_ui_mask').width(); if (mh != h) $('#hdf_ui_mask').height(h); if (mw != w) $('#hdf_ui_mask').width(w); }, /* 显示mask */ show: function(option) { if (!option) option = {}; var skip = $.isEmptyObject(this.layers) ? false : true; if (typeof(option.id) == 'undefined') { option.id = 'id' + this.count; this.count++; } this.layers[option.id] = 1; if (skip) return; $(window).bind('resize scroll', this.refreshSize); if (option.duration == undefined) option.duration = this.duration; if (option.opacity == undefined) option.opacity = this.opacity; if ($('#hdf_ui_mask').size() == 0) $(document.body).prepend(''); this.refreshSize(); $('#hdf_ui_mask').stop().fadeTo(0,0).fadeTo(option.duration, option.opacity); }, /* 隐藏mask */ hide: function(option) { if (!option) option = {}; if (typeof(option.id) == 'undefined') { this.count--; option.id = 'id' + this.count; } delete this.layers[option.id]; if (!$.isEmptyObject(this.layers)) return; if (option.duration == undefined) option.duration = this.duration; $('#hdf_ui_mask').fadeOut(option.duration); $(window).unbind('resize scroll', this.refreshSize); }, /* 将对象浮于mask上 */ raise: function(obj, level) { if (!level) level = 0; $(obj).attr('defaultzindex', $(obj).css('z-index')); $(obj).attr('raised', 1); $(obj).css('z-index', 9999 + parseInt(level)); }, /* 复原对象(沉到mask下) */ sink: function(obj) { if ($(obj).attr('raised')) { $(obj).attr('raised', null); zindex = $(obj).attr('defaultzindex'); if (!zindex) zindex = 1; $(obj).css('z-index', zindex); } } } }; $.extend({ getUrlDomain: function(url) { /* pure domain, return */ if (url.match(/^[a-zA-Z\.\-]+$/)) return url; match = url.match(/^https?:\/\/([a-zA-Z\.]+)/); return (match && match.length > 1) ? match[1] : ''; }, isCrossDomain: function(target_domain, site_domain) { if (!site_domain) site_domain = document.domain; domain = this.getUrlDomain(target_domain); return true; return (domain != site_domain); }, cross_domain_ajax: function(option) { /* add crossdomain function for jquery ajax */ if (this.isCrossDomain(this.getUrlDomain(option.url))) { option.dataType = 'jsonp'; } this.ajax(option); } }); $.fn.extend({ /* 用于输入框缺省文字显示,比如"请输入疾病名称"之类的. 选中以后恢复正常 */ defaultText: function(text, option) { if (!text) return; $(this).attr('defaultText', text); $(this).focus(function() { if ($(this).val() == $(this).attr('defaultText')) { $(this).val('').css('color', (typeof(option) == 'object' && typeof(option.focusColor) == 'string') ? option.focusColor : 'black'); } }).blur(function() { if ($(this).val() == ''|| $(this).val() == $(this).attr('defaultText')) { $(this).val($(this).attr('defaultText')).css('color', (typeof(option) == 'object' && typeof(option.color) == 'string') ? option.color : '#999'); } }); if ($(this).val() == text || !$(this).val()) $(this).blur(); }, realText: function() { if ($(this).val() == $(this).attr('defaultText')) $(this).val(''); } }); $(function() { $(':text,textarea').each(function() { var txt = $(this).attr('defaultText'); if (txt) $(this).defaultText(txt); }); $('form').submit(function() {$(this).children(':text,textarea').realText();}); }); /* bubble */ hdf_bubble_msg = { option: { anchor_id : 'logo', width : 350, max_width : 500, position : 'fixed', //fixed, float, 仅用于全局弹出 show_close : true, show_arrow : true, align : 'bottom', style : 'orange', align_autofix : true, content_margin : 5, close_timeout : 0, click_close : false, arrow_offset_x : 'center', // left offset or 'center' arrow_offset_y : 'center', // top offset or 'center' pop_callback : null, close_callback : null, content_type : 'html', modal : false }, current_config: {}, border: { blue: { path : '//i1.hdfimg.com/my/img/', margin : 0, width : 19, arrow_size : 24, arrow_offset_x: 40, arrow_offset_y: 10, font_color : '#2899BF', background : 'white', texture : 'bubble_msg_blue.png', texture_v : 'bubble_msg_blue_v.png', texture_h : 'bubble_msg_blue_h.png' }, orange: { path : '//i1.hdfimg.com/my/img/', margin : 0, width : 19, arrow_size : 24, arrow_offset_x: 40, arrow_offset_y: 10, font_color : '#efb400', background : 'white', texture : 'bubble_msg_orange.png', texture_v : 'bubble_msg_orange_v.png', texture_h : 'bubble_msg_orange_h.png' }, green: { path : '//i1.hdfimg.com/my/img/', margin : 0, width : 45, arrow_size : 62, arrow_offset_x: 40, arrow_offset_y: 10, font_color : '#2899BF', background : '#e0f6c4', texture : 'bubble_msg_green.png', texture_v : 'bubble_msg_green_v.gif', texture_h : 'bubble_msg_green_h.gif' }, green_simple: { path : '//i1.hdfimg.com/my/img/', margin : 0, width : 3, arrow_size : 0, arrow_offset_x: 0, arrow_offset_y: 0, font_color : '#000', background : '#FFF', texture : 'bubble_msg_green_simple.gif', texture_v : 'bubble_msg_green_simple.gif', texture_h : 'bubble_msg_green_simple.gif' } }, init: function() { this._preload(); }, pop: function(content, option) { if (!this.ready) { $(function() {hdf_bubble_msg.pop(content, option);}); return; } /* cancel current auto close and click_close */ this.clear_timeout(); if (!$.trim(content)) return this.close_callback({status:false}); /* 取消绑定所有事件 */ $(document).unbind('click', hdf_bubble_msg.click); $(window).unbind('scroll resize', this._fix_position); /* working config */ config = {}; for (var k in this.option) config[k] = this.option[k]; if (option == undefined) option = {}; for (var k in option) config[k] = option[k]; /* 确定是否需要重建bubble原始代码 */ var is_recreate = (typeof(this.current_config.style) == 'string' && this.current_config.style == config.style) ? false : true; /* 覆盖上一次config, 开始新pop流程 */ this.current_config = config; /* ajax content */ if (config.content_type == 'ajax') { /* check if it can process ajax request */ if (config.ajax_trigger && typeof(config.ajax_trigger) == 'function') { /* skip and end */ if (!config.ajax_trigger()) return this.close_callback({status:false}); } this.current_config.content_type = 'html'; ajax_option = { url: content, cache:false, context: this, scriptCharset:'UTF-8', success: function(data){ if (typeof(data) == 'object') { if (data.content) { content = data.content; } else { content = ''; } } else { content = data; } return this.pop(content, this.current_config); }, error: function(a,b,c) { }}; return $.cross_domain_ajax(ajax_option); //continue to ajax request } if (this.border[config.style] == undefined) config.style = 'blue'; border = this.border[config.style]; if (config.width < border.arrow_size + border.width * 2) config.width = border.arrow_size + border.width * 2; if (config.width > config.max_width) config.width = config.max_width; if (typeof(config.anchor_id) == 'string' && config.anchor_id[0] != '#') config.anchor_id = '#' + config.anchor_id; anchor = $(config.anchor_id); anchor_offset = anchor.offset(); if (!anchor_offset) { /* 如果找不到定位点, 则只允许align为center, bottom-right, 缺省为bottom-right, (bottom-right对应align为top-left) */ anchor_offset = this._calc_fixed_anchor_offset(); config.anchor_id = "#hdf_bubble_msg_null_id", config.show_arrow = false; anchor = $('#hdf_bubble_msg_null_id'); } /* check and prepare msg board */ if (is_recreate && $('#bubble_msg').size() > 0) $('#bubble_msg').empty().attr('id', ''); if ($('#bubble_msg').size() == 0) { msg_html = $(''); /* msg board top */ msg_block = $(''); msg_block.append(''); msg_block.append($('').append('')); msg_block.append(''); msg_html.append(msg_block); /* msg board body */ msg_block = $(''); msg_block.append(''); msg_block.append($('').append($('').append($('').append(''))).append('')); msg_html.append(msg_block); /* msg board bottom */ msg_block = $(''); msg_block.append(''); msg_block.append($('').append('')); msg_block.append(''); msg_html.append(msg_block); $(document.body).append(msg_html); msg_html = null; msg_block = null; $('#bubble_msg_body').mouseover(function(){hdf_bubble_msg.mouseover();}).mouseout(function(){hdf_bubble_msg.mouseout();}); } if (config.show_close) { $('#bubble_msg_close').show(); $('#bubble_msg_content').css('margin-top', (config.content_margin - 14 > 2 ? config.content_margin - 14 : 2)); } else $('#bubble_msg_close').hide(); /* prepare dimension */ $('#bubble_msg' ).hide(); $('#bubble_msg' ).css('width', config.width); $('#bubble_msg_top' ).css('width', config.width - border.width * 2); $('#bubble_msg_bottom').css('width', config.width - border.width * 2); $('#bubble_msg_left' ).css('width', config.width); $('#bubble_msg_right' ).css('width', config.width - border.width); $('#bubble_msg_body' ).css('width', config.width - border.width * 2); /* prepare position according to align */ $('#bubble_msg_arrow_top' ).hide(); $('#bubble_msg_arrow_left' ).hide(); $('#bubble_msg_arrow_right' ).hide(); $('#bubble_msg_arrow_bottom').hide(); /* 计算出显示位置前, 先填充内容 */ $('#bubble_msg_content').html(content); config.height = 0; /* 位置原始数据已准备好, config.width, config.height, anchor_offset.left, anchor_offset.top, anchor.height(), anchor.width() */ var top_confirmed = false; var msg_poped = false; /* left 始终能正确计算, 只需要定位top即可, arrow_x,y在top确认以后即同时确定, 不需要判断 */ while (!top_confirmed) { var calc_top = 'null'; var calc_left = 'null'; var calc_arrow_x = 0; var calc_arrow_y = 0; /* 计算 arrow_x, arrow_y */ if (config.show_arrow) { calc_arrow_x = (config.width - border.width * 2 - border.arrow_size) / 2; if (calc_arrow_x > border.arrow_offset_x) calc_arrow_x = border.arrow_offset_x; calc_arrow_y = (config.height - border.width * 2 - border.arrow_size) / 2; if (calc_arrow_y > border.arrow_offset_y) calc_arrow_y = border.arrow_offset_y; } if (config.align.indexOf('top') >= 0) { /* 处理居上时的top值 */ calc_top = anchor_offset.top - config.height - border.margin; if (config.height > 0) top_confirmed = true; } if (config.align.indexOf('bottom') >= 0) { /* 处理居下时的top值 */ calc_top = anchor_offset.top + anchor.height() + border.margin; top_confirmed = true; } if (config.align.indexOf('left') >= 0) { /* 处理居左时的left值 */ calc_left = anchor_offset.left - config.width - border.margin; } if (config.align.indexOf('right') >= 0) { /* 处理居上时的left值 */ calc_left = anchor_offset.left + anchor.width() + border.margin; } if (config.align == 'center') { calc_left = anchor_offset.left + anchor.width() / 2 - config.width / 2; if (config.height > 0) { cacl_top = anchor_offset.top + anchor.height() / 2 - config.height / 2; top_confirmed = true; } } /* 当algin=left, right时 */ if (calc_top == 'null') { if (config.height > 0) { calc_top = anchor_offset.top - border.arrow_size / 2 - calc_arrow_y - border.width + ((config.arrow_offset_y == 'center') ? anchor.height() / 2 : config.arrow_offset_y); top_confirmed = true; } } /* 当align=top,bottom时 */ if (calc_left == 'null') { calc_left = anchor_offset.left - border.arrow_size / 2 - calc_arrow_x - border.width + ((config.arrow_offset_x == 'center') ? anchor.width() / 2 : config.arrow_offset_x); } /* 只有上, 下显示时才能移动left, 否则统一重新调整到bottom */ if (calc_left < 0 && config.align_autofix && (config.align == 'top' || config.align == 'bottom')) { calc_arrow_x += calc_left; /* 注意是加, calc_left为负数 */ if (calc_arrow_x < 0) calc_arrow_x = 0; calc_left = 0; } /* final judgement */ /* 因为left始终都能确认, 所以先判断left是否正常显示 */ if (calc_left < 0 && confirm.align != 'bottom' && config.align_autofix) { config.align = 'bottom'; top_confirmed = false; continue; } if (top_confirmed) { if ((calc_top < 0) && (config.align != 'bottom') && (config.align_autofix)) { config.align = 'bottom'; top_confirmed = false; } } else { if (!msg_poped) { $('#bubble_msg').css('left', calc_left).stop().show(); config.height = $('#bubble_msg_body').height() + border.width * 2; msg_poped = true; } else { /* what happened? */ alert('消息无法正确定位'); top_confirmed = true; //cancel operation } } } /* 位置数据已准备好, calc_left, calc_top, calc_arrow_x calc_arrow_y */ config.left = calc_left; config.top = calc_top; /* 显示箭头 */ if (config.show_arrow) { if (config.align == 'top' || config.align == 'bottom') $('#bubble_msg_arrow_'+config.align).css('margin-left', calc_arrow_x).show(); if (config.align == 'left' || config.align == 'right' ) $('#bubble_msg_arrow_'+config.align).css('margin-top', calc_arrow_y).show(); } /* 在最终正确位置上显示 */ if (this.current_config.modal) { hdf_ui.mask.show(); hdf_ui.mask.raise('#bubble_msg'); } $('#bubble_msg').css('top', config.top).css('left', config.left).stop().show(); /* 修正内容高度小于箭头宽度的问题 */ if ((config.align == 'left' || config.align == 'right') && $('#bubble_msg_body').height() < border.arrow_size) { $('#bubble_msg_body').height(border.arrow_size); config.height = $('#bubble_msg').height(); } this.visible = true; /* 执行pop callback */ if (typeof(config.pop_callback) == 'function') config.pop_callback(); /* 开启close_timeout */ this.set_timeout(); /* 0.5秒后绑定鼠标点击事件 */ setTimeout(function() { $(document).click($.proxy(hdf_bubble_msg.click, hdf_bubble_msg)) }, 500); /* 绑定窗口变化事件 */ $(window).bind('scroll resize', $.proxy(this._fix_position, this)); /* 执行一次, 防止窗口初始化时已经有滚动 */ this._fix_position({immediately:true}); return true; }, content: function(html_code) { $('#bubble_msg_content').html(html_code); }, close: function(option) { /* 清除定时关闭 */ this.clear_timeout(); /* 取消绑定鼠标点击事件 */ $(document).unbind('click', hdf_bubble_msg.click); /* 取消绑定窗口变化事件 */ $(window).unbind('scroll resize', this._fix_position); if (!option) option = {}; if ($('#bubble_msg').css('display') && $('#bubble_msg').css('display') != 'none') { if (!option.immediately) { if (this.current_config.modal) { $('#bubble_msg').slideUp(function() {hdf_ui.mask.hide(); hdf_ui.mask.sink('#bubble_msg');}); } else { $('#bubble_msg').slideUp(); } } else { $('#bubble_msg').hide(); if (this.current_config.modal) { hdf_ui.mask.hide(); hdf_ui.mask.sink('#bubble_msg'); } } this.visible = false; if (!option.status) option.status = true; this.close_callback(option); } }, close_callback: function(option) { if (this.current_config != undefined && typeof(this.current_config.close_callback) == 'function') { this.current_config.close_callback(option); } }, config: function(option) { if (typeof(option) != 'object') return; for(var k in option) { this.option[k] = option[k]; } }, set_timeout: function() { if (this.current_config.close_timeout > 0) { this.timeout_handle = setTimeout($.proxy(this.close, this), this.current_config.close_timeout); } }, clear_timeout: function() { if (this.timeout_handle) clearTimeout(this.timeout_handle); this.timeout_handle = null; }, mouseover: function() { this.clear_timeout(); this.mouse_inside = true; }, mouseout: function() { this.set_timeout(); this.mouse_inside = false; }, click: function() { if (this.current_config == undefined || this.current_config.click_close == undefined) return; rule = this.current_config.click_close; if (this.mouse_inside) { if (rule == 'all' || rule == 'both' || rule == true || (typeof(rule) == 'string' && rule.indexOf('inside') >= 0)) this.close(); } else { if (rule == 'all' || rule == 'both' || rule == true || (typeof(rule) == 'string' && rule.indexOf('outside') >= 0)) this.close(); } }, reposition: function() { h = this.current_config.height; w = this.current_config.width; ah = $('#bubble_msg').height(); aw = $('#bubble_msg').width(); if (h != ah) { this.current_config.height = ah; if (this.current_config.align.indexOf('top') >= 0) this.current_config.top += (h - ah); } if (w != aw) { this.current_config.width = aw; if (this.current_config.align.indexOf('left') >= 0) this.current_config.left += (w - aw); } this._fix_position(); }, _fix_position: function(option) { /* 窗口未改变大小, 不需要重新定位 */ if (this._is_global_pop()) { if ((typeof(option) == 'object' && typeof(option.immediately) != 'undefined') || this.current_config.position == 'fixed') { if ($.browser.msie && $.browser.version.indexOf('6') == 0) { var offsetTop = this.current_config.top + $(window).scrollTop(); var offsetLeft = this.current_config.left + $(window).scrollLeft(); $("#bubble_msg").css({top: offsetTop, left:offsetLeft }); } else { if (config.align == 'top-left') { $('#bubble_msg').css({left:'', top:'', bottom:'0px', right:'0px', position:'fixed'}); } else { $('#bubble_msg').css({left:'', top:'', bottom:$(window).height() * 0.62 - this.current_config.height, right:($(window).width() - this.current_config.width) / 2, position:'fixed'}); } } } else { var offsetTop = this.current_config.top + $(window).scrollTop(); var offsetLeft = this.current_config.left + $(window).scrollLeft(); $("#bubble_msg").animate({top : offsetTop, left:offsetLeft },{ duration:600 , queue:false }); } } }, _calc_fixed_anchor_offset: function() { if (this.current_config.align == 'center') { /* 屏幕中心, 垂直黄金点 */ anchor_offset = {left: $(window).width() / 2, top:$(window).height() * 0.38}; } else { /* 屏幕右下角 */ this.current_config.align = 'top-left'; anchor_offset = {left: $(window).width(), top:$(window).height()}; } return anchor_offset; }, _is_global_pop: function() { return typeof(this.current_config.anchor_id) == 'string' && this.current_config.anchor_id == '#hdf_bubble_msg_null_id'; }, _preload: function() { /* preload border images */ for(var border in this.border) { for(var k in this.border[border]) { if (typeof(this.border[border][k]) == 'string' && k.indexOf('texture') == 0) { /* fix ie 6 png problem, use gif instead */ if ($.browser.msie && $.browser.version.indexOf('6') == 0) { this.border[border][k] = this.border[border][k].replace('.png', '.gif'); } $("").attr("src", this.border[border].path + this.border[border][k]); } } } }, /* working variables */ visible: false, ready:false }; $(function() {hdf_bubble_msg.ready = true;}); $.fn.extend({ bubble: function(content, option) { if (typeof(content) == 'object') { if (typeof(content.config) != 'undefined') { hdf_bubble_msg.config(content.config); } if (typeof(content.call) != 'undefined' && typeof(hdf_bubble_msg[content.call]) == 'function') { hdf_bubble_msg[content.call](); } return this; } if (typeof(option) != 'object') option = {}; option.anchor_id = this; hdf_bubble_msg.pop(content, option); return this; }, bubble_content: function(html) { hdf_bubble_msg.content(html); return this; }, bubble_close: function(time, callback) { hdf_bubble_msg.close(time, callback); return this; }, bubble_tooltip: function(content, option) { $(this).mouseover(function() {$(this).bubble(content, option);}); if (option.close_timeout == undefined || option.close_timeout == 0) { option.close_timeout = 0; option.show_close = false; $(this).mouseout(function() {$(this).bubble_close(true);}); } }, bubble_focus: function(content, option) { option.close_timeout = 0; $(this).focus(function() {$(this).bubble(content, option);}).blur(function() {$(this).bubble_close(true);}); }, bubble_click: function(content, option) { option.close_timeout = 0; option.show_close = true; $(this).click(function() {$(this).bubble(content, option);}); }, bubble_visible: function() { return hdf_bubble_msg.visible; } }); hdf_bubble_msg.init(); /* bubble queue ------------------------------------------------------------ */ /* * register参数格式: * emergency: 紧急程度 0-9 * anchor: 弹出元素位置, ID * content: 弹出内容 * option: 弹出层参数 * callback: 当被选中时的回调函数 */ hdf_bubble_queue = { /* working variables */ requests : [], first_bubble_time : 1000, follow_bubble_time: 5000, timer_handle : null, enable : true, bubble_limit : 0, //unlimit bubble_count : 0, //unlimit /* functions */ register : function(req) { if (!req || !req.emergency || !req.content) return; /* 查找是否有同样的请求, 如果有则忽略 */ for(var i = 0; i < this.requests.length; i++) { if (req.content == this.requests[i].content) { return this; } } this.requests[this.requests.length] = req; return this; }, process : function() { if (!this.enable) return this; /* 如果bubble在弹出状态(可能是手动弹出的原因等), 则等待下一次再弹出 */ if ($(document).bubble_visible()) { this.start(this.follow_bubble_time); return this; } this.clearTimer(); /* sort */ for (var i=0; i