(函数($){/***基本States命名空间。**拥有局部状态变量允许我们使用states名称空间*而不必总是声明“Drupal.states”。*/var状态=药物状态={//应该推迟的函数数组。延期:[]};/***附加状态。*/Drupal.behaviors.states={附加:函数(上下文,设置){for(settings.states中的var选择器){for(设置中的var状态。状态[选择器]){新的州。受抚养人({元素:$(选择器),状态:状态。州。消毒(州),从属对象:设置。状态[选择器][状态]});}}//立即执行所有延迟的函数。while(状态。延迟。长度){(states.delayed.shift())();}}};/***表示依赖于其他元素的元素的对象。**@param参数*对象具有以下键(所有键都是必需的):*-element:从属元素的jQuery对象*-state:描述依赖状态的state对象*-dependees:具有依赖性规范的对象。列出所有元素*这个元素所依赖的。*/状态。从属=函数(args){扩展(this,{values:{},oldValue:undefined},args);for(this.dependees中的var选择器){this.initializeDependee(选择器,this.dependees[选择器]);}};/***比较函数,用于将元素的值与*依赖项设置中的规范。如果对象类型不能为*在该列表中,默认使用===运算符。*/状态。Dependent.com比较={“RegExp”:函数(引用,值){返回参考测试(值);},“函数”:函数(引用,值){//“reference”变量是一个比较函数。返回参考(值);},“数字”:功能(参考,值){//如果“reference”是数字,“value”是字符串,则强制转换引用//作为字符串,然后在compare()中应用严格比较。否则//表单的states数组中的数字键无法匹配字符串值//从jQuery的val()返回。return(value.constructor.name===“字符串”)?compare(字符串(引用),值):比较(引用,值);}};状态。Dependent.protype={/***初始化此依赖项所依赖的元素之一。**@param选择器*描述被依赖者的CSS选择器。*@param dependeeStates*必须监视以跟踪*受抚养人的合规状态。*/initializeDependee:函数(选择器,dependeeStates){var self=此;//缓存此依赖项的状态。self.values[选择器]={};$.each(dependeeStates,函数(状态,值){state=状态。州。消毒(州);//初始化此状态的值。self.values[selector][state.pristine]=未定义;//监视此依赖项的指定状态的状态更改。$(选择器).bind('state:'+状态,函数(e){var符合=self.compare(value,e.value);自我更新(选择器、状态、符合性);});//确保我们刚刚参与的活动确实已被解雇。新的州。触发器({选择器:选择器,状态:状态});});},/***将值与引用值进行比较。**@param引用*用于引用的值。*@param值*要与参考值进行比较的值。*@返回*正确、未定义或错误。*/比较:函数(引用,值){if(状态中的reference.constructor.name。从属比较){//对某些引用值类型使用自定义比较函数。返回状态。依赖比较[reference.constructor.name](reference,value);}其他{//否则做一个简单的比较。返回比较(引用、值);}},/***更新受依赖者状态的值。**@param选择器*描述受抚养人的CSS选择器。*@param状态*描述受依赖者更新状态的State对象。*@param值*被依赖者更新状态的新值。*/更新:函数(选择器、状态、值){//只有当“new”值实际上是新值时才执行操作。if(value!==this.values[selector][state.pristine]){this.values[选择器][state.pristine]=值;this.reevaluate();}},/***触发器在状态更改时更改事件。*/重新评估:函数(){var值=未定义;//合并所有单个值以确定此依赖项是否符合要求。for(this.values中的var选择器){for(this.values[选择器]中的var状态){state=状态。州。消毒(州);var符合=this.values[selector][state.pristine];value=三元(value,invert(compliance,state.invert));}}//仅在值实际更改时调用状态更改事件。if(value!==this.oldValue){//存储新值,以便稍后比较该值//实际上发生了变化。this.oldValue=值;//规格化该值以匹配规格化的状态名称。value=反转(value,this.state.invert);//通过添加“触发器:true”,我们确保状态更改不会进入//无限循环。this.element.trigger({type:'state:'+this.state,value:value,trigger:true});}}};状态。触发器=函数(args){$.extend(this,args);if(states.Trigger.states中的this.state){this.element=$(this.selector);//仅当触发器初始值设定项尚未附加到此//元素。否则,我们将以重复事件告终。if(!this.element.data('trigger:'+this.state)){this.initialize();}}};状态。触发器原型={初始化:函数(){var self=此;var触发器=状态。触发器状态[this.state];if(触发器类型==“函数”){//我们有一个自定义触发器初始化函数。trigger.call(window,this.element);}其他{$.each(触发器、函数(事件、值Fn){self.defaultTrigger(事件,值Fn);});}//将此触发器标记为已为此元素初始化。this.element.data('trigger:'+this.state,true);},defaultTrigger:函数(事件,valueFn){var self=此;var oldValue=valueFn.call(this.element);//附加事件回调。this.element.bind(事件,函数(e){var值=值Fn.call(self-element,e);//仅当值实际更改时才触发事件。if(oldValue!==值){self.element.trigger({type:'state:'+self.state,value:value,oldValue:oldValue});oldValue=值;}});states.delayed.push(函数(){//触发事件一次以进行初始化。self.element.trigger({type:'state:'+self.state,value:oldValue,oldValue:undefined});});}};/***此状态列表包含用于监视状态的函数*元素的。每当一个元素依赖于另一个元素的状态时,*将这些触发函数之一添加到从属对象,以便*可以更新从属元素。*/状态。触发器状态={//“空”描述要监视的状态空:{//“keyup”是我们关注的(本机DOM)事件。“keyup”:函数(){//与该触发器关联的函数返回//状态。return this.val()==“”;}},已检查:{“change”:函数(){return this.attr('checked');}},//对于单选按钮,仅在选中单选按钮时返回值。值:{“keyup”:函数(){//单选按钮具有相同的功能:输入[name=“key”]选择器。如果(this.length>1){//无线电的初始检查值未定义,因此我们返回false。return this.filter(':checked').val()|false;}return this.val();},“change”:函数(){//单选按钮具有相同的功能:输入[name=“key”]选择器。如果(this.length>1){//无线电的初始检查值未定义,因此我们返回false。return this.filter(':checked').val()|false;}return this.val();}},塌陷:{“折叠”:函数(e){return(e!==未定义&&e中的“value”)?e.value:this.is('.scolledge');}}};/***状态对象用于描述状态和执行别名。*/状态。状态=功能(状态){//稍后我们可能需要原始的未解析名称。this.pristine=this.name=状态;//规范化状态名称。while(真){//迭代删除感叹号并反转值。while(this.name.charAt(0)==“!”){this.name=this.name.substring(1);this.invert=!this.invert;}//将状态替换为其规范化名称。if(states.State.aliases中的this.name){this.name=状态。州别名[this.name];}其他{断裂;}}};/***通过清理传递的值来创建新的State对象。*/状态。State.sanitize=函数(状态){if(state instanceof states.state){返回状态;}其他{返回新状态。州(州);}};/***此别名列表用于规范化状态并关联否定名称*具有各自的逆状态。*/状态。State.aliases=州别名{“已启用”:“!”!禁用',“不可见”:“!可见','无效':'!有效',“未受影响”:“!触摸’,'可选':'!必需','填充':'!空','未选中':'!选中',“无关”:“!相关',“展开”:“!”!坍塌','读写':'!只读'};状态。州原型={反转:假,/***确保仅使用状态对象返回名称。*/toString:function(){返回this.name;}};/***全局状态更改处理程序。这些都绑定到“文档”以涵盖所有*状态发生变化的元素。发送到页面内元素的事件*向这些处理程序冒泡。我们使用这个系统,以便主题和模块*可以为页面的特定部分重写这些状态更改处理程序。*/{$(document).bind('状态:禁用',函数(e){//仅当此更改由依赖项而不是//元素监视本身。if(e.触发器){$(e.target).attr(“禁用”,e.value).filter('.form element')最近的('.form-item,.form-submit,.form-wrapper')[e.value?'addClass':'removeClass']('form-disabled');//注意:WebKit晚间节目没有正确反映这一变化。//请参见https://bugs.webkit.org/show_bug.cgi?id=23789}});$(document).bind(“状态:必需”,函数(e){if(e.触发器){如果(e.value){$(e.target).最近('.form-item,.form-wrapper').find('label').append('*');}其他{$(e.target).closest('.form-item,.form-wrapper').find('label.form-required').remove();}}});$(document).bind('状态:可见',函数(e){if(e.触发器){$(e.target).closest('.form-item,.form-submit,.form-wrapper')[e.value?'show':'hide']();}});$(document).bind('状态:已检查',函数(e){if(e.触发器){$(e.target).attr('checked',e.value);}});$(document).bind('状态:折叠',函数(e){if(e.触发器){if($(e.target).is('.scolledge')!==e.value){$('>图例a',e.target).click();}}});}/***这些是实现加法“操作符”的助手函数*实现特定于状态的任何逻辑。*/{//与第三个未定义状态按位AND。三元函数(a,b){返回a===未定义?b:(b===未定义?a:a&&b);};//当invert为true时,反转a(如果未定义)。函数反转(a,反转){return(反转&&a!==未定义)!a:a;};//比较两个值,同时忽略未定义的值。功能比较(a,b){返回(a===b)?(a===未定义?a:true):(a==未确定||b===尚未定义);}}})(jQuery);