JSFiddle - React, Tailwind, and code Playground
by sukobuto
HTML
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://raw.github.com/jquery/jquery-color/master/jquery.color.js"></script>
<h1>"Yellow Fade" を View 側で実装</h1>
<p>
ViewModel は UI に対する依存をしないというのが、一応 MVVM のルールであるため、<br>
foreach バインディングの afterRender 系レンダリングサポートを View 側で実装してみました。<br>
PC版 <-> モバイル版 での View の載せ替えなどが予想される場合に有効です。<br><br>
ViewModel のプロパティなのか View の関数なのかが紛らわしいという場合は、<br>
View の関数を適当な名前空間(オブジェクト)でまとめるとよさそうです。
</p>
<hr>
<form data-bind="submit:addItem">
追加するアイテム: <input type="text" data-bind='value:itemToAdd, valueUpdate: "afterkeydown"' />
<button type="submit" data-bind="enable: itemToAdd().length > 0">追加</button>
</form>
<p>レシピ</p>
<ul data-bind="foreach: { data: allItems, afterAdd: yellowFade }">
<li data-bind="text: $data,
css: { selected: $root.selectedItems.indexOf($data) > -1 },
click: $root.toggleSelect"></li>
</ul>
<script type="text/javascript">
// View 側で Yellow Fade の実装を行う
function yellowFade(element) {
$(element).filter("li")
.animate({ backgroundColor: 'yellow' }, 200)
.animate({ backgroundColor: '#eeeeff' }, 800);
}
</script>
<div>
<button data-bind="click: removeSelected, enable: selectedItems().length > 0">削除</button>
<button data-bind="click: sortItems, enable: allItems().length > 1">ソート</button>
</div>
CSS
h1 {
font-size: 20px;
margin: 10px 0;
}
ul {
user-select: none;
}
li {
background: #eeeeff;
border: solid 1px #aaaaee;
margin: 10px;
cursor: pointer;
width: 300px;
}
li.selected {
background: #ffdddd;
}
JavaScript
$(function() {
// ViewModel には UI に関する定義が一切無い状態
var BetterListModel = function () {
var self = this;
this.itemToAdd = ko.observable("");
this.allItems = ko.observableArray(["オリーブオイル", "パンチェッタ", "アボカド", "謎パスタ", "イタリアンパセリ", "岩塩ファサー", "追いオリーブ"]); // Initial items
this.selectedItems = ko.observableArray(["Ham"]); // Initial selection
this.addItem = function () {
if ((this.itemToAdd() != "") && (this.allItems.indexOf(this.itemToAdd()) < 0)) // Prevent blanks and duplicates
this.allItems.push(this.itemToAdd());
this.itemToAdd(""); // Clear the text box
};
this.removeSelected = function () {
this.allItems.removeAll(this.selectedItems());
this.selectedItems([]); // Clear selection
};
this.sortItems = function() {
this.allItems.sort();
};
this.toggleSelect = function(item, event) {
if (event.ctrlKey) {
if (self.selectedItems.indexOf(item) > -1) self.selectedItems.remove(item);
else self.selectedItems.push(item);
} else {
self.selectedItems.removeAll();
self.selectedItems.push(item);
}
};
};
ko.applyBindings(new BetterListModel());
});