我没有学过前端,所以这篇文章注定要班门弄斧了。

通常,须要用到什么技术什么语言时,我才去学,学了也不一定掌握,就是记不住!所以如今明确了。学习的时候,亦或是攻克难点的时候,一定要记录下来。并不一定非要呈现什么高大上的技术。但求复原自己的心路历程足以。
大家都知道。近期股市非常火爆。当然这几天正在调整期呵呵,神车复牌都交出一天涨停一天跌停的答卷自降为灵车,相比于528垂直过山车,见怪不怪了。非常多人尽管没投入大量精力炒股,但还是时刻关注着股市行情,上班族们总不能时刻盯着手机看吧。所以我就想到了股票插件,chrome浏览器(361极速浏览器也OK)中的股票插件https://chrome.google.com/webstore/detail/%E8%82%A1%E7%A5%A8%E6%8F%90%E9%86%92%E5%8A%A9%E6%89%8B/goiffchdhlcehhgdpdbocefkohlhmlom#,这个玩意能够加入自选股,而且差点儿实时地通过新浪財经同步(就是看着数字就放心了),试用过后发现挺有意思,于是尝试获取源代码,把这个插件的全部html/js/css/image文件都下载下来,而且依照chrome插件开发教程把文件结构、manifest都一步步搞定,如今已经在github开源:https://github.com/hustlbj/chrome-extensions仓库中的StockHelper。
简介一下这个小插件:在浏览器插件栏中的图标是background.html,实时获取自选股的价格,然后刷新到图标和标题中;popup.html是点击图标以后弹出的详情页面,能够查看每支股票的价格折线图、日K线图、成交量之类的详情,选中某支股票,则该支股票的当前价会实时刷新到图标中。options.html是点击自选股后打开的页面。进行自选股的加入删除,输入名称、简写、代码都能够查找。

它的股票代码是保存在一个stocks.js文件里的。我们在加入新股票输入部分字母时,会运行autocomplete来自己主动搜索匹配stock.js中的股票然后为我们呈现一个选项列表。这就是自己主动填充的功能,例如以下图:

那么问题来了,将候选数据保存在本地文件(变量)中。尽管检索速度快,可是新股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向远程url请求数据,在浏览器的控制台Network界面,发现有请求和响应数据,而且响应数据和我们直接在浏览器中訪问该url的内容一样比方http://suggest3.sinajs.cn/suggest/?

q=shang&limit=10&timestamp=1433840697966&key=shang。除了key字段是我们的远程URL查找必需的以外,autocomplete自己主动加入了q、limit、timestamp參数。可是收到数据(浏览器控制台的Response中输出了var
suggestvalue="shanghai ind h,31,00363,00363,上海实业控股,shsykg;shanghai tonva。

。。是正确地)后并没有运行parse函数和兴许的format相关函数。


错误排查:
首先检查autocomplete源代码(不要看min.js,下载相应版本号的autocomplete源代码),打开这个文件发现,autocomplete的參数列表:delay、scroll、highlight、max、minChar、dataType、extraParams等參数都是有的。formatItem等函数、parse函数也都有,可是似乎并没有运行parse()。

autocomplete中原始的parse函数,我们做一些log调试:
 
我们在调用autocomplete时自己定义的parse函数,由于浏览器控制台并未输出自己定义parse的log。所以该函数并未运行。

原始的parse()函数也并未运行。


再依据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()函数进行解析。


解决方式:
调用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错误。一个问题解决,又一个问题来了。


排查和解决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]并无差错。

receiveData(q, data)中调用了select.display(data, q),display中也打上console.log("display")输出日志,里面调用了init()函数和fillList()函数,init中并无数据处理相关代码。所以我们关注fillList()。进入fillList()函数,打上console.log("fillList")输出日志作为函数跟踪。不难发现,fillList()函数对我们的parse后的data做了一些处理然后传给了formatItem函数,至此,整条路径基本完毕。观察它是怎样调用formatItem函数的:

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+1、max,而data[i].data是没有定义的,所以formatItem时报出了item.name undefined错误!

!OK。排查阶段最终完了。问题出在了parse返回的数据data并不符合fullList()函数中对data的操作!

所以。改动自己定义的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

