UNPKG

landers.upload

Version:

landers.upload

1,590 lines (1,402 loc) 56.6 kB
/** * 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