Skip to content

Commit

Permalink
Merge pull request #6 from RubyLouvre/master
Browse files Browse the repository at this point in the history
Merge pull request #5 from RubyLouvre/master
  • Loading branch information
dengzhizhi committed Feb 13, 2014
2 parents c25d24f + 1f50e38 commit fcf415e
Show file tree
Hide file tree
Showing 85 changed files with 16,483 additions and 9,486 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

<h1>Avalon</h1>
<p>迷你简单易用的MVVM框架</p>
<p>前端做久了就会发现HTML(DOM)才是所有前端的真正精髓汇聚地。不管JS和CSS都是为DOM服务的。但是DOM遍布荆棘与陷阱,因此才出现像jQuery那样专门为它填坑的库,
当下的前端开发就是一边填坑一边写业务中进行。avalon的诞生改变了这一切,让我们摆脱DOM的掣肘,专注于需求本身,将可变的数据与操作数据的方法封装成模型。
在更高的层次上组织代码,提高软件的可维护性,可扩展性和可重用性。</p>
<hr>
<ul>
<li>avalon.js 兼容IE6,及标准浏览器</li>
Expand All @@ -21,12 +24,17 @@
<li>让DOM操作的代码近乎绝迹</li>
<li>使用类似CSS的重叠覆盖机制,让各个ViewModel分区交替地渲染页面</li>
<li>节点移除时,智能卸载对应的视图刷新函数,节约内存</li>
<li>操作数据即操作DOM,对ViewModel的操作都会同步到View与Model去。</li>
<li><strong>操作数据即操作DOM</strong>,对ViewModel的操作都会同步到View与Model去。</li>
<li>自带AMD模块加载器,省得与其他加载器进行整合。</li>
</ul>
<div><img src="https://raw2.github.com/RubyLouvre/avalon/master/ecosphere.jpg" width="400" height="640"></div>
<p>相关学习教程:<a href="http://www.cnblogs.com/rubylouvre/p/3181291.html">《入门教程》</a>→<a href="http://rubylouvre.github.io/mvvm/">官网</a>→
<a href="http://vdisk.weibo.com/s/aMO9PyIQCnLOF/1375154475">HTML5交流会有关avalon的PPT</a>→<a href="http://www.cnblogs.com/rubylouvre/p/3385373.html">《avalon最佳实践》</a>
</p>
<h3>运行github中的示例</h3>
<p>将项目下载到本地,里面有一个叫server.exe的.NET小型服务器(可以需要安装<a href="http://dl.pconline.com.cn/download/54972.html">.Net4.0</a>才能运行),
点击它然后打开里面与index开头的HTML文件,一边看运行效果,一边看源码进行学习。</p>
<p><img src="https://raw2.github.com/RubyLouvre/avalon/master/example.jpg"/></p>

<p>大家也可以在<a href="http://huati.weibo.com/k/avalon%E5%BF%AB%E6%8A%A5?from=501&order=time">新浪微博</a>第一时间了解它的变更或各种秘笈分享!</p>