一场由股票提醒助手插件引发的血案——浅入浅出 jquery autocomplete的更多相关文章

  1. 360浏览器有个 谷歌访问助手(插件管理里搜谷歌即可) 可以免费访问:谷歌搜索,Google+ gmail

    360浏览器有个 谷歌访问助手(插件管理里搜谷歌即可) 可以免费访问:谷歌搜索,Google+ gmail

  2. 一场由过滤器Filter引发的血案

    一场由过滤器Filter引发的血案 事件起因 本来应该是下图的登录界面 变成了这样 What's the fuck????? 抓狂 原因 解决方法: 在过滤器中给资源文件开个绿色通道

  3. 九:SpringBoot-整合Mybatis框架,集成分页助手插件

    九:SpringBoot-整合Mybatis框架,集成分页助手插件 1.Mybatis框架 1.1 mybatis特点 1.2 适用场景 2.SpringBoot整合MyBatis 2.1 核心依赖 ...

  4. 一个无锁消息队列引发的血案(四)——月:RingQueue(上) 自旋锁

    目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...

  5. [WCF]缺少一行代码引发的血案

    这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性.具体来说,这是一个关于如何自动为服务接口(契约 ...

  6. dubbox微服务实例及引发的“血案”

    Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成. 主要核心部件: Remoting: 网络通信框架 ...

  7. Integer.parseInt 引发的血案

    Integer.parseInt 处理一个空字符串, 结果出错了, 程序没有注意到,搞了很久, 引发了血案啊!! 最后,终于 观察到了, 最后的部分: Caused by: java.lang.NoC ...

  8. 写JQuery 插件 什么?你还不会写JQuery 插件

    http://www.cnblogs.com/Leo_wl/p/3409083.html 前言 如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui ...

  9. jquery autocomplete插件

    jquery autocomplete插件 https://goodies.pixabay.com/jquery/auto-complete/demo.html autocomplete-table ...

随机推荐

  1. Lex与Yacc学习(二)之第一个Lex程序

    用lex识别单词 构建一个识别不同类型英语单词的简单程序.先识别词性(名词,动词等),然后再扩展到处理符合简单英语语法的多个单词的句子. 先列出要识别的一组动词: is    am   are   w ...

  2. LeetCode695--岛屿的最大面积

    ''' 岛屿的最大面积 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被水包围着 ...

  3. Python算法-二叉树深度优先遍历

    二叉树 组成: 1.根节点  BinaryTree:root 2.每一个节点,都有左子节点和右子节点(可以为空)  TreeNode:value.left.right 二叉树的遍历: 遍历二叉树:深度 ...

  4. 信安实验-RC4加密算法

    RC4加密算法 算法具体就不介绍了,应信安老师要求整理及掌握. #include<bits/stdc++.h> using namespace std; const int N=256; ...

  5. 也来“玩”Metro UI之磁贴(二)

    继昨天的“也来“玩”Metro UI之磁贴(一)”之后,还不过瘾,今天继续“玩”吧——今天把单选的功能加进来,还有磁贴的内容,还加了发光效果(CSS3,IE9+浏览器),当然,还是纯CSS,真的要感谢 ...

  6. 【Luogu】P3414组合数(快速幂)

    题目链接 从n的元素中选零个,选一个,选两个,选三个...选n个的方案数和,其实就是n个元素中取任意多个元素的方案数,那对于每一个元素,都有取或不取两种情况,所以方案数最终为2^n个. #includ ...

  7. 关于java读取文件IO流学习总结(一)

    IO流的分类: 1.根据流的数据对象来分: 高端流:所有的内存中的流都是高端流,比如:InputStreamReader 低端流:所有的外界设备中的流都是低端流,比如InputStream,Outpu ...

  8. 【2018.9.20】JOI 2017 Final T3「JOIOI 王国 / The Kingdom of JOIOI」

    题目链接 题目描述 JOIOI 王国是一个 $H$ 行 $W$ 列的长方形网格,每个 $1\times 1$ 的子网格都是一个正方形的小区块.为了提高管理效率,我们决定把整个国家划分成两个省 $JOI ...

  9. STL学习笔记(二) vector和string

    条款13:vector.string优先于动态分配数组 string是basic_string<char>的类型定义许多string的背后实现都采用了引用计数的技术,可以消除不必要的内存拷 ...

  10. 解决PHP无法接收post超过1000个字段的问题

    今天在做与后台交互的的过程中,发现php对于接收的POST有一个限制,超出1000个字段之后便无法接收,项目要求在不改变PHP配置的情况下通过前端方式解决,通过分析并且网上差一些大牛的资料终于找到了解 ...