// Generated by CoffeeScript 2.0.0-beta4
(function() {
// ------------------------------------------------------------------------
// 變數與常數設置
// ------------------------------------------------------------------------
// 模組名稱。
var Attribute, ClassName, EVENT_NAMESPACE, Error, Event, MODULE_NAMESPACE, NAME, Selector, Settings, TARGET;
NAME = 'transfer';
// 模組事件鍵名。
EVENT_NAMESPACE = `.${NAME}`;
// 模組命名空間。
MODULE_NAMESPACE = `module-${NAME}`;
// 模組設定。
Settings = {
// 消音所有提示,甚至是錯誤訊息。
silent: false,
// 顯示除錯訊息。
debug: true,
// 監聽 DOM 結構異動並自動重整快取。
observeChanges: true,
// 當值移動時所會呼叫的回呼函式。
onMove: (values, to) => {},
// 當值有所移動、新增或移除時所會呼叫的函式。
onChange: (value) => {},
// 當值被選取時所會呼叫的函式。
onSelect: (value) => {},
// 當值被取消選取時所會呼叫的函式。
onUnselect: (value) => {},
// 搜尋時所會呼叫的函式。
onSearch: () => {}
};
// 事件名稱。
Event = {
CHANGE: `change${EVENT_NAMESPACE}`,
SELECT: `select${EVENT_NAMESPACE}`,
UNSELECT: `unselect${EVENT_NAMESPACE}`,
MOVE: `move${EVENT_NAMESPACE}`,
SEARCH: `search${EVENT_NAMESPACE}`,
CLICK: `click${EVENT_NAMESPACE}`
};
// 元素屬性標籤。
Attribute = {
VALUE: 'data-value'
};
// 目標
TARGET = {
DESTINATION: 'destination',
SOURCE: 'source'
};
// 樣式名稱。
ClassName = {
ITEM: 'item',
ADD: 'add',
SELECTED: 'selected'
};
// 選擇器名稱。
Selector = {
DESTINATION_ITEMS: '.destination.list .items',
DESTINATION_ITEM: '.destination.list .items .item',
DESTINATION_SELECTED_ITEM: '.destination.list .items .selected.item',
SOURCE_ITEMS: '.source.list .items',
SOURCE_ITEM: '.source.list .items .item',
SOURCE_SELECTED_ITEM: '.source.list .items .selected.item',
ANY_ITEM: '.items .item',
ACTION_BUTTON: '.ts.add.button, .ts.remove.button',
ITEM: (value) => {
return `.items .item[data-value='${value}']`;
},
SELECTED_ITEM: (value) => {
return `.items .selected.item[data-value='${value}']`;
}
};
// 錯誤訊息。
Error = {};
// ------------------------------------------------------------------------
// 模組註冊
// ------------------------------------------------------------------------
ts.register({NAME, MODULE_NAMESPACE, Error, Settings}, ({$allModules, $this, element, debug, settings}) => {
var module;
// ------------------------------------------------------------------------
// 區域變數
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// 模組定義
// ------------------------------------------------------------------------
return module = {
get: {
values: (from) => {
var $item, values;
values = [];
switch (from) {
case TARGET.DESTINATION:
$item = $this.find(Selector.DESTINATION_ITEM);
break;
case TARGET.SOURCE:
$item = $this.find(Selector.SOURCE_ITEM);
}
$item.each(function() {
return values.push(ts(this).attr(Attribute.VALUE));
});
return values;
},
selected: (from) => {
var $item, selected;
selected = [];
switch (from) {
case TARGET.DESTINATION:
$item = $this.find(Selector.DESTINATION_SELECTED_ITEM);
break;
case TARGET.SOURCE:
$item = $this.find(Selector.SOURCE_SELECTED_ITEM);
}
$item.each(function() {
return selected.push(ts(this).attr(Attribute.VALUE));
});
return selected;
},
destination: {
values: () => {
return module.get.values(TARGET.DESTINATION);
},
selected: () => {
return module.get.selected(TARGET.DESTINATION);
}
},
source: {
values: () => {
return module.get.values(TARGET.SOURCE);
},
selected: () => {
return module.get.selected(TARGET.SOURCE);
}
},
$item: (value) => {
return $this.find(Selector.ITEM(value));
}
},
create: {
$value: (value, text) => {
return ts('
').html(text).addClass(ClassName.ITEM).attr(Attribute.VALUE, value);
}
},
add: {
destination: {
value: (value, text) => {
module.add.value(TARGET.DESTINATION, value, text);
return $allModules;
}
},
source: {
value: (value, text) => {
module.add.value(TARGET.SOURCE, value, text);
return $allModules;
}
},
value: (to, value, text) => {
var $targetItems, i, item, len;
switch (to) {
case TARGET.DESTINATION:
$targetItems = $this.find(Selector.DESTINATION_ITEMS);
break;
case TARGET.SOURCE:
$targetItems = $this.find(Selector.SOURCE_ITEMS);
}
if (Array.isArray(value)) {
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
if (module.has.value(item.value)) {
continue;
}
$targetItems.append(module.create.$value(item.value, item.text));
}
} else {
if (module.has.value(value)) {
return;
}
$targetItems.append(module.create.$value(value, text));
}
module.scroll.toBottom($targetItems);
return module.trigger.change(value);
}
},
has: {
value: (value) => {
return module.get.$item(value).length !== 0;
}
},
remove: {
value: (value) => {
var i, item, len;
if (Array.isArray(value)) {
for (i = 0, len = value.length; i < len; i++) {
item = value[i];
module.get.$item(item).remove();
}
} else {
module.get.$item(value).remove();
}
module.trigger.change(value);
return $allModules;
}
},
set: {
destination: {
value: (values) => {
$this.find(Selector.DESTINATION_ITEM).remove();
module.add.destination.value(value);
return $allModules;
}
},
source: {
value: (values) => {
$this.find(Selector.SOURCE_ITEM).remove();
module.add.source.value(value);
return $allModules;
}
}
},
scroll: {
toBottom: ($items) => {
var items;
items = $items.get();
return items.scrollTop = items.scrollHeight;
},
destination: {
toBottom: () => {
return module.scroll.toBottom($this.find(Selector.DESTINATION_ITEMS));
}
},
source: {
toBottom: () => {
return module.scroll.toBottom($this.find(Selector.SOURCE_ITEMS));
}
}
},
move: {
values: (to, values) => {
var $targetItems, i, len, value;
if (!Array.isArray(values)) {
values = [values];
}
if (values.length === 0) {
return;
}
switch (to) {
case TARGET.DESTINATION:
$targetItems = $this.find(Selector.DESTINATION_ITEMS);
break;
case TARGET.SOURCE:
$targetItems = $this.find(Selector.SOURCE_ITEMS);
}
for (i = 0, len = values.length; i < len; i++) {
value = values[i];
ts(Selector.ITEM(value)).appendTo($targetItems);
module.unselect.value(value);
}
module.scroll.toBottom($targetItems);
module.trigger.move(values, to);
return module.trigger.change(values);
},
to: {
destination: (value) => {
module.move.values(TARGET.DESTINATION, value);
return $allModules;
},
source: (value) => {
module.move.values(TARGET.SOURCE, value);
return $allModules;
}
}
},
select: {
value: (value) => {
module.get.$item(value).addClass(ClassName.SELECTED);
module.trigger.select(value);
return $allModules;
},
destination: {
all: () => {
$this.find(Selector.DESTINATION_ITEM).each(function() {
return module.select.value(ts(this).attr(Attribute.VALUE));
});
return $allModules;
}
},
source: {
all: () => {
$this.find(Selector.SOURCE_ITEM).each(function() {
return module.select.value(ts(this).attr(Attribute.VALUE));
});
return $allModules;
}
}
},
unselect: {
value: (value) => {
module.get.$item(value).removeClass(ClassName.SELECTED);
module.trigger.unselect(value);
return $allModules;
},
all: () => {
module.unselect.destination.all();
module.unselect.source.all();
return $allModules;
},
destination: {
all: () => {
$this.find(Selector.DESTINATION_ITEM).each(function() {
return module.unselect.value(ts(this).attr(Attribute.VALUE));
});
return $allModules;
}
},
source: {
all: () => {
$this.find(Selector.SOURCE_ITEM).each(function() {
return module.unselect.value(ts(this).attr(Attribute.VALUE));
});
return $allModules;
}
}
},
is: {
selected: (value) => {
return $this.find(Selector.SELECTED_ITEM(value)).length !== 0;
}
},
trigger: {
change: (value) => {
return $this.trigger(Event.CHANGE, element, value);
},
select: (value) => {
return $this.trigger(Event.SELECT, element, value);
},
unselect: (value) => {
return $this.trigger(Event.UNSELECT, element, value);
},
move: (values, to) => {
return $this.trigger(Event.MOVE, element, values, to);
}
},
bind: {
events: () => {
$this.on(Event.CHANGE, (event, context, value) => {
debug("發生 CHANGE 事件", context, value);
return settings.onChange.call(context, event, value);
});
$this.on(Event.SELECT, (event, context, value) => {
debug("發生 SELECT 事件", context, value);
return settings.onSelect.call(context, event, value);
});
$this.on(Event.UNSELECT, (event, context, value) => {
debug("發生 UNSELECT 事件", context, value);
return settings.onUnselect.call(context, event, value);
});
$this.on(Event.MOVE, (event, context, values, to) => {
debug("發生 MOVE 事件", context, values, to);
return settings.onMove.call(context, event, values, to);
});
$this.on(Event.CLICK, Selector.ANY_ITEM, function() {
var value;
debug("發生 CLICK 事件", this);
value = ts(this).attr(Attribute.VALUE);
if (module.is.selected(value)) {
return module.unselect.value(value);
} else {
return module.select.value(value);
}
});
return $this.on(Event.CLICK, Selector.ACTION_BUTTON, function() {
debug("發生 BUTTON CLICK 事件", this);
if (ts(this).hasClass(ClassName.ADD)) {
return module.move.to.destination(module.get.source.selected());
} else {
return module.move.to.source(module.get.destination.selected());
}
});
}
},
// ------------------------------------------------------------------------
// 基礎方法
// ------------------------------------------------------------------------
initialize: () => {
debug('初始化穿梭框', element);
return module.bind.events();
},
instantiate: () => {
return debug('實例化穿梭框', element);
},
refresh: () => {
return $allModules;
},
destroy: () => {
debug('摧毀穿梭框', element);
$this.removeData(MODULE_NAMESPACE).off(EVENT_NAMESPACE);
return $allModules;
}
};
});
}).call(this);