1.JS补遗
outerHeight()包括内边距和边框,输入includeMargin参数就可以包括外边距
innerHeight()包括内边距、不包括边框
height()随浏览器的盒模式作相应的改变
css(‘height’)包含px单位
offset()获取元素相对文档的偏移量,.left和.top取左右偏移及上下偏移
2.jQuery补遗
jQuery工具函数
$.extend(target,[object1],[objectN])
将object1……objectN合并到target对象中,键值相同的项将被替换
用途:替换默认的配置项$.extend(default,options)
代码实现:
$.extend([deep],target,object1,[objectN])
深拷贝的方式,子项也将被递归合并
$.extend(object)
扩展jQuery类,即为静态方法
$.fn.extend(object)
扩展jQuery对象的方法,即为原型属性上的公有方法
$.each(object, [callback])
遍历数组或者对象
$.grep(array, callback, [invert])
根据回调函数过滤数组,invert默认为false,回调函数返回值为true的项构成结果集
$.makeArray(obj)
将类数组对象arguments转化成数组,可以应用数组的方法
$.map(arr|obj,callback)
对数组元素进行操作后构成新数组,利用null以及[]的形式裁断或增加数组元素的数目
$.inArray(value,array,[fromIndex])
返回value在数组中的索引,不在数组中返回-1,fromIndex起始位置
$.merge(first,second)
第二个数组的元素跟在第一个数组的元素后面输出,并替换第一个数组
$.unique(array)
处理DOM元素,删除重复的数组
$.parseJSON(json)
将json形式的字符串(双引号包裹)转化成json对象输出,可以用键值对读取
jQuery-ajax
暂缺
3.HTML5新技术
FileList对象(ie8无法用输入框获取文件对象)
<input type=’file’>元素的files属性中包含文件对象,设置multiple属性可以支持多文件上传,该File对象继承Blob,包含size、type(MIME类型)属性、slice方法,在此基础上又扩展出name、lastModifiedDate两个属性
获取该对象可使用
document.getElementById(‘idname’).files[0]
FileReader对象
首先创建一个FileReader实例,其次有三个方法可供调用,均为异步读取,通过监听对象的onload事件读取result数据,abort方法停止读取
readAsBinaryString(Blob blob)传入blob对象(file对象继承blob对象),然后将读取数据的结果作为二进制的形式放大片FileReader对象的result属性里;
readAsText(Blob blob, optional DOMString encoding)传入blob对象、编码格式,以文本字符串形式存储在result中;
readAsDataURL(Blob blob)传入blob对象,读取内容作为url属性,处理图片的src地址
调用方法
var resultFile = document.getElementById("fileDemo").files[0]; if (resultFile) { var reader = new FileReader(); reader.readAsDataURL(resultFile); reader.onload = function (e) { console.log(this.result) ; }; }
http://www.cnblogs.com/fly_dragon/archive/2012/06/02/2532035.html
FormData对象
首先创建一个FormData实例,然后使用append方法往该实例中加入键值对,可以是简单的数据,也可以是blob对象或者文件对象,再通过ajax的方式将该实例发送给后台;
另一种方式是使用表单元素创建实例,如new FormData(someformelement)
示例(问题是后台怎么接受):
var newFormData = new FormData(someFormElement); newFormData.append("accountnum", 123456); newFormData .append("userfile", fileInputElement.files[0]); var oFileBody = "<a id="a"><b id="b">hey!</b></a>"; // Blob对象包含的文件内容 var oBlob = new Blob([oFileBody], { type: "text/xml"}); newFormData.append("webmasterfile", oBlob);
http://www.cnblogs.com/lhb25/p/html5-formdata-tutorials.html
4.upload插件的使用
配置项(form表单上传文件的时候,需要添加enctype="multipart/form-data"):
trigger触发元素,即点击后能弹出对话框的元素,和form、<input type=’file’>同等大小
accept限定上传文件的类型,<input type=’file’>的accept属性
action上传地址,form的action属性,ajax的url,关联后台的方法或url
name文件的名字
data附带的数据,form通过input上传,ajax通过额外的上传数据
multiple是否允许多文件上传
change上传文件的输入框改变时调用,上下文是上传输入框,参数是文件对象
success、error上传成功或失败时调用,form通过iframe加载解析文档内容,ajax直接返回
progress上传进度的函数function(event, position, total, percent, files){}
调用方式是new出一个Uploader实例或者new出一个MultipleUploader实例(针对多个上传文件input的情况,以数组形式传入相应的trigger)
示例:
var uploader = new Uploader({ trigger: '.upload-btn', name: 'image', action: '/upload', accept: 'image/*', data: {'xsrf': 'hash'}, multiple: true, error: function(file) { alert(122); }, success: function(response) { alert(response); }, progress: function(event, position, total, percent, files) { console.log(percent); } });
5.upload插件的源码
架构:
对支持html5的浏览器使用ajax的方式上传,不支持的浏览器使用表单上传,通过iframe禁止页面刷新,以及获取后台返回的响应
源码:
var iframeCount = 0; function Uploader(options) { if (!(this instanceof Uploader)) { return new Uploader(options); } if (isString(options)) { options = {trigger: options}; } var settings = { trigger: null, name: null, action: null, data: null, accept: null, change: null, error: null, multiple: true, success: null }; if (options) { $.extend(settings, options); } var $trigger = $(settings.trigger);// 触发元素,创建的form和<input type='file'>和它同等大小,点击弹出文件选择对话框 settings.action = settings.action || $trigger.data('action') || '/upload'; settings.name = settings.name || $trigger.attr('name') || $trigger.data('name') || 'file'; settings.data = settings.data || parse($trigger.data('data')); settings.accept = settings.accept || $trigger.data('accept'); settings.success = settings.success || $trigger.data('success'); this.settings = settings; this.setup(); this.bind(); } Uploader.prototype.setup = function() { this.form = $( '<form method="post" enctype="multipart/form-data"' + 'target="" action="' + this.settings.action + '" />' ); //调用newIframe函数创建新的iframe框架,createInputs创建输入框,键值对作为name和value this.iframe = newIframe(); this.form.attr('target', this.iframe.attr('name')); var data = this.settings.data; this.form.append(createInputs(data)); if (window.FormData) { this.form.append(createInputs({'_uploader_': 'formdata'})); } else { this.form.append(createInputs({'_uploader_': 'iframe'})); } var input = document.createElement('input'); input.type = 'file'; input.name = this.settings.name; if (this.settings.accept) { input.accept = this.settings.accept; } if (this.settings.multiple) { input.multiple = true; input.setAttribute('multiple', 'multiple'); } this.input = $(input); var $trigger = $(this.settings.trigger); this.input.attr('hidefocus', true).css({ position: 'absolute', top: 0, right: 0, opacity: 0, outline: 0, cursor: 'pointer', height: $trigger.outerHeight(), fontSize: Math.max(64, $trigger.outerHeight() * 5) }); this.form.append(this.input); this.form.css({ position: 'absolute', top: $trigger.offset().top, left: $trigger.offset().left, overflow: 'hidden', width: $trigger.outerWidth(), height: $trigger.outerHeight(), zIndex: findzIndex($trigger) + 10 }).appendTo('body'); return this; }; Uploader.prototype.bind = function() { var self = this; var $trigger = $(self.settings.trigger); $trigger.mouseenter(function() {// 不是多此一举??? self.form.css({ top: $trigger.offset().top, left: $trigger.offset().left, width: $trigger.outerWidth(), height: $trigger.outerHeight() }); }); self.bindInput(); }; Uploader.prototype.bindInput = function() { var self = this; self.input.change(function(e) { // ie9 don't support FileList Object self._files = this.files || [{ name: e.target.value }]; var file = self.input.val(); if (self.settings.change) { self.settings.change.call(self, self._files); } else if (file) { return self.submit(); } }); }; Uploader.prototype.submit = function() { var self = this; if (window.FormData && self._files) { var form = new FormData(self.form.get(0));// 表单元素即包含上传输入框,为什么还要往formdata对象中添加文件??? form.append(self.settings.name, self._files); var optionXhr; if (self.settings.progress) { var files = self._files; optionXhr = function() { var xhr = $.ajaxSettings.xhr(); if (xhr.upload) { xhr.upload.addEventListener('progress', function(event) { var percent = 0; console.log(event.loaded) var position = event.loaded || event.position; /*event.position is deprecated*/ var total = event.total; if (event.lengthComputable) { percent = Math.ceil(position / total * 100); } self.settings.progress(event, position, total, percent, files); }, false); } return xhr; }; } $.ajax({ url: self.settings.action, type: 'post', processData: false, contentType: false, data: form, xhr: optionXhr, context: this, success: self.settings.success, error: self.settings.error }); return this; } else { self.iframe = newIframe();// 之前创建一个iframe,何必再创建??? self.form.attr('target', self.iframe.attr('name')); $('body').append(self.iframe); self.iframe.one('load', function() { // https://github.com/blueimp/jQuery-File-Upload/blob/9.5.6/js/jquery.iframe-transport.js#L102 // Fix for IE endless progress bar activity bug // (happens on form submits to iframe targets): $('<iframe src="javascript:false;"></iframe>') .appendTo(self.form) .remove();// 添加再删除是怎么回事??? var response; try { response = $(this).contents().find("body").html();// contents()获取直接子节点,包含文本节点和html节点 } catch (e) { response = "cross-domain"; } $(this).remove(); if (!response) { if (self.settings.error) {// ajax上传成功失败时调用接口,表单上传需要传入相应的参数 self.settings.error(self.input.val()); } } else { if (self.settings.success) { self.settings.success(response); } } }); self.form.submit(); } return this; }; //重复上传多个文件的时候使用,以及上传成功或失败时使用 Uploader.prototype.refreshInput = function() { //replace the input element, or the same file can not to be uploaded var newInput = this.input.clone(); this.input.before(newInput); this.input.off('change'); this.input.remove(); this.input = newInput; this.bindInput(); }; Uploader.prototype.change = function(callback) { if (!callback) { return this; } this.settings.change = callback; return this; }; Uploader.prototype.success = function(callback) { var me = this; this.settings.success = function(response) { me.refreshInput(); if (callback) { callback(response); } }; return this; }; Uploader.prototype.error = function(callback) { var me = this; this.settings.error = function(response) { if (callback) { me.refreshInput(); callback(response); } }; return this; }; Uploader.prototype.enable = function(){ this.input.prop('disabled', false); this.input.css('cursor', 'pointer'); }; Uploader.prototype.disable = function(){ this.input.prop('disabled', true); this.input.css('cursor', 'not-allowed'); }; // Helpers // ------------- function isString(val) { return Object.prototype.toString.call(val) === '[object String]'; } function createInputs(data) { if (!data) return []; var inputs = [], i; for (var name in data) { i = document.createElement('input'); i.type = 'hidden'; i.name = name; i.value = data[name]; inputs.push(i); } return inputs; } function parse(str) {// 解析a=3&b=4形式的字符串 if (!str) return {}; var ret = {}; var pairs = str.split('&'); var unescape = function(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }; for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].split('='); var key = unescape(pair[0]); var val = unescape(pair[1]); ret[key] = val; } return ret; } function findzIndex($node) { var parents = $node.parentsUntil('body');// parentsUntil方法遍历寻找祖先元素,源自jquery var zIndex = 0; for (var i = 0; i < parents.length; i++) { var item = parents.eq(i); if (item.css('position') !== 'static') { zIndex = parseInt(item.css('zIndex'), 10) || zIndex; } } return zIndex; } function newIframe() { var iframeName = 'iframe-uploader-' + iframeCount; var iframe = $('<iframe name="' + iframeName + '" />').hide(); iframeCount += 1; return iframe; } //多个input元素时候的调用方式 function MultipleUploader(options) { if (!(this instanceof MultipleUploader)) { return new MultipleUploader(options); } if (isString(options)) { options = {trigger: options}; } var $trigger = $(options.trigger); var uploaders = []; $trigger.each(function(i, item) { options.trigger = item; uploaders.push(new Uploader(options)); }); this._uploaders = uploaders; } MultipleUploader.prototype.submit = function() { $.each(this._uploaders, function(i, item) { item.submit(); }); return this; }; MultipleUploader.prototype.change = function(callback) { $.each(this._uploaders, function(i, item) { item.change(callback); }); return this; }; MultipleUploader.prototype.success = function(callback) { $.each(this._uploaders, function(i, item) { item.success(callback); }); return this; }; MultipleUploader.prototype.error = function(callback) { $.each(this._uploaders, function(i, item) { item.error(callback); }); return this; }; MultipleUploader.prototype.enable = function (){ $.each(this._uploaders, function (i, item){ item.enable(); }); return this; }; MultipleUploader.prototype.disable = function (){ $.each(this._uploaders, function (i, item){ item.disable(); }); return this; };