├── $q ├── DOMready.js ├── Qdelegate.js └── jsonP.js ├── ChineseSort.js ├── README.md ├── getCurInteractiveScript.js ├── getOwnPrototype.js ├── ie8cors.js ├── overloaded.js └── tools ├── arrayTool.js ├── funTool.js ├── isXXX.js └── strTool.js /$q/DOMready.js: -------------------------------------------------------------------------------- 1 | //参考司徒正美的博客http://www.cnblogs.com/rubylouvre/p/4536334.html 2 | //功能类似jQuery的$(document).ready,可以在dom树解析完成时执行dom操作的函数,不用等到图片等资源加载再执行 3 | function DOMready(fn) { 4 | var d = document 5 | if (d.addEventListener) { 6 | d.addEventListener('DOMContentLoaded', fn, false) 7 | } else { 8 | //IE8-兼容 9 | var done = false, 10 | // 只执行一次用户的回调函数init() 11 | init = function() { 12 | if (!done) { 13 | done = true; 14 | fn(); 15 | } 16 | }; 17 | (function() { 18 | try { 19 | // DOM树未创建完之前调用doScroll会抛出错误 20 | d.documentElement.doScroll('left'); 21 | } catch (e) { 22 | //延迟再试一次~ 23 | setTimeout(arguments.callee, 50); 24 | return; 25 | } 26 | // 没有错误就表示DOM树创建完毕,然后立马执行用户回调 27 | init(); 28 | })(); 29 | //监听document的加载状态 30 | d.onreadystatechange = function() { 31 | // 如果用户是在domReady之后绑定的函数,就立马执行 32 | if (d.readyState == 'complete') { 33 | d.onreadystatechange = null; 34 | init(); 35 | } 36 | }; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /$q/Qdelegate.js: -------------------------------------------------------------------------------- 1 | //inspired by oui-dom-events https://github.com/oneuijs/oui-dom-events/blob/master/src/index.js 2 | 3 | function $q(selector) { 4 | // 使用全局变量来保存获取的对象。若不存在则新建变量 5 | window.$qObj = window.$qObj || {} 6 | //将选择器替换为可用的变量名,按需要再扩展,已经匹配 '#' '.' ' ' '+' ':'' 7 | var sel2pro = selector.replace(/\#/g, "$ID").replace(/\./g, "$CL").replace(/\s/g, "$SS").replace(/\+/g, "$AD").replace(/\:/g, "$CO") 8 | 9 | if (window.$qObj[sel2pro] === undefined) { 10 | window.$qObj[sel2pro] = new onObj(document.querySelectorAll(selector)) 11 | } 12 | return window.$qObj[sel2pro] 13 | } 14 | 15 | (function() { 16 | window.$qEv = {} 17 | var $qEv = window.$qEv; 18 | $qEv.bindEvent = function(eve, selector, fn, once) { 19 | var el = this.el; 20 | var els; 21 | if (selector instanceof Function) { 22 | fn = selector; 23 | els = el 24 | } else { 25 | els = document.querySelectorAll(selector) 26 | } 27 | var matched; 28 | selector=selector||""; 29 | this.fnName.push(eve + '&' +selector+'&'+ fn.name) 30 | var that = this 31 | this.fn.push(function(event) { 32 | e = event || window.event 33 | target = e.target || e.srcElement 34 | for (var i = 0; i < els.length; i++) { 35 | var _el = els[i] 36 | // 使用node.contains来判断是否父子元素的关系。兼容ie系列浏览器,性能优良 37 | // 跟传递的事件代理区别是,触发事件的是dom树上第一个被匹配到的符合条件的元素 38 | // 而不是距离事件目标最近的元素 39 | if (_el === target || _el.contains(target)) { 40 | matched = _el; 41 | break; 42 | } 43 | } 44 | if (matched) { 45 | fn.apply(matched, [].slice.call(arguments)); 46 | //黑科技callee 47 | if (once) { 48 | for (var j = 0; j < el.length; j++) { 49 | $qEv.removeEvent(el[j], eve, arguments.callee) 50 | } 51 | var index = that.fnName.indexOf(eve + '&' +selector+'&'+ fn.name) 52 | console.log(index) 53 | that.fn.splice(index, 1) 54 | that.fnName.splice(index, 1) 55 | } 56 | } 57 | }) 58 | for (var j = 0; j < el.length; j++) { 59 | $qEv.addEvent(el[j], eve, this.fn[this.fn.length - 1]) 60 | } 61 | }; 62 | 63 | if (window.addEventListener) { 64 | $qEv.addEvent = function(ele, eve, fn) { 65 | ele.addEventListener(eve, fn) 66 | return this 67 | } 68 | $qEv.removeEvent = function(ele, eve, fn) { 69 | ele.removeEventListener(eve, fn); 70 | return this 71 | } 72 | $qEv.fireEvent = function(target, eve) { 73 | var evt = document.createEvent("HTMLEvents"); 74 | evt.initEvent(eve, true, true); 75 | for (var i = 0; i < target.length; i++) { 76 | target[i].dispatchEvent(evt); 77 | } 78 | } 79 | } else { 80 | // 万恶的ie9- 81 | $qEv.addEvent = function(ele, eve, fn) { 82 | ele.attachEvent("on" + eve, fn); 83 | return this 84 | } 85 | $qEv.removeEvent = function(ele, eve, fn) { 86 | ele.detachEvent("on" + eve, fn); 87 | return this 88 | } 89 | $qEv.fireEvent = function(target, eve) { 90 | var evt = document.createEventObject(); 91 | for (var i = 0; i < target.length; i++) { 92 | target[i].fireEvent('on' + event, evt) 93 | } 94 | } 95 | } 96 | })() 97 | 98 | 99 | function onObj(el) { 100 | this.el = el 101 | this.fn = [] 102 | this.fnName = [] 103 | } 104 | 105 | onObj.prototype = { 106 | constructor: onObj, 107 | on: function() { 108 | window.$qEv.bindEvent.apply(this, arguments) 109 | return this 110 | }, 111 | click: function() { 112 | var arg = [].slice.call(arguments) 113 | arg.unshift('click') 114 | window.$qEv.bindEvent.apply(this, arg) 115 | return this 116 | }, 117 | mouseover: function() { 118 | var arg = [].slice.call(arguments) 119 | arg.unshift('mouseover') 120 | window.$qEv.bindEvent.apply(this, arg) 121 | return this 122 | }, 123 | dblclick: function() { 124 | var arg = [].slice.call(arguments) 125 | arg.unshift('dblclick') 126 | window.$qEv.bindEvent.apply(this, arg) 127 | return this 128 | }, 129 | once: function() { 130 | var arg = [].slice.call(arguments) 131 | arg.push(true) 132 | window.$qEv.bindEvent.apply(this, arg) 133 | return this 134 | }, 135 | off: function(eve, selector,fn) { 136 | fn = !(fn instanceof Function) && arguments[2] ? arguments[2] : fn 137 | var el = this.el; 138 | selector=selector||'' 139 | var index = this.fnName.indexOf(eve + '&' +selector+'&'+ fn.name) 140 | if (index !== -1) { 141 | for (var j = 0; j < el.length; j++) { 142 | window.$qEv.removeEvent(el[j], eve, this.fn[index]) 143 | } 144 | this.fn.splice(index, 1) 145 | this.fnName.splice(index, 1) 146 | } 147 | return this 148 | }, 149 | // 取消绑定到该元素的事件eve的所有监听事件 150 | offEvent: function(eve) { 151 | var el = this.el; 152 | var index = 0; 153 | while (index < this.fnName.length) { 154 | if (this.fnName[index].split("&")[0] === eve) { 155 | for (var j = 0; j < el.length; j++) { 156 | window.$qEv.removeEvent(el[j], eve, this.fn[index]) 157 | } 158 | this.fn.splice(index, 1) 159 | this.fnName.splice(index, 1) 160 | index-- 161 | } 162 | index++ 163 | } 164 | return this 165 | }, 166 | fire: function(eve, selector) { 167 | var el = this.el 168 | var target = []; 169 | if (selector) { 170 | var sel = document.querySelectorAll(selector); 171 | // 同样是使用contains来判断,不使用冒泡 172 | for (var k = 0; k < el.length; k++) { 173 | for (var j = 0; j < sel.length; j++) { 174 | if (el[k].contains(sel[j])) { 175 | target.push(sel[j]) 176 | } 177 | } 178 | } 179 | } else { 180 | target = el 181 | } 182 | window.$qEv.fireEvent(target, eve) 183 | return this 184 | } 185 | } 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | //可以使用匿名函数,可以链式绑定 196 | //如果要解除事件代理,不能绑定匿名函数 197 | //once是只响应一次的事件,严格模式不支持,once事件也可以取消 198 | // fire是触发已经绑定的事件 199 | // offEvent解除绑定到该事件的所有函数的绑定 200 | // $q('body').el里以数组的形式存储着获取的元素 201 | // 也可以使用a = new onObj(el)来,a.on(eve,selector,fn)的形式来使用 202 | //example 203 | function con() { 204 | console.log(this) 205 | } 206 | 207 | function bon() { 208 | console.log(new Date) 209 | } 210 | 211 | $q('body').on('click', 'div', con) 212 | // $q('body').fireAll('.cell') 213 | // console.log(window.$qObj) 214 | // $q('body').once('click', 'div', bon) 215 | // $q('body').off('click', 'div', bon) 216 | // $q('body').fire('click', 'div') 217 | // $q('div').off('click') 218 | -------------------------------------------------------------------------------- /$q/jsonP.js: -------------------------------------------------------------------------------- 1 | function JsonP(url,data,callback) { 2 | var jsp = document.createElement("script") 3 | jsp.type = "text/javascript" 4 | var dataStr = "" 5 | for(var i in data) { 6 | dataStr+=("&"+encodeURIComponent(i)+"="+encodeURIComponent(obj[i])) 7 | } 8 | jsp.src = url+"?callback="+callback+dataStr 9 | document.body.appendChild(jsp) 10 | } 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ChineseSort.js: -------------------------------------------------------------------------------- 1 | function ChineseSort(arr) { 2 | var strGB = "啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥薄雹保堡饱宝抱报暴豹鲍爆杯碑悲卑北辈背贝钡倍狈备惫焙被奔苯本笨崩绷甭泵蹦迸逼鼻比鄙笔彼碧蓖蔽毕毙毖币庇痹闭敝弊必辟壁臂避陛鞭边编贬扁便变卞辨辩辫遍标彪膘表鳖憋别瘪彬斌濒滨宾摈兵冰柄丙秉饼炳病并玻菠播拨钵波博勃搏铂箔伯帛舶脖膊渤泊驳捕卜哺补埠不布步簿部怖擦猜裁材才财睬踩采彩菜蔡餐参蚕残惭惨灿苍舱仓沧藏操糙槽曹草厕策侧册测层蹭插叉茬茶查碴搽察岔差诧拆柴豺搀掺蝉馋谗缠铲产阐颤昌猖场尝常长偿肠厂敞畅唱倡超抄钞朝嘲潮巢吵炒车扯撤掣彻澈郴臣辰尘晨忱沉陈趁衬撑称城橙成呈乘程惩澄诚承逞骋秤吃痴持匙池迟弛驰耻齿侈尺赤翅斥炽充冲虫崇宠抽酬畴踌稠愁筹仇绸瞅丑臭初出橱厨躇锄雏滁除楚础储矗搐触处揣川穿椽传船喘串疮窗幢床闯创吹炊捶锤垂春椿醇唇淳纯蠢戳绰疵茨磁雌辞慈瓷词此刺赐次聪葱囱匆从丛凑粗醋簇促蹿篡窜摧崔催脆瘁粹淬翠村存寸磋撮搓措挫错搭达答瘩打大呆歹傣戴带殆代贷袋待逮怠耽担丹单郸掸胆旦氮但惮淡诞弹蛋当挡党荡档刀捣蹈倒岛祷导到稻悼道盗德得的蹬灯登等瞪凳邓堤低滴迪敌笛狄涤翟嫡抵底地蒂第帝弟递缔颠掂滇碘点典靛垫电佃甸店惦奠淀殿碉叼雕凋刁掉吊钓调跌爹碟蝶迭谍叠丁盯叮钉顶鼎锭定订丢东冬董懂动栋侗恫冻洞兜抖斗陡豆逗痘都督毒犊独读堵睹赌杜镀肚度渡妒端短锻段断缎堆兑队对墩吨蹲敦顿囤钝盾遁掇哆多夺垛躲朵跺舵剁惰堕蛾峨鹅俄额讹娥恶厄扼遏鄂饿恩而儿耳尔饵洱二贰发罚筏伐乏阀法珐藩帆番翻樊矾钒繁凡烦反返范贩犯饭泛坊芳方肪房防妨仿访纺放菲非啡飞肥匪诽吠肺废沸费芬酚吩氛分纷坟焚汾粉奋份忿愤粪丰封枫蜂峰锋风疯烽逢冯缝讽奉凤佛否夫敷肤孵扶拂辐幅氟符伏俘服浮涪福袱弗甫抚辅俯釜斧脯腑府腐赴副覆赋复傅付阜父腹负富讣附妇缚咐噶嘎该改概钙盖溉干甘杆柑竿肝赶感秆敢赣冈刚钢缸肛纲岗港杠篙皋高膏羔糕搞镐稿告哥歌搁戈鸽胳疙割革葛格蛤阁隔铬个各给根跟耕更庚羹埂耿梗工攻功恭龚供躬公宫弓巩汞拱贡共钩勾沟苟狗垢构购够辜菇咕箍估沽孤姑鼓古蛊骨谷股故顾固雇刮瓜剐寡挂褂乖拐怪棺关官冠观管馆罐惯灌贯光广逛瑰规圭硅归龟闺轨鬼诡癸桂柜跪贵刽辊滚棍锅郭国果裹过哈骸孩海氦亥害骇酣憨邯韩含涵寒函喊罕翰撼捍旱憾悍焊汗汉夯杭航壕嚎豪毫郝好耗号浩呵喝荷菏核禾和何合盒貉阂河涸赫褐鹤贺嘿黑痕很狠恨哼亨横衡恒轰哄烘虹鸿洪宏弘红喉侯猴吼厚候后呼乎忽瑚壶葫胡蝴狐糊湖弧虎唬护互沪户花哗华猾滑画划化话槐徊怀淮坏欢环桓还缓换患唤痪豢焕涣宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍谎灰挥辉徽恢蛔回毁悔慧卉惠晦贿秽会烩汇讳诲绘荤昏婚魂浑混豁活伙火获或惑霍货祸击圾基机畸稽积箕肌饥迹激讥鸡姬绩缉吉极棘辑籍集及急疾汲即嫉级挤几脊己蓟技冀季伎祭剂悸济寄寂计记既忌际妓继纪嘉枷夹佳家加荚颊贾甲钾假稼价架驾嫁歼监坚尖笺间煎兼肩艰奸缄茧检柬碱硷拣捡简俭剪减荐槛鉴践贱见键箭件健舰剑饯渐溅涧建僵姜将浆江疆蒋桨奖讲匠酱降蕉椒礁焦胶交郊浇骄娇嚼搅铰矫侥脚狡角饺缴绞剿教酵轿较叫窖揭接皆秸街阶截劫节桔杰捷睫竭洁结解姐戒藉芥界借介疥诫届巾筋斤金今津襟紧锦仅谨进靳晋禁近烬浸尽劲荆兢茎睛晶鲸京惊精粳经井警景颈静境敬镜径痉靖竟竞净炯窘揪究纠玖韭久灸九酒厩救旧臼舅咎就疚鞠拘狙疽居驹菊局咀矩举沮聚拒据巨具距踞锯俱句惧炬剧捐鹃娟倦眷卷绢撅攫抉掘倔爵觉决诀绝均菌钧军君峻俊竣浚郡骏喀咖卡咯开揩楷凯慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕颗科壳咳可渴克刻客课肯啃垦恳坑吭空恐孔控抠口扣寇枯哭窟苦酷库裤夸垮挎跨胯块筷侩快宽款匡筐狂框矿眶旷况亏盔岿窥葵奎魁傀馈愧溃坤昆捆困括扩廓阔垃拉喇蜡腊辣啦莱来赖蓝婪栏拦篮阑兰澜谰揽览懒缆烂滥琅榔狼廊郎朗浪捞劳牢老佬姥酪烙涝勒乐雷镭蕾磊累儡垒擂肋类泪棱楞冷厘梨犁黎篱狸离漓理李里鲤礼莉荔吏栗丽厉励砾历利傈例俐痢立粒沥隶力璃哩俩联莲连镰廉怜涟帘敛脸链恋炼练粮凉梁粱良两辆量晾亮谅撩聊僚疗燎寥辽潦了撂镣廖料列裂烈劣猎琳林磷霖临邻鳞淋凛赁吝拎玲菱零龄铃伶羚凌灵陵岭领另令溜琉榴硫馏留刘瘤流柳六龙聋咙笼窿隆垄拢陇楼娄搂篓漏陋芦卢颅庐炉掳卤虏鲁麓碌露路赂鹿潞禄录陆戮驴吕铝侣旅履屡缕虑氯律率滤绿峦挛孪滦卵乱掠略抡轮伦仑沦纶论萝螺罗逻锣箩骡裸落洛骆络妈麻玛码蚂马骂嘛吗埋买麦卖迈脉瞒馒蛮满蔓曼慢漫谩芒茫盲氓忙莽猫茅锚毛矛铆卯茂冒帽貌贸么玫枚梅酶霉煤没眉媒镁每美昧寐妹媚门闷们萌蒙檬盟锰猛梦孟眯醚靡糜迷谜弥米秘觅泌蜜密幂棉眠绵冕免勉娩缅面苗描瞄藐秒渺庙妙蔑灭民抿皿敏悯闽明螟鸣铭名命谬摸摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌谋牟某拇牡亩姆母墓暮幕募慕木目睦牧穆拿哪呐钠那娜纳氖乃奶耐奈南男难囊挠脑恼闹淖呢馁内嫩能妮霓倪泥尼拟你匿腻逆溺蔫拈年碾撵捻念娘酿鸟尿捏聂孽啮镊镍涅您柠狞凝宁拧泞牛扭钮纽脓浓农弄奴努怒女暖虐疟挪懦糯诺哦欧鸥殴藕呕偶沤啪趴爬帕怕琶拍排牌徘湃派攀潘盘磐盼畔判叛乓庞旁耪胖抛咆刨炮袍跑泡呸胚培裴赔陪配佩沛喷盆砰抨烹澎彭蓬棚硼篷膨朋鹏捧碰坯砒霹批披劈琵毗啤脾疲皮匹痞僻屁譬篇偏片骗飘漂瓢票撇瞥拼频贫品聘乒坪苹萍平凭瓶评屏坡泼颇婆破魄迫粕剖扑铺仆莆葡菩蒲埔朴圃普浦谱曝瀑期欺栖戚妻七凄漆柒沏其棋奇歧畦崎脐齐旗祈祁骑起岂乞企启契砌器气迄弃汽泣讫掐恰洽牵扦钎铅千迁签仟谦乾黔钱钳前潜遣浅谴堑嵌欠歉枪呛腔羌墙蔷强抢橇锹敲悄桥瞧乔侨巧鞘撬翘峭俏窍切茄且怯窃钦侵亲秦琴勤芹擒禽寝沁青轻氢倾卿清擎晴氰情顷请庆琼穷秋丘邱球求囚酋泅趋区蛆曲躯屈驱渠取娶龋趣去圈颧权醛泉全痊拳犬券劝缺炔瘸却鹊榷确雀裙群然燃冉染瓤壤攘嚷让饶扰绕惹热壬仁人忍韧任认刃妊纫扔仍日戎茸蓉荣融熔溶容绒冗揉柔肉茹蠕儒孺如辱乳汝入褥软阮蕊瑞锐闰润若弱撒洒萨腮鳃塞赛三叁伞散桑嗓丧搔骚扫嫂瑟色涩森僧莎砂杀刹沙纱傻啥煞筛晒珊苫杉山删煽衫闪陕擅赡膳善汕扇缮墒伤商赏晌上尚裳梢捎稍烧芍勺韶少哨邵绍奢赊蛇舌舍赦摄射慑涉社设砷申呻伸身深娠绅神沈审婶甚肾慎渗声生甥牲升绳省盛剩胜圣师失狮施湿诗尸虱十石拾时什食蚀实识史矢使屎驶始式示士世柿事拭誓逝势是嗜噬适仕侍释饰氏市恃室视试收手首守寿授售受瘦兽蔬枢梳殊抒输叔舒淑疏书赎孰熟薯暑曙署蜀黍鼠属术述树束戍竖墅庶数漱恕刷耍摔衰甩帅栓拴霜双爽谁水睡税吮瞬顺舜说硕朔烁斯撕嘶思私司丝死肆寺嗣四伺似饲巳松耸怂颂送宋讼诵搜艘擞嗽苏酥俗素速粟僳塑溯宿诉肃酸蒜算虽隋随绥髓碎岁穗遂隧祟孙损笋蓑梭唆缩琐索锁所塌他它她塔獭挞蹋踏胎苔抬台泰酞太态汰坍摊贪瘫滩坛檀痰潭谭谈坦毯袒碳探叹炭汤塘搪堂棠膛唐糖倘躺淌趟烫掏涛滔绦萄桃逃淘陶讨套特藤腾疼誊梯剔踢锑提题蹄啼体替嚏惕涕剃屉天添填田甜恬舔腆挑条迢眺跳贴铁帖厅听烃汀廷停亭庭挺艇通桐酮瞳同铜彤童桶捅筒统痛偷投头透凸秃突图徒途涂屠土吐兔湍团推颓腿蜕褪退吞屯臀拖托脱鸵陀驮驼椭妥拓唾挖哇蛙洼娃瓦袜歪外豌弯湾玩顽丸烷完碗挽晚皖惋宛婉万腕汪王亡枉网往旺望忘妄威巍微危韦违桅围唯惟为潍维苇萎委伟伪尾纬未蔚味畏胃喂魏位渭谓尉慰卫瘟温蚊文闻纹吻稳紊问嗡翁瓮挝蜗涡窝我斡卧握沃巫呜钨乌污诬屋无芜梧吾吴毋武五捂午舞伍侮坞戊雾晤物勿务悟误昔熙析西硒矽晰嘻吸锡牺稀息希悉膝夕惜熄烯溪汐犀檄袭席习媳喜铣洗系隙戏细瞎虾匣霞辖暇峡侠狭下厦夏吓掀锨先仙鲜纤咸贤衔舷闲涎弦嫌显险现献县腺馅羡宪陷限线相厢镶香箱襄湘乡翔祥详想响享项巷橡像向象萧硝霄削哮嚣销消宵淆晓小孝校肖啸笑效楔些歇蝎鞋协挟携邪斜胁谐写械卸蟹懈泄泻谢屑薪芯锌欣辛新忻心信衅星腥猩惺兴刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅锈秀袖绣墟戌需虚嘘须徐许蓄酗叙旭序畜恤絮婿绪续轩喧宣悬旋玄选癣眩绚靴薛学穴雪血勋熏循旬询寻驯巡殉汛训讯逊迅压押鸦鸭呀丫芽牙蚜崖衙涯雅哑亚讶焉咽阉烟淹盐严研蜒岩延言颜阎炎沿奄掩眼衍演艳堰燕厌砚雁唁彦焰宴谚验殃央鸯秧杨扬佯疡羊洋阳氧仰痒养样漾邀腰妖瑶摇尧遥窑谣姚咬舀药要耀椰噎耶爷野冶也页掖业叶曳腋夜液一壹医揖铱依伊衣颐夷遗移仪胰疑沂宜姨彝椅蚁倚已乙矣以艺抑易邑屹亿役臆逸肄疫亦裔意毅忆义益溢诣议谊译异翼翌绎茵荫因殷音阴姻吟银淫寅饮尹引隐印英樱婴鹰应缨莹萤营荧蝇迎赢盈影颖硬映哟拥佣臃痈庸雍踊蛹咏泳涌永恿勇用幽优悠忧尤由邮铀犹油游酉有友右佑釉诱又幼迂淤于盂榆虞愚舆余俞逾鱼愉渝渔隅予娱雨与屿禹宇语羽玉域芋郁吁遇喻峪御愈欲狱育誉浴寓裕预豫驭鸳渊冤元垣袁原援辕园员圆猿源缘远苑愿怨院曰约越跃钥岳粤月悦阅耘云郧匀陨允运蕴酝晕韵孕匝砸杂栽哉灾宰载再在咱攒暂赞赃脏葬遭糟凿藻枣早澡蚤躁噪造皂灶燥责择则泽贼怎增憎曾赠扎喳渣札轧铡闸眨栅榨咋乍炸诈摘斋宅窄债寨瞻毡詹粘沾盏斩辗崭展蘸栈占战站湛绽樟章彰漳张掌涨杖丈帐账仗胀瘴障招昭找沼赵照罩兆肇召遮折哲蛰辙者锗蔗这浙珍斟真甄砧臻贞针侦枕疹诊震振镇阵蒸挣睁征狰争怔整拯正政帧症郑证芝枝支吱蜘知肢脂汁之织职直植殖执值侄址指止趾只旨纸志挚掷至致置帜峙制智秩稚质炙痔滞治窒中盅忠钟衷终种肿重仲众舟周州洲诌粥轴肘帚咒皱宙昼骤珠株蛛朱猪诸诛逐竹烛煮拄瞩嘱主著柱助蛀贮铸筑住注祝驻抓爪拽专砖转撰赚篆桩庄装妆撞壮状椎锥追赘坠缀谆准捉拙卓桌琢茁酌啄着灼浊兹咨资姿滋淄孜紫仔籽滓子自渍字鬃棕踪宗综总纵邹走奏揍租足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座亍丌兀丐廿卅丕亘丞鬲孬噩丨禺丿匕乇夭爻卮氐囟胤馗毓睾鼗丶亟鼐乜乩亓芈孛啬嘏仄厍厝厣厥厮靥赝匚叵匦匮匾赜卦卣刂刈刎刭刳刿剀剌剞剡剜蒯剽劂劁劐劓冂罔亻仃仉仂仨仡仫仞伛仳伢佤仵伥伧伉伫佞佧攸佚佝佟佗伲伽佶佴侑侉侃侏佾佻侪佼侬侔俦俨俪俅俚俣俜俑俟俸倩偌俳倬倏倮倭俾倜倌倥倨偾偃偕偈偎偬偻傥傧傩傺僖儆僭僬僦僮儇儋仝氽佘佥俎龠汆籴兮巽黉馘冁夔勹匍訇匐凫夙兕亠兖亳衮袤亵脔裒禀嬴蠃羸冫冱冽冼凇冖冢冥讠讦讧讪讴讵讷诂诃诋诏诎诒诓诔诖诘诙诜诟诠诤诨诩诮诰诳诶诹诼诿谀谂谄谇谌谏谑谒谔谕谖谙谛谘谝谟谠谡谥谧谪谫谮谯谲谳谵谶卩卺阝阢阡阱阪阽阼陂陉陔陟陧陬陲陴隈隍隗隰邗邛邝邙邬邡邴邳邶邺邸邰郏郅邾郐郄郇郓郦郢郜郗郛郫郯郾鄄鄢鄞鄣鄱鄯鄹酃酆刍奂劢劬劭劾哿勐勖勰叟燮矍廴凵凼鬯厶弁畚巯坌垩垡塾墼壅壑圩圬圪圳圹圮圯坜圻坂坩垅坫垆坼坻坨坭坶坳垭垤垌垲埏垧垴垓垠埕埘埚埙埒垸埴埯埸埤埝堋堍埽埭堀堞堙塄堠塥塬墁墉墚墀馨鼙懿艹艽艿芏芊芨芄芎芑芗芙芫芸芾芰苈苊苣芘芷芮苋苌苁芩芴芡芪芟苄苎芤苡茉苷苤茏茇苜苴苒苘茌苻苓茑茚茆茔茕苠苕茜荑荛荜茈莒茼茴茱莛荞茯荏荇荃荟荀茗荠茭茺茳荦荥荨茛荩荬荪荭荮莰荸莳莴莠莪莓莜莅荼莶莩荽莸荻莘莞莨莺莼菁萁菥菘堇萘萋菝菽菖萜萸萑萆菔菟萏萃菸菹菪菅菀萦菰菡葜葑葚葙葳蒇蒈葺蒉葸萼葆葩葶蒌蒎萱葭蓁蓍蓐蓦蒽蓓蓊蒿蒺蓠蒡蒹蒴蒗蓥蓣蔌甍蔸蓰蔹蔟蔺蕖蔻蓿蓼蕙蕈蕨蕤蕞蕺瞢蕃蕲蕻薤薨薇薏蕹薮薜薅薹薷薰藓藁藜藿蘧蘅蘩蘖蘼廾弈夼奁耷奕奚奘匏尢尥尬尴扌扪抟抻拊拚拗拮挢拶挹捋捃掭揶捱捺掎掴捭掬掊捩掮掼揲揸揠揿揄揞揎摒揆掾摅摁搋搛搠搌搦搡摞撄摭撖摺撷撸撙撺擀擐擗擤擢攉攥攮弋忒甙弑卟叱叽叩叨叻吒吖吆呋呒呓呔呖呃吡呗呙吣吲咂咔呷呱呤咚咛咄呶呦咝哐咭哂咴哒咧咦哓哔呲咣哕咻咿哌哙哚哜咩咪咤哝哏哞唛哧唠哽唔哳唢唣唏唑唧唪啧喏喵啉啭啁啕唿啐唼唷啖啵啶啷唳唰啜喋嗒喃喱喹喈喁喟啾嗖喑啻嗟喽喾喔喙嗪嗷嗉嘟嗑嗫嗬嗔嗦嗝嗄嗯嗥嗲嗳嗌嗍嗨嗵嗤辔嘞嘈嘌嘁嘤嘣嗾嘀嘧嘭噘嘹噗嘬噍噢噙噜噌噔嚆噤噱噫噻噼嚅嚓嚯囔囗囝囡囵囫囹囿圄圊圉圜帏帙帔帑帱帻帼帷幄幔幛幞幡岌屺岍岐岖岈岘岙岑岚岜岵岢岽岬岫岱岣峁岷峄峒峤峋峥崂崃崧崦崮崤崞崆崛嵘崾崴崽嵬嵛嵯嵝嵫嵋嵊嵩嵴嶂嶙嶝豳嶷巅彳彷徂徇徉後徕徙徜徨徭徵徼衢彡犭犰犴犷犸狃狁狎狍狒狨狯狩狲狴狷猁狳猃狺狻猗猓猡猊猞猝猕猢猹猥猬猸猱獐獍獗獠獬獯獾舛夥飧夤夂饣饧饨饩饪饫饬饴饷饽馀馄馇馊馍馐馑馓馔馕庀庑庋庖庥庠庹庵庾庳赓廒廑廛廨廪膺忄忉忖忏怃忮怄忡忤忾怅怆忪忭忸怙怵怦怛怏怍怩怫怊怿怡恸恹恻恺恂恪恽悖悚悭悝悃悒悌悛惬悻悱惝惘惆惚悴愠愦愕愣惴愀愎愫慊慵憬憔憧憷懔懵忝隳闩闫闱闳闵闶闼闾阃阄阆阈阊阋阌阍阏阒阕阖阗阙阚丬爿戕氵汔汜汊沣沅沐沔沌汨汩汴汶沆沩泐泔沭泷泸泱泗沲泠泖泺泫泮沱泓泯泾洹洧洌浃浈洇洄洙洎洫浍洮洵洚浏浒浔洳涑浯涞涠浞涓涔浜浠浼浣渚淇淅淞渎涿淠渑淦淝淙渖涫渌涮渫湮湎湫溲湟溆湓湔渲渥湄滟溱溘滠漭滢溥溧溽溻溷滗溴滏溏滂溟潢潆潇漤漕滹漯漶潋潴漪漉漩澉澍澌潸潲潼潺濑濉澧澹澶濂濡濮濞濠濯瀚瀣瀛瀹瀵灏灞宀宄宕宓宥宸甯骞搴寤寮褰寰蹇謇辶迓迕迥迮迤迩迦迳迨逅逄逋逦逑逍逖逡逵逶逭逯遄遑遒遐遨遘遢遛暹遴遽邂邈邃邋彐彗彖彘尻咫屐屙孱屣屦羼弪弩弭艴弼鬻屮妁妃妍妩妪妣妗姊妫妞妤姒妲妯姗妾娅娆姝娈姣姘姹娌娉娲娴娑娣娓婀婧婊婕娼婢婵胬媪媛婷婺媾嫫媲嫒嫔媸嫠嫣嫱嫖嫦嫘嫜嬉嬗嬖嬲嬷孀尕尜孚孥孳孑孓孢驵驷驸驺驿驽骀骁骅骈骊骐骒骓骖骘骛骜骝骟骠骢骣骥骧纟纡纣纥纨纩纭纰纾绀绁绂绉绋绌绐绔绗绛绠绡绨绫绮绯绱绲缍绶绺绻绾缁缂缃缇缈缋缌缏缑缒缗缙缜缛缟缡缢缣缤缥缦缧缪缫缬缭缯缰缱缲缳缵幺畿巛甾邕玎玑玮玢玟珏珂珑玷玳珀珉珈珥珙顼琊珩珧珞玺珲琏琪瑛琦琥琨琰琮琬琛琚瑁瑜瑗瑕瑙瑷瑭瑾璜璎璀璁璇璋璞璨璩璐璧瓒璺韪韫韬杌杓杞杈杩枥枇杪杳枘枧杵枨枞枭枋杷杼柰栉柘栊柩枰栌柙枵柚枳柝栀柃枸柢栎柁柽栲栳桠桡桎桢桄桤梃栝桕桦桁桧桀栾桊桉栩梵梏桴桷梓桫棂楮棼椟椠棹椤棰椋椁楗棣椐楱椹楠楂楝榄楫榀榘楸椴槌榇榈槎榉楦楣楹榛榧榻榫榭槔榱槁槊槟榕槠榍槿樯槭樗樘橥槲橄樾檠橐橛樵檎橹樽樨橘橼檑檐檩檗檫猷獒殁殂殇殄殒殓殍殚殛殡殪轫轭轱轲轳轵轶轸轷轹轺轼轾辁辂辄辇辋辍辎辏辘辚軎戋戗戛戟戢戡戥戤戬臧瓯瓴瓿甏甑甓攴旮旯旰昊昙杲昃昕昀炅曷昝昴昱昶昵耆晟晔晁晏晖晡晗晷暄暌暧暝暾曛曜曦曩贲贳贶贻贽赀赅赆赈赉赇赍赕赙觇觊觋觌觎觏觐觑牮犟牝牦牯牾牿犄犋犍犏犒挈挲掰搿擘耄毪毳毽毵毹氅氇氆氍氕氘氙氚氡氩氤氪氲攵敕敫牍牒牖爰虢刖肟肜肓肼朊肽肱肫肭肴肷胧胨胩胪胛胂胄胙胍胗朐胝胫胱胴胭脍脎胲胼朕脒豚脶脞脬脘脲腈腌腓腴腙腚腱腠腩腼腽腭腧塍媵膈膂膑滕膣膪臌朦臊膻臁膦欤欷欹歃歆歙飑飒飓飕飙飚殳彀毂觳斐齑斓於旆旄旃旌旎旒旖炀炜炖炝炻烀炷炫炱烨烊焐焓焖焯焱煳煜煨煅煲煊煸煺熘熳熵熨熠燠燔燧燹爝爨灬焘煦熹戾戽扃扈扉礻祀祆祉祛祜祓祚祢祗祠祯祧祺禅禊禚禧禳忑忐怼恝恚恧恁恙恣悫愆愍慝憩憝懋懑戆肀聿沓泶淼矶矸砀砉砗砘砑斫砭砜砝砹砺砻砟砼砥砬砣砩硎硭硖硗砦硐硇硌硪碛碓碚碇碜碡碣碲碹碥磔磙磉磬磲礅磴礓礤礞礴龛黹黻黼盱眄眍盹眇眈眚眢眙眭眦眵眸睐睑睇睃睚睨睢睥睿瞍睽瞀瞌瞑瞟瞠瞰瞵瞽町畀畎畋畈畛畲畹疃罘罡罟詈罨罴罱罹羁罾盍盥蠲钅钆钇钋钊钌钍钏钐钔钗钕钚钛钜钣钤钫钪钭钬钯钰钲钴钶钷钸钹钺钼钽钿铄铈铉铊铋铌铍铎铐铑铒铕铖铗铙铘铛铞铟铠铢铤铥铧铨铪铩铫铮铯铳铴铵铷铹铼铽铿锃锂锆锇锉锊锍锎锏锒锓锔锕锖锘锛锝锞锟锢锪锫锩锬锱锲锴锶锷锸锼锾锿镂锵镄镅镆镉镌镎镏镒镓镔镖镗镘镙镛镞镟镝镡镢镤镥镦镧镨镩镪镫镬镯镱镲镳锺矧矬雉秕秭秣秫稆嵇稃稂稞稔稹稷穑黏馥穰皈皎皓皙皤瓞瓠甬鸠鸢鸨鸩鸪鸫鸬鸲鸱鸶鸸鸷鸹鸺鸾鹁鹂鹄鹆鹇鹈鹉鹋鹌鹎鹑鹕鹗鹚鹛鹜鹞鹣鹦鹧鹨鹩鹪鹫鹬鹱鹭鹳疒疔疖疠疝疬疣疳疴疸痄疱疰痃痂痖痍痣痨痦痤痫痧瘃痱痼痿瘐瘀瘅瘌瘗瘊瘥瘘瘕瘙瘛瘼瘢瘠癀瘭瘰瘿瘵癃瘾瘳癍癞癔癜癖癫癯翊竦穸穹窀窆窈窕窦窠窬窨窭窳衤衩衲衽衿袂袢裆袷袼裉裢裎裣裥裱褚裼裨裾裰褡褙褓褛褊褴褫褶襁襦襻疋胥皲皴矜耒耔耖耜耠耢耥耦耧耩耨耱耋耵聃聆聍聒聩聱覃顸颀颃颉颌颍颏颔颚颛颞颟颡颢颥颦虍虔虬虮虿虺虼虻蚨蚍蚋蚬蚝蚧蚣蚪蚓蚩蚶蛄蚵蛎蚰蚺蚱蚯蛉蛏蚴蛩蛱蛲蛭蛳蛐蜓蛞蛴蛟蛘蛑蜃蜇蛸蜈蜊蜍蜉蜣蜻蜞蜥蜮蜚蜾蝈蜴蜱蜩蜷蜿螂蜢蝽蝾蝻蝠蝰蝌蝮螋蝓蝣蝼蝤蝙蝥螓螯螨蟒蟆螈螅螭螗螃螫蟥螬螵螳蟋蟓螽蟑蟀蟊蟛蟪蟠蟮蠖蠓蟾蠊蠛蠡蠹蠼缶罂罄罅舐竺竽笈笃笄笕笊笫笏筇笸笪笙笮笱笠笥笤笳笾笞筘筚筅筵筌筝筠筮筻筢筲筱箐箦箧箸箬箝箨箅箪箜箢箫箴篑篁篌篝篚篥篦篪簌篾篼簏簖簋簟簪簦簸籁籀臾舁舂舄臬衄舡舢舣舭舯舨舫舸舻舳舴舾艄艉艋艏艚艟艨衾袅袈裘裟襞羝羟羧羯羰羲籼敉粑粝粜粞粢粲粼粽糁糇糌糍糈糅糗糨艮暨羿翎翕翥翡翦翩翮翳糸絷綦綮繇纛麸麴赳趄趔趑趱赧赭豇豉酊酐酎酏酤酢酡酰酩酯酽酾酲酴酹醌醅醐醍醑醢醣醪醭醮醯醵醴醺豕鹾趸跫踅蹙蹩趵趿趼趺跄跖跗跚跞跎跏跛跆跬跷跸跣跹跻跤踉跽踔踝踟踬踮踣踯踺蹀踹踵踽踱蹉蹁蹂蹑蹒蹊蹰蹶蹼蹯蹴躅躏躔躐躜躞豸貂貊貅貘貔斛觖觞觚觜觥觫觯訾謦靓雩雳雯霆霁霈霏霎霪霭霰霾龀龃龅龆龇龈龉龊龌黾鼋鼍隹隼隽雎雒瞿雠銎銮鋈錾鍪鏊鎏鐾鑫鱿鲂鲅鲆鲇鲈稣鲋鲎鲐鲑鲒鲔鲕鲚鲛鲞鲟鲠鲡鲢鲣鲥鲦鲧鲨鲩鲫鲭鲮鲰鲱鲲鲳鲴鲵鲶鲷鲺鲻鲼鲽鳄鳅鳆鳇鳊鳋鳌鳍鳎鳏鳐鳓鳔鳕鳗鳘鳙鳜鳝鳟鳢靼鞅鞑鞒鞔鞯鞫鞣鞲鞴骱骰骷鹘骶骺骼髁髀髅髂髋髌髑魅魃魇魉魈魍魑飨餍餮饕饔髟髡髦髯髫髻髭髹鬈鬏鬓鬟鬣麽麾縻麂麇麈麋麒鏖麝麟黛黜黝黠黟黢黩黧黥黪黯鼢鼬鼯鼹鼷鼽鼾齄"; 3 | var pinyinSpell = ["a", 0, "ai", 2, "an", 15, "ang", 24, "ao", 27, "ba", 36, "bai", 54, "ban", 62, "bang", 77, "bao", 89, "bei", 106, "ben", 121, "beng", 125, "bi", 131, "bian", 155, "biao", 167, "bie", 171, "bin", 175, "bing", 181, "bo", 190, "bu", 211, "ca", 220, "cai", 221, "can", 232, "cang", 239, "cao", 244, "ce", 249, "ceng", 254, "cha", 256, "chai", 267, "chan", 270, "chang", 280, "chao", 293, "che", 302, "chen", 308, "cheng", 318, "chi", 333, "chong", 349, "chou", 354, "chu", 366, "chuai", 382, "chuan", 383, "chuang", 390, "chui", 396, "chun", 401, "chuo", 408, "ci", 410, "cong", 422, "cou", 428, "cu", 429, "cuan", 433, "cui", 436, "cun", 444, "cuo", 447, "da", 453, "dai", 459, "dan", 471, "dang", 486, "dao", 491, "de", 503, "deng", 506, "di", 513, "dian", 532, "diao", 548, "die", 557, "ding", 564, "diu", 573, "dong", 574, "dou", 584, "du", 591, "duan", 606, "dui", 612, "dun", 616, "duo", 625, "e", 637, "en", 650, "er", 651, "fa", 659, "fan", 667, "fang", 684, "fei", 695, "fen", 707, "feng", 722, "fo", 737, "fou", 738, "fu", 739, "ga", 784, "gai", 786, "gan", 792, "gang", 803, "gao", 812, "ge", 822, "gei", 839, "gen", 840, "geng", 842, "gong", 849, "gou", 864, "gu", 873, "gua", 891, "guai", 897, "guan", 900, "guang", 911, "gui", 914, "gun", 930, "guo", 933, "ha", 939, "hai", 940, "han", 947, "hang", 966, "hao", 969, "he", 978, "hei", 996, "hen", 998, "heng", 1002, "hong", 1007, "hou", 1016, "hu", 1023, "hua", 1041, "huai", 1050, "huan", 1055, "huang", 1069, "hui", 1083, "hun", 1104, "huo", 1110, "ji", 1120, "jia", 1173, "jian", 1190, "jiang", 1230, "jiao", 1243, "jie", 1271, "jin", 1298, "jing", 1318, "jiong", 1343, "jiu", 1345, "ju", 1362, "juan", 1387, "jue", 1394, "jun", 1404, "ka", 1415, "kai", 1419, "kan", 1424, "kang", 1430, "kao", 1437, "ke", 1441, "ken", 1456, "keng", 1460, "kong", 1462, "kou", 1466, "ku", 1470, "kua", 1477, "kuai", 1482, "kuan", 1486, "kuang", 1488, "kui", 1496, "kun", 1507, "kuo", 1511, "la", 1515, "lai", 1522, "lan", 1525, "lang", 1540, "lao", 1547, "le", 1556, "lei", 1558, "leng", 1569, "li", 1572, "lia", 1606, "lian", 1607, "liang", 1621, "liao", 1632, "lie", 1645, "lin", 1650, "ling", 1662, "liu", 1676, "long", 1687, "lou", 1696, "lu", 1702, "lv", 1722, "luan", 1736, "lue", 1742, "lun", 1744, "luo", 1751, "ma", 1763, "mai", 1772, "man", 1778, "mang", 1787, "mao", 1793, "me", 1805, "mei", 1806, "men", 1822, "meng", 1825, "mi", 1833, "mian", 1847, "miao", 1856, "mie", 1864, "min", 1866, "ming", 1872, "miu", 1878, "mo", 1879, "mou", 1896, "mu", 1899, "na", 1914, "nai", 1921, "nan", 1926, "nang", 1929, "nao", 1930, "ne", 1935, "nei", 1936, "nen", 1938, "neng", 1939, "ni", 1940, "nian", 1951, "niang", 1958, "niao", 1960, "nie", 1962, "nin", 1969, "ning", 1970, "niu", 1976, "nong", 1980, "nu", 1984, "nv", 1987, "nuan", 1988, "nue", 1989, "nuo", 1991, "o", 1995, "ou", 1996, "pa", 2003, "pai", 2009, "pan", 2015, "pang", 2023, "pao", 2028, "pei", 2035, "pen", 2044, "peng", 2046, "pi", 2060, "pian", 2077, "piao", 2081, "pie", 2085, "pin", 2087, "ping", 2092, "po", 2101, "pu", 2110, "qi", 2125, "qia", 2161, "qian", 2164, "qiang", 2186, "qiao", 2194, "qie", 2209, "qin", 2214, "qing", 2225, "qiong", 2238, "qiu", 2240, "qu", 2248, "quan", 2261, "que", 2272, "qun", 2280, "ran", 2282, "rang", 2286, "rao", 2291, "re", 2294, "ren", 2296, "reng", 2306, "ri", 2308, "rong", 2309, "rou", 2319, "ru", 2322, "ruan", 2332, "rui", 2334, "run", 2337, "ruo", 2339, "sa", 2341, "sai", 2344, "san", 2348, "sang", 2352, "sao", 2355, "se", 2359, "sen", 2362, "seng", 2363, "sha", 2364, "shai", 2373, "shan", 2375, "shang", 2391, "shao", 2399, "she", 2410, "shen", 2422, "sheng", 2438, "shi", 2449, "shou", 2496, "shu", 2506, "shua", 2539, "shuai", 2541, "shuan", 2545, "shuang", 2547, "shui", 2550, "shun", 2554, "shuo", 2558, "si", 2562, "song", 2578, "sou", 2586, "su", 2589, "suan", 2602, "sui", 2605, "sun", 2616, "suo", 2619, "ta", 2627, "tai", 2636, "tan", 2645, "tang", 2663, "tao", 2676, "te", 2687, "teng", 2688, "ti", 2692, "tian", 2707, "tiao", 2715, "tie", 2720, "ting", 2723, "tong", 2733, "tou", 2746, "tu", 2750, "tuan", 2761, "tui", 2763, "tun", 2769, "tuo", 2772, "wa", 2783, "wai", 2790, "wan", 2792, "wang", 2809, "wei", 2819, "wen", 2852, "weng", 2862, "wo", 2865, "wu", 2874, "xi", 2903, "xia", 2938, "xian", 2951, "xiang", 2977, "xiao", 2997, "xie", 3015, "xin", 3036, "xing", 3046, "xiong", 3061, "xiu", 3068, "xu", 3077, "xuan", 3096, "xue", 3106, "xun", 3112, "ya", 3126, "yan", 3142, "yang", 3175, "yao", 3192, "ye", 3207, "yi", 3222, "yin", 3275, "ying", 3291, "yo", 3309, "yong", 3310, "you", 3325, "yu", 3346, "yuan", 3390, "yue", 3410, "yun", 3420, "za", 3432, "zai", 3435, "zan", 3442, "zang", 3446, "zao", 3449, "ze", 3463, "zei", 3467, "zen", 3468, "zeng", 3469, "zha", 3473, "zhai", 3487, "zhan", 3493, "zhang", 3510, "zhao", 3525, "zhe", 3535, "zhen", 3545, "zheng", 3561, "zhi", 3576, "zhong", 3619, "zhou", 3630, "zhu", 3644, "zhua", 3670, "zhuai", 3672, "zhuan", 3673, "zhuang", 3679, "zhui", 3686, "zhun", 3692, "zhuo", 3694, "zi", 3705, "zong", 3720, "zou", 3727, "zu", 3731, "zuan", 3739, "zui", 3741, "zun", 3745, "zuo", 3747]; 4 | //存放汉字串的拼音 5 | var strToPinyin = {}; 6 | // 存放单个汉字的拼音 7 | var charToPinyin = {}; 8 | 9 | function getGB2312Spell(str, sp) { 10 | var i, c, t, p, ret = ""; 11 | if (sp == null) sp = ""; 12 | var strP = []; 13 | for (i = 0; i < str.length; i++) { 14 | var ch = str.charCodeAt(i); 15 | if (ch >= 0x4e00) { 16 | p = strGB.indexOf(str.charAt(i)); 17 | if (p > -1 && p < 3755) { 18 | for (t = pinyinSpell.length - 1; t > 0; t = t - 2) 19 | if (pinyinSpell[t] <= p) break; 20 | if (t > 0) ret += pinyinSpell[t - 1] + sp; 21 | } 22 | } else { 23 | ret += String.fromCharCode(ch) + sp; 24 | } 25 | } 26 | return ret.substr(0, ret.length - sp.length); 27 | }; 28 | 29 | function getCharIndexStr(str) { 30 | if (strToPinyin && strToPinyin[str]) { 31 | return strToPinyin[str] 32 | } 33 | var chars = str.split(''); 34 | var rtn = ''; 35 | for (var i = 0; i < chars.length; i++) { 36 | var ch = chars[i]; 37 | if (charToPinyin && charToPinyin[ch]) { 38 | rtn += charToPinyin[ch] 39 | } else { 40 | var convertStr = getGB2312Spell(ch).charAt(0); 41 | charToPinyin[ch] = convertStr; 42 | rtn += convertStr; 43 | } 44 | } 45 | strToPinyin[str] = rtn 46 | return rtn; 47 | }; 48 | var sortArr = arr.sort(function(str1, str2) { 49 | var str1IndexStr = getCharIndexStr(str1); 50 | var str2IndexStr = getCharIndexStr(str2); 51 | return (str1IndexStr > str2IndexStr); 52 | }) 53 | 54 | return sortArr 55 | } 56 | 57 | 58 | 59 | 60 | 61 | // example 62 | // console.log( ChineseSort(['张','陈','李'])) 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # littleJS 2 | 3 | 4 | 5 | ####存放一些上网找到的或者自己写的js文件 6 | 7 | #####ie6,ie7 not support,some use es6 8 | #####正在阅读源码,准备加入lodash和underscore中比较好用的函数 9 | #$q 10 | ##Qdelegate 11 | 12 | #####事件代理类似jquery的on方法。 13 | #####使用形式为$q(selector).on(event[,selector],handle),$q(selector).off(event[,selector],handle) 14 | #####使用兼容性良好的node.contains方法而不是事件冒泡。性能更强 15 | #####跟传统的事件代理区别是,触发事件的将会是dom树上第一个被匹配到的符合条件的元素,而不是距离事件目标最近的符合条件的父元素 16 | #####兼容ie系列的事件模型 17 | #####目前支持on,off,once,fire,offEvent。 18 | #####严格模式下不支持once 19 | #####fire可以触发事件,执行绑定的函数 20 | #####offEvent解除绑定到该事件的所有函数的绑定 21 | ##### 22 | #####$q(selector).el 里以数组的形式存储着获取的元素 23 | #####可以使用匿名函数。 24 | #####如果需要解除匿名函数的绑定,需要以: 25 | #####var a = new onObj(el),a.on(eve,selector,fn)的形式来使用该工具 26 | #####把事件处理相关函数和取得的父元素绑定到全局变量$qE和$qObj,加快代码运行速度,谢谢欧碧童鞋的提醒。 27 | 28 | ##JSONp 29 | #####启用jsonp 30 | 31 | ##DOMready 32 | 33 | #####功能类似jQuery的$(document).ready。 34 | #####可以在dom树解析完成时执行dom操作的函数,不用等到图片等资源加载再执行。 35 | 36 | >参考自司徒正美的博客http://www.cnblogs.com/rubylouvre/p/4536334.html 37 | 38 | #tools 39 | 40 | ##arrayTool 41 | 42 | 关于数组的函数集合,目前有数组唯一化的函数 43 | 44 | 45 | ##ChineseSort 46 | 47 | 应对不支持localecompare时需要中文排序的情况(某些型号的三星手机)。 48 | 参考自论坛的方法,做了包装和优化 49 | 50 | 51 | 52 | ##getCurInteractiveScript 53 | 54 | 获取正在运行的js文件。 55 | 来自司徒正美的书籍《js框架设计》 56 | 57 | 58 | 59 | ###etOwnPrototype 60 | 61 | 将对象中本身(非继承至原型)的属性和值以二维数组的形式返回。 62 | 有点接近Object.keys 63 | 64 | 65 | 66 | ##IE8cors 67 | 68 | 启用XDomainRequest,让IE8支持跨域。 69 | 照搬至博客,晚点整合进jQuery或是原生js 70 | 71 | >http://mcgivery.com/ie8-and-cors/ 72 | 73 | 74 | 75 | ##isXXX 76 | 77 | 类型判断。 78 | 来自网上或者自己的尝试 79 | 80 | ##overloaded 81 | 函数重载,利用了闭包 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /getCurInteractiveScript.js: -------------------------------------------------------------------------------- 1 | //获取正在执行的js标签 2 | function getCurInteractiveScript(){ 3 | //先看ff4+原生支持的 4 | if(document.currentScript){ 5 | return document.currentScript; 6 | } 7 | 8 | var elems = document.getElementsByTagName("script"); 9 | for(var i=0,elem;elem=elems[i++];){ 10 | if(elem.readyState === 'interactive'){ 11 | return elem; 12 | } 13 | } 14 | 15 | return null; 16 | } 17 | -------------------------------------------------------------------------------- /getOwnPrototype.js: -------------------------------------------------------------------------------- 1 | function getOwnProperty(obj) { 2 | 3 | var proName = []; 4 | var proValue = [] 5 | for (var i in obj) { 6 | if (obj.hasOwnProperty(i)) { 7 | proName.push(i) 8 | proValue.push(obj[i]) 9 | } 10 | } 11 | return [proName,proValue] 12 | } 13 | 14 | console.log(getOwnProperty({tom:'sdaf',bob:'fasdf'})) 15 | -------------------------------------------------------------------------------- /ie8cors.js: -------------------------------------------------------------------------------- 1 | //http://mcgivery.com/ie8-and-cors/ 2 | 3 | 4 | var RequestHelper = { 5 | GatewayURL: "https://www.yourdomain.on.ca/secure/gateway.html", 6 | Busy: false, 7 | sendRequest: function(url,success,$){ 8 | var protocol = location.protocol; 9 | if(window.XDomainRequest){ 10 | if(protocol == "http:"){ 11 | if(RequestHelper.Busy){ 12 | setTimeout(function(){ 13 | RequestHelper.sendRequest(url,success,$); 14 | },50); 15 | } else { 16 | RequestHelper.Busy = true; 17 | $("body").append(""); 18 | $("#ajaxProxy").load(function(){ 19 | ajaxProxy.postMessage(url,"*"); 20 | $(window).bind("message",function(e){ 21 | $("#ajaxProxy").remove(); 22 | $(window).unbind("message"); 23 | RequestHelper.Busy = false; 24 | success(e.originalEvent.data); 25 | }); 26 | }); 27 | } 28 | } else { 29 | var xdr = new XDomainRequest(); 30 | xdr.open("get", url); 31 | xdr.onprogress = function () { }; 32 | xdr.ontimeout = function () { }; 33 | xdr.onerror = function () { }; 34 | xdr.onload = function() { 35 | success(xdr.responseText); 36 | } 37 | setTimeout(function () { 38 | xdr.send(); 39 | }, 0); 40 | } 41 | } else { 42 | $.ajax({ 43 | type: "GET", 44 | url: url, 45 | dataType: "html", 46 | async:true, success: 47 | function (response){ 48 | success(response); } 49 | }); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /overloaded.js: -------------------------------------------------------------------------------- 1 | function addMethod(obj,name,fn) { 2 | var old = obj[name] 3 | obj[name] = function () { 4 | arguments.length==fn.length?fn.apply(this.arguments):typeof old =='function'&&old.apply(this.arguments) 5 | } 6 | } 7 | 8 | //参考自js ninja 利用了闭包的原理来实现函数重载 9 | -------------------------------------------------------------------------------- /tools/arrayTool.js: -------------------------------------------------------------------------------- 1 | function uniqArr(arr) { 2 | if (arr.length > 1) { 3 | arr.sort((a, b) => a - b) 4 | var last = arr[0] 5 | var uniq = [] 6 | uniq[0] = last 7 | for (var i = 1; i < arr.length; i++) { 8 | if (arr[i] !== last) { 9 | uniq.push(arr[i]); 10 | last = arr[i] 11 | } 12 | } 13 | return uniq 14 | } else { 15 | return arr 16 | } 17 | } 18 | 19 | //利用对象属性的哈希特性 20 | function uniq(arr) { 21 | 'use strict' 22 | const obj = {} 23 | arr.forEach(function(i) { 24 | if (obj[i] === undefined) { obj[i] = i } 25 | }) 26 | return Object.keys(obj).map(j => Number(j)) 27 | } 28 | 29 | // 返回数组最大最小值 30 | function maxArr(arr) { 31 | return (arr && arr instanceof Array) ? Math.max.apply(null, arr) : false 32 | } 33 | 34 | function minArr(arr) { 35 | return (arr && arr instanceof Array) ? Math.min.apply(null, arr) : false 36 | } 37 | 38 | // 打乱数组,快排有用? 39 | function shuffle(arr) { 40 | if (!arr && arr instanceof Array) { 41 | return false 42 | } 43 | var len = arr.length 44 | var randVal 45 | var rand 46 | var nArr = [] 47 | for (var i = 0; i < len; i++) { 48 | (function(i) { 49 | rand = Math.floor(Math.random() * (i + 1)) 50 | nArr[i] = nArr[rand] 51 | nArr[rand] = arr[i] 52 | }(i)) 53 | } 54 | return nArr 55 | } 56 | // 主要用于arguments 57 | function toArray(arg) { 58 | return Array.prototype.slice.call(arg) 59 | } 60 | 61 | 62 | 63 | 64 | 65 | var arr = [1, 3, 4, 1, 6, 7, 1] 66 | 67 | console.log(shuffle(arr)) 68 | -------------------------------------------------------------------------------- /tools/funTool.js: -------------------------------------------------------------------------------- 1 | function delay(func, wait) { 2 | var args = slice.call(arguments, 2); 3 | return setTimeout(function() { 4 | return func.apply(null, args); 5 | }, wait); 6 | }; 7 | 8 | 9 | // 函数节流方法, throttle方法主要用于控制函数的执行频率, 在被控制的时间间隔内, 频繁调用函数不会被多次执行 10 | // 在时间间隔内如果多次调用了函数, 时间隔截止时会自动调用一次, 不需要等到时间截止后再手动调用(自动调用时不会有返回值) 11 | // throttle函数一般用于处理复杂和调用频繁的函数, 通过节流控制函数的调用频率, 节省处理资源 12 | // 例如window.onresize绑定的事件函数, 或element.onmousemove绑定的事件函数, 可以用throttle进行包装 13 | // throttle方法返回一个函数, 该函数会自动调用func并进行节流控制 14 | function throttle(func, wait) { 15 | var context, args, timeout, throttling, more, result; 16 | // whenDone变量调用了debounce方法, 因此在多次连续调用函数时, 最后一次调用会覆盖之前调用的定时器, 清除状态函数也仅会被执行一次 17 | // whenDone函数在最后一次函数执行的时间间隔截止时调用, 清除节流和调用过程中记录的一些状态 18 | var whenDone = _.debounce(function() { 19 | more = throttling = false; 20 | }, wait); 21 | // 返回一个函数, 并在函数内进行节流控制 22 | return function() { 23 | // 保存函数的执行上下文和参数 24 | context = this; 25 | args = arguments; 26 | // later函数在上一次函数调用时间间隔截止时执行 27 | var later = function() { 28 | // 清除timeout句柄, 方便下一次函数调用 29 | timeout = null; 30 | // more记录了在上一次调用至时间间隔截止之间, 是否重复调用了函数 31 | // 如果重复调用了函数, 在时间间隔截止时将自动再次调用函数 32 | if (more) 33 | func.apply(context, args); 34 | // 调用whenDone, 用于在时间间隔后清除节流状态 35 | whenDone(); 36 | }; 37 | // timeout记录了上一次函数执行的时间间隔句柄 38 | // timeout时间间隔截止时调用later函数, later中将清除timeout, 并检查是否需要再次调用函数 39 | if (!timeout) 40 | timeout = setTimeout(later, wait); 41 | // throttling变量记录上次调用的时间间隔是否已经结束, 即是否处于节流过程中 42 | // throttling在每次函数调用时设为true, 表示需要进行节流, 在时间间隔截止时设置为false(在whenDone函数中实现) 43 | if (throttling) { 44 | // 节流过程中进行了多次调用, 在more中记录一个状态, 表示在时间间隔截止时需要再次自动调用函数 45 | more = true; 46 | } else { 47 | // 没有处于节流过程, 可能是第一次调用函数, 或已经超过上一次调用的间隔, 可以直接调用函数 48 | result = func.apply(context, args); 49 | } 50 | // 调用whenDone, 用于在时间间隔后清除节流状态 51 | whenDone(); 52 | // throttling变量记录函数调用时的节流状态 53 | throttling = true; 54 | // 返回调用结果 55 | return result; 56 | }; 57 | } 58 | 59 | 60 | // debounce与throttle方法类似, 用于函数节流, 它们的不同之处在于: 61 | // -- throttle关注函数的执行频率, 在指定频率内函数只会被执行一次; 62 | // -- debounce函数更关注函数执行的间隔, 即函数两次的调用时间不能小于指定时间; 63 | // 如果两次函数的执行间隔小于wait, 定时器会被清除并重新创建, 这意味着连续频繁地调用函数, 函数一直不会被执行, 直到某一次调用与上一次调用的时间不小于wait毫秒 64 | // debounce函数一般用于控制需要一段时间之后才能执行的操作, 例如在用户输入完毕200ms后提示用户, 可以使用debounce包装一个函数, 绑定到onkeyup事件 65 | // ---------------------------------------------------------------- 66 | // @param {Function} func 表示被执行的函数 67 | // @param {Number} wait 表示允许的时间间隔, 在该时间范围内重复调用会被重新推迟wait毫秒 68 | // @param {Boolean} immediate 表示函数调用后是否立即执行, true为立即调用, false为在时间截止时调用 69 | // debounce方法返回一个函数, 该函数会自动调用func并进行节流控制 70 | function debounce(func, wait, immediate) { 71 | // timeout用于记录函数上一次调用的执行状态(定时器句柄) 72 | // 当timeout为null时, 表示上一次调用已经结束 73 | var timeout; 74 | // 返回一个函数, 并在函数内进行节流控制 75 | return function() { 76 | // 保持函数的上下文对象和参数 77 | var context = this, 78 | args = arguments; 79 | var later = function() { 80 | // 设置timeout为null 81 | // later函数会在允许的时间截止时被调用 82 | // 调用该函数时, 表明上一次函数执行时间已经超过了约定的时间间隔, 此时之后再进行调用都是被允许的 83 | timeout = null; 84 | if (!immediate) 85 | func.apply(context, args); 86 | }; 87 | // 如果函数被设定为立即执行, 且上一次调用的时间间隔已经过去, 则立即调用函数 88 | if (immediate && !timeout) 89 | func.apply(context, args); 90 | // 创建一个定时器用于检查和设置函数的调用状态 91 | // 创建定时器之前先清空上一次setTimeout句柄, 无论上一次绑定的函数是否已经被执行 92 | // 如果本次函数在调用时, 上一次函数执行还没有开始(一般是immediate设置为false时), 则函数的执行时间会被推迟, 因此timeout句柄会被重新创建 93 | clearTimeout(timeout); 94 | // 在允许的时间截止时调用later函数 95 | timeout = setTimeout(later, wait); 96 | }; 97 | }; 98 | 99 | function once(func) { 100 | // ran记录函数是否被执行过 101 | // memo记录函数最后一次执行的结果 102 | var ran = false, 103 | memo; 104 | return function() { 105 | // 如果函数已被执行过, 则直接返回第一次执行的结果 106 | if (ran) 107 | return memo; 108 | ran = true; 109 | return memo = func.apply(this, arguments); 110 | }; 111 | }; 112 | 113 | 114 | // 函数第n次开始就不能执行,返回undefined..感觉好奇怪lodash作者的思路 115 | function before(n, func) { 116 | var result; 117 | if (typeof func != 'function') { 118 | throw new TypeError(FUNC_ERROR_TEXT); 119 | } 120 | return function() { 121 | if (--n > 0) { 122 | return result = func.apply(this, arguments); 123 | } 124 | if (n <= 1) { 125 | func = undefined; 126 | } 127 | return result; 128 | }; 129 | } 130 | 131 | // 照搬至上面的before,函数最多可以执行n次 132 | function doTimes(func,n) { 133 | var result; 134 | if (typeof func != 'function') { 135 | throw new TypeError(FUNC_ERROR_TEXT); 136 | } 137 | return function() { 138 | if (--n > 0) { 139 | return result = func.apply(this, arguments); 140 | } 141 | if (n <= 0) { 142 | func = undefined; 143 | } 144 | return result; 145 | }; 146 | } 147 | 148 | -------------------------------------------------------------------------------- /tools/isXXX.js: -------------------------------------------------------------------------------- 1 | function isNum(number) { 2 | return number!==''&&!isNaN(''+number) 3 | } 4 | 5 | 6 | 7 | function isNum2(num) { 8 | return ( /^\d*$/g).test(String(num)) 9 | } 10 | 11 | 12 | function isObject(obj) { 13 | return obj !== null && typeof(obj) === 'object' 14 | } 15 | -------------------------------------------------------------------------------- /tools/strTool.js: -------------------------------------------------------------------------------- 1 | // from vue source code 2 | 3 | 4 | var camelizeRE = /-(\w)/g 5 | export function camelize (str) { 6 | return str.replace(camelizeRE, toUpper) 7 | } 8 | 9 | function toUpper (_, c) { 10 | return c ? c.toUpperCase() : '' 11 | } 12 | 13 | /** 14 | * Hyphenate a camelCase string. 15 | * 16 | * @param {String} str 17 | * @return {String} 18 | */ 19 | 20 | var hyphenateRE = /([a-z\d])([A-Z])/g 21 | export function hyphenate (str) { 22 | return str 23 | .replace(hyphenateRE, '$1-$2') 24 | .toLowerCase() 25 | } 26 | 27 | /** 28 | * Converts hyphen/underscore/slash delimitered names into 29 | * camelized classNames. 30 | * 31 | * e.g. my-component => MyComponent 32 | * some_else => SomeElse 33 | * some/comp => SomeComp 34 | * 35 | * @param {String} str 36 | * @return {String} 37 | */ 38 | 39 | var classifyRE = /(?:^|[-_\/])(\w)/g 40 | export function classify (str) { 41 | return str.replace(classifyRE, toUpper) 42 | } 43 | 44 | 45 | 46 | //限制输入框输入最大值 47 | 48 | function lengthLimit(selector,limit) { 49 | [].slice.call(document.querySelectorAll(selector)).forEach(function(i){ 50 | i.addEventListener('change',function(){ 51 | if(i.value.length>limit) { 52 | i.value=i.value.substr(0,limit) 53 | } 54 | }) 55 | }) 56 | } 57 | --------------------------------------------------------------------------------