landers.upload
Version:
landers.upload
1,590 lines (1,402 loc) • 56.6 kB
JavaScript
/**
* class Landers.upload
* @param {[type]} $container [description]
* @param {[type]} $input [description]
* @param {[type]} key [description]
* @param {[type]} opts [description]
* @return {[type]} [description]
*/
Landers.upload = function($container, $input, key, opts){
opts = opts || {};
this.key = key;
this.container = $('<ul class="landers-upload"></ul>').appendTo($container);
this.input = $input;
this.apiUrl = opts.apiUrl || '/upload';
this.scope = opts.scope;
this.opts = {};
this.enable = opts.enable === false ? false : true;
this.$tip = opts.$tip;
this.amount = opts.amount || 0;
this.debug = opts.debug || false;
var me = this;
this.instanceOptions= {
key: key,
apiUrl: this.apiUrl,
size: opts.size ? opts.size : {width: 150, height: 120},
debug: this.debug,
attrClass: opts.attrClass,
onUploade: function(){
var data = me.getValue();
opts.onUploade && opts.onUploade();
opts.onChange && opts.onChange(data);
},
onRemove: function(){
var data = me.getValue();
opts.onRemove && opts.onRemove();
opts.onChange && opts.onChange(data);
},
onChange: function(){
var data = me.getValue();
opts.onChange && opts.onChange(data);
}
};
this.init();
};
/**
* 与服务端通信
* @param {[type]} act [description]
* @param {[type]} params [description]
* @return {[type]} [description]
*/
Landers.upload.prototype.server = function(act, params){
var me = this;
params = $.extend(params || {}, {
act: act,
key: me.key
});
return $.ajax({
url: me.apiUrl,
data: params,
dataType: 'json',
type: 'GET',
success: function(rspn, textStatus, xhr){
},
error: function(xhr, textStatus, errorThrown){
alert(xhr.responseJSON.message);
}
});
};
/**
* 格式化单项数据结构
* @return {[type]} [description]
*/
Landers.upload.prototype.formatItemData = function( dat ){
dat = dat || '';
if (typeof dat === 'string') {
dat = $.trim(dat);
return {
original: dat,
small: dat,
mini: dat
};
} else {
dat.small = dat.small || dat.original;
dat.mini = dat.mini || dat.original;
return dat;
}
}
/**
* 取得输入数据
* @return {[type]} [description]
*/
Landers.upload.prototype.getInput = function(){
var me = this;
var value = $.trim(me.input.val()) || '';
if ( value ) {
try {
value = $.parseJSON(value);
if ( !$.isArray(value)) {
value = [value];
}
} catch (e) {
value = value.split(',');
}
} else {
value = [];
}
var data = value.map(function(item){
return me.formatItemData(item);
});
// 同步一下
me.setInput( data );
return data;
};
/**
* 将数据回存到input上
* @param {[type]} data [description]
*/
Landers.upload.prototype.setInput = function( data ){
var me = this;
if (data) {
data = JSON.stringify(data);
} else {
data = '';
}
me.input.val( data);
};
/**
* 将数据回存到input上
* @param {[type]} data [description]
*/
Landers.upload.prototype.getValue = function(){
var me = this;
var data = [], $containers = me.instanceContainers();
$containers.each(function(i, item){
var $item = $(item);
var instance = $item.data('instance');
if ( instance.data && instance.data.original ) {
data.push( instance.data );
}
});
if (me.maxAmount() <= 1) {
data = data[0];
}
return data;
}
/**
* 新增实例
* @param {[type]} dat [description]
*/
Landers.upload.prototype.addIntance = function(data){
var me = this;
var instance = new Landers.upload.instance(data, me.instanceOptions);
var instance_contaner = instance.container.eq(0);
instance_contaner.data('instance', instance);
me.container.append( instance_contaner );
};
/**
* 显示界面
* @return {[type]} [description]
*/
Landers.upload.prototype.show = function(){
var me = this.clear();
var data = me.getInput();
var count = Math.max(data.length, me.maxAmount());
for (var i=0; i<=count-1; i++) {
var dat = data[i] || me.formatItemData();
me.addIntance(dat);
}
};
/**
* 初始化
* @return {[type]} [description]
*/
Landers.upload.prototype.init = function(){
var me = this;
me.server('options')
.success(function(rspn){
me.instanceOptions.isAllowRemote = rspn.data.is_allow_remote;
me.instanceOptions.isAllowDelete = rspn.data.is_allow_delete;
me.instanceOptions.csrfToken = rspn.data.csrfToken;
me.instanceOptions.maxAmount = rspn.data.max_amount;
setTimeout(function(){
me.show();
}, 200);
});
};
/**
* 最多实例数量
* @return {[type]} [description]
*/
Landers.upload.prototype.maxAmount = function(){
var me = this;
return me.amount || parseInt(me.instanceOptions.maxAmount) || 1;
};
/**
* 取得所有实例的contaner
* @return {[type]} [description]
*/
Landers.upload.prototype.instanceContainers = function(){
var me = this;
return me.container.children();
};
/**
* 清空所有
* @return {[type]} [description]
*/
Landers.upload.prototype.clear = function(){
var me = this;
me.instanceContainers().remove();
return me;
};
/**
* 清空所有值
* @return {[type]} [description]
*/
Landers.upload.prototype.clearValue = function(){
var me = this;
me.instanceContainers().each(function(i, item){
var $item = $(item);
var instance = $item.data('instance');
if (instance) instance.data = {};
});
me.setInput('');
return me;
};
/**
* class Landers.upload.instance
* @param {[type]} data [description]
* @param {[type]} opts [description]
* @return {[type]} [description]
*/
Landers.upload.instance = function(data, opts){
// 初始化数据
this.data = data;
// 初始化属性
this.key = opts.key;
this.isAllowRemote = opts.isAllowRemote || false;
this.isAllowDelete = opts.isAllowDelete || false;
this.isAllowCutImage = opts.isAllowCutImage || false;
this.size = opts.size;
this.debug = opts.debug;
this.enable = opts.enable !== false;
this.isDirect = opts.isDirect !== false;
this.apiUrl = opts.apiUrl;
this.isRemainOriginalName = opts.isRemainOriginalName;
this.onUploade = opts.onUploade;
this.onChange = opts.onChange;
this.onRemove = opts.onRemove;
this.fileType = null;
this.uploading = false;
this.csrfToken = opts.csrfToken;
this.attrClass = opts.attrClass;
// 初始界面和事件
this.container = $(this.buildHtml('normal'));
this.preview = this.container.find('.upload-preview');
this.initData()
.initContainer()
.initHoverEvent()
.initButtonEvent()
.show()
.setButtonVisiableOrHidden();
};
/**
* 初始化方法集
* @type {Object}
*/
Landers.upload.instance.prototype = {
_getExtensionName: function(path){
var me = this;
var file_info = Landers.path.parse(path);
if (file_info) {
if ( file_info.extname ) {
return file_info.extname.toLowerCase();
} else if (file_info.query) {
for (var k in file_info.query) {
var ext_name = file_info.query[k];
if (me.isImageType(ext_name)) {
return ext_name;
}
}
}
}
return '';
},
initContainer: function(){
var me = this;
// 初始化containerl界面
me.container.css(me.size);
if ( me.attrClass ) me.container.addClass(me.attrClass);
me.preview.css({
width: me.size.width - 4,
height: me.size.height - 4,
});
// 触发mouseout 事件
setTimeout(function(){
me.container.trigger('mouseout');
}, 1500);
me.container.find('[data-toggle="tooltip"]').tooltip();
return me;
},
initData: function(){
var me = this;
me.data = me.data || {};
me.data.original = me.data.original || '';
me.data.small = me.data.small || '';
me.data.mini = me.data.mini || '';
me.fileType = me._getExtensionName(me.data.original);
return me;
},
/**
* 初始化hover事件
* @param {[type]} $instance [description]
* @return {[type]} [description]
*/
initHoverEvent: function($instance){
var me = this;
me.container.hover(
function(){
if ( me.uploading ) return;
var $btns = $(this).find('.buttons');
$btns.stop().animate({bottom: '0px'} , 300);
},
function(){
var $btns = $(this).find('.buttons');
$btns.stop().animate({'bottom':'-' + $btns.height() + 'px'}, 300);
}
);
return me;
},
setButtonVisiableOrHidden: function(){
var me = this;
//隐藏第1个实例的左移按钮
setTimeout(function(){
// 向前、向后移 按钮
var $siblings = me.container.siblings().add(me.container);
$siblings.find('.btn-move-prev, .btn-move-next').parent().show();
$first = $siblings.filter(':first');
$last = $siblings.filter(':last');
$first.find('.btn-move-prev').parent().hide();
$last.find('.btn-move-next').parent().hide();
// 删除按钮
me.container.find('.btn-remove').parent().ifShow( me.data && me.data.original );
// 图像工具
me.container.find('.btn-image-tools').parent().ifShow( me.isImageType() );
// 下载链接
me.container.find('.btn-download-file').parent().ifShow( me.data && me.data.original, function( bool ){
$(this).children('a').attr({'href': me.data.original, 'target': '_blank'});
});
}, 50)
return me;
},
/**
* 初始化按钮事件
* @param {[type]} $instance [description]
* @return {[type]} [description]
*/
initButtonEvent: function(){
var me = this;
me.container.find('input[name=file]').change(function(){
var value = $(this).val();
if ( value ) {
me.fileType = me._getExtensionName(value);
me.uploadLocal( $(this) );
}
});
me.container.find('.btn-remove').click(function(){
if ( me.isAllowDelete ) {
if ( !confirm('确定要删除吗?') ) return;
me.remove($(this));
me.container.showTopResponse('success', '文件已删除', 1000);
} else {
if ( !confirm('确定要移除吗?') ) return;
me.remove($(this));
me.container.showTopResponse('success', '文件已移除', 1000);
}
});
me.container.find('.btn-upload-remote').click(function(){
me.uploadRemote($(this));
});
me.container.find('.btn-move-prev').click(function(){
var $container = $(this).closest('.upload-item');
var $prev = $container.prev();
if (!$prev.length) return;
$prev.before($container);
me.setButtonVisiableOrHidden();
me.onChange && me.onChange();
});
me.container.find('.btn-move-next').click(function(){
var $container = $(this).closest('.upload-item');
var $next = $container.next();
if (!$next.length) return;
$next.after($container);
me.setButtonVisiableOrHidden();
me.onChange && me.onChange();
});
return me;
}
};
/**
* 生成HTML
* @param {[type]} key [description]
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.buildHtml = function(key){
var me = this, str = '';
switch(key) {
case 'dialog_upload_remote':
str += '<div class="zoc p5 pb0">';
str += ' <span class="fl">粘贴URL到以下文本框内</span>';
if ( me.isAllowRemote )
str += ' <label class="fr"><input type="checkbox" id="is_allow_getremote" checked/>抓取到服务器</label>';
str += '</div>';
str += '<div class="tc ph5"><input type="text" id="remoteurl" class="text noime" style="width:98%; padding:3px;"></div>';
break;
case 'dialog_cut_image':
str += '<form>';
str += '<table width="100%" height="100%">';
str += '<tr><td class="wrap-jcrop">';
str += ' <img src="{url}" onload="Landers.image.auto(this, true, 800, 600, true)" style="margin:0 auto;"/>';
str += '</td></tr>';
str += '</table>';
str += '<input name="x" type="hidden"/>';
str += '<input name="y" type="hidden"/>';
str += '<input name="w" type="hidden"/>';
str += '<input name="h" type="hidden"/>';
str += '<input name="img_w" type="hidden"/>';
str += '<input name="img_h" type="hidden"/>';
str += '<input name="url" type="hidden"/>';
str += '</form>';
break;
case 'file':
str = '<input name="file" type="file" ContentEditable="false">';
break;
case 'normal':
str += '<li class="upload-item">';
str += '<div class="upload-preview">';
str += '<div class="preview-flash"></div>';
str += '<img src="" class="preview-image" onload="Landers.image.auto(this, true, ' + (me.size.width - 4) + ', ' + (me.size.height - 4) + ', true)"/>';
str += '<div class="preview-file-type"><div></div></div>';
str += '</div>';
if ( me.enable ) {
str += '<div class="buttons"><table border="0" width="100%" height="100%"><tr>';
str += '<td style="display:none"><a class="button btn-move-prev" href="javascript:;" data-toggle="tooltip" data-placement="top" title="向前移">';
str += ' <i class="glyphicon glyphicon-chevron-left"></i>';
str += '</a></td>';
str += '<td><a class="button btn-upload-local" href="javascript:;" data-toggle="tooltip" data-placement="top" title="上传或重传">';
str += '<i class="glyphicon glyphicon-open"></i>';
str += me.buildHtml('file');
str += '</a></td>';
str += '<td style="display:none"><a class="button btn-download-file" href="#" data-toggle="tooltip" data-placement="top" title="下载文件">';
str += '<i class="glyphicon glyphicon-save"></i>';
str += '</a></td>';
if ( me.isAllowRemote ){
str += '<td><a class="button btn-upload-remote" href="javascript:;" data-toggle="tooltip" data-placement="top" title="引用外部资源">';
str += '<input type="hidden" name="url"/>';
str += '<i class="glyphicon glyphicon-link"></i>';
str += '</a></td>';
}
if ( me.isAllowDelete ) {
str += ' <td style="display:none"><a class="button btn-remove" href="javascript:;" data-toggle="tooltip" data-placement="top" title="移除文件">';
str += '<i class="glyphicon glyphicon-trash"></i>';
str += ' </a></td>';
}
// str += ' <td class="image-tools-buttons">';
// str += ' <a class="button btn-image-tools" href="javascript:;" data-toggle="tooltip" data-placement="top" title="图像工具">';
// str += '<i class="glyphicon glyphicon-picture"></i>';
// str += ' </a>';
// str += ' <ul class="vlist">';
// str += ' <li><a class="button btn-cut-image" href="javascript:;" title="裁剪"><i class="glyphicon glyphicon-wrench"></i></a></li>';
// str += ' <li><a class="button btn-rotate-0" href="javascript:;" title="旋转到0°"> 0° </a></li>';
// str += ' <li><a class="button btn-rotate-90" href="javascript:;" title="旋转到90°"> 90° </a></li>';
// str += ' <li><a class="button btn-rotate-180" href="javascript:;" title="旋转到180°"> 180° </a></li>';
// str += ' <li><a class="button btn-rotate-270" href="javascript:;" title="旋转到270°"> 270° </a></li>';
// str += ' </ul>';
// str += ' </td>';
str += '<td style="display:none"><a class="button btn-move-next" href="javascript:;" data-toggle="tooltip" data-placement="top" title="向后移">';
str += ' <i class="glyphicon glyphicon-chevron-right"></i>';
str += '</a></td>';
str += '</tr></table></div>';
}
str += '</li>';
};
return str;
};
/**
* 是否是图像类型
* @param {[type]} type [description]
* @return {Boolean} [description]
*/
Landers.upload.instance.prototype.isImageType = function(type){
var me = this;
type = type || me.fileType;
return $.inArray(type, [
'jpg', 'jpeg', 'gif', 'png', 'bmp', 'ico'
]) >= 0;
};
Landers.upload.instance.prototype.getAbsoluteUrl = function(url){
return url;
};
/**
* 显示界面
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.show = function(){
var me = this;
//对于显示来说,优先级为:small > mini > original (originall图片体积偏大)
var url = me.getAbsoluteUrl( me.data.small || me.data.mini || me.data.original );
if ( !url ) return me;
var url_info = Landers.url.parse(url);
var ext_name = url_info.extname || '未知类型';
ext_name = ext_name.toLowerCase();
if ( me.isImageType(ext_name) ) {
me.previewImage(url);
} else {
switch( ext_name ){
case 'swf':; case 'flv' :
me.previewFlash( url );
break;
case 'mp3':
me.previewAudio(url);
break;
case 'mp4':
me.previewVideo(url);
break;
default:
me.previewFileType( ext_name );
break;
}
}
return me;
};
Landers.upload.instance.prototype.clearPreview = function(){
var me = this;
me.preview.children().hide();
}
/**
* 预览Flash
* @param {[type]} url [description]
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.previewFlash = function(url){
var me = this;
me.clearPreview();
var $preview = me.preview.find('.preview-flash').show();
// Landers.loader.jsm('landers.flash', function(){
// Landers.flash.show($preview, url, me.size.width, me.size.height);
// });
};
/**
* 预览图像
* @param {[type]} url [description]
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.previewImage = function(url){
var me = this;
me.clearPreview();
var $preview = me.preview.find('.preview-image').show();
$preview.attr('src', url);
if ( !url ) $preview.hide();
};
/**
* 预览文件类型
* @param {[type]} url [description]
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.previewFileType = function( type ){
var me = this;
me.clearPreview();
var $preview = me.preview.find('.preview-file-type').show();
$preview.children().attr('class', '').addClass('file-type-' + type)
};
/**
* 预览音频
* @param {[type]} url [description]
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.previewAudio = function(text){
var me = this;
me.clearPreview();
var $preview = me.preview.find('.preview-audio').show();
};
/**
* 预览视频
* @param {[type]} url [description]
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.previewVideo = function(text){
var me = this;
me.clearPreview();
var $preview = me.preview.find('.preview-video').show();
};
/**
* 生成IFrameID
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.generateUploadIframeID = function(){
var me = this;
var date = new Date(),
uniqid = [
date.getYear(),
date.getMonth() + 1,
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds()
].join('');
return 'UploadResult' + '_' + me.key + '_' + me.container.index() + '_' + uniqid;
};
/**
* 上传本地文件
* @param {[type]} $input [description]
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.uploadLocal = function($input){
var me = this;
if (!me.enable || !me.isDirect) return;
// 记录input 原 parent
var $button = $input.parent();
me.container.showTopResponse('info', '上传中...', 500, function(){
me.uploading = true;
//创建IFRAME
var iframe_name = me.generateUploadIframeID();
$iframe = $('<iframe name="' + iframe_name + '" src="about:blank" class="upload-iframe"></iframe>');
me.container.append( $iframe );
//创建上传表单
$input.wrap('<form encType="multipart/form-data" class="upload-form"></form>');
if ( me.debug) iframe_name = '_blank';
var $form = $input.parent().attr({
target: iframe_name,
method: 'post',
action: Landers.url.qs.set( me.apiUrl, {act: 'upload'})
});
$form.append( $('<input name="key" type="hidden"/>').val(me.key) );
$form.append( $('<input name="_token" type="hidden"/>').val(me.csrfToken) );
// 是否使用原来的文件名
if (me.data && me.data.val && me.isRemainOriginalName){
$form.append( $('<input name="filename" type="hidden"/>').val(me.data.val) );
}
function strip_html(str) {
var reTag = /<(?:.|\s)*?>/g;
return str.replace(reTag,"");
}
function get_upload_result(){
var ret = Landers.iframe.html($iframe);
if ( !ret ) return;
var content = strip_html(ret);
try {
return $.parseJSON(content);
} catch(e) {
if (content.indexOf('413 Request Entity Too Large')) {
return {
success: false,
message: '上传文件过大'
};
}
if (content.indexOf('404 Http Not Found')) {
return {
success: false,
message: '404 Http Not Found'
};
}
return {
success: false,
message: content
};
}
}
function wait_for_upload(callback){
var rspn = get_upload_result();
var self = arguments.callee;
if ( rspn ){
// 处理成功与否
if ( !rspn.success ) {
me.container.showTopResponse('error', rspn.message, 3000);
} else {
me.container.showTopResponse('success', '上传成功', 3000);
me.data = {
original: rspn.data.url,
small: rspn.data.url_small,
mini: rspn.data.url_mini
};
};
me.uploading = false;
me.show();
// 上传结束后的回调
callback && callback();
} else {
setTimeout(function(){
self( callback );
}, 200);
}
}
var handle_after_upload = function(){
// 上传结束后将 $input清空并移回原处
$button.append( $input.val('') );
// 销毁 form
$form.remove();
// 销毁 iframe
$iframe.remove();
// 设置按钮
me.setButtonVisiableOrHidden();
// 回调
me.onUploade && me.onUploade.call(me);
};
// 提交表单,触发上传
$('body').append($form);
$form.trigger('submit');
// 监听 iframe 内容
Landers.iframe.ready( $iframe, function(){
wait_for_upload( handle_after_upload );
});
});
};
/**
* 移除
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.remove = function(){
var me = this;
me.data = {};
me.previewImage();
me.onRemove && me.onRemove();
me.setButtonVisiableOrHidden();
};
/**
* 销毁实例
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.destroy = function(){
me.container.unbind('hover')
me.container.find('*').unbind('click').unbind('change');
me.container.remove();
};
/**
* 上传远程文件
* @return {[type]} [description]
*/
Landers.upload.instance.prototype.uploadRemote = function($event){
var me = this;
var remote_url = prompt('输入引用的资源 URI:');
if ( remote_url ) {
me.container.showTopResponse('success', '引用成功', 3000);
me.data = {
original: remote_url,
small: remote_url,
mini: remote_url
};
} else {
me.container.showTopResponse('warning', '取消引用', 3000);
}
$event.trigger('blur');
me.show();
// 回调
me.onUploade && me.onUploade.call(me);
};
Landers.upload.instance.plugins = {};
$(function(){
var icons = {
'message-success': '<i class="glyphicon glyphicon-ok-sign"></i>',
'message-warning': '<i class="glyphicon glyphicon-warning-sign"></i>',
'message-info': '<i class="glyphicon glyphicon-repeat rotating"></i>',
'message-error': '<i class="glyphicon glyphicon-remove-sign"></i>',
};
var Timer = {
data: {},
clear: function(key){
if ( this.data[key] ) {
clearTimeout( this.data[key] );
this.data[key] = null;
}
},
set: function(key, value){
this.data[key] = value;
}
};
$.fn.showTopResponse = function(status, message, remain, callback){
var $me = $(this);
// 创建对象
var $message = $me.find('.top-response');
if ( !$message.length ) {
$message = $('<div class="top-response"></div>').appendTo($me);
}
// 唯一标识
var unique_id = $me.data('unique-id');
if ( ! unique_id ) {
unique_id = "top-response" + new Date().getTime();
$me.data('unique-id', unique_id);
}
// 清空定时器
Timer.clear(unique_id);
$me.hideResponse(function(){
var classes = Object.keys(icons).join(' ');
var icon_key = 'message-' + status;
$message.removeClass( classes )
.html( icons[icon_key] + ' ' + message )
.addClass( icon_key )
.stop()
.animate({
top: '0px'
}, 200, '', function(){
if ( remain ) {
Timer.set(unique_id, setTimeout(function(){
if ( callback ) {
callback();
} else {
$me.hideResponse();
}
}, remain));
}
});
});
}
$.fn.hideResponse = function( callback){
var $me = $(this);
var $message = $me.find('.top-response');
$message.stop()
.animate({
top: '-' + $message.height() + 'px',
}, 200, '', callback);
};
});
/*
* Purl (A JavaScript URL parser) v2.3.1
* Developed and maintanined by Mark Perkins, mark@allmarkedup.com
* Source repository: https://github.com/allmarkedup/jQuery-URL-Parser
* Licensed under an MIT-style license. See https://github.com/allmarkedup/jQuery-URL-Parser/blob/master/LICENSE for details.
*/
;(function(factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else {
window.purl = factory();
}
})(function() {
var tag2attr = {
a : 'href',
img : 'src',
form : 'action',
base : 'href',
script : 'src',
iframe : 'src',
link : 'href',
embed : 'src',
object : 'data'
},
key = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'], // keys available to query
aliases = { 'anchor' : 'fragment' }, // aliases for backwards compatability
parser = {
strict : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs
loose : /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
},
isint = /^[0-9]+$/;
function parseUri( url, strictMode ) {
var str = decodeURI( url ),
res = parser[ strictMode || false ? 'strict' : 'loose' ].exec( str ),
uri = { attr : {}, param : {}, seg : {} },
i = 14;
while ( i-- ) {
uri.attr[ key[i] ] = res[i] || '';
}
// build query and fragment parameters
uri.param['query'] = parseString(uri.attr['query']);
uri.param['fragment'] = parseString(uri.attr['fragment']);
// split path and fragement into segments
uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/');
uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/');
// compile a 'base' domain attribute
uri.attr['base'] = uri.attr.host ? (uri.attr.protocol ? uri.attr.protocol+'://'+uri.attr.host : uri.attr.host) + (uri.attr.port ? ':'+uri.attr.port : '') : '';
return uri;
}
function getAttrName( elm ) {
var tn = elm.tagName;
if ( typeof tn !== 'undefined' ) return tag2attr[tn.toLowerCase()];
return tn;
}
function promote(parent, key) {
if (parent[key].length === 0) return parent[key] = {};
var t = {};
for (var i in parent[key]) t[i] = parent[key][i];
parent[key] = t;
return t;
}
function parse(parts, parent, key, val) {
var part = parts.shift();
if (!part) {
if (isArray(parent[key])) {
parent[key].push(val);
} else if ('object' == typeof parent[key]) {
parent[key] = val;
} else if ('undefined' == typeof parent[key]) {
parent[key] = val;
} else {
parent[key] = [parent[key], val];
}
} else {
var obj = parent[key] = parent[key] || [];
if (']' == part) {
if (isArray(obj)) {
if ('' !== val) obj.push(val);
} else if ('object' == typeof obj) {
obj[keys(obj).length] = val;
} else {
obj = parent[key] = [parent[key], val];
}
} else if (~part.indexOf(']')) {
part = part.substr(0, part.length - 1);
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
// key
} else {
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
}
}
}
function merge(parent, key, val) {
if (~key.indexOf(']')) {
var parts = key.split('[');
parse(parts, parent, 'base', val);
} else {
if (!isint.test(key) && isArray(parent.base)) {
var t = {};
for (var k in parent.base) t[k] = parent.base[k];
parent.base = t;
}
if (key !== '') {
set(parent.base, key, val);
}
}
return parent;
}
function parseString(str) {
return reduce(String(str).split(/&|;/), function(ret, pair) {
try {
pair = decodeURIComponent(pair.replace(/\+/g, ' '));
} catch(e) {
// ignore
}
var eql = pair.indexOf('='),
brace = lastBraceInKey(pair),
key = pair.substr(0, brace || eql),
val = pair.substr(brace || eql, pair.length);
val = val.substr(val.indexOf('=') + 1, val.length);
if (key === '') {
key = pair;
val = '';
}
return merge(ret, key, val);
}, { base: {} }).base;
}
function set(obj, key, val) {
var v = obj[key];
if (typeof v === 'undefined') {
obj[key] = val;
} else if (isArray(v)) {
v.push(val);
} else {
obj[key] = [v, val];
}
}
function lastBraceInKey(str) {
var len = str.length,
brace,
c;
for (var i = 0; i < len; ++i) {
c = str[i];
if (']' == c) brace = false;
if ('[' == c) brace = true;
if ('=' == c && !brace) return i;
}
}
function reduce(obj, accumulator){
var i = 0,
l = obj.length >> 0,
curr = arguments[2];
while (i < l) {
if (i in obj) curr = accumulator.call(undefined, curr, obj[i], i, obj);
++i;
}
return curr;
}
function isArray(vArg) {
return Object.prototype.toString.call(vArg) === "[object Array]";
}
function keys(obj) {
var key_array = [];
for ( var prop in obj ) {
if ( obj.hasOwnProperty(prop) ) key_array.push(prop);
}
return key_array;
}
function purl( url, strictMode ) {
if ( arguments.length === 1 && url === true ) {
strictMode = true;
url = undefined;
}
strictMode = strictMode || false;
url = url || window.location.toString();
return {
data : parseUri(url, strictMode),
// get various attributes from the URI
attr : function( attr ) {
attr = aliases[attr] || attr;
return typeof attr !== 'undefined' ? this.data.attr[attr] : this.data.attr;
},
// return query string parameters
param : function( param ) {
return typeof param !== 'undefined' ? this.data.param.query[param] : this.data.param.query;
},
// return fragment parameters
fparam : function( param ) {
return typeof param !== 'undefined' ? this.data.param.fragment[param] : this.data.param.fragment;
},
// return path segments
segment : function( seg ) {
if ( typeof seg === 'undefined' ) {
return this.data.seg.path;
} else {
seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end
return this.data.seg.path[seg];
}
},
// return fragment segments
fsegment : function( seg ) {
if ( typeof seg === 'undefined' ) {
return this.data.seg.fragment;
} else {
seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end
return this.data.seg.fragment[seg];
}
}
};
}
purl.jQuery = function($){
if ($ != null) {
$.fn.url = function( strictMode ) {
var url = '';
if ( this.length ) {
url = $(this).attr( getAttrName(this[0]) ) || '';
}
return purl( url, strictMode );
};
$.url = purl;
}
};
purl.jQuery(window.jQuery);
return purl;
});
; (function (window, $) {
window.Landers = window.Landers || {};
Landers.url = Landers.url || {
real: function(url){
var s1 = '../', s2 = '/';
while(url.indexOf(s1) > -1) {
var arr = url.split(s1);
var left = arr[0] || '';
var right = arr.slice(1).join(s1);
if (left) {
left = left.split(s2);
if (!left[left.length-1]) left.pop();
left.pop();
left = left.join(s2);
}
url = left + s2 + right;
}
return url;
},
build:function(protocol, host, path, port){
var ret = protocol + host;
if (port && port!=80) ret += ':' + port;
path = path || '';
var _ = path.indexOf('/')===0 ? '' : '/';
ret += _ + path; return ret;
},
qs:{
parse:function(str){
if (typeof str !== 'string') {
return {};
}
str = str.trim().replace(/^(\?|#)/, '');
if (!str) {
return {};
}
return str.trim().split('&').reduce(function (ret, param) {
var parts = param.replace(/\+/g, ' ').split('=');
var key = parts[0];
var val = parts[1];
key = decodeURIComponent(key);
// missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
val = val === undefined ? null : decodeURIComponent(val);
if (!ret.hasOwnProperty(key)) {
ret[key] = val;
} else if (Array.isArray(ret[key])) {
ret[key].push(val);
} else {
ret[key] = [ret[key], val];
}
return ret;
}, {});
},
stringify:function(obj){
return obj ? Object.keys(obj).map(function (key) {
var val = obj[key];
if (Array.isArray(val)) {
return val.map(function (val2) {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
},
get:function(key, url) {
url = url || document.location.href;
var ret = null, submatch;
if (submatch = url.match(/\?([^#]*)#?/)){
var s = '&' + submatch[1];
var ret = this.parse(s);
if (ret) delete ret[''];
return key ? ret[key] : ret;
} else {
return '';
}
},
set:function(url, params){
url = url || document.location.href;
var parse = Landers.url.parse(url);
var anchor = parse.anchor ? ('#' + parse.anchor) : '';
if ( anchor ) url = url.replace(anchor, '');
for ( var key in params ){
var val = params[key];
val = encodeURI(val);
var reg = new RegExp('(\\?|&)'+ key +'=([^&]*)(&|$)','gi');
var pst = url.match(reg);
if (typeof pst == 'undefined' || pst === null){
url += ((url.indexOf('?')==-1)?'?':'&') + key + '=' + val;
continue;
}
var t = pst[0];
var retxt = t.substring(0,t.indexOf('=')+1) + val;
if (t.charAt(t.length-1)=='&') retxt += '&';
url = url.replace(reg,retxt);
}
url += anchor;
return url;
}
},
parse: function(url, key) {
var parse = purl(url);
var attr = parse.attr();
attr['port'] = attr['port'] || {
http:80, https:443, ftp:21
}[attr['protocol']] || '';
// 兼容原先调用
attr['anchor'] = attr['fragment'];
attr['pwd'] = attr['password'];
attr['filename'] = attr['file'];
var arr_file = attr['file'].split('.');
attr['basename'] = arr_file[0];
attr['extname'] = arr_file[1];
attr['dirname'] = attr['base'] + attr['directory'];
attr['domain'] = attr['host'];
attr['query'] = parse.data.param.query;
return key ? attr[key] : attr;
}
};
})(this, jQuery);
! function(win, $) {
win.Landers = win.Landers || {};
win.Landers.image = win.Landers.image || {
complete: true,
isReady: function(oimg) {
return oimg.readyState == 'complete' || oimg.readyState == 'interactive' || oimg.complete == true;
},
load: function(src, callback) {
var id = '_contain_for_load',
$cont = $('#' + id);
if (!$cont.length) {
$cont = $('<div></div>').attr({
id: id
})
.css({
width: '0px',
height: '0px',
overflow: 'hidden'
})
.appendTo($('body'));
}
var $o = $('<img/>').appendTo($cont);
$o.attr('src', src);
var o = $o.get(0),
me = this;
var _ = function() {
if (me.isReady(o)) {
if (callback) setTimeout(function() {
callback($o);
}, 200);
return $o;
}
return false;
};
var ret = _();
if (ret) return ret;
(function() {
var self = arguments.callee;
setTimeout(function() {
if (!_()) self();
}, 300);
})();
},
size: function(xo_src, callback) {
var me = this;
var src = typeof xo_src === 'string' ? xo_src : $(xo_src).attr('src');
me.load(src, function($img) {
callback({
width: $img.width(),
height: $img.height()
});
setTimeout(function() {
$img.remove();
}, 1000);
});
},
placeholder: function(oimg, w, h) {
var $o = $(oimg),
$p = $o.parent();
w = w || $o.width() || $p.width();
h = h || $o.height() || $p.height() || w;
w = w || 100;
h = h || 100;
$o.attr('src', 'https://placeholdit.imgix.net/~text?txtsize=25&txt=' + w + '%C3%97' + h + '&w=' + w + '&h=' + h);
oimg.onload = null;
oimg.onerror = null;
},
auto: function(img, is_inner, width, height, is_center, callback) {
function scale_zoom(size1, size2, is_inner, is_center) {
if (is_inner === undefined) is_inner = true;
if (!is_inner && is_center === undefined) is_center = true;
var $w1 = size1.width,
$h1 = size1.height;
var $w2 = size2.width,
$h2 = size2.height;
if (
($w1 == $w2 && $h1 == $h2) ||
($w1 < $w2 && $h1 < $h2 && is_inner)
) {
var ret = {
width: $w1,
height: $h1
};
if (is_center) {
ret['margin-left'] = ($w2 - $w1) / 2;
ret['margin-top'] = ($h2 - $h1) / 2;
};
return ret;
}
var $w, $h;
if ($w2 > 0 && $h2 > 0) {
if ($w1 / $h1 >= $w2 / $h2) {
if (is_inner) {
$w = $w2;
$h = ($w2 * $h1) / $w1;
} else {
$w = ($w1 * $h2) / $h1;
$h = $h2;
}
} else {
if (is_inner) {
$w = ($w1 * $h2) / $h1;
$h = $h2;
} else {
$w = $w2;
$h = ($w2 * $h1) / $w1;
}
};
} else {
if ($w2 > 0) {
$w = $w2;
$h = ($w2 * $h1) / $w1;
};
if ($h2 > 0) {
$h = $h2;
$w = ($w1 * $h2) / $w2;
};
}
$w = Math.round($w);
$h = Math.round($h);
var ret = {
width: $w,
height: $h
};
if (is_center) {
ret['margin-left'] = ($w2 - $w) / 2;
ret['margin-top'] = ($h2 - $h) / 2;
}
return ret;
};
var $img = $(img),
$parent = $img.parent();
width = parseInt(width);
height = parseInt(height);
$img.css({
width: '',
height: ''
});
var size1 = {
width: $img.width(),
height: $img.height()
};
var size2 = {
width: width || $parent.width(),
height: height || $parent.height()
};
var padding = parseInt($parent.css('padding')) * 2;
$parent.css({
width: size2.width + padding,
height: size2.height + padding,
overflow: 'hidden'
});
var visibility = {
visibility: 'visible'
};
if (is_center) $img.parent().css('text-align', 'left');
if (!size1.width || !size1.height) {
this.size($img.attr('src'), function(size1) {
$img.css(scale_zoom(size1 - padding, size2 - padding, is_inner, is_center)).css(visibility);
callback && callback();
});
} else {
$img.css(scale_zoom(size1, size2, is_inner, is_center)).css(visibility);
callback && callback();
}
},
reload: function(xo, callback) {
var $o = $(xo);
if (!$o.length) return;
$o.unbind('load');
var src = $o.attr('src');
src = Landers.url.qs.set(src, {
rnd: Math.random()
});
$o.attr('src', src);
if (callback) {
setTimeout(callback, 200);
}
}
};
}(window, jQuery);
; !function (win, $) {
win.Landers = win.Landers || {};
Landers.iframe = Landers.iframe || {
contentWindow:function(iframe){
return $(iframe).get(0).contentWindow;
},
create:function(name, data, is_url, container, xwin){
var owin = !xwin ? win : this.get(xwin, 2);
var obody = owin.document.body;
var $iframe = $('<iframe name="' + name + '"></iframe>', obody);
if (container) {
$iframe.appendTo($(container, owin));
} else {
$iframe.appendTo($(owin.document.body));
}
$iframe.attr({id:name, frameborder:'0', scrolling:'no'});
if (is_url) {
$iframe.attr({src:data});
} else {
this.html($iframe, data);
}
return $iframe.get(0);
},
get: function(mix){
if (!mix) {
return $('iframe').get(0);
} else {
switch (typeof mix) {
case 'string':
return $('iframe[name=' + mix + ']').get(0);
case 'object':
return $(mix).get(0);
default:
throw 'error';
}
}
},
html: function(mix, html){
var contentWindow = this.contentWindow(mix);
if (html === undefined) {
var $body = $(contentWindow.document.body);
return $body.html();
} else {
var html = '<html><head></head><body>' + (html || '') + '</body></html>';
contentWindow.document.open();
contentWindow.document.write(html);
contentWindow.document.close();
}
},
ready: function(mix, callback) {
var $iframe = $(mix);
$($iframe.get(0).document).ready(callback);
},
// ready:function(m