/** | |
* @file 简单的小按钮(支持鼠标按住移入移出控件区域时的视图变化) | |
* @author sushuang(sushuang@baidu.com) | |
* @date 2014-03 | |
*/ | |
define(function (require) { | |
var $ = require('jquery'); | |
var Component = require('./Component'); | |
var lib = require('../lib'); | |
// Constant | |
var MAIN_CSS = 'dtui-btn'; | |
var EVENTS = ['click', 'mouseenter', 'mouseleave']; | |
/** | |
* 模板中声明方法举例: | |
* <div data-cpt=" | |
* type: 'button', | |
* name: 'xxxxx', | |
* text: lib.ob('this is a button')"></div> | |
* 或 | |
* <div data-cpt=" | |
* type: 'button', | |
* name: 'xxxxx', | |
* viewModel: { | |
* text: lib.ob('this is a button') | |
* }"></div> | |
* | |
* @class | |
* @extends common/component/Component | |
*/ | |
var Button = Component.extend({ | |
/** | |
* @protected | |
* @type {Object} | |
*/ | |
_define: { | |
viewModel: function () { | |
return { | |
// button内的文字。如果text是lib.ob,则可由外部控制文字的变化。 | |
text: lib.ob(''), | |
// encodeHTML是否交由控件负责 | |
dontEncodeHTML: false | |
}; | |
}, | |
viewModelPublic: ['text'], | |
css: MAIN_CSS | |
}, | |
/** | |
* @override | |
* @protected | |
*/ | |
_init: function () { | |
var viewModel = this._viewModel(); | |
var $el = this.$el(); | |
var that = this; | |
var hoverCss = this.getFullCss('-hover').join(' '); | |
var activeCss = this.getFullCss('-active').join(' '); | |
var actived = false; | |
var $doc = $(document); | |
this._eventHandlerMap = {}; | |
$el.on(this._event('mouseenter'), onMouseEnter); | |
$el.on(this._event('mouseleave'), onMouseLeave); | |
$el.on(this._event('mousedown'), onMouseDown); | |
$el.on(this._event('mouseup'), onMouseUp); | |
var me = this; | |
$.each(EVENTS, function (idx, eventName) { | |
$el.on(me._event(eventName), function (e) { | |
me.trigger.call(me, eventName, e); | |
}); | |
}); | |
// binding ob | |
if (lib.obTypeOf(viewModel.text) === 'ob') { | |
this._disposable( | |
viewModel.text.subscribe(updateViewByModel, this) | |
); | |
} | |
// 设初始值 | |
var initVal = lib.value(viewModel.text); | |
$el.html( | |
viewModel.dontEncodeHTML ? initVal : lib.encodeHTML(initVal) | |
); | |
function onMouseEnter() { | |
if (viewModel.disabled()) { | |
return; | |
} | |
$el.addClass(hoverCss); | |
if (actived) { | |
$el.addClass(activeCss); | |
} | |
} | |
function onMouseLeave() { | |
$el.removeClass(hoverCss); | |
$el.removeClass(activeCss); | |
} | |
function onMouseDown() { | |
if (viewModel.disabled()) { | |
return; | |
} | |
$el.addClass(activeCss); | |
actived = true; | |
// FIXME | |
// 这个简单实现并不仔细(stopPropagation),但是暂不认为影响很大。 | |
$doc.one( | |
that._event('mouseup'), | |
function () { | |
actived = false; | |
} | |
); | |
} | |
function onMouseUp() { | |
$el.removeClass(activeCss); | |
} | |
function updateViewByModel(nextText) { | |
// 暂时内部所有内容都当做text | |
$el.html( | |
viewModel.dontEncodeHTML | |
? nextText | |
: lib.encodeHTML(nextText) | |
); | |
} | |
}, | |
/** | |
* @override | |
* @protected | |
*/ | |
_parseViewModel: function (inputViewModel, cptDef) { | |
// 兼容直接在ctpDef设text,而非在viewModel上设text的情况。 | |
// 这是为了简化模板书写。 | |
if (cptDef.text != null) { | |
inputViewModel.text = cptDef.text; | |
} | |
if (cptDef.css != null) { | |
inputViewModel.css = cptDef.css; | |
} | |
if (cptDef.dontEncodeHTML != null) { | |
inputViewModel.dontEncodeHTML = cptDef.dontEncodeHTML; | |
} | |
return inputViewModel; | |
}, | |
/** | |
* 注册事件:click、mouseenter、mouseleave | |
* | |
* @public | |
* @param {string} event 不可带后缀 | |
* @param {Function} handler 处理器 | |
*/ | |
on: function (event, handler) { | |
lib.assert(event.indexOf('.') < 0); | |
var eventHandlerMap = this._eventHandlerMap; | |
if ($.inArray(event, EVENTS) >= 0) { | |
eventHandlerMap[event] = eventHandlerMap[event] || []; | |
eventHandlerMap[event].push(handler); | |
} | |
}, | |
/** | |
* 触发事件处理handle | |
* | |
* @public | |
* @param {string} eventName 要触发的事件名 | |
* @param {Object} event 事件对象 | |
*/ | |
trigger: function (eventName, event) { | |
var viewModel = this._viewModel(); | |
var handleList = this._eventHandlerMap[eventName]; | |
if (viewModel.disabled()) { | |
return; | |
} | |
if (handleList && handleList.length) { | |
$.each(handleList, function (idx, handle) { | |
if ($.isFunction(handle)) { | |
handle.call(this, event); | |
} | |
}); | |
} | |
}, | |
/** | |
* 销毁 | |
* | |
* @override | |
* @protected | |
*/ | |
_dispose: function () { | |
this.$el().off(); | |
this._eventHandlerMap = null; | |
} | |
}); | |
return Button; | |
}); |