unparam: function (url, query) { var json = {}; if (!url || !avalon.type(url) === 'string') { return json; } url = url.replace(/^[^?=]*\?/gi, '').split('#')[0]; //去除网址与hash信息 //考虑到key中可能有特殊符号如“[].”等,而[]却有是否被编码的可能,所以,牺牲效率以求严谨,就算传了key参数,也是全部解析url。 var pairs = url.split('&'), pair, key, val, i = 0, len = pairs.length; for (; i < len; ++i) { pair = pairs[i].split('='); key = decode(pair[0]); try { val = decode(pair[1] || ''); } catch (e) { avalon.log(e + 'decodeURIComponent error : ' + pair[1], 3); val = pair[1] || ''; } key = key.replace(/\[\]$/, ''); //如果参数名以[]结尾,则当作数组 var item = json[key]; if (item === void 0) { json[key] = val; //第一次 } else if (Array.isArray(item)) { item.push(val) //第三次或三次以上 ; } else { json[key] = [ item, val ]; //第二次,将它转换为数组 } } return query ? json[query] : json; },
setTimeout(function () { element.innerHTML = pageHTML; vm.rootElement = element.getElementsByTagName('*')[0]; element.style.display = 'block'; if (continueScan) { continueScan(); } else { avalon.log('avalon\u8BF7\u5C3D\u5FEB\u5347\u52301.3.7+'); avalon.scan(element, [vmodel].concat(vmodels)); if (typeof options.onInit === 'function') { options.onInit.call(element, vmodel, options, vmodels); } } }, 100);
vm.$remove = function () { if (blurHandler) { avalon.unbind(window, 'click', blurHandler); } if (scrollHandler) { avalon.unbind(window, 'scroll', scrollHandler); } if (resizeHandler) { avalon.unbind(window, 'resize', resizeHandler); } vmodel.toggle = false; listNode && vmodel.container && vmodel.container.contains(listNode) && vmodel.container.removeChild(listNode); avalon.log('dropdown $remove'); };
request: function () { var opts = this.options; var node = this.transport = DOC.createElement('script'); avalon.log('ScriptTransport.sending.....'); if (opts.charset) { node.charset = opts.charset; } var load = node.onerror === null; //判定是否支持onerror var self = this; node.onerror = node[load ? 'onload' : 'onreadystatechange'] = function () { self.respond(); }; node.src = opts.url; head.insertBefore(node, head.firstChild); },
request: function () { var self = this; var opts = this.options; avalon.log('XhrTransport.request.....'); var transport = this.transport = new avalon.xhr(); if (opts.crossDomain && !('withCredentials' in transport)) { avalon.error('\u672C\u6D4F\u89C8\u5668\u4E0D\u652F\u6301crossdomain xhr'); } transport.open(opts.type, opts.url, opts.async, opts.username, opts.password); if (this.mimeType && transport.overrideMimeType) { transport.overrideMimeType(this.mimeType); } this.requestHeaders['X-Requested-With'] = 'XMLHttpRequest'; for (var i in this.requestHeaders) { transport.setRequestHeader(i, this.requestHeaders[i] + ''); } var dataType = this.options.dataType; if ('responseType' in transport && /^(blob|arraybuffer|text)$/.test(dataType)) { transport.responseType = dataType; this.useResponseType = true; } //必须要支持 FormData 和 file.fileList 的浏览器 才能用 xhr 发送 //标准规定的 multipart/form-data 发送必须用 utf-8 格式, 记得 ie 会受到 document.charset 的影响 transport.send(opts.hasContent && (this.formdata || this.querystring) || null); //在同步模式中,IE6,7可能会直接从缓存中读取数据而不会发出请求,因此我们需要手动发出请求 if (!opts.async || transport.readyState === 4) { this.respond(); } else { if (transport.onerror === null) { //如果支持onerror, onload新API transport.onload = transport.onerror = function (e) { this.readyState = 4; //IE9+ this.status = e.type === 'load' ? 200 : 500; self.respond(); }; } else { transport.onreadystatechange = function () { self.respond(); }; } } },
vm.$init = function (continueScan) { if (inited) return; inited = true; var dataTemplate = vmodel._getTemplate('data'), selectTemplate = vmodel._getTemplate('select'); vmodel.template = vmodel.template.replace(/\{\{MS_OPTION_SELECT\}\}/g, selectTemplate).replace(/\{\{MS_OPTION_DATA\}\}/g, dataTemplate).replace(/\{\{MS_OPTION_ID\}\}/g, id); element.innerHTML = vmodel.template; vmodel.rootElement = element.getElementsByTagName('*')[0]; vmodel._getSelect(); if (continueScan) { continueScan(); } else { avalon.log('\u8BF7\u5C3D\u5FEB\u5347\u5230avalon1.3.7+'); avalon.scan(element, [vmodel].concat(vmodels)); // callback after inited if (typeof options.onInit === 'function') { //vmodels是不包括vmodel的 options.onInit.call(element, vmodel, options, vmodels); } } };
request: function () { var self = this; var opts = this.options; var ID = 'iframe-upload-' + this.uniqueID; var form = opts.form; var iframe = this.transport = createIframe(ID); //form.enctype的值 //1:application/x-www-form-urlencoded 在发送前编码所有字符(默认) //2:multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。 //3:text/plain 空格转换为 "+" 加号,但不对特殊字符编码。 var backups = { target: form.target || '', action: form.action || '', enctype: form.enctype, method: form.method }; var fields = opts.data ? addDataToForm(form, opts.data) : []; //必须指定method与enctype,要不在FF报错 //表单包含文件域时,如果缺少 method=POST 以及 enctype=multipart/form-data, // 设置target到隐藏iframe,避免整页刷新 form.target = ID; form.action = opts.url; form.method = 'POST'; form.enctype = 'multipart/form-data'; avalon.log('iframe transport...'); this.uploadcallback = avalon.bind(iframe, 'load', function (event) { self.respond(event); }); form.submit(); //还原form的属性 for (var i in backups) { form[i] = backups[i]; } //移除之前动态添加的节点 fields.forEach(function (input) { form.removeChild(input); }); },
vm.$init = function (continueScan) { if (inited) return; inited = true; vmodel.arrClass = _init(vmodel.position); // 埋个钩子 vmodel.widgetElement.setAttribute('oni-tooltip-id', vmodel.$id); if (vmodel.event == 'mouseenter' && vmodel.delegate) { vmodel.event = 'mouseover'; } tooltipElem = tooltipELementMaker(vmodel.container); vm.rootElement = tooltipElem; avalon.scan(tooltipElem, [vmodel].concat(vmodels)); vmodel.event && element.setAttribute('ms-' + vmodel.event + '-101', '_showHandlder($event)'); if (continueScan) { continueScan(); } else { avalon.log('avalon\u8BF7\u5C3D\u5FEB\u5347\u52301.3.7+'); avalon.scan(element, [vmodel].concat(vmodels)); if (typeof options.onInit === 'function') { options.onInit.call(element, vmodel, options, vmodels); } } };
start: function (options) { if (History.started) throw new Error('avalon.history has already been started'); History.started = true; this.options = avalon.mix({}, History.defaults, options); //IE6不支持maxHeight, IE7支持XMLHttpRequest, IE8支持window.Element,querySelector, //IE9支持window.Node, window.HTMLElement, IE10不支持条件注释 //确保html5Mode属性存在,并且是一个布尔 this.html5Mode = !!this.options.html5Mode; //监听模式 this.monitorMode = this.html5Mode ? 'popstate' : 'hashchange'; if (!supportPushState) { if (this.html5Mode) { avalon.log('\u5982\u679C\u6D4F\u89C8\u5668\u4E0D\u652F\u6301HTML5 pushState\uFF0C\u5F3A\u5236\u4F7F\u7528hash hack!'); this.html5Mode = false; } this.monitorMode = 'hashchange'; } if (!supportHashChange) { this.monitorMode = 'iframepoll'; } this.prefix = '#' + this.options.hashPrefix + '/'; //确认前后都存在斜线, 如"aaa/ --> /aaa/" , "/aaa --> /aaa/", "aaa --> /aaa/", "/ --> /" this.basepath = ('/' + this.options.basepath + '/').replace(/^\/+|\/+$/g, '/'); // 去最左右两边的斜线 this.fragment = this.getFragment(); anchorElement.href = this.basepath; this.rootpath = this._getAbsolutePath(anchorElement); var that = this; var html = '<!doctype html><html><body>@</body></html>'; if (this.options.domain) { html = html.replace('<body>', '<script>document.domain =' + this.options.domain + '</script><body>'); } this.iframeHTML = html; if (this.monitorMode === 'iframepoll') { //IE6,7在hash改变时不会产生历史,需要用一个iframe来共享历史 avalon.ready(function () { if (that.iframe) return; var iframe = that.iframe || document.getElementById(that.iframeID) || document.createElement('iframe'); iframe.src = 'javascript:0'; iframe.style.display = 'none'; iframe.tabIndex = -1; document.body.appendChild(iframe); that.iframe = iframe.contentWindow; that._setIframeHistory(that.prefix + that.fragment); }); } // 支持popstate 就监听popstate // 支持hashchange 就监听hashchange // 否则的话只能每隔一段时间进行检测了 function checkUrl(e) { var iframe = that.iframe; if (that.monitorMode === 'iframepoll' && !iframe) { return false; } var pageHash = that.getFragment(), hash; if (iframe) { //IE67 var iframeHash = that.getHash(iframe); //与当前页面hash不等于之前的页面hash,这主要是用户通过点击链接引发的 if (pageHash !== that.fragment) { that._setIframeHistory(that.prefix + pageHash); hash = pageHash //如果是后退按钮触发hash不一致 ; } else if (iframeHash !== that.fragment) { that.location.hash = that.prefix + iframeHash; hash = iframeHash; } } else if (pageHash !== that.fragment) { hash = pageHash; } if (hash !== void 0) { that.fragment = hash; that.fireRouteChange(hash, { fromHistory: true }); } } //thanks https://github.com/browserstate/history.js/blob/master/scripts/uncompressed/history.html4.js#L272 // 支持popstate 就监听popstate // 支持hashchange 就监听hashchange(IE8,IE9,FF3) // 否则的话只能每隔一段时间进行检测了(IE6, IE7) switch (this.monitorMode) { case 'popstate': this.checkUrl = avalon.bind(window, 'popstate', checkUrl); this._fireLocationChange = checkUrl; break; case 'hashchange': this.checkUrl = avalon.bind(window, 'hashchange', checkUrl); break; case 'iframepoll': this.checkUrl = setInterval(checkUrl, this.options.interval); break; } //根据当前的location立即进入不同的路由回调 avalon.ready(function () { that.fireRouteChange(that.fragment || '/', { replace: true }); }); },
setTimeout(function () { // Fix busy state in FF3 node.parentNode.removeChild(node); avalon.log('iframe.parentNode.removeChild(iframe)'); });
json: function (text) { if (!avalon.parseJSON) { avalon.log('avalon.parseJSON\u4E0D\u5B58\u5728,\u8BF7\u5347\u7EA7\u5230\u6700\u65B0\u7248'); } return avalon.parseJSON(text); },
vm.$init = function (continueScan) { //根据multiple的类型初始化组件 if (vmodel.multiple) { //创建菜单 listNode = createListNode(); var list = listNode.firstChild; elemParent.insertBefore(listNode, element); list.appendChild(element); } else { //如果是单选 var title; titleNode = avalon.parseHTML(titleTemplate); title = titleNode.firstChild; elemParent.insertBefore(titleNode, element); title.appendChild(element); titleNode = title; //设置title宽度 vmodel.titleWidth = computeTitleWidth(); //设置label值 setLabelTitle(vmodel.value); //注册blur事件 blurHandler = avalon.bind(document.body, 'click', function (e) { //判断是否点击发生在dropdown节点内部 //如果不在节点内部即发生了blur事件 if (titleNode.contains(e.target)) { vmodel._toggle(); return; } else if (listNode && listNode.contains(e.target)) { return; } if (!vmodel.__cursorInList__ && !vmodel.multiple && vmodel.toggle) { vmodel.toggle = false; } }); if (vmodel.position) { //监听window的滚动及resize事件,重新定位下拉框的位置 scrollHandler = avalon.bind(window, 'scroll', _positionListNode); resizeHandler = avalon.bind(window, 'resize', _positionListNode); } } //如果原来的select没有子节点,那么为它添加option与optgroup if (!hasBuiltinTemplate) { element.appendChild(getFragmentFromData(dataModel)); avalon.each([ 'multiple', 'size' ], function (i, attr) { avalon(element).attr(attr, vmodel[attr]); }); } if (!vmodel.multiple) { var duplexName = (element.msData['ms-duplex'] || '').trim(), duplexModel; if (duplexName && (duplexModel = avalon.getModel(duplexName, vmodels))) { duplexModel[1].$watch(duplexModel[0], function (newValue) { vmodel.value = newValue; }); } vmodel.$watch('value', function (n, o) { avalon.nextTick(function () { var onChange = avalon.type(vmodel.onChange) === 'function' && vmodel.onChange || false; if (keepState) { keepState = false; return; } function valueStateKeep(stateKeep) { if (stateKeep) { keepState = true; vmodel.value = o; } else { if (duplexModel) { duplexModel[1][duplexModel[0]] = n; element.value = n; } vmodel.currentOption = setLabelTitle(n); } } if (onChange && onChange.call(element, n, o, vmodel, valueStateKeep) !== false || !onChange) { if (duplexModel) { duplexModel[1][duplexModel[0]] = n; element.value = n; } vmodel.currentOption = setLabelTitle(n); } }); }); } else { vmodel.value.$watch('length', function () { vmodel.multipleChange = !vmodel.multipleChange; optionsSync(); }); } //同步disabled或者enabled var disabledAttr = element.msData['ms-disabled'], disabledModel, enabledAttr = element.msData['ms-enabled'], enabledModel; if (disabledAttr && (disabledModel = avalon.getModel(disabledAttr, vmodels))) { disabledModel[1].$watch(disabledModel[0], function (n) { vmodel.enable = !n; }); vmodel.enable = !disabledModel[1][disabledModel[0]]; } if (enabledAttr && (enabledModel = avalon.getModel(enabledAttr, vmodels))) { enabledModel[1].$watch(enabledModel[0], function (n) { vmodel.enable = n; }); vmodel.enable = enabledModel[1][enabledModel[0]]; } vmodel.enable = !element.disabled; //同步readOnly var readOnlyAttr = vmodel.readonlyAttr, readOnlyModel; if (readOnlyAttr && (readOnlyModel = avalon.getModel(readOnlyAttr, vmodels))) { readOnlyModel[1].$watch(readOnlyModel[0], function (n) { vmodel.readOnly = n; }); vmodel.readOnly = readOnlyModel[1][readOnlyModel[0]]; } // 获取$source信息(兼容$source异步传值) if (vmodel.$source) { if (avalon.type(vmodel.$source) === 'string') { var sourceModel = avalon.getModel(vmodel.$source, vmodels); sourceModel && (vmodel.$source = sourceModel[1][sourceModel[0]]); } else if (!vmodel.$source.$id) { vmodel.$source = null; } else if (vmodel.$source.length > 0) { vmodel._refresh(vmodel.$source.length); } //对data的改变做监听,由于无法检测到对每一项的改变,检测数据项长度的改变 vmodel.$source && vmodel.$source.$watch && vmodel.$source.$watch('length', function (n) { vmodel._refresh(n); }); } // 新异步方式 vmodel.source.$watch('length', function (n) { vmodel._refresh(n); }); avalon.scan(element.parentNode, [vmodel].concat(vmodels)); if (continueScan) { continueScan(); } else { avalon.log('\u8BF7\u5C3D\u5FEB\u5347\u5230avalon1.3.7+'); if (typeof options.onInit === 'function') { options.onInit.call(element, vmodel, options, vmodels); } } vmodel.multiple && optionsSync(); };
onScrolling: function () { avalon.log("正在滚动") },
onScrollEnd: function () { avalon.log("滚动结束") }
onScrollTop: function () { avalon.log("滚动到顶部") },
vm.$init = function (continueScan) { if (inited) return; inited = true; vmodel.widgetElement.style.position = 'relative'; //document body情形需要做一下修正 vmodel.viewElement = vmodel.widgetElement == document.body ? document.getElementsByTagName('html')[0] : vmodel.widgetElement; vmodel.viewElement.style.overflow = vmodel.viewElement.style.overflowX = vmodel.viewElement.style.overflowY = 'hidden'; if (vmodel.widgetElement == document.body) vmodel.widgetElement.style.overflow = vmodel.widgetElement.style.overflowX = vmodel.widgetElement.style.overflowY = 'hidden'; vmodel._position = vmodel.position.split(','); var frag = avalon.parseHTML(options.template); vmodel.widgetElement.appendChild(frag); if (continueScan) { continueScan(); } else { avalon.log('avalon\u8BF7\u5C3D\u5FEB\u5347\u52301.3.7+'); avalon.scan(element, [vmodel].concat(vmodels)); if (typeof options.onInit === 'function') { options.onInit.call(element, vmodel, options, vmodels); } } var children = vmodel.widgetElement.childNodes; avalon.each(children, function (i, item) { var ele = avalon(item); if (ele.hasClass('oni-scrollbar') || ele.hasClass('ui-scrollbar')) { bars.push(ele); } else if (ele.hasClass('oni-scrollbar-scroller') || ele.hasClass('ui-scrollbar-scroller')) { scroller = ele; } }); // 竖直方向支持滚轮事件 if (vmodel.position.match(/left|right/g)) { var vs = [], hs = []; avalon.each(vmodel._position, function (i, item) { if (item.match(/left|right/g)) { vs.push([ i, item ]); } else { hs.push([ i, item ]); } }); function wheelLike(diretion, arr, e, func) { avalon.each(arr, function (i, item) { if (!bars[i].data('oni-scrollbar-needed')) return; vmodel._computer(func || function (obj) { return vmodel._clickComputer(obj, diretion); }, item[0], item[1], function (breakOut) { if (!breakOut) e.preventDefault(); }, 'breakOutCallbackCannotIgnore'); }); } function myOnWheel(e) { if (vmodel.disabled) return; if (vmodel.inFocuse) { wheelLike(e.wheelDelta > 0 ? 'up' : 'down', vs, e); } } function myKeyDown(e) { if (vmodel.disabled) return; var k = e.keyCode; if (k > 32 && k < 41 & vmodel.inFocuse) { // 方向按键 if (k in { 37: 1, 39: 1, 38: 1, 40: 1 }) { wheelLike(k in { 37: 1, 38: 1 } ? 'up' : 'down', k in { 38: 1, 40: 1 } ? vs : hs, e) // end or home // pageup or pagedown ; } else { var diretion = k in { 33: 1, 36: 1 } ? 'up' : 'down'; wheelLike(diretion, vs, e, function (obj) { var _top = scroller[0].scrollTop; // home, pageup if (k in { 33: 1, 36: 1 }) { if (_top) e.preventDefault() // end, pagedown ; } else { if (_top < obj.scrollerH - obj.viewH) e.preventDefault(); } // home or end // end plus 100, easy to trigger breakout if (k in { 36: 1, 35: 1 }) { return { x: 0, y: k == 36 ? 0 : obj.draggerparHeight - obj.draggerHeight + 100 } // pageup or pagedown // a frame ; } else { // frame 计算方式更新为百分比 var frame = (obj.draggerparHeight - obj.draggerHeight) * obj.viewH / (obj.scrollerH - obj.viewH); return vmodel._clickComputer(obj, diretion, strToNumber(frame) || 1); } }); } } } // document.body直接如此处理 if (vmodel.widgetElement == document.body) { vmodel.inFocuse = true; wheelArr.push(myOnWheel); keyArr.push(myKeyDown); } else { avalon.bind(element, 'mouseenter', function (e) { vmodel.inFocuse = true; wheelArr.push(myOnWheel); keyArr.push(myKeyDown); }); avalon.bind(element, 'mouseleave', function (e) { vmodel.inFocuse = false; for (var i = 0, len = wheelArr.length; i < len; i++) { if (wheelArr[i] === myOnWheel) { wheelArr.splice(i, 1); keyArr.splice(i, 1); break; } } }); } // 所有组件实例公用一个事件绑定 if (!wheelBinded) { wheelBinded = true; avalon.bind(document, 'mousewheel', function (e) { var cb = wheelArr[wheelArr.length - 1]; cb && cb(e); }); // keyborad,,,simida // left 37 // right 39 // top 38 // down 40 // pageup 33 // pagedown 34 // home 36 // end 35 avalon.bind(document, 'keydown', function (e) { var cb = keyArr[keyArr.length - 1]; cb && cb(e); }); } } avalon.bind(element, 'mouseenter', function () { avalon.each(bars, function (i, item) { vmodel._show('e', false, item); }); }); avalon.bind(element, 'mouseleave', function () { vmodel._hide(); }); vmodel.update('init'); if (scroller && scrollerGetted.length) { avalon.each(scrollerGetted, function (i, func) { func(); }); scrollerGetted = []; } };