一般,需要用到什么技术什么语言时,我才去学,学了也不必定掌握,就是记不住!因此现在明确了。学习的时候,亦或是攻克难点的时候,必定要记录下来。并不必定非要呈现什么高大上的技术。但求复原本身的心路历程足以。
简介一下这个小插件:在浏览器插件栏中的图标是background.html,实时获取自选股的价格,而后刷新到图标和标题中;popup.html是点击图标之后弹出的详情页面,可以查看每支股票的价格折线图、日K线图、成交量之类的详情,选中某支股票,则该支股票的当前价会实时刷新到图标中。options.html是点击自选股后打开的页面。进行自选股的加入删除,输入名称、简写、代码都可以查找。
它的股票代码是保存在一个stocks.js文件里的。咱们在加入新股票输入部分字母时,会运行autocomplete来本身主动搜索匹配stock.js中的股票而后为咱们呈现一个选项列表。这就是本身主动填充的功能,例如如下图:css
那么问题来了,将候选数据保存在本地文件(变量)中。尽管检索速度快,但是新股IPO之后还得更新插件版本号或者你本身把代码加到stocks.js中。虽然说不难,但是我可替广大小白表示忍不了。。好嘛,既然源码都搞定了,修复个小bug也是顺便的事,不修复不舒服斯基。
查看源代码,options.html中引用的是
jquery 1.7
autocomplete 1.1(注意版本号,新的autocomplete的參数列表可能不一样,这里不作讨论)
默认參数:
咱们看autocomplete是怎样使用的(input表明输入框对象):
input.autocomplete(stockInfos, {
省略很是多參数设置,
formatItem: function(){},
fomatMatch: function(){},
formatResult: function(){}
}).result(function() {})。
很是明显,stockInfos就是从本地文件里读入的候选数据源,format相关函数就是规定本身主动补全时怎样来匹配,最后的result则是选中某项候选值后界面需要作的显示工做。
首先。需要解决
怎样用远程数据源替换掉本地的静态数据源stockInfos来做为autocomplete的候选数据源(本文不探讨本地变量做为数据源。。)。不懂怎么办,搜索之,參考
http://www.cnblogs.com/weixing/archive/2013/06/06/3120535.html 远程数据源的调用方法,
这里要注意的是jquery.autocomplete或者是jquery.UI版本号不正确的话,可能并不是这些參数设置,比方新版本号的jquery.UI中的autocomplete
http://api.jqueryui.com/autocomplete/,咱们仍是
使用autocomplete 1.1,看源代码的话最好不要用min版本号。改动的方法就是。把上面调用autocomplete时第一个參数stockInfos替换成
URL。同一时候设置
dataType參数。当需要向远程传递參数时还需要
extraParams參数,假设远程传回的数据格式不适合autocomplete,咱们还需要
本身定义parse函数。而后我先是改为了例如如下(http://suggest3.sinajs.cn/suggest/key=你的查找,这是新浪提供的接口,相似的还有很是多。这里不作详述):
错误排查:
首先检查autocomplete源代码(不要看min.js,下载相应版本号的autocomplete源代码),打开这个文件发现,autocomplete的參数列表:delay、scroll、highlight、max、minChar、dataType、extraParams等參数都是有的。formatItem等函数、parse函数也都有,但是彷佛并无运行parse()。
autocomplete中
原始的parse函数,咱们作一些log调试:
咱们在调用autocomplete时本身定义的parse函数,因为浏览器控制台并未输出本身定义parse的log。因此该函数并未运行。
原始的parse()函数也并未运行。jquery
再依据autocomplete源代码进行溯源,
调用parse的函数是request函数,也就是依据url參数来向远程请求,由于浏览器控制台中有请求和响应,因此request函数确定运行了,分析其源代码,
ajax发送请求后假设成功则运行success标签相应的处理程序,
这里并无error相应的处理程序,推測多是收到的错误响应。因此并无运行success,咱们加入error处理函数:
在浏览器控制台观察其执行。如我所料执行到了error处理程序中:
果真,ajax请求收到的是返回被断定为错误类型,因此并无运行success处理函数。请求响应Headers例如如下:
发现响应的Headers的Content-Type是text/html,而咱们在调用autocomplete时设置的dataType类型是json,显然是冲突的(不能盲目照抄别人的代码!仍是要依据本身的实际状况!),因此request函数中以为收到的信息是错误的,因此没有运行success处理,也就没有运行parse()函数进行解析。git
解决方式:
调用autocomplete时,
dataType參数依据本身的数据源类型来定,比方个人
数据源返回的是text/html,并不是json。因此我这里改为text。再次运行:
成功运行了本身定义的parse函数。
这里,个人parse函数解析还有bug,因此解析返回的数组是空,请不要在乎,依据原始数据来作调整处理就能够。
parse函数解析成功后,构造一个数组parsed返回,在这里parse函数返回的是[Object, Object, Object, ...]例如如下:
而后会运行formatItem函数:
控制台报出item是undefined,并且item.name也报出了Uncaught TypeError: Cannot read property 'name' of undefined错误。一个问题解决,又一个问题来了。
。github
。web
排查和解决parse()解析源数据(数据格式不正确。undefined错误)的问题:
继续追踪autocomplete源码,
request函数在success处理程序中运行parse函数结果保存在parsed变量中,而后调用success(term, parsed)函数,success()函数是调用request函数时传入的函数见request声明function request(term, success, failure)。继续追踪request调用的地方有两处,一处使search中的request(value, findValueCallback, findValueCallback),还有一处是
onChange()函数中的request(currentValue, receiveData, hideResultsNow),在这两处分别打上console.log("search")和console.log("onChange")。又一次在浏览器中执行,发现Console端输出了onChange,说明是
onChange函数调用了request来发起请求、处理返回结果等等兴许。
因此,request在执行完parse函数之后。调用了传进来的reveiceData函数。继续追踪receiveData函数,在该函数中打上console.log("receiveData"),还可以输出一下data[0],又一次执行后发现输出了receiveData 和data[0]并没有差错。ajax
receiveData(q, data)中调用了select.display(data, q),display中也打上console.log("display")输出日志,里面调用了init()函数和fillList()函数,init中并没有数据处理相关代码。因此咱们关注fillList()。进入fillList()函数,打上console.log("fillList")输出日志做为函数跟踪。不难发现,fillList()函数对咱们的parse后的data作了一些处理而后传给了formatItem函数,至此,整条路径基本完毕。观察它是怎样调用formatItem函数的:chrome
var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
而咱们的data格式为:
data是一个数组,data[i]索引到数组中的元素,而data[i].data却没有定义!因此咱们在最初调用autocomplete时的formatItem(item, i, max)接收了三个參数data[i].data、i+一、max,而data[i].data是没有定义的,因此formatItem时报出了item.name undefined错误!
!OK。排查阶段最终完了。问题出在了parse返回的数据data并不符合fullList()函数中对data的操做!json
因此。改动本身定义的parse函数:
再次在浏览器中执行,成功了!
最后,总结一下autocomplete()的运行流程:
你的js中调用$(你的输入框).autocomplete(本地数据源或者远程URL, {
參数列表,
dataType: json或者text等等,
extraParams:{參数名: function(){ return 參数值如$(你的输入框).val()}},
parse: function(){},
format相关函数,
}).result(function(){});
而后,当你在输入框中输入时。autocomplete就调用onChange函数->request()函数向URL发送请求->parse()函数处理远程的数据,而后产出一个数组[{data:{ }, value{ }}, {...}, {...}, {...}, ...] -> receiverData() -> display() -> fillList() -> formatItem()。
不管如何。感谢七一〇提供的股票提醒助手,想研究的同窗到个人github下载就能够https://github.com/hustlbj/chrome-extensions