jquery functionn seeColor(list){ //省略 } seeColor()里面的表示什么,有时候还可以写成form

游走键盘上的苦逼。
这个系列,主要是把ractive 的一些常规用法,以及编码规范来做一个系统的讲解。
希望通过本系列可以让对ractive 感兴趣的同学。有一个初步的认识。
RactiveJS是一个模板驱动的UI库,融入了很多Backbone的元素。但又与Backbone不同,它有自己的Two-way binding引擎。
而Backbone 却需要插件支持。
Two-way binding (双向绑定) 也就是 大家常说的 MVVM 或者 MV* 什么的。
这个,它不是跟 angularjs 类似了?
二、Get started
官方给了个 “60 second setup” 教程。 简短的一段代码描述了RactiveJS 引擎的运行。
ps:目前最新稳定版是 0.7 ,后面的内容都是基于这个版本的
index.html
&!doctype html&
&html lang='en-GB'&
&meta charset='utf-8'&
&title&Ractive test&/title&
&h1&Ractive test&/h1&
1. This is the element we'll render our Ractive to.
&div id='container'&&/div&
2. You can load a template in many ways. For convenience, we'll include it in
a script tag so that we don't need to mess around with AJAX or multiline strings.
Note that we've set the type attribute to 'text/ractive' - though it can be
just about anything except 'text/javascript'
&script id='template' type='text/ractive'&
&p&Hello, {{name}}!&/p&
3. You can always get the most recent stable version from the URL below.
If you want the newest features (unstable!), use the 'edge' version instead:
http://cdn.ractivejs.org/edge/ractive.min.js
If you need IE8 support, change 'ractive' to 'ractive-legacy'.
&script src='http://cdn.ractivejs.org/latest/ractive.min.js'&&/script&
4. We've got an element in the DOM, we've created a template, and we've
loaded the library - now it's time to build our Hello World app.
var ractive = new Ractive({
// The `el` option can be a node, an ID, or a CSS selector.
el: '#container',
// We could pass in a string, but for the sake of convenience
// we're passing the ID of the &script& tag above.
template: '#template',
// Here, we're passing in some initial data
data: { name: 'world' }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
&!doctype html&&html lang='en-GB'&&head&&&&meta charset='utf-8'&&&&title&Ractive test&/title&&/head&&&body&&&&h1&Ractive test&/h1&&&&&!--&&&&&& 1. This is the element we'll render our Ractive to.&&--&&&&div id='container'&&/div&&&&&!--&&&&&& 2. You can load a template in many ways. For convenience, we'll include it in&&&&&& a script tag so that we don't need to mess around with AJAX or multiline strings.&&&&&& Note that we've set the type attribute to 'text/ractive' - though it can be&&&&&& just about anything except 'text/javascript'&&--&&&&script id='template' type='text/ractive'&&&&&&p&Hello, {{name}}!&/p&&&&/script&&&&&!--&&&&&& 3. You can always get the most recent stable version from the URL below.&&&&&& If you want the newest features (unstable!), use the 'edge' version instead:&&&&&&&&&&& http://cdn.ractivejs.org/edge/ractive.min.js&&&&&&& If you need IE8 support, change 'ractive' to 'ractive-legacy'.&&--&&&&script src='http://cdn.ractivejs.org/latest/ractive.min.js'&&/script&&&&&!--&&&&&& 4. We've got an element in the DOM, we've created a template, and we've&&&&&& loaded the library - now it's time to build our Hello World app.&&--&&&&script&&&&&var ractive = new Ractive({&&&&&&// The `el` option can be a node, an ID, or a CSS selector.&&&&&&el: '#container',&&&&&&&// We could pass in a string, but for the sake of convenience&&&&&&// we're passing the ID of the &script& tag above.&&&&&&template: '#template',&&&&&&&// Here, we're passing in some initial data&&&&&&data: { name: 'world' }&&&&});&&&/script&&/body&&/html&
我们可以用官方提供的CDN来引入基础库文件
&script src='http://cdn.ractivejs.org/latest/ractive.min.js'&&/script&
&script src='http://cdn.ractivejs.org/latest/ractive.min.js'&&/script&
然后跟大多数框架类似,我们需要一个模板。RactiveJS支持,字符串,或者以script text 类型的容器。
&script id='template' type='text/ractive'&
&p&Hello, {{name}}!&/p&
<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda
&script id='template' type='text/ractive'&&&&&&p&Hello, {{name}}!&/p& &/script&
最后就是初始化代码。至此,一个基本的RactiveJS Demo 就完成了。
var ractive = new Ractive({
// The `el` option can be a node, an ID, or a CSS selector.
el: '#container',
// We could pass in a string, but for the sake of convenience
// we're passing the ID of the &script& tag above.
template: '#template',
// Here, we're passing in some initial data
data: { name: 'world' }
<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda
&script&&&&&var ractive = new Ractive({&&&&&&// The `el` option can be a node, an ID, or a CSS selector.&&&&&&el: '#container',&&&&&&&// We could pass in a string, but for the sake of convenience&&&&&&// we're passing the ID of the &script& tag above.&&&&&&template: '#template',&&&&&&&// Here, we're passing in some initial data&&&&&&data: { name: 'world' }&&&&});&&&/script&
el 可以是一个选择器,或者Element元素。 指示将要运行引擎的容器。
template 可以是一个选择器,一段文本。或RactiveJS (Ractive.parse())预编译的模板对象。
可以理解为,需要绑定的数据源。 在data里面指定的变量,可以随意的在template里面使用。
RactiveJS 内置了基本的选择器模块,Template引擎,封装的Event,Node等对象。
所以如果没有特别的需求,我们几乎可以不用jQuery 这类框架了。
点到为止。
后面几个阶段,我们就RactiveJS的配置项,内置API及用法做详细说明。
好长一段时间都在研究一些奇怪的前端框架,为的是找到适合自己的一套前端解决方案。
直到遇到ractive.js , 这是一款国外的JS大牛()写的。
因为有研究过angularjs。知道了“脏值检测”,才真正对这系列的框架感兴趣,也就是大家都叫的MVVM,Two-way binding等。
这个文章不讲怎么写Ractivejs的基础代码,而是来说说components 组件的写法。
Shadow DOM API 我想做过JS的都有了解过。
template,css,js
当我们把这些以往死了都要拆开的东西又放到一堆。就有了Shadow DOM Components 的意思了。
Ractivejs有提供的rvc.js工具 就很好的实现了这种想法。另外值得一提的是,google做这个算是做到了极致(请移步:http://www.polymer-project.org)
基于Ractivejs + rvc.js 结合下 Shadow DOM 的思想。就有了
ractivejs components template
&!-- template --&
&div class="ui-com"&
这里可以写羞羞的代码。。。
&!-- CSS --&
.ui-com{ color:#f00 }
&!-- JavaScript --&
component.exports = {
onrender: function () {
//组件渲染完成的回调
123456789101112131415161718
&!-- template --&&div class="ui-com"&&&&&这里可以写羞羞的代码。。。&/div&&&!-- CSS --&&style&&&&&.ui-com{ color:#f00 }&/style&&&!-- JavaScript --&&script&&&&&component.exports = {&&&&&&&&onrender: function () {&&&&&&&&&&&&//组件渲染完成的回调&&&&&&&&}&&&&};&/script&
这段代码看似很简单。但是很好的归纳了HTML组件的几个要素。在Shadow DOM 不怎么流行,或说受限于浏览器版本的时候。
我们可以用这种方式很好的来组织我们的组件代码。
使用同样让人很愉悦
基于requirejs 插件机制的导入
JavaScript
//基于requirejs 插件机制的导入
require([ 'rvc!foo' ], function ( Foo ) {
var ractive = new Foo({ /* ... */ });
define([ 'rvc!foo' ], function ( Foo ) {
var ractive = new Foo({ /* ... */ });
//基于requirejs 插件机制的导入require([ 'rvc!foo' ], function ( Foo ) {&&var ractive = new Foo({ /* ... */ });});&define([ 'rvc!foo' ], function ( Foo ) {&&var ractive = new Foo({ /* ... */ });});
直接用link引入
&!-- 引入组件 --&
&link rel='ractive' href='./foo' name='foo' /&
&!-- 使用方法 --&
&!-- 其它羞羞的代码 --&
&!-- 引入组件 --&&link rel='ractive' href='./foo' name='foo' /&&&!-- 使用方法 --&&foo /&&&!-- 其它羞羞的代码 --&
看到这些代码,大家的顾忌肯定是,这不就是一种规范嘛,肯定是需要预编译的。浏览器怕是吃不销。
然而退一步说,我们要的就是一种规范,也许我就是想让我一个写HTML代码的人,能用这种规则来写组件。
比起写成片的JS代码,看着要直接的多。
剩下的事情,让Ractivejs 配合 Nodejs 做个及时编译。感觉效果还是挺美的。
点到为止,看完你可能对这几个字眼感兴趣。
http://www.ractivejs.org/
/ractivejs/rvc
https://www.polymer-project.org/
So&#8230; 下次再聊Ractivejs 的入门吧。
工作需要,写了个时间分割的 小函数。
传入上班时间段 , 午休时间段和分割区间 即可 得出所有从开始到结束的时间分割区间。
使用方法:
时间分割算法
JavaScript
* 时间分割函数
* @param se 上班时间段 开始 - 结束
* @param ee 休息时间段 开始 -
* @param sp 分割区间(0.5 , 1...等)
* @returns {Array}
function sp_time(se, ee, sp) {
se = se.split("-"), ee = ee.split("-");
sp = sp * 60;
var times = [], _sp = [];
var t = _t(ee[0]), e = _t(ee[1]),
s = _t(se[0]), d = _t(se[1]);
for (var i = s, l = i &= i++) {
if (i & t && i & e) {
i = i + (e - t);
if (i == s || i == d || i % sp == 0) {
var h = (i / 60 && 0), s = (i % 60);
h = h & 10 ? "0" + h :
s = s & 10 ? "0" + s :
times.push(h + ":" + s);
for (var i = 0, l = times. i & l - 1; i--) {
_sp.push(times[i++] + " ~ " + times[i++]);
function _t(t) {
t = t.split(":");
t[1] = t[1] / 60;
return parseFloat(parseFloat(t[0]) + t[1]) * 60
var arr = sp_time("9:00-18:00", "12:00-14:00", 0.5);
console.log(arr.join("\r\n"));
12345678910111213141516171819202122232425262728293031323334353637383940414243
/**&&&& * 时间分割函数&&&& * @param se 上班时间段 开始 - 结束&&&& * @param ee 休息时间段 开始 -&&结束&&&& * @param sp 分割区间(0.5 , 1...等)&&&& * @returns {Array}&&&& */&&&&function sp_time(se, ee, sp) {&&&&&&&&&se = se.split("-"), ee = ee.split("-");&&&&&&&&sp = sp * 60;&&&&&&&&&var times = [], _sp = [];&&&&&&&&var t = _t(ee[0]), e = _t(ee[1]),&&&&&&&&&&&&s = _t(se[0]), d = _t(se[1]);&&&&&&&&&for (var i = s, l = d; i &= l; i++) {&&&&&&&&&&&&if (i & t && i & e) {&&&&&&&&&&&&&&&&i = i + (e - t);&&&&&&&&&&&&}&&&&&&&&&&&&&if (i == s || i == d || i % sp == 0) {&&&&&&&&&&&&&&&&var h = (i / 60 && 0), s = (i % 60);&&&&&&&&&&&&&&&&h = h & 10 ? "0" + h : h;&&&&&&&&&&&&&&&&s = s & 10 ? "0" + s : s;&&&&&&&&&&&&&&&&times.push(h + ":" + s);&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&&for (var i = 0, l = times.length; i & l - 1; i--) {&&&&&&&&&&&&_sp.push(times[i++] + " ~ " + times[i++]);&&&&&&&&}&&&&&&&&&return _sp;&&&&&&&&function _t(t) {&&&&&&&&&&&&t = t.split(":");&&&&&&&&&&&&t[1] = t[1] / 60;&&&&&&&&&&&&return parseFloat(parseFloat(t[0]) + t[1]) * 60&&&&&&&&}&&&&}&&&&&var arr = sp_time("9:00-18:00", "12:00-14:00", 0.5);&&&&console.log(arr.join("\r\n"));
http://blog.csdn.net/wts/article/details/
http://www.blogjava.net/JAVA-HE/archive//242477.html?opt=admin
/hxling/archive//2791067.html
安装及配置
官方网站:/jsdoc3/jsdoc/
建议不要直接通过“Download ZIP”功能直接下载,而是到Release中下载稳定版本,比如3.2.2
下载后,直接解压到某个目录,比如d:\jsdoc
然后设置windows环境变量,在path中增加d:\jsdoc,这样我们在那个目录下,都可以执行jsdoc命令了。当然还有个前提,就是windows环境变量中已经把jdk配置好了。
假设要对d:\js\myjs.js生成jsdoc文档,则:
1、打开dos窗口
2、在dos窗口中执行命令:
view plaincopy在CODE上查看代码片派生到我的代码片
jsdoc d:\js\myjs.js
jsdoc d:\js\myjs.js
回车后,会在d:\js目录下生成一个out文件夹,里面就是html形式的doc了。
如果要对js目录中所有js文件生成文档,则执行:
view plaincopy在CODE上查看代码片派生到我的代码片
jsdoc d:\js
jsdoc d:\js
如果要对js目录中的个别文件生成文档,则执行:
view plaincopy在CODE上查看代码片派生到我的代码片
jsdoc d:\js\a.js d:\js\b.js
<div class="crayon-num" data-line="crayon-56fda9
jsdoc d:\js\a.js d:\js\b.js
如果要指定生成文档的目录,则可以在命令行后继续增加参数: -d d:\out
这个时候,jsdoc是使用的默认模板生成的jsdoc,效果不是很理想,我们需要找到好一点的模板。
执行jsdoc &#8211;help,回车,我们会看到该命令支持的所有参数。
jsdoc的完整官方文档:http://usejsdoc.org/
执行jsdoc &#8211;debug,回车,我们会看到一个Java窗口程序,好像是Rhino的,不懂,这个窗口跟调试有关。
执行命令生成doc 文档
jsdoc .\WLogin.js -t d:\docstrap\template -c d:\docstrap\template\jsdoc.conf.json -d d:\docstrap_doc
<div class="crayon-num" data-line="crayon-56fda
jsdoc .\WLogin.js -t d:\docstrap\template -c d:\docstrap\template\jsdoc.conf.json -d d:\docstrap_doc
gulp下使用,jsdoc插件()
grunt 下面有jsdoc 插件,最近弄gulp 也顺便搜了下。发现gulp版本的 jsdoc 也有了。
github地址:/jsBoot/gulp-jsdoc
具体使用方法也比较傻瓜。
首先,安装
npm install --save-dev gulp-jsdoc
npm install --save-dev gulp-jsdoc
JavaScript
var jsdoc = require("gulp-jsdoc");
gulp.src("./src/*.js")
.pipe(jsdoc('./documentation-output'))
<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda<div class="crayon-num" data-line="crayon-56fda<div class="crayon-num crayon-striped-num" data-line="crayon-56fda
var jsdoc = require("gulp-jsdoc");&gulp.src("./src/*.js").pipe(jsdoc('./documentation-output'))
之前也有知道鼠标的滚轮事件,但是今天有以前的同事问到我,让我给你个demo。
我尝试用jQuery 来写了下,发现居然在firefox 下居然没效果。
JavaScript
var $doc = $(document);
$doc.bind("mousewheel", function (event) {
var oriEvent = originalEvent,
scrollTop = this.scrollTop || 0;
this.scrollTop = (scrollTop + ((event.deltaY * event.deltaFactor) * -1));
if (oriEvent.deltaY & 0 && this.scrollTop % 300 == 0) {
console.log("up")
} else if (oriEvent.deltaY & 0 && this.scrollTop % 300 == 0) {
console.log("down")
12345678910111213
var $doc = $(document);$doc.bind("mousewheel", function (event) {&&&&var oriEvent = originalEvent,&&&&&&&&scrollTop = this.scrollTop || 0;&&&&&this.scrollTop = (scrollTop + ((event.deltaY * event.deltaFactor) * -1));&&&&&if (oriEvent.deltaY & 0 && this.scrollTop % 300 == 0) {&&&&&&&&console.log("up")&&&&} else if (oriEvent.deltaY & 0 && this.scrollTop % 300 == 0) {&&&&&&&&console.log("down")&&&&}});
搜了下资料,原来是firefox 下面 mousewheel 不支持这个;
firefox 下面要用 DOMMouseScroll 代替。更多差异请见表。
以上输出差异见下面(IE7, IE10, Chrome, 以及FireFox,鼠标向下滚动, win7)(可单独查看表格内容):
属性名\浏览器
×没有该属性
×没有该属性
×没有该属性
DOMMouseScroll
mousewheel
mousewheel
mousewheel
fromElement
×没有该属性
×没有该属性
[object HTMLDivElement]
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
behaviorCookie
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
contentOverflow
×没有该属性
×没有该属性
×没有该属性
behaviorPart
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
dataTransfer
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
returnValue
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
wheelDelta
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
cancelBubble
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
srcElement
×没有该属性
[object HTMLDivElement]
[object HTMLDivElement]
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
boundElements
×没有该属性
×没有该属性
×没有该属性
propertyName
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
initMouseWheelEvent
×没有该属性
×没有该属性
function initMouseWheelEvent() { [native code] }
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
relatedTarget
×没有该属性
getModifierState
function getModifierState() { [native code] }
×没有该属性
function getModifierState() { [native code] }
×没有该属性
initMouseEvent
function initMouseEvent() { [native code] }
function initMouseEvent() { [native code] }
function initMouseEvent() { [native code] }
×没有该属性
×没有该属性
[object Window]
[object Window]
[object Window]
×没有该属性
initUIEvent
function initUIEvent() { [native code] }
function initUIEvent() { [native code] }
function initUIEvent() { [native code] }
×没有该属性
×没有该属性
cancelable
×没有该属性
currentTarget
[object HTMLBodyElement]
[object HTMLBodyElement]
[object HTMLBodyElement]
×没有该属性
defaultPrevented
×没有该属性
eventPhase
×没有该属性
×没有该属性
×没有该属性
[object HTMLDivElement]
[object HTMLDivElement]
[object HTMLDivElement]
×没有该属性
×没有该属性
function initEvent() { [native code] }
function initEvent() { [native code] }
function initEvent() { [native code] }
×没有该属性
preventDefault
function preventDefault() { [native code] }
function preventDefault() { [native code] }
function preventDefault() { [native code] }
×没有该属性
stopImmediate
Propagation
function stopImmediate
Propagation() { [native code] }
function stopImmediate
Propagation() { [native code] }
function stopImmediate
Propagation() { [native code] }
×没有该属性
stopPropagation
function stopPropagation() { [native code] }
function stopPropagation() { [native code] }
function stopPropagation() { [native code] }
×没有该属性
×没有该属性
BUBBLING_PHASE
×没有该属性
CAPTURING_PHASE
×没有该属性
webkitDirection
InvertedFromDevice
×没有该属性
×没有该属性
×没有该属性
wheelDeltaY
×没有该属性
×没有该属性
×没有该属性
wheelDeltaX
×没有该属性
×没有该属性
×没有该属性
webkitMovementY
×没有该属性
×没有该属性
×没有该属性
webkitMovementX
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
clipboardData
×没有该属性
×没有该属性
×没有该属性
initWebKitWheelEvent
×没有该属性
function initWebKitWheelEvent() { [native code] }
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
rangeParent
[object HTMLDivElement]
×没有该属性
×没有该属性
×没有该属性
rangeOffset
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
mozMovementX
×没有该属性
×没有该属性
×没有该属性
mozMovementY
×没有该属性
×没有该属性
×没有该属性
mozPressure
×没有该属性
×没有该属性
×没有该属性
mozInputSource
×没有该属性
×没有该属性
×没有该属性
initNSMouseEvent
function initNSMouseEvent() { [native code] }
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
initMouseScrollEvent
function initMouseScrollEvent() { [native code] }
×没有该属性
×没有该属性
×没有该属性
originalTarget
[object HTMLDivElement]
×没有该属性
×没有该属性
×没有该属性
explicitOriginalTarget
[object HTMLDivElement]
×没有该属性
×没有该属性
×没有该属性
preventBubble
function preventBubble() { [native code] }
×没有该属性
×没有该属性
×没有该属性
preventCapture
function preventCapture() { [native code] }
×没有该属性
×没有该属性
×没有该属性
getPreventDefault
function getPreventDefault() { [native code] }
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
CONTROL_MASK
×没有该属性
×没有该属性
×没有该属性
SHIFT_MASK
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
×没有该属性
SCROLL_PAGE_UP
×没有该属性
×没有该属性
×没有该属性
SCROLL_PAGE_DOWN
×没有该属性
×没有该属性
×没有该属性
MOZ_SOURCE_UNKNOWN
×没有该属性
×没有该属性
×没有该属性
MOZ_SOURCE_MOUSE
×没有该属性
×没有该属性
×没有该属性
MOZ_SOURCE_PEN
×没有该属性
×没有该属性
×没有该属性
MOZ_SOURCE_ERASER
×没有该属性
×没有该属性
×没有该属性
MOZ_SOURCE_CURSOR
×没有该属性
×没有该属性
×没有该属性
MOZ_SOURCE_TOUCH
×没有该属性
×没有该属性
×没有该属性
MOZ_SOURCE_KEYBOARD
×没有该属性
×没有该属性
×没有该属性
HORIZONTAL_AXIS
×没有该属性
×没有该属性
×没有该属性
VERTICAL_AXIS
×没有该属性
×没有该属性
×没有该属性
顺便推荐下jQuery mousewheel 插件/brandonaaron/jquery-mousewheel
所以上面的代码要改进了
JavaScript
var $doc = $(document);
$doc.bind("mousewheel DOMMouseScroll",function(event){
var $doc = $(document);&$doc.bind("mousewheel DOMMouseScroll",function(event){//...&});
这样一来,就能兼容forefox了。
另外值得一提的是,我们要获取滚轮的delta。有说法是获取 event.wheelDelta 属性
但是我尝试了多次,在我的firefox下得到的都是 undefined 。后来看了下资料,发现wheelDelta不是标准的.
所以在很多情况下是获取不到 wheelDelta。
有篇讨论这个问题的帖子,可以看看/questions/8886281/event-wheeldelta-returns-undefined
引用Rob W的回复:
The event object in a jQuery event handler does not reflect the real event. wheelDelta is a non-standard event property IE and Opera, available through the originalEvent property of the jQuery event.
In jQuery 1.7+, the detail property is not available at the jQuery Event object. So, you should also use event.originalEvent.detail to for this property at the DOMMouseScroll event. This method is backwards-compatible with older jQuery versions.
event.originalEvent.wheelDelta
Demo: http://jsfiddle.net/eXQf3/22/
See also: /category/events/event-object/
这里有个解决方案可以用:
JavaScript
function extractDelta(e) {
if (e.wheelDelta) {
return e.wheelD
if (e.originalEvent.detail) {
return e.originalEvent.detail * -40;
if (e.originalEvent && e.originalEvent.wheelDelta) {
return e.originalEvent.wheelD
12345678910111213
function extractDelta(e) {&&&&if (e.wheelDelta) {&&&&&&&&return e.wheelDelta;&&&&}&&&&&if (e.originalEvent.detail) {&&&&&&&&return e.originalEvent.detail * -40;&&&&}&&&&&if (e.originalEvent && e.originalEvent.wheelDelta) {&&&&&&&&return e.originalEvent.wheelDelta;&&&&}}
后面还发现浏览器间对于 delta的值也是有所不同的。所以使用的时候,最好根据实际情况做处理。
jQuery在1.5开始引入deferred(延迟),简单说,deferred对象就是jQuery的回调函数解决方案。
jQuery1.5中,Deferred对象提供一种方式来注册多个回调,添加到自已管理的回调队列中,调用适当的回调队列,并转达同步或异步函数的成功或失败状态。
deferred对象有三种执行状态:未完成(pending),已完成(resolved)和已失败(rejected)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051deferred object = &#123;
& & always&#40;alwaysCallbacks &#91;, alwaysCallbacks&#93;&#41;
& & //延迟对象不管成功或失败都最终会执行该方法
& & done&#40;doneCallbacks&#41;
& & //延迟对象成功完成后调用
& & fail&#40;failCallbacks&#41;
& & //延迟对象失败后调用
& & isRejected&#40;&#41;
& & //确定延迟对象是否已失败
& & isResolved&#40;&#41;
& & //确定延迟对象是否已成功
& & notify&#40; args &#41;
& & //用来触发一个自定义事件fireEvent
& & notifyWith&#40;context, &#91;args&#93;&#41;
& & //跟notify一样,但可以指定上下文
& & pipe&#40;&#91;doneFilter&#93; &#91;, failFilter&#93; &#91;, progressFilter&#93; &#41;
& & //jQuery的1.8,deferred.pipe()方法已经被淘汰。
& & //用deferred.then()替代
& & progress&#40; progressCallbacks &#41;
& & //用来监控函数执行过程,进度处理程序,见:notify 方法
& & reject&#40;&#91;args&#93;&#41;
& & //使延迟对象的状态变为失败,对应的回调函数绑定方法为fail。
& & rejectWith&#40;context, &#91;args&#93;&#41;
& & //使用方法与reject一样,但是可以指定上下文,使用可以参考 resolveWidth
& & resolve&#40;&#91;args&#93;&#41;
& & //使延迟对象的状态变为成功,对应的回调函数绑定方法为done。
& & resolveWith&#40;context, &#91;args&#93;&#41;
& & //使用方法与resolve一样,但是可以指定上下文
& & state&#40;&#41;
& & //查询延迟对象的状态,有三种:pending resolved rejected
& & then&#40;doneCallbacks, failCallbacks &#91;, progressCallbacks&#93;&#41;
& & //一种缩写,用法与done,fail一样
& & promise&#40;&#91;target&#93;&#41;
& & //在原来的deferred对象上返回另一个deferred对象,
& & //这个新的deferred对象屏蔽了改变状态的方法。
入门应用:
123$.ajax&#40;&test.php&&#41;
.done&#40;function&#40;&#41;&#123; alert&#40;&成功了!&&#41;; &#125;&#41;
.fail&#40;function&#40;&#41;&#123; alert&#40;&出错啦!&&#41;; &#125;&#41;;
从1.5开始,ajax对象不再返回xhr对象,而是deferred对象。通过.done执行成功回调,通过.fail执行失败回调。
返回一个Deferred对象,允许你为多个事件指定一个回调函数。
123$.when&#40;$.ajax&#40;&test.php&&#41;,$.ajax&#40;&test2.php&&#41;&#41;
.done&#40;function&#40;&#41;&#123; alert&#40;&成功了!&&#41;; &#125;&#41;
.fail&#40;function&#40;&#41;&#123; alert&#40;&出错啦!&&#41;; &#125;&#41;;
这是一个与操作,只有test.php和test2.php都成功时才会执行done,否则执行
2、resolve和reject的用法
123456789101112131415var def = $.Deferred&#40;&#41;; //创建deferred对象
var readConf = function&#40;&#41;&#123;
& & fs.readFile&#40;'test.txt','utf-8', function&#40;err, data&#41; &#123;
& & & & if &#40;err&#41; &#123;
& & & & & &def.reject&#40;&#41;; //改变deferred对象状态成失败
& & & & &#125; else &#123;
& & & & & &def.resolve&#40;&#41;; //改变deferred对象状态成成功
& & & & &#125;
& & &#125;&#41;;
& & return def; &//返回
$.when&#40;readConf&#40;&#41;&#41;
.done&#40;function&#40;&#41;&#123; alert&#40;&成功了!&&#41;; &#125;&#41;
.fail&#40;function&#40;&#41;&#123; alert&#40;&出错啦!&&#41;; &#125;&#41;;
3、promise用法
例2中,定义的def为全局变量,在作用域范围内,可以通过def.reject()或def.resolve()来改变其本身的状态,这样影响def的安全性,promise在原来的deferred对象上返回另一个deferred对象,这个新的deferred对象屏蔽了改变状态的方法。
1234567891011121314151617var def = $.Deferred&#40;&#41;; //创建deferred对象
var readConf = function&#40;&#41;&#123;
& & fs.readFile&#40;'test.txt','utf-8', function&#40;err, data&#41; &#123;
& & & & if &#40;err&#41; &#123;
& & & & & &def.reject&#40;&#41;; //改变deferred对象状态成失败
& & & & &#125; else &#123;
& & & & & &def.resolve&#40;&#41;; //改变deferred对象状态成成功
& & & & &#125;
& & &#125;&#41;;
& & return def.promise&#40;&#41;; &//通过promise返回deferred对象,起到状态保护作用
$.when&#40;readConf&#40;&#41;&#41;
.done&#40;function&#40;&#41;&#123; alert&#40;&成功了!&&#41;; &#125;&#41;
.fail&#40;function&#40;&#41;&#123; alert&#40;&出错啦!&&#41;; &#125;&#41;;
def.reject&#40;&#41;; //更改无效
4、notify和progress用法
两者一般结合使用,有点自定义事件的意思。
123456789101112131415161718192021var def = $.Deferred&#40;&#41;; //创建deferred对象
var readConf = function&#40;&#41;&#123;
& & def.notify&#40;'start'&#41;;
& & fs.readFile&#40;'test.txt','utf-8', function&#40;err, data&#41; &#123;
& & & & if &#40;err&#41; &#123;
& & & & & & def.reject&#40;&#41;; //改变deferred对象状态成失败
& & & & & & def.notify&#40;'fail'&#41;;
& & & & &#125; else &#123;
& & & & & & def.resolve&#40;&#41;; //改变deferred对象状态成成功
& & & & & & def.notify&#40;'success'&#41;;
& & & & &#125;
& & &#125;&#41;;
& & return def;
$.when&#40;readConf&#40;&#41;&#41;
.progress&#40;function&#40;_event&#41;&#123;
& & console.log&#40;_event&#41;; //打印start,fail 或 start,success
& & //_event是def.notify参数中指定的自定义事件名,是一个字符串
& & //此处可以跟据不同事件进行相应的逻辑处理
&#125;&#41;;
5、then用法
12$.when&#40;readConf&#40;&#41;&#41;
.then&#40;function&#40;&#41;&#123; alert&#40;&成功了!&&#41;; &#125;,function&#40;&#41;&#123; alert&#40;&出错啦!&&#41;; &#125;&#41;;
最近公司项目有需求,所以把一个插件进行了二次封装。并且在基础上完善了部分功能。最后就成了一个上传组件。
部分功能还会继续完善,后续再更新。
这就不啰嗦了,直接放代码了
123456789101112131415161718192021222324252627282930&div class=&select_imgb& id=&crop-wrap&&
& & &form data-action=&imgupuload.do& method=&post& enctype=&multipart/form-data& target=&imgifr& data-dom=&form&&
& & & & &input type=&text& name=&x& data-dom=&x&/&
& & & & &input type=&text& name=&y& data-dom=&y&/&
& & & & &input type=&text& name=&w& data-dom=&w&/&
& & & & &input type=&text& name=&h& data-dom=&h&/&
& & & & &input type=&text& name=&u& data-dom=&u&/&
& & & & &iframe class=&upload-iframe& id=&imgifr& name=&imgifr& src=&about:blank&&&/iframe&
& & & & &div class=&clearfix&&
& & & & & & &div class=&upload-btn&&
& & & & & & & & &input class=&file& data-dom=&file& name=&file& type=&file&/&
& & & & & & & & &a href=&javascript:void(0);&&&span&&span&选择头像&/span&&/span&&/a&
& & & & & & &/div&
& & & & &/div&
& & & & &p class=&mt_5&&仅支持上传大小3MB以内,JPG、PNG、GIF、BMP格式的图片&/p&
& & & & &div class=&crop-box clearfix&&
& & & & & & &div class=&crop-box-left&&
& & & & & & & & &div class=&crop-img-adapt& data-dom=&adapt&&
& & & & & & & & & & &img src=&./crop/crop2.jpg& alt=&& data-dom=&crop&/&
& & & & & & & & &/div&
& & & & & & &/div&
& & & & & & &div class=&crop-box-right&&
& & & & & & & & &div class=&crop-img-small&&
& & & & & & & & & & &img src=&./crop/crop2.jpg& alt=&& data-dom=&small&/&
& & & & & & & & &/div&
& & & & & & & & 头像预览
& & & & & & &/div&
& & & & &/div&
& & &/form&
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869/* crop ui */
.upload-btn &#123;
& & display: block;
& & float: left;
& & margin-right: 5px;
& & overflow: hidden;
& & width: 68px;
& & height: 25px;
& & position: relative;
.upload-btn input &#123;
& & position: absolute;
& & height: 25px;
& & width: 68px;
& & opacity: 0;
& & cursor: pointer;
.upload-iframe &#123;
& & display: none;
.crop-box &#123;
& & width: 360px;
.crop-img-small &#123;
& & overflow: hidden;
& & padding: 0;
& & width: 96px;
& & height: 96px;
& & text-align:center;
& & border: 1px solid #cccccc;
.crop-box-left &#123;
& & float: left;
.crop-box-right &#123;
& & float: right;
.crop-img-adapt &#123;
& & width: 256px;
& & height: 248px;
& & border: 1px solid #cccccc;
.crop-img-adapt img&#123;
& & max-width: 100%;
& & max-height: 100%;
.clearfix:after &#123;
& & content: &\0020&;
& & display: block;
& & height: 0;
& & clear: both
.clearfix &#123;
& & _zoom: 1
*+html .clearfix &#123;
& & overflow: hidden
JavaScript:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406/**
&* 截图上传控件
&* development by Ryan
&* mail: zengyi.
&* useing jQuery JavaScript frame v1.6.1+
;;;&#40;function &#40;$&#41; &#123;
& & &* 构造函数
& & &* @constructor
& & var Cutting = function &#40;&#41; &#123;
& & & & this.initialize.apply&#40;this, arguments&#41;;
& & &#125;
& & &* 扩展原型
& & &* @type {{constructor: Function, initialize: Function, create: Function, position: Function, select: Function, update: Function, setCrop: Function, preview: Function, imgReady: null}}
& & Cutting.prototype = &#123;
& & & & //构造函数
& & & & constructor: Cutting,
& & & & //初始化函數
& & & & initialize: function &#40;element, options&#41; &#123;
& & & & & & var t = this;
& & & & & & this.element = $&#40;element&#41;;
& & & & & & this.options = $.extend&#40;true, &#123;
& & & & & & & & SIZE_MID: 96.0,
& & & & & & & & maxWidth: 256.0,
& & & & & & & & maxHeight: 248.0,
& & & & & & & & drag: false,
& & & & & & & & initcallback: function &#40;&#41; &#123;
& & & & & & & & &#125;,
& & & & & & & & dblcallback: function &#40;&#41; &#123;
& & & & & & & & &#125;
& & & & & & &#125;, options&#41;;
& & & & & & this.maxWidth = this.options.maxWidth;
& & & & & & this.maxHeight = this.options.maxHeight;
& & & & & & this.SIZE_MID = this.options.SIZE_MID;
& & & & & & this.dblclick = this.options.dblcallback;
& & & & & & //初始化dom
& & & & & & this.element.find&#40;&[data-dom]&&#41;.each&#40;function &#40;i, o&#41; &#123;
& & & & & & & & var dom = $&#40;o&#41;, domName = dom.data&#40;&dom&&#41;;
& & & & & & & & domName && &#40;t&#91;domName&#93; = dom&#41;;
& & & & & & &#125;&#41;;
& & & & & & this.action = this.form.data&#40;&action&&#41; || &&;
& & & & & & this.form.attr&#40;&action&, this.action&#41;;
& & & & & & this.file.change&#40;function &#40;e&#41; &#123;
& & & & & & & & t.select&#40;this&#41;;
& & & & & & &#125;&#41;;
& & & & & & this.options.drag && this.create&#40;this.options.initcallback&#41;;
& & & & &#125;,
& & & & /**
& & & & &* 自适应图片,并创建控件
& & & & &* @param img
& & & & &* @param afterAdapt
& & & & &*/
& & & & create: function &#40;img, afterAdapt&#41; &#123;
& & & & & & var t = this;
& & & & & & if &#40;typeof img === &function&&#41; &#123;
& & & & & & & & afterAdapt = img, img = null;
& & & & & & &#125;
& & & & & & img = img || t.crop&#91;0&#93;;
& & & & & & //预先设置图片不可见,以防出现闪烁的情况。
& & & & & & img.style.visibility = 'hidden';
& & & & & & var maxHeight = this.maxHeight, maxWidth = this.maxWidth;
& & & & & & var aspect = maxWidth / maxHeight;
& & & & & & //利用imgReady提前获取图片大小自适应大小
& & & & & & t.imgReady&#40;img.src, function &#40;&#41; &#123;
& & & & & & & & var w = this.width, h = this.height, adaptW, adaptH;
& & & & & & & & var picAspect = w / h;
& & & & & & & & if &#40;w &= maxWidth && h &= maxHeight&#41; &#123;
& & & & & & & & & & adaptW = w;
& & & & & & & & & & adaptH = h;
& & & & & & & & &#125; else &#123;
& & & & & & & & & & if &#40;picAspect & aspect&#41; &#123;
& & & & & & & & & & & & adaptW = w & maxWidth ? maxWidth : w;
& & & & & & & & & & & & adaptH = adaptW / w * h;
& & & & & & & & & & &#125; else &#123;
& & & & & & & & & & & & adaptH = h & maxHeight ? maxHeight : h;
& & & & & & & & & & & & adaptW = adaptH / h * w;
& & & & & & & & & & &#125;
& & & & & & & & &#125;
& & & & & & & & img.width = adaptW;
& & & & & & & & img.height = adaptH;
& & & & & & & & img.style.visibility = 'visible';
& & & & & & &#125;, function &#40;&#41; &#123;
& & & & & & & & t.position&#40;&#41;;
& & & & & & & & if &#40;t.cropApi&#41; &#123;
& & & & & & & & & & t.update&#40;img&#41;;
& & & & & & & & &#125; else &#123;
& & & & & & & & & & t.setCrop&#40;img, img.width, img.height, t.options.initcallback&#41;;
& & & & & & & & &#125;
& & & & & & & & typeof afterAdapt === 'function' && afterAdapt.call&#40;img, img.width, img.height&#41;;
& & & & & & &#125;, function &#40;&#41; &#123;
& & & & & & & & window.console && console.log&#40;&图片加载失败!&&#41;;
& & & & & & &#125;&#41;;
& & & & &#125;,
& & & & /**
& & & & &* &设置图片位置
& & & & &*/
& & & & position: function &#40;&#41; &#123;
& & & & & & var t = this, maxWidth = this.maxWidth, maxHeight = this.maxHeight;
& & & & & & var crop = t.crop, width = crop.width&#40;&#41;, height = crop.height&#40;&#41;;
& & & & & & console.log&#40;&#91;maxWidth, maxHeight, width, height&#93;&#41;;
& & & & & & crop.css&#40;&#123;
& & & & & & & & marginLeft: &#40;width & maxWidth&#41; ? &#40;maxWidth - width&#41; / 2 : 0,
& & & & & & & & marginTop: &#40;height & maxHeight&#41; ? &#40;maxHeight - height&#41; / 2 : 0
& & & & & & &#125;&#41;;
& & & & &#125;,
& & & & /**
& & & & &* 选中文件后
& & & & &* @param fileInput
& & & & &*/
& & & & select: function &#40;fileInput&#41; &#123;
& & & & & & var t = this;
& & & & & & var files = fileInput.files;
& & & & & & if &#40;files&#41; &#123;
& & & & & & & & //ff and chrome
& & & & & & & & if &#40;!files.length&#41; &#123;
& & & & & & & & & & return;
& & & & & & & & &#125;
& & & & & & & & //遍历files并处理
& & & & & & & & for &#40;var i = 0; i & files.length; i++&#41; &#123;
& & & & & & & & & & var file = files&#91;i&#93;;
& & & & & & & & & & var imageType = /image.*/;
& & & & & & & & & & //通过type属性进行图片格式过滤
& & & & & & & & & & if &#40;!file.type.match&#40;imageType&#41;&#41; &#123;
& & & & & & & & & & & & continue;
& & & & & & & & & & &#125;
& & & & & & & & & & standardHandle&#40;file&#41;;
& & & & & & & & &#125;
& & & & & & &#125; else &#123;
& & & & & & & & //ie
& & & & & & & & ieHandle&#40;&#41;;
& & & & & & &#125;
& & & & & & function ieHandle&#40;&#41; &#123;
& & & & & & & & submitForm&#40;t.form, &#123;'flag': 0&#125;, 'avatarUploadHandle', function &#40;resp&#41; &#123;
& & & & & & & & & & if &#40;resp&#41; &#123;
& & & & & & & & & & & & var info = resp&#91;&var&&#93;;
& & & & & & & & & & & & if &#40;resp.code === 'S_OK'&#41; &#123;
& & & & & & & & & & & & & & var path = avatarUrl + info;
& & & & & & & & & & & & & & t.crop.attr&#40;&src&, path&#41;;
& & & & & & & & & & & & & & t.small.attr&#40;&src&, path&#41;;
& & & & & & & & & & & & & & t.u.val&#40;info&#41;;
& & & & & & & & & & & & & & t.create&#40;&#41;;
& & & & & & & & & & & & &#125; else &#123;
& & & & & & & & & & & & & & info = info || '未知错误';
& & & & & & & & & & & & & & tip&#40;info, 2&#41;;
& & & & & & & & & & & & &#125;
& & & & & & & & & & &#125;
& & & & & & & & &#125;&#41;;
& & & & & & &#125;
& & & & & & function standardHandle&#40;file&#41; &#123;
& & & & & & & & //读入文件
& & & & & & & & var reader = new FileReader&#40;&#41;;
& & & & & & & & reader.onload = function &#40;e&#41; &#123;
& & & & & & & & & & var imgData = e.target.result;
& & & & & & & & & & t.crop.attr&#40;&src&, imgData&#41;;
& & & & & & & & & & t.small.attr&#40;&src&, imgData&#41;;
& & & & & & & & & & t.create&#40;&#41;;
& & & & & & & & &#125;
& & & & & & & & reader.readAsDataURL&#40;file&#41;;
& & & & & & &#125;
& & & & &#125;,
& & & & /**
& & & & &* 更新选区
& & & & &* @param img
& & & & &*/
& & & & update: function &#40;img&#41; &#123;
& & & & & & var crop = this.cropApi,width = img.width,height = img.height,
& & & & & & & & initValue = &#40;width & height ? height : width&#41; & this.SIZE_MID ? &#40;width & height ? height : width&#41; / 2 : width;
& & & & & & crop.setSelection&#40;&#40;width - initValue&#41; / 2, &#40;height - initValue&#41; / 2, &#40;width + initValue&#41; / 2, &#40;height + initValue&#41; / 2, true&#41;;
& & & & & & crop.setOptions&#40;&#123; show: true &#125;&#41;;
& & & & & & crop.update&#40;&#41;;
& & & & & & this.preview&#40;img, crop.getSelection&#40;&#41;&#41;;
& & & & &#125;,
& & & & /**
& & & & &* 设置截图控件
& & & & &* @param img
& & & & &* @param width
& & & & &* @param height
& & & & &* @param afterInit
& & & & &*/
& & & & setCrop: function &#40;img, width, height, afterInit&#41; &#123;
& & & & & & //截图区域偏移值
& & & & & & var initValue = &#40;width & height ? height : width&#41; & this.SIZE_MID ? &#40;width & height ? height : width&#41; / 2 : width;
& & & & & & //初始化截图控件
& & & & & & this.cropApi = $&#40;img&#41;.imgAreaSelect&#40;&#123;
& & & & & & & & keys: true,
& & & & & & & & fadeSpeed: 200,
& & & & & & & & handles: true,
& & & & & & & & aspectRatio: '1:1',
& & & & & & & & parent: this.adapt,
& & & & & & & & onInit: $.proxy&#40;this.preview, this&#41;,
& & & & & & & & onSelectChange: $.proxy&#40;this.preview, this&#41;,
& & & & & & & & ondblclick: $.proxy&#40;this.dblclick, this&#41;,
& & & & & & & & persistent: true,
& & & & & & & & imageWidth: width,
& & & & & & & & imageHeight: height,
& & & & & & & & instance: true,
& & & & & & & & x1: &#40;width - initValue&#41; / 2,
& & & & & & & & y1: &#40;height - initValue&#41; / 2,
& & & & & & & & x2: &#40;width + initValue&#41; / 2,
& & & & & & & & y2: &#40;height + initValue&#41; / 2
& & & & & & &#125;&#41;;
& & & & & & //初始化完成后的回调
& & & & & & typeof afterInit === 'function' && afterInit.call&#40;img, width, height&#41;;
& & & & &#125;,
& & & & //预览图生成
& & & & preview: function &#40;img, selection&#41; &#123;
& & & & & & if &#40;!selection.width || !selection.height&#41; &#123;
& & & & & & & & return;
& & & & & & &#125;
& & & & & & var SIZE_MID = this.SIZE_MID;
& & & & & & var w = selection.width;
& & & & & & var h = selection.height;
& & & & & & var iw = img.width;
& & & & & & var ih = img.height;
& & & & & & var ox = selection.x1;
& & & & & & var oy = selection.y1;
& & & & & & var getMargin = function &#40;size, pos, limit&#41; &#123;
& & & & & & & & return -Math.round&#40;limit * pos / size&#41;;
& & & & & & &#125;;
& & & & & & var getSize = function &#40;size, isize, limit&#41; &#123;
& & & & & & & & return Math.round&#40;limit * isize / size&#41;;
& & & & & & &#125;;
& & & & & & var setCss = function &#40;elem, limit&#41; &#123;
& & & & & & & & elem && elem.css&#40;&#123;
& & & & & & & & & & width: getSize&#40;w, iw, limit&#41;,
& & & & & & & & & & height: getSize&#40;h, ih, limit&#41;,
& & & & & & & & & & marginLeft: getMargin&#40;w, ox, limit&#41;,
& & & & & & & & & & marginTop: getMargin&#40;h, oy, limit&#41;
& & & & & & & & &#125;&#41;;
& & & & & & &#125;;
& & & & & & setCss&#40;this.small, SIZE_MID&#41;;
& & & & & & this.w.val&#40;w&#41;;
& & & & & & this.h.val&#40;h&#41;;
& & & & & & this.x.val&#40;ox&#41;;
& & & & & & this.y.val&#40;oy&#41;;
& & & & &#125;,
& & & & /**
& & & & &* 提交截图数据
& & & & &* @param callback
& & & & &*/
& & & & submit: function &#40;callback&#41; &#123;
& & & & & & var t = this;
& & & & & & var flag = 1;
& & & & & & if &#40;$.browser !== 'msie'&#41; &#123;
& & & & & & & & flag = 2;
& & & & & & &#125;
& & & & & & submitForm&#40;t.form, &#123;flag: flag&#125;, 'avatarUploadHandle', function &#40;resp&#41; &#123;
& & & & & & & & var info = resp&#91;&var&&#93;;
& & & & & & & & if &#40;resp.code === 'S_OK'&#41; &#123;
& & & & & & & & & & callback && callback.call&#40;t, info&#41;
& & & & & & & & &#125; else &#123;
& & & & & & & & & & info = info || '未知错误';
& & & & & & & & & & alert&#40;info&#41;;
& & & & & & & & &#125;
& & & & & & &#125;&#41;;
& & & & & & t.form.attr&#40;&action&, t.options.action&#41;;
& & & & &#125;,
& & & & /**
& & & & &* 图片头数据加载就绪事件 - 更快获取图片尺寸
& & & & &* @version & &
& & & & &* @author & &TangBin
& & & & &* @see & & & &/?p=1121
& & & & &* @param & &{String} & &图片路径
& & & & &* @param & &{Function} & &尺寸就绪
& & & & &* @param & &{Function} & &加载完毕 (可选)
& & & & &* @param & &{Function} & &加载错误 (可选)
& & & & &* @example imgReady('.hk/intl/zh-CN/images/logo_cn.png', function () {
& & & & & & alert('size ready: width=' + this.width + '; height=' + this.height);
& & & & &});
& & & & &*/
& & & & imgReady: &#40;function &#40;&#41; &#123;
& & & & & & var list = &#91;&#93;, intervalId = null,
& & & & & & // 用来执行队列
& & & & & & & & tick = function &#40;&#41; &#123;
& & & & & & & & & & var i = 0;
& & & & & & & & & & for &#40;; i & list.length; i++&#41; &#123;
& & & & & & & & & & & & list&#91;i&#93;.end ? list.splice&#40;i--, 1&#41; : list&#91;i&#93;&#40;&#41;;
& & & & & & & & & & &#125;
& & & & & & & & & & ;
& & & & & & & & & & !list.length && stop&#40;&#41;;
& & & & & & & & &#125;,
& & & & & & // 停止所有定时器队列
& & & & & & & & stop = function &#40;&#41; &#123;
& & & & & & & & & & clearInterval&#40;intervalId&#41;;
& & & & & & & & & & intervalId = null;
& & & & & & & & &#125;;
& & & & & & return function &#40;url, ready, load, error&#41; &#123;
& & & & & & & & var onready, width, height, newWidth, newHeight,
& & & & & & & & & & img = new Image&#40;&#41;;
& & & & & & & & img.src = url;
& & & & & & & & // 如果图片被缓存,则直接返回缓存数据
& & & & & & & & if &#40;img.complete&#41; &#123;
& & & & & & & & & & ready.call&#40;img&#41;;
& & & & & & & & & & load && load.call&#40;img&#41;;
& & & & & & & & & & return;
& & & & & & & & &#125;
& & & & & & & & ;
& & & & & & & & width = img.width;
& & & & & & & & height = img.height;
& & & & & & & & // 加载错误后的事件
& & & & & & & & img.onerror = function &#40;&#41; &#123;
& & & & & & & & & & error && error.call&#40;img&#41;;
& & & & & & & & & & onready.end = true;
& & & & & & & & & & img = img.onload = img.onerror = null;
& & & & & & & & &#125;;
& & & & & & & & // 图片尺寸就绪
& & & & & & & & onready = function &#40;&#41; &#123;
& & & & & & & & & & newWidth = img.width;
& & & & & & & & & & newHeight = img.height;
& & & & & & & & & & if &#40;newWidth !== width || newHeight !== height ||
& & & & & & & & & & & & // 如果图片已经在其他地方加载可使用面积检测
& & & & & & & & & & & & newWidth * newHeight & 1024
& & & & & & & & & & & & &#41; &#123;
& & & & & & & & & & & & ready.call&#40;img&#41;;
& & & & & & & & & & & & onready.end = true;
& & & & & & & & & & &#125;
& & & & & & & & & & ;
& & & & & & & & &#125;;
& & & & & & & & onready&#40;&#41;;
& & & & & & & & // 完全加载完毕的事件
& & & & & & & & img.onload = function &#40;&#41; &#123;
& & & & & & & & & & // onload在定时器时间差范围内可能比onready快
& & & & & & & & & & // 这里进行检查并保证onready优先执行
& & & & & & & & & & !onready.end && onready&#40;&#41;;
& & & & & & & & & & load && load.call&#40;img&#41;;
& & & & & & & & & & // IE gif动画会循环执行onload,置空onload即可
& & & & & & & & & & img = img.onload = img.onerror = null;
& & & & & & & & &#125;;
& & & & & & & & // 加入队列中定期执行
& & & & & & & & if &#40;!onready.end&#41; &#123;
& & & & & & & & & & list.push&#40;onready&#41;;
& & & & & & & & & & // 无论何时只允许出现一个定时器,减少浏览器性能损耗
& & & & & & & & & & if &#40;intervalId === null&#41; intervalId = setInterval&#40;tick, 40&#41;;
& & & & & & & & &#125;
& & & & & & & & ;
& & & & & & &#125;;
& & & & &#125;&#41;&#40;&#41;
& & &#125;;
& & window&#91;&Cutting&&#93; = Cutting;
& & &* 插件化
& & &* @param option
& & &* @returns {*}
& & $.fn.cutting = function &#40;option&#41; &#123;
& & & & var args = Array.apply&#40;null, arguments&#41;;
& & & & args.shift&#40;&#41;;
& & & & return this.each&#40;function &#40;&#41; &#123;
& & & & & & var $this = $&#40;this&#41;,
& & & & & & & & data = $this.data&#40;'Cutting'&#41;,
& & & & & & & & options = typeof option === 'object' && option;
& & & & & & if &#40;!data&#41; &#123;
& & & & & & & & $this.data&#40;'Cutting', &#40;data = new Cutting&#40;this, options&#41;&#41;&#41;;
& & & & & & &#125;
& & & & & & if &#40;typeof option == 'string' && typeof data&#91;option&#93; == 'function'&#41; &#123;
& & & & & & & & data&#91;option&#93;.apply&#40;data, args&#41;;
& & & & & & &#125;
& & & & &#125;&#41;;
& & &#125;;
& & $.fn.cutting.Constructor = Cutting;
& & &* iframe upload
& & &* @param form
& & &* @param extraData
& & &* @param handleName
& & &* @param handle
& & function submitForm&#40;form, extraData, handleName, handle&#41; &#123;
& & & & var data = $.extend&#40;&#123;
& & & & & & 'sid': window.sid,
& & & & & & 'func': handleName
& & & & &#125;, extraData&#41;;
& & & & var action = form.data&#40;&action&&#41;;
& & & & form.attr&#40;'action', form.prop&#40;'action'&#41; + '?' + $.param&#40;data&#41;&#41;;
& & & & window&#91;handleName&#93; = handle;
& & & & window.callback = function &#40;&#41; &#123;
& & & & &#125;;
& & & & form.submit&#40;&#41;;
& & &#125;
&#125;&#41;&#40;jQuery&#41;;
DOMO1 普通调用:
12345678910111213141516171819& & var cut = new Cutting&#40;&#crop-wrap&,&#123;
& & & & SIZE_MID: 96.0, &// 缩略图规格
& & & & maxWidth: 256.0, // 画布最大宽度
& & & & maxHeight: 248.0,// 画布最大高度
& & & & drag: false, & & // 是否初始化画布
& & & & initcallback: function &#40;&#41; &#123;
& & & & & & alert&#40;&初始化完成!&&#41;;
& & & & &#125;, //初始化完成后,执行
& & & & dblcallback: function &#40;&#41; &#123;
& & & & & & alert&#40;&双击提交!&&#41;;
& & & & &#125; & //双击选取执行
& & &#125;&#41;;
& & cut.create&#40;function &#40;&#41; &#123;
& & & & console.log&#40;&创建完毕&&#41;;
& & &#125;&#41;;
& & cut.submit&#40;function &#40;&#41; &#123;
& & & & console.log&#40;&提交后的操作&&#41;;
& & &#125;&#41;;
DOMO2 插件调用:
123456789101112131415161718& & //创建API
& & $&#40;&#crop-wrap&&#41;.cutting&#40;&#123;
& & & & SIZE_MID: 96.0, &// 缩略图规格
& & & & maxWidth: 256.0, // 画布最大宽度
& & & & maxHeight: 248.0,// 画布最大高度
& & & & drag: false, & & // 是否初始化画布
& & & & initcallback: function &#40;&#41; &#123;
& & & & & & alert&#40;&初始化完成!&&#41;;
& & & & &#125;, //初始化完成后,执行
& & & & dblcallback: function &#40;&#41; &#123;
& & & & & & alert&#40;&双击提交!&&#41;;
& & & & &#125; & //双击选取执行
& & &#125;&#41;;
& & //方法调用
& & $&#40;&#crop-wrap&&#41;.cutting&#40;&submit&,function&#40;t, info&#41;&#123;
& & & & alert&#40;&提交后的操作!&&#41;;
& & &#125;&#41;;
最后,祝大家生活愉快!
谈到 JavaScript 你会想到什么呢?浏览器?很好。Node?很好。还有其他的吗?肯定还会有。不过今天,我一不说浏览器,二不说 Node,我要说语言。
「语言这东西由说的必要吗?我每天写那么多程序,经手的代码都超过五位数行了,难道我还不会语言?笑话!还不如给我看 MVC、设计模式、代码案例,那些东西可更有用。」
——且慢——
没错,每个 JS 程序员都必定熟悉 JavaScript 语言,了解它的特性,比如对象、原型、函数以及 this等等。熟悉到甚么程度?没错,就是到天天用,用成条件反射,好像直接刻进脑子里。但是,你有没有想过,这些「特性」的背后是什么?它们的机理是什么?哦,你肯定不会想——废话,自己用了这么久的东西自己还不懂?另外,机理有用吗?对于「码农」来说,可能没用,但是不了解某个东西的机理,它的一些问题你就没法处理,至少没法处理清楚。
比如,许多人都知道细胞呼吸的过程是「燃烧」葡萄糖,产生二氧化碳和水,可以用方程 C 6H 12O 6 + O 2 → CO 2 + H 2O 概括。然而简单的方程无法解释,为什么细胞可以进行无氧呼吸,同样消耗葡萄糖产生能量(尽管数量少于完整的呼吸),却不消耗氧气呢?原来,细胞呼吸实际上有三个步骤:糖酵解、三羧酸循环和氧化磷酸化。在第一步「糖酵解」中,葡萄糖被分解成更简单的化合物丙酮酸,随后丙酮酸被送入三羧酸循环,得到二氧化碳和 NADH。NADH 在最后一步送入氧化磷酸化,在线粒体内膜上和氧气结合,得到水,这个过程放出的能量形成质子浓差,推动 ATP 合成酶运转合成大量的「能量通货」ATP。整个过程只有第三个步骤消耗氧气;三个步骤里,糖酵解和氧化磷酸化放出能量,三羧酸循环反而消耗能量,因而在无氧条件下,只有糖酵解可以完成。
从这个例子可以看出,你若是不了解细胞呼吸的机理,你就无法解释无氧呼吸是怎么回事。不了解机理,就无法得心应手。于 JavaScript 也是一样的。不过呢,程序语言的境况要比生物学要简单的多。如果把我们研究的东西比作机器的话,生物学、化学、物理学摆在我们面前的是一个个黑箱,我们必须费尽心思,用各种实验如光谱、传感器、比较跟踪分析等等才能轻微地撬开这个箱子的一角,从而窥视里面无比精妙的机构;与之相反,编译器、解释器那个箱子则是完全透明,里面那台精密的机器就在你眼前,你可以直接靠过去看个够。编译器要是开源的话那就更好了,这回连箱子都没了,现在不仅可以看了,连拆都可以,它已经完全是你手里的玩物了。
不仅如此,语言的设计师们会把这门语言的所有机理(没错——所有)写在一本书里,这本书就是这门语言的规范,那台机器的蓝图。在实践中重要的语言——例如 C、C++、Java,它们的规范甚至是国际标准。JavaScript 也不例外:ECMA 组织的 ECMA 262 规范就是 JavaScript 这门语言的标准,也包含了它的全部机理。我可以说,要是读懂了 ECMA 262,完全可以做出一个 JavaScript 解释器出来。
在大多数程序员的眼里,做编译器和解释器的都是一群神奇生物,他们能制作出一个神奇的东西,能让你写的代码「动起来」,就像是魔法师一样。对啊,程序就是现代魔法,而写编译器的估计就是「现代魔法师」里最神秘的一群了。你可能知道语言有「语法」甚至能写出一个而简单语言的语法定义来,但是叫你写个语法解析器你就熄火了——从未接触过这个领域,怎么写的出来!我估计这里的各位写一个「计算器」都会比较困难——不是按按钮的计算器,是敲一行表达式出结果的计算器,而且表达式要支持加减乘除和括弧。(其实按按钮的计算器也会牵扯到语法解析的知识,各位都懂设计模式,知道建立联系吗?)
但语法解析真没你想象中的那么神秘,它实际上就是从句子里提取出含义的过程,只不过各位,你们平常「亲手处理」的字符串,要么表示数据(「配置文件」),要么表示流程(「自动化脚本」)。如果项目是那种老板甲方天天催,一坏损失几百万的那种的话,我估计,你会,数据上 XML 流程上 Lua,完事。表示数据?XML 各种复杂数据都不在话下,而且类库众多,全球通用;表示流程?Lua 是正经的嵌入式脚本语言,体积小,速度快,功能强大。
所以啊,你不会有机会亲自写个语法解析器的,至少在工作里,不会有的!语法解析器是庞大的编译原理冰山上最简单的一角,光这一角,Grune 和 Jacobs 写了整整一本书,比一本小字典还大;这一角之外的东西,比如编译器后端部分的各种优化,更是卷帙浩繁——而它们还只是编译器技术的部分。程序语言的机理更多的是建构在编译器技术之外的另一块大陆:语言理论之上。在语言理论的世界里,已经几乎不会出现代码了,全是公式。没错!公式!总之,「语言的机理」对一般程序员来说,实在是太遥远了,太不可企及了,我们只能像仰望星空一样仰望那群大魔导士。
各位可能穷尽一生也不会亲自写一个编译器,因而有些人就抛出论调说「编译器那一大堆东西,于我无用,不用学!」不过正如我前面说的,原理不掌握,你应用语言永远不能得心应手,你对程序语言的理解,绝对无法和掌握这个神秘领域的人相提并论,达到相同的高度。例如 JavaScript 的函数调用,你写 object.m(xs)可以进行正确的「方法调用」,但 f = object.m;f(xs) 就有问题(f 得不到正确的 this)。相比这个问题困扰过很多人吧!一些书籍会为了解释这个现象会把函数调用分成两种,一个是「普通调用」,一个是「方法调用」,然后强调他们在语法和语义上的区别云云。当然我不是想推翻这句话,它是对的,而且是个相当好的解释;但实际上,按照规范(11.2.3 节),JavaScript 根本就不区分所谓「普通调用」和「方法调用」。下面把 11.2.3 节原样抄下来:
产生式 「CallExpression : MemberExpression Arguments」 依如下方法解释
令 ref 为解释 MemberExpression 的结果
令 func 为 GetValue(ref)
令 argList 为解释 Arguments 的结果,它应该是由各个参数组成的列表(见 11.2.4)
如果 Type(func) 不是 Object,抛出 TypeError 异常
如果 IsCallable(func) 为假,抛出 TypeError 异常
如果 Type(ref) 是 Reference 则:
如果 IsPropertyReferernce(ref) 为真,则
令 thisValue 为 GetBase(ref)
否则(此时 ref 的基底是一个环境记录)
令 thisValue 为对 GetBase(ref) 调用 ImplicitThisValue 的结果
否则 ref 不是 Reference:
令 thisValue 为 undefined
返回对 func 调用 [[Call]] 内方法的结果,其中 this 指定为 thisValue,参数表指定为 argList。
产生式 「CallExpression : CallExpression Arguments」 也依相同方法解释,惟第一步里MemberExpression 换成 CallExpression。
如果 func 是原生 ECMAScript 对象,CallExpression 解释结果一定不会是 Reference 类型;其为宿主对象时是否是 Reference 由实现决定,但如果是,只能是非严格的属性 Referrnce。
上面这些东西直接抄自 ECMA 262,原封未动。这段文字为 CallExpression 语法(JavaScript 里的函数调用)赋予了含义。ECMA 262 里 CallExpression 的语法是两条产生式:
CallExpression
→ MemberExpression Arguments
CallExpression
→ CallExpression Arguments
这两条产生式随后被赋予「函数调用」的语义。所谓「方法调用」所必须的 this信息实际上是被MemberExpression 的值携带的。携带 this 信息的东西叫做 Reference,它是解释器使用的一种内部类型,可以记录某个表达式所「关联」的 this 信息。规范里并没有「方法调用」这个说法,「方法调用」这个词汇是为了解释 Reference 造出来的。「方法调用」这个词算是个不错的词,相比规范里精确却叫人难懂的 Reference,「方法调用」和「普通调用」的分野显然要简单得多。毕竟规范要精确、无歧义地定义一门语言,而程序员使用的时候,第一,不需要了解到如此程度;第二,说的太精确会伤人脑细胞,程序员的脑子可都金贵得很,不能磕着碰着。程序员的脑子是人脑,人脑可以接受不太精确的信息,然后结合经验,形成你写程序时候的行为准则。编译器则不同,编译器是运行在电脑上的,电脑里的东西必须精确,所以编译器作者看规范看得最勤快;也因为如此,做编译器的人往往是理解语言更为深入、最理解语言机理的人。
如果说「方法调用」算是个要解释的话,坊间书籍里有些解释就不那么好了,甚至是错误的,比如月影那本大部头《JavaScript 王者归来》里面那个「最长行匹配」就误导了不少人,还有 Douglas 宣称的「JavaScript 里所有数值都是浮点」。这些错处或多或少都是因为对规范不熟悉导致的(虽然 ECMA 262 v3 的佶屈聱牙也要负一般责任)。而它们也是我开始写「JavaScript 原理」的原因。我看规范看了不少次,本身参与了对它的翻译,外加现在在维护
这个 altjs 语言(编译到 JavaScript 的语言),对 JS 的各种特性,都有所接触。
所以,我打算在这里,第一从严谨的角度出发分析 ECMA 规范和 JavaScript,第二写写这两年来的一些真人经历,主要是 moescript 开发的经历。我希望 jser 们可以追随一个编译器作者和分析者的脚步,来审视你们日复一日使用的东西,看能不能得到一些启发。除开 JS,我也会谈及一些其他的知识和技术,还有少少的个人评价。个人水平有限,还望看官包涵;如果有错误,就大胆的来批好了。
有关「节后三问」
为了让我的书不变成「耳边风」,我会在每一节后面加三个问题。这些题目希望各位认真把它做出来。笔者比照 TAOCP,为每个题目标出了难度。它们如下表列:
[D] 非常简单,您应该在几分钟内就可以解答出来。
[C] 比较简单的问题。可能需要好好阅读问题,并且大概要 20 分钟。
[B] 中等难度的问题。为了完整解答它,你可能需要几个小时的努力。(当然,你的电脑联网的话时间可能更长)。本书中的多数题目都是这个难度。
[A] 相当困难或者繁杂的题目,或许需要几个星期才能把它做完。大学教授会把它作为学期大作业。
[论外] 对于这个难度的问题,可能还没有人知道答案。如果你在大学或者研究所的话,你可以把它作为研究方向。如果你把它做出来了,首先应该发篇论文,而不是找我(不过如果我看到阁下的研究成果的话,我会去亲自找您)。
下面是难度的示例:
[D] 难度 [B] 表示什么?
[C] 证明 173
= 4913;并推广你的结论。(这类问题笔者可不喜欢。)
[B] 证明用筛法筛选小于 n 的所有素数的时间复杂度(基于余数判断次数)是 O(n log log n)。
[A] 写一个完整的 JavaScript 解释器,并通过 。
[论外] P 和 NP 相等吗?
[C] 查阅文献,世界上第一个编译器是谁写的?它叫什么名字?有哪些后续版本?
[B] 除了生物代谢过程,化学反应的机理也很重要(这也就是为什么许多诺贝尔奖得主都是研究化学动力学的)。有些看似简单的化学反应可能拥有相当复杂的反应历程,比如 H 2 + O 2 → H 2O。查阅文献,这个反应的机理是什么?牵扯到了多少种中间产物?氢气和氧气按一定比例混合后会爆炸,而这个混合比有上下界,只有在上下界确定的范围内才会爆炸。从反应机理出发解释上下界存在的原因。
[B] 文章说「表示数据用 XML 很好」——XML 确实很适合来表示数据,然而近年来的 Web 服务提供的数据接口却以 JSON 为主。分析下 JSON 相对 XML 的优劣。
(本回完)
通常我们操作Excel可以用ColdFusion内置的CFSPREADSHEET标签来做。但是其灵活性不怎么滴。
所以通过查相关资料,结合下Java的内容。就自己扩展了个ColdFusion关于Excel操作的工具类。
但是中间遇到个问题:
就是当我们通过下面的代码创建一个Java类的时候,会抛出一个很奇怪的错误(偶尔):
CreateObject(&#8220;java&#8221;,&#8221;org.apache.poi.poifs.filesystem.POIFSFileSystem&#8221;).Init(CreateObject(&#8220;java&#8221;,&#8221;java.io.FileInputStream&#8221;).Init(ARGUMENTS.FilePath));
错误信息:
错误根源:coldfusion.runtime.java.JavaObjectInstantiationException: Object instantiation exception.
错误详细:Object instantiation exception. An exception occurred while instantiating a Java object. The class must not be an interface or an abstract class. Error: &#8221;.
后来去查阅了很多国外的资料,最后终于找到了问题的可能性。
Some files just don&#8217;t play nicely with the POI library for some reason. When you can open/save and get it to work, it must just be an oddity with the original file. I think someone once told me that the size of the file has to be a multiple of 512K or something strange.
这算是一种情况,另外,当文件路径错误,Excel版本等都会造成这个问题。
具体解决方案就是避免这些问题:检查文件路径,检查是否有高版本的Excel文件,到低版本Excel里面打开过

我要回帖

更多关于 function 的文章

 

随机推荐