namespace drunk { import util = drunk . util ; /**
     * 绑定声明接口
     */ export interface IBindingDefinition { name ? : string ; isDeepWatch ? : boolean ; isTerminal ? : boolean ; isInterpolate ? : boolean ; priority ? : number ; retainAttribute ? : boolean ; expression ? : string ; attribute ? : string ; init ? ( parentViewModel ? , placeholder ? ) : void ; update ? ( newValue , oldValue ) : void ; release ? ( ) : void ; } export interface IBindingConstructor { new ( ... args ) : Binding ; isDeepWatch ? : boolean ; isTerminal ? : boolean ; priority ? : number ; retainAttribute ? : boolean ; } /**
     * 元素与viewModel绑定创建的函数接口
     */ export interface IBindingGenerator { ( viewModel , element , parentViewModel ? , placeHolder ? ) : Function ; } /**
     * 更新函数接口
     */ export interface IBindingAction { ( newValue , oldValue ) : any ; } const refKey = 'DRUNK-BINDING-ID-LIST' ; /** 终止型绑定信息列表,每个绑定信息包含了name(名字)和priority(优先级)信息 */ const terminalBindingDescriptors = [ ] ; /** 终止型绑定的名称 */ var terminalBindings = [ ] ; export function binding ( name ) { return function ( constructor ) { Binding . register ( name , constructor ) ; } ; } /**
     * 绑定类
     */ export class Binding { /** 实例 */ private static instancesById : { [ id ] : Binding ; } = { } ; /**
         * 缓存的所有绑定声明的表
         */ static definitions : { [ name ] : IBindingConstructor ; } = { } ; param element static getByElement ( element ) { if ( ! element [ refKey ] ) { return [ ] ; } return element [ refKey ] . map ( id => Binding . instancesById [ id ] ) ; } param element param binding static setWeakRef ( element , binding ) { if ( ! element [ refKey ] ) { element [ refKey ] = [ ] ; } util . addArrayItem ( element [ refKey ] , util . uniqueId ( binding ) ) ; } param element param binding static removeWeakRef ( element , binding ) { if ( element [ refKey ] ) { util . removeArrayItem ( element [ refKey ] , util . uniqueId ( binding ) ) ; } } param name param def static register < T extends IBindingDefinition > ( name , definition ) ; static register ( name , IBindingConstructor ) ; static register < T extends IBindingDefinition > ( name , definition ) { definition . priority = definition . priority || Binding . Priority . normal ; if ( definition . isTerminal ) { Binding . _setTernimalBinding ( name , definition . priority ) ; } if ( Object . prototype . toString . call ( definition ) === '[object Object]' ) { let ctor = < any > function ( ... args ) { Binding . apply ( this , args ) ; } ; ctor . isTerminal = definition . isTerminal ; ctor . priority = definition . priority ; ctor . retainAttribute = definition . retainAttribute ; ctor . isDeepWatch = definition . isDeepWatch ; util . extend ( ctor . prototype , Binding . prototype , definition ) ; definition = ctor ; } if ( Binding . definitions [ name ] ) { console . warn ( name , `绑定原已定义为: ` , Binding . definitions [ name ] ) ; console . warn ( `替换为: ` , definition ) ; } Binding . definitions [ name ] = < IBindingConstructor > definition ; } param name return static getByName ( name ) { return Binding . definitions [ name ] ; } return static getTerminalBindings ( ) { return terminalBindings . slice ( ) ; } param viewModel param element static create ( viewModel , element , descriptor , parentViewModel ? , placeholder ? ) { let Ctor = Binding . definitions [ descriptor . name ] ; if ( ! Ctor . retainAttribute && element . removeAttribute ) { element . removeAttribute ( `${ config . prefix }${ descriptor . name }${ descriptor . attribute ? ':' + descriptor . attribute : '' }` ) ; } let binding = new Ctor ( viewModel , element , descriptor ) ; util . addArrayItem ( viewModel . _bindings , binding ) ; Binding . setWeakRef ( element , binding ) ; Component . setWeakRef ( element , viewModel ) ; binding . $initialize ( parentViewModel , placeholder ) ; } param name param priority private static _setTernimalBinding ( name , priority ) { for ( let i = 0 , item ; item = terminalBindingDescriptors [ i ] ; i ++ ) { if ( item . name === name ) { item . priority = priority ; break ; } } terminalBindingDescriptors . push ( { name , priority } ) ; terminalBindingDescriptors . sort ( ( a , b ) => b . priority - a . priority ) ; terminalBindings = terminalBindingDescriptors . map ( item => item . name ) ; } /**
         * binding名称
         */ name : string ; value : any ; /**
         * 是否深度监听表达式
         */ isDeepWatch : boolean ; /**
         * 是否是绑定在一个插值表达式
         */ isInterpolate : boolean ; /**
         * 绑定的表达式
         */ expression : string ; /**
         * 指令附带的2级属性
         */ attribute : string ; /**
         * 是否已经不可用
         */ protected _isActived : boolean = true ; /**
         * 移除watcher方法
         */ protected _unwatch : ( ) => void ; /**
         * 内置的update包装方法
         */ protected _update : ( newValue : any , oldValue : any ) => void ; protected _isDynamic : boolean ; private _firstUpdate : boolean ; param viewModel param element param definition constructor ( public viewModel , public element , descriptor ) { this . _firstUpdate = true ; Binding . instancesById [ util . uniqueId ( this ) ] = this ; util . extend ( this , descriptor ) ; } /**
         * 初始化绑定
         */ $initialize ( ownerViewModel , placeholder ? ) { var self = this as IBindingDefinition ; if ( typeof self . init === 'function' ) { self . init ( ownerViewModel , placeholder ) ; } this . _isActived = true ; if ( typeof self . update !== 'function' ) { return ; } let expression = this . expression ; let isInterpolate = this . isInterpolate ; let viewModel = this . viewModel ; let getter = Parser . parseGetter ( expression , isInterpolate ) ; if ( ! getter . dynamic ) { return self . update ( viewModel . $eval ( expression , isInterpolate ) , undefined ) ; } this . _update = ( newValue , oldValue ) => { if ( ! this . _isActived || ( ! this . _firstUpdate && ! util . isObjectOrNotEqual ( newValue , this . value ) ) ) { return this . _firstUpdate = false ; } this . _firstUpdate = false ; this . value = newValue ; ( this as IBindingDefinition ) . update ( newValue , oldValue ) ; } ; this . _unwatch = viewModel . $watch ( expression , this . _update , this . isDeepWatch , false ) ; this . _isDynamic = true ; } /**
         * 移除绑定并销毁
         */ $dispose ( ) { if ( ! this . _isActived ) { return ; } if ( typeof this [ "release" ] === "function" ) { this [ "release" ] ( ) ; } if ( this . _unwatch ) { this . _unwatch ( ) ; } Binding . removeWeakRef ( this . element , this ) ; delete Binding . instancesById [ util . uniqueId ( this ) ] ; this . _unwatch = this . _update = this . element = this . expression = this . viewModel = null ; this . _isActived = false ; } param value $setValue ( value ) { this . value = value ; this . viewModel . $setValue ( this . expression , value ) ; } $execute ( ) { if ( ! this . _isDynamic ) { return ; } let key = Watcher . getNameOfKey ( this . expression , this . isDeepWatch ) ; let watcher = this . viewModel . _watchers [ key ] ; if ( watcher ) { this . _update ( watcher . value , undefined ) ; } } } export module Binding { /**
         * 优先级(没办法啊，枚举类型不能在类里面定义)
         */ export enum Priority { low = - 100 , high = 100 , normal = 0 , aboveNormal = 50 , belowNormal = - 50 } } }