Expand Down
10 changes: 6 additions & 4 deletions avalon.datepicker.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@
<a class="ui-datepicker-next ui-corner-all" ms-click="updateMonth(1)" ms-attr-title="nextText" ms-if="group.number===numberOfMonths -1">
<span class="ui-icon ui-icon-circle-triangle-e">next</span></a>
<div class="ui-datepicker-title">
<select ms-each-el="monthNamesShort" ms-duplex="currentMonth" ms-if="changeMonth">
<option ms-if="showMonth($index)" ms-value="{{$index}}" ms-selected="currentMonth + group.number === $index">{{el}}</option>
<select ms-each-el="monthNames" ms-duplex="currentMonth" ms-if="changeMonth">
<option ms-visible="showMonth($index)" ms-value="{{$index}}" ms-selected="currentMonth + group.number === $index">{{el}}</option>
</select>
<select ms-each-el="years" ms-duplex="currentYear" ms-if="changeYear">
<option ms-if="showYear(el)" ms-value="el" ms-selected="currentYear === el">{{el}}年</option>
<option ms-visible="showYear(el)" ms-value="el" >{{el + yearSuffix}}</option>
</select>
{{title}}</div>
</div>
<table class="ui-datepicker-calendar">
<!---设置星期--->
<thead>
<tr>
<th ms-if="showWeek" class="ui-datepicker-week-col">{{weekHeader}}</th> <th ms-repeat="dayNamesMin" ms-class-ui-datepicker-week-end="$first || $last"><span ms-attr-title="el">{{el}}</span></th>
<th ms-if="showWeek" class="ui-datepicker-week-col">{{weekHeader}}</th>
<th ms-repeat="dayNames" ms-class-ui-datepicker-week-end="$first || $last"><span ms-attr-title="dayNameTitles[$index]">{{el}}</span></th>
</tr>
</thead>
<tbody ms-each-week="WEEKMAP[group.number]" >
Expand Down
81 changes: 59 additions & 22 deletions avalon.datepicker.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl) {
//http://xdsoft.net/jqplugins/datetimepicker/
function formatMonth(date, format) {
if (Array.isArray(format)) {
return format[this.currentMonth]
} else if (format) {
return avalon.filters.date(date, format);
} else {
return this.currentMonth
}
}
function formatYear(date, format) {
if (format) {
return avalon.filters.date(date, format);
} else {
return this.currentYear + (this.yearSuffix || "")
}
}
var widget = avalon.ui.datepicker = function(element, data, vmodels) {
var $element = avalon(element), options = data.datepickerOptions, model
var now = new Date, datepickerEl
// element.stopScan = true
var nowTime = new Date(now.getFullYear(), now.getMonth(), now.getDate()) - 0
var model = avalon.define(data.datepickerId, function(vm) {
avalon.mix(vm, options)
Expand All @@ -12,17 +27,21 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl
vm.currentDate = now.getDate()
vm.title = {
get: function() {
var format = "";
if (!this.changeYear && this.changeMonth) {
format = "yyyy年";
} else if (this.formatTitle) {
format = this.formatTitle
var format, currentDate = new Date(this.currentYear, this.currentMonth, this.currentDate)
if (!this.changeYear && !this.changeMonth) {
format = this.titleFormat
if (!format) {
return formatMonth.call(this, currentDate, this.titleFormatOnlyMonth)
+ " " + formatYear.call(this, currentDate, this.titleFormatOnlyYear);
}
} else if (!this.changeYear && this.changeMonth) {
return formatYear.call(this, currentDate, this.titleFormatOnlyYear)
} else if (this.changeYear && !this.changeMonth) {
format = "MMMM";
} else if (!this.changeYear && !this.changeMonth) {
format = "MMMM yyyy年";
return formatMonth.call(this, currentDate, this.titleFormatOnlyMonth)
} else {
return ""
}
return format && avalon.filters.date(new Date(this.currentYear, this.currentMonth, this.currentDate), format);
return avalon.filters.date(currentDate, format);
}
};
vm.years = {
Expand All @@ -35,6 +54,7 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl
return avalon.range(min, max + 1)
}
}

vm.$watch("currentMonth", function(val) {
var d = new Date(vm.currentYear, vm.currentMonth, vm.currentDate)
d.setMonth(val);
Expand All @@ -57,7 +77,11 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl
return
m = d.getMonth();
var y = d.getFullYear();
try{
vm.currentYear = y;
}catch(e){
alert(vm.currentYear)
}
vm.currentMonth = m
}
vm.showDate = function(date) {
Expand Down Expand Up @@ -127,10 +151,12 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl
vm.$watch("numberOfMonths", getGroups)
getGroups(vm.numberOfMonths)
vm.getWeekNumberOfYear = function(date) {
var time,
checkDate = new Date(date.time);
checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
time = checkDate.getTime();
if(!date)
return
var checkDate = new Date(date.time);
checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7))
var time = checkDate.getTime();

checkDate.setMonth(0); // Compare with Jan 1
checkDate.setDate(1);
return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
Expand Down Expand Up @@ -212,8 +238,14 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl
at: "left bottom",
my: "left top"
})
if (typeof model.onShow === "function") {
model.onShow.call(element, model)
}
} else {
element.value = avalon.filters.date(vm.selectedTime, vm.dateFormat)
element.value = avalon.filters.date(model.selectedTime, model.dateFormat)
if (typeof model.onHide === "function") {
model.onHide.call(element, model)
}
}
})
})
Expand All @@ -222,8 +254,6 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl
$element.bind("focus", function() {
model.toggle = true
})

//element.stopScan = false
datepickerEl = avalon.parseHTML(tmpl).firstChild
document.body.appendChild(datepickerEl)
avalon.scan(datepickerEl, [model].concat(vmodels))
Expand All @@ -232,10 +262,11 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl

}
widget.defaults = {
dayNamesMin: "日一二三四五六".split(""),
monthNamesShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
changeMonth: true,
changeYear: true,
dayNames: "日一二三四五六".split(""), //设置日历上方的星期显示
dayNameTitles: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], //设置鼠标移上去时,星期的title
monthNames: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
changeMonth: false,
changeYear: false,
toggle: false,
yearRange: "y-10:y+10", //你只能改动这里面的数字
showOtherMonths: true,
Expand All @@ -250,7 +281,13 @@ define(["avalon.position", "text!avalon.datepicker.html"], function(avalon, tmpl
minDate: null,
maxDate: null,
numberOfMonths: 1,
dateFormat: "MM/dd/yyyy"
yearSuffix: "年",
onShow: avalon.noop, //当我们只点它时,就会调用此方法,this指向input,参数为VM
onHide: avalon.noop, //当我们选中一个日期时,它会使用dateFormat格式化它,将它输入到目标input里,并调用此方法,this指向input,参数为VM
titleFormat: "MM月yyyy年",
titleFormatOnlyYear: "yyyy年",
titleFormatOnlyMonth: "MM月", //可以是数组,如["风月","芽月","花月","牧月","获月","热月","果月","霞月","雾月","霜月","雪月", "雨月"]
dateFormat: "MM/dd/yyyy"//日期格式,自己设置
}
return avalon
})
10 changes: 5 additions & 5 deletions avalon.draggable.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ define(["avalon"], function(avalon) {
}
if (window.VBArray && !("msUserSelect" in document.documentElement.style)) {
var _ieSelectBack;//fix IE6789
function returnFalse() {
return false;
function returnFalse(event) {
event.returnValue = false
}
fixUserSelect = function() {
_ieSelectBack = body.onselectstart;
Expand Down Expand Up @@ -368,8 +368,8 @@ define(["avalon"], function(avalon) {
data.containment = [
$offset.left,
$offset.top,
Math.floor($offset.left + elem.offsetWidth - data.marginLeft - data.$element.width()),
Math.floor($offset.top + elem.offsetHeight - data.marginTop - data.$element.height())
Math.floor($offset.left + elem.offsetWidth - data.marginLeft ),//- data.$element.width()
Math.floor($offset.top + elem.offsetHeight - data.marginTop )//- data.$element.height()
]

}
Expand All @@ -379,7 +379,7 @@ define(["avalon"], function(avalon) {
return avalon
})
/*
ms-draggable="VMID?" , VMID为一个VM的ID,可选
ms-draggable="ID?,opt?" , ID为一个VM的ID,可选,没有为离它最近的VM;opt为VM的一个对象属性,可选
下面这些全部可用data-drag-*进行配置
drag 为VM中一个方法名
stop 为VM中一个方法名
Expand Down
37 changes: 37 additions & 0 deletions avalon.hotkeys.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>avalon.hotkeys</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="avalon.js" type="text/javascript"></script>
<style>
#aaa textarea{
width:400px;
height:200px;
border:1px solid red;
}
</style>
<script>
require("avalon.hotkeys", function(avalon) {
avalon.define("xxx", function(vm) {
vm.callback1 = function(e) {
alert(new Date - 0 + " ctrl+1")
e.preventDefault()
}
vm.callback2 = function(e) {
alert(new Date - 0 + " ctrl+alt+f")
e.preventDefault()
}
})
avalon.scan()
})
</script>
</head>
<body >
<div id="aaa" ms-controller="xxx" >
<textarea class="bbb" ms-hotkeys-ctrl+1="callback1">ctrl+1</textarea>
<textarea class="bbb" ms-hotkeys-ctrl+alt+f="callback2">ctrl+alt+f</textarea>
</div>

</body>
</html>
93 changes: 93 additions & 0 deletions avalon.hotkeys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
define(["avalon"], function(avalon) {
//组合键绑定
var specialKeys = {
8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111: "/",
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 186: ";", 191: "/",
220: "\\", 222: "'", 224: "meta"
}
var shiftNums = {
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
".": ">", "/": "?", "\\": "|"
}

function sortKey(key) {
return key.replace("++", "+add").split("+").sort().join("+")
}
var callbacks = []
function check(event, hotkeys) {
var special = specialKeys[ event.keyCode ],
//将keyCode转换为各种值
character = String.fromCharCode(event.which).toLowerCase(),
modif = "", possible = {};

// 处理各种组合情况 (alt|ctrl|shift+X)
if (event.altKey && special !== "alt") {
modif += "alt+";
}

if (event.ctrlKey && special !== "ctrl") {
modif += "ctrl+";
}

if (event.metaKey && !event.ctrlKey && special !== "meta") {
modif += "meta+";
}

if (event.shiftKey && special !== "shift") {
modif += "shift+";
}

if (character) {
possible[ sortKey(modif + character) ] = true;
possible[ sortKey(modif + shiftNums[ character ]) ] = true;

if (modif === "shift+") {
possible[ shiftNums[ character ] ] = true;
}
}
if (possible[ hotkeys ]) {
return true
}
}
avalon.bindingHandlers.hotkeys = function(data, vmodels) {
data.specialBind = function(elem, fn) {
var obj = {
elem: elem,
fn: fn,
hotkeys: sortKey(data.param)
}
callbacks.push(obj)
data.specialUnbind = function() {
avalon.Array.remove(callbacks, obj)
delete data.specialBind
delete data.specialUnbind
}
}
avalon.bindingHandlers.on(data, vmodels)
}
avalon.bindingExecutors.hotkeys = avalon. bindingExecutors.on
var root = document.documentElement
var hotkeysCallback = function(e) {
var safelist = callbacks.concat()
for (var i = 0, obj; obj = safelist[i++]; ) {
if (root.contains(obj.elem)) {
if (check.call(obj.elem, e, obj.hotkeys)) {
return obj.fn.call(obj.elem, e)
}
} else {
avalon.Array.remove(callbacks, obj)
}
}
}
avalon.bind(document, "keydown", hotkeysCallback)
return avalon
})


//用法 ms-hotkeys-ctrl+1="jumpHead" ms-hotkeys-ctrl+u="deleteLine"
Loading

0 comments on commit fcf415e

Please sign in to comment.