/**+--------------------------------------------------------------------+|CivicCRM版本4.2|+--------------------------------------------------------------------+|版权所有CiviCRM LLC(c)2004-2012|+--------------------------------------------------------------------+|此文件是CiviCRM的一部分|| ||CiviCRM是自由软件;您可以复制、修改和分发它||根据GNU事务通用公共许可证的条款||2007年11月19日第3版和CiviCRM许可例外|| ||CiviCRM的发布是希望它会有用,但||无任何担保;甚至没有||适销性或特定用途的适用性||有关更多详细信息,请参阅GNU事务通用公共许可证|| ||你应该收到一份GNU Affero General Public的副本||许可证和CiviCRM许可例外||使用此程序;如果没有,请联系CiviCRM LLC||请访问info[at]civicrm[DOT]org。如果您对||GNU Affero通用公共许可证或CiviCRM许可证||请参阅CiviCRM许可证常见问题解答,网址为http://civicrm.org/licensing网站 |+--------------------------------------------------------------------+**版权所有(C)2009 Bevan Rudge*根据学术免费许可证版本3.0授权给CiviCRM。**@file定义jQuery.dashboard()插件。**使用jQuery 1.3、jQuery UI1.6和几个jQuery UI扩展,大多数是Sortable* http://visualjquery.com/* http://docs.jquery.com/UI/Sortable* http://ui.jquery.com/download(下载)*可排序*可拖动*UI核心**/(函数($){//创建闭包。//仪表板对象的构造函数。$.fn.dashboard=功能(选项){//仪表板的公共属性。var仪表板={};dashboard.element=this.empty();仪表板就绪=假;dashboard.columns=数组();dashboard.widgets=阵列();//仪表板的公共属性结束。/***仪表板的公共方法。*///将所有列(包括widget.minimized状态)的小部件顺序保存到options.ajaxCallbacks.saveColumns。dashboard.saveColumns=函数(){//更新空占位符的显示状态。for(dashboard.columns中的var c){var col=仪表板列[c];if(col类型==“对象”){//该列是否有任何可见的子级(不包括空占位符)?if(col.element.children(':visible)).not(col.emptyPlaceholder).length>0){col.emptyPlaceholder.hide();}其他{col.empty占位符.show();}}}//除非仪表板完成初始化,否则不要保存对服务器的任何更改。if(!dashboard.ready){回报;}//构建要发布到服务器的参数列表。var参数={};//对于每一列。。。for(dashboard.coluns中的varc){//此列中可排序元素的ID。if(typeofdashboard.coluns[c]==“object”)var ids=dashboard.coluns[c].element.sortable(“toArray”);//对于每个id。。。for(id中的var w){//把“widget-”从前面删掉,这样我们就有了真正的widget id。if(typeofids[w]=='string')var id=ids[w].substring('widget-'.length);//向params对象添加一个平面属性,该属性看起来像PHP服务器的数组元素。//不幸的是,jQuery并没有为我们做到这一点。if(typeofdashboard.widgets[id]=='object')params['columns['+c+']['+id+']']=(dashboard.widgets[id].mimized?'1':'0');}}//ajaxCallback设置会覆盖任何重复的属性。$.extend(params,opts.ajaxCallbacks.saveColumns.data);$.post(opts.ajaxCallbacks.saveColumns.url,参数,函数(响应,状态){invokeCallback(opts.callback.saveColumns,仪表板);});};//将仪表板置于全屏模式,为用户退出全屏模式时保存元素。//不向DOM添加元素–这是调用方的责任。//但会显示和隐藏元素。dashboard.enterFullscreen=函数(元素){//隐藏列。for(dashboard.coluns中的varc){if(typeofdashboard.coluns[c]==“object”)dashboors.columns[c].element.hide();}if(!dashboard.fullscreen){//初始化。var标记=''+opts.fullscreenHeaderInner+'';仪表板.fullscreen={headerElement:$(标记).prependTo(dashboard.element).click(dashboard.exitFullscreen).hide()};}dashboard.fullscreen.headerElement.slideDown();dashboard.fullscreen.currentElement=元素.show();仪表板.fullscreen.displayed=true;invokeCallback(opts.callback.interFullscreen,dashboard,dashtools.fullscreen.currentElement);};//使仪表板脱离全屏模式,隐藏活动的全屏元素。dashboard.exitFullscreen=函数(){if(!dashboard.fullscreen.displayed){回报;}dashboard.fullscreen.headerElement.slideUp();dashboard.fullscreen.currentElement.hide();仪表板.fullscreen.displayed=假;//显示列。for(dashboard.coluns中的varc){if(typeofdashboard.coluns[c]==“object”)dashboard.coluns[c].element.show();}invokeCallback(opts.callback.exitFullscreen,dashboard,dashtools.fullscreen.currentElement);};//仪表板的公共方法结束。/***仪表板的私有属性。*///用于确定是否有任何未完成的ajax请求等待仪表板的初始化。var asynchronousRequestCounter=0;//用于确定两个度假事件是否由同一UI事件产生。var currentReSortEvent=空;//将调用者的选项与默认选项合并。var opts=$.extend({},$.fn.dashboard.defaults,选项);//执行在此处“分叉”并在init()中重新启动。告诉用户我们正忙于处理一个问题。var throbber=$(opts.throberMarkup).appendTo(dashboard.element);$.getJSON(opts.ajaxCallback.getWidgetsByColumn.url,opts.ajaxCallback.setWidgets ByColumm.data,init);异步请求计数器++;返回仪表盘;//仪表板对象的构造函数和私有属性结束。/***仪表板的专用方法。*///getWidgetsByColumn的Ajax回调。函数init(小部件、状态){异步请求计数器--;throbber.remove();var标记='
  • '+opts.emptyPlaceholderInner+'
  • ';//在DOM中构建仪表板。对于每一列。。。//(不要在小部件上迭代,因为如果数据集有空列,这将严重破坏。)var emptyDashboard=true;for(var c=0;c<opts.columns;c++){//将该列保存到公共范围以实现外部可访问性,将其保存到本地范围以实现可读性。var col=仪表板.列[c]={initialWidgets:Array(),元素:$('').appendTo(dashboard.element)};//现在添加空占位符,将其隐藏并保存。col.emptyPlaceholder=$(标记).appendTo(col.element).hide();//对于此列中的每个小部件。for(小部件中的var-id[c]){var widgetID=id.split('-');//构建一个新的小部件对象并将其保存到各种公共访问位置。col.initialWidgets[id]=仪表板.widgets[widgetID[1]]=小部件({id:小部件id[1],元素:$('
  • ').appendTo(col.element),initialColumn:列,最小化:(小部件[c][widgetID[1]]>0?true:false)});//将空仪表板设置为falseemptyDashboard=false;}}if(空仪表板){空仪表板状态();}invokeCallback(opts.callback.init,仪表板);}//当仪表板为空时调用的函数函数为空仪表板条件(){cj(“.show-refresh”).hide();cj(“空消息”).show();}//初始化完成后,每个小部件的构造函数都会调用此函数,以便仪表板可以完成初始化。函数completeInit(){//如果有任何小部件正在等待ajax请求完成以完成初始化,请不要执行任何操作。if(异步请求计数器>0){回报;}//使小部件可以跨列排序。仪表板.sortableElement=$('.column').sortable({连接方式:[“.列”],//可拖动小部件的元素的类。handle:“.widget头”,//占位符元素的类(“ghost”小部件显示如果现在释放,拖动的项目将到达的位置。)placeholder:'占位符',激活:函数(事件,ui){var h=cj(ui.item).height();$('.placeholder').css('height',h+'px');},不透明度:0.2,//Maks确保只有小部件是可排序的,而不是空占位符。项目:“>.widget”,forcePlaceholderSize:true,//回调函数。更新:已重置,开始:hideEmptyPlaceholders});//更新空占位符。dashboard.saveColumns();dashboard.ready=true;invokeCallback(opts.callback.ready,dashboard);}//当任何列表发生更改(并且用户已完成重新排序)时进行回调。重新调用的函数(e,ui){//只有当我们还没有根据这个UI DOM事件的更改处理度假村时,才可以做任何事情。//(当项目从一个列表移动到另一个列表时,对每个列表调用resorted()一次。)if(!currentReSortEvent||e.originalEvent!=当前ReSort事件){currentReSortEvent=e.originalEvent;dashboard.saveColumns();}}//当用户开始重新调用列表时的回调。隐藏所有空占位符。函数hideEmptyPlaceholders(e,ui){for(dashboard.coluns中的varc){if(typeofdashboard.coluns[c]==“object”)dashboard.coluns[c].emptyPlaceholder.hide();}}//@todo使用事件库注册、绑定和调用事件。//@param回调是一个函数。//@param the这是该函数执行时给定的上下文。它在该函数中变为“this”。函数invokeCallback(回调,This,parameterOne){if(回调){callback.call(The This,parameterOne);}}/***小部件对象*仪表板专用子类*构造函数启动*/功能小部件(小部件){//将默认选项与为此小部件定义的选项合并。小部件=$.extend({},$.fn.dashboard.widget.defaults,小部件);/***小部件的公共方法。*///切换minimaze()和maximize()方法。widget.toggleMinimize=函数(){if(小部件最小化){widget.maximize();}其他{widget.minimize();}widget.hideSettings();dashboard.saveColumns();};widget.minimize=函数(){$('.widget-content',widget.element).slideUp(opts.animationSpeed);$(widget.controls.minimize.element).addClass('maximize-icon');$(widget.controles.minimize.element).removeClass(“最小化图标”);widget.minimized=true;};widget.maximize=函数(){$('.widget-content',widget.element).slideDown(opts.animationSpeed);$(widget.controls.minimize.element).removeClass('maximize-icon');$(widget.controls.minimize.element).addClass('minimize-icon');widget.minimized=错误;};//切换小部件是否处于设置显示模式。widget.toggleSettings=函数(){if(widget.settings.displayed){//小工具总是将设置退出到最大化状态。widget.maximize();widget.hideSettings();invokeCallback(opts.widgetCallback.hideSettings,小部件);}其他{widget.minimize();widget.showSettings();invokeCallback(opts.widgetCallback.showSettings,小部件);}};widget.showSettings=函数(){if(widget.settings.element){widget.settings.element.show();//设置通过AJAX加载。只有在加载设置后才执行脚本。if(widget.settings.ready){getJavascript(widget.settings.script);}}其他{//设置尚未初始化。现在就这样做。initSettings();}widget.settings.displayed=true;};widget.hideSettings=函数(){if(widget.settings.element){widget.settings.element.hide();}widget.settings.displayed=false;};widget.saveSettings=函数(){//构建参数列表以POST到服务器。var参数={};//serializeArray()返回对象数组。处理它。var fields=widget.settings.element.serializeArray();for(字段中的变量i){var字段=字段[i];//将值放入PHP将解析到数组服务器端的平面对象属性中。//(不幸的是,jQuery没有这样做)params['settings['+field.name+']']=field.value;}//这里的事情变得一团糟。//@todo重构以使用currentState和targetedState属性来确定需要什么//以在任何UI或AJAX事件上达到任何所需的状态–因为这些并不总是//匹配。//例如,当用户在Ajax事件处理程序之前从以前的//调用UI事件。//首先隐藏设置。widget.toggleSettings();//保存真实的设置元素,以便稍后恢复引用。var settingsElement=小部件.settings.element;//清空设置表单。widget.settings.innerElement.empty();initThrobber();//这样,showSettings()和hideSettings(。widget.settings.element=小部件.throber.hide();widget.settings.ready=假;//将设置保存到服务器。$.extend(参数,opts.ajaxCallback.widgetSettings.data,{id:widget.id});$.post(opts.ajaxCallbacks.widgetSettings.url,参数,函数(响应,状态){//将响应合并到小部件设置中。$.extend(小部件设置,响应);//恢复对真实设置元素的引用。widget.settings.element=设置元素;//确保设置表单为空,并添加更新的设置表单。widget.settings.innerElement.empty().append(widget.settings.markup);widget.settings.ready=true;//在我们重新加载设置表单之前,用户是否已经跳回设置显示模式?if(widget.settings.displayed){//哎哟!然后,我们最好注意隐藏throbber并显示设置表单。widget.throbber.hide();widget.showSettings();invokeCallback(opts.widgetCallback.saveSettings,仪表板);}},'json');//不要让表单提交冒泡。返回false;};widget.enterFullscreen=函数(){//确保小部件实际上支持全屏模式。if(!widget.fullscreenUrl){回报;}$('
    ').html('
    加载。。。
    ').对话框({自动打开:true,标题:小部件.title,模态:true,高度:'自动',width:'自动',位置:[100125],关闭:函数(事件,ui){cj(this).dialog(“销毁”);$('#crm-dashlet-container').remove();$('#crm-dashlet-fullscreen-content').remove();}});$.ajax(美元)({url:widget.fullscreenUrl,成功:功能(内容){$('#crm-dashlet-fullscreen-content').html(内容);}}); };//退出全屏模式。widget.exitFullscreen=函数(){//这只是仪表板的包装。exitFullscreen()完成了繁重的工作。dashboard.exitFullscreen();};//将控件添加到小部件。id用于内部使用,图像文件名位于images/dashboard/(a.gif)中。widget.addControl=函数(id,控件){var标记=''; control.element=$(标记).prependTo($('.widget-controls',widget.element))点击(control.callback);};//一种仅由外部脚本使用或从外部脚本使用的外部方法,用于重新加载内容。未在内部调用或使用。//小部件必须提供执行此操作的脚本以及调用它的脚本。widget.reloadContent=函数(){getJavascript(widget.reloadContentScript);invokeCallback(opts.widgetCallback.reloadContent,小部件);};//从面板中删除小部件,并保存列。widget.remove=函数(){if(确认('是否确实要删除“'+widget.title+'”?'){invokeCallback(opts.widgetCallback.remove,小部件);widget.element.fadeOut(opts.animationSpeed,function(){$(this).remove();dashboard.saveColumns();});}};//结束小部件的公共方法。/***小部件的公共属性。*///默认控件。外部脚本可以使用widget.addControls()添加更多内容widget.controls={设置:{description:'配置此dashlet',回调:widget.toggleSettings},最小化:{description:'折叠或展开此dashlet',回调:小部件.toggleMinimize},全屏显示:{description:'以全屏模式查看此dashlet',回调:widget.enterFullscreen},关闭:{description:'从仪表板中删除此dashlet',回调:小工具.remove}};//结束小部件的公共属性。/***小部件的私有属性。*///我们将再次“分叉”执行,所以让我们告诉用户等待,直到调用AJAX回调。var throbber=$(opts.throberMarkup).appendTo(widget.element);var params=$.extend({},opts.ajaxCallback.getWidget.data,{id:widget.id});$.getJSON(opts.ajaxCallbacks.getWidget.url,params,init);//帮助仪表板跟踪我们是否有任何未决的初始化请求。异步请求计数器++;返回小部件;//小部件的私有属性结束。/***小部件的私有方法。*///用于小部件初始化的Ajax回调。函数init(数据、状态){异步请求计数器--;$.extend(小部件,数据);//删除不适用于此小部件的控件。if(!widget.settings){删除widget.controls.settings;}if(!widget.fullscreenUrl){删除widget.controls.fullscreen;}widget.element.attr('id','widget-'+widget.id).addClass(widget.classes);throbber.remove();//构建并添加小部件的DOM元素。$(widgetHTML()).appendTo(widget.element);//保存内容元素,以便外部脚本可以轻松地重新加载它。widget.contentElement=$('.widget-content',widget.element);$.each(widget.controls,widget.addControl);//切换初始状态,使其初始化为正确的状态。widget.minimized=!小工具最小化;widget.toggleMinimize();getJavascript(widget.initScript);invokeCallback(opts.widgetCallback.get,小部件);//completeInit()是仪表板的专用方法。让它完成仪表板的初始化。completeInit();}//为小部件构建内部HTML。函数小部件HTML(){var html=“”;html+='
    ';html+='

    “+小部件.title+”

    ';html+='
    '+widget.content+'
    ';html+='
    ';返回html;}//初始化小部件设置窗格。函数initSettings(){//覆盖小部件设置(布尔值)。initThrobber();小部件设置={元素:widget.throbber.show(),就绪:错误};//获取此小部件的设置标记和脚本可执行文件。var params=$.extend({},opts.ajaxCallback.widgetSettings.data,{id:widget.id});$.getJSON(opts.ajaxCallback.widgetSettings.url,参数,函数(响应,状态){$.extend(小部件设置,响应);//构建设置表单并将其添加到DOM。绑定表单的提交事件处理程序/回调。widget.settings.element=$(widgetSettingsHTML()).appendTo($('.widget-wrapper',widget.element)).submit(widget.saveSettings);//也绑定取消按钮的事件处理程序。widget.settings.cancelButton=$('.widget-settings-cancel',widget.settings.element).click(cancelEditSettings);//从AJAX数据中提供的HTML标记构建并添加内部表单元素。widget.settings.innerElement=$('.widget-settings-inner',widget.settings.element).append(widget.settings.markup);widget.settings.ready=true;if(widget.settings.displayed){//如果用户没有单击设置窗格,则显示表单。widget.throbber.hide();widget.showSettings();}getJavascript(widget.settings.initScript);});}//为小部件设置表单构建HTML。函数小部件设置HTML(){var html=“”;html+='
    ';html+='
    ';html+='
    ';html+='';html+='';html+='
    ';html+='
    ';返回html;}//初始化一个通用的小部件内容悸动器,供设置表单和外部脚本使用。函数initThrobber(){if(!小部件.throber){widget.throbber=$(opts.throberMarkup).appendTo($('.widget-wrapper',widget.element));}};//取消按钮单击的事件处理程序/回调。//@todo test当通过键盘“单击”取消按钮时,所有浏览器都会捕捉到这一点。函数cancelEditSettings(){widget.toggleSettings();返回false;};//Helper函数在服务器上执行外部脚本。//@todo如果能为脚本提供一些上下文,那就太好了。怎么用?函数getJavascript(url){if(url){$.getScript(url);}}};};//仪表板的公共静态属性。默认设置。$.fn.dashboard.defaults={列:2,emptyPlaceholderInner:'仪表板的此列中没有Dashlet。',fullscreenHeaderInner:'返回仪表板模式',throbberMarkup:'
    加载。。。
    ',动画速度:200,回调:{},小部件回调:{}};//默认小部件设置。$.fn.dashboard.widget={默认值:{最小化:false,设置:false,全屏:假}};})(jQuery);//关闭结束