通过jquery-validate和bootstrap实现表单后面提示打钩或打叉的效果和真实的表单验证

首先,需要下载以下框架的代码,版本没有严格的要求。

一、工具文件准备

1、jquery.js  2、bootstrap.css 3、jquery.validate.js

这三个文件非常容易下载,下载然后看看包里有名字跟以上名字一致的就是了。

二、在html中引用css文件和js文件

三、创建一个新的的js文件,这个文件使用来调用jquery.validate.js中封装的方法的,代码如下

以下如error和element等都是jq对象,可以使用jq方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$().ready(function() {
var validaObj = $("#form_login").validate({ //创建一个validate对象,可以自己查询使用一些该对象的衍生方法
rules: {
username: {
required: true,
minlength: 4,
maxlength: 8
}
},
messages: {
username: {
required: "",
minlength: "",
maxlength: ""
}

},
success: function(e) { //关键方法,该方法会在validate完成该输入框的判断以后进行一次调用并且会取消默认的显示错误的方法(大概会吧)
//如果进行调试,会方法输入框的class属性会在根据是否合法改变其样式为 "error"和"valid"中的一种,通过判断这个进行判断
if (e.prev().hasClass("valid")) { //此处e相当于错误信息这个html标签本身,然后找e的前一个标签是否有"valid"类样式,有则说明当前输入框验证正确
e.removeClass("glyphicon-remove"); //boostrap的样式,查手册,bootstrap3的全局样式里的表单里有样式说明,添加了对应样式span标签会变为图形。
//比如在引入bootstrap.css的情况下 <span class = "glyphicon glyphicon-ok form-control-feedback" ></span> 就是一个打钩的图案
e.addClass("glyphicon-ok");
}
if(e.prev().hasClass("error")){ // 判断输入框里有样式"error"则把打叉换成打钩e.removeClass("glyphicon-ok");
e.addClass("glyphicon-remove");
}

},
errorPlacement: function(error, element) { //决定错误信息要放在哪里的方法,error是label对象,element是当前验证的输入框对象
error.addClass('glyphicon glyphicon-remove form-control-feedback');
error.appendTo(element.parent());

}

});

当然使用框架很爽,那些什么点击验证,多少长度什么格式都封装好了,注意逗号的分割规律使用就没什么大问题

使用新浪SAE和PHPthink遇到的坑总结

纪念用,以前放在新浪博客来着,刚学编程的时候,hx1603, 16年的3月报的传一培训

1、使用微信官方的示例复制到代码中进行测试,经常不能产生作用,必要的时候还是要自己打最最简单的代码进行测试。

2、新浪sae不支持在服务器上通过代码进行读写,就是那些fopen之类的函数都不能用。

3、由于微信端和我方服务器之间的交互基本上依靠xml和json完成,所有使用最简单的字符串拼接会使得代码十分容易理解,少用网上复制的经常会看不懂。

4、还有千万写代码的时候要小心,自己曾遇到的坑包括占位符写错(就是这么傻),路径两个斜杠,文件后缀写错,phpthink忘记namespace等等,都是泪啊。

5、使用微信jssdk时候,页面的签名一定要做成动态的,因为页面分享以后会自动在后面加入其它代码导致签名错误,动态获取当前页面的url可以使用

$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];来获取。
6、还有有时会遇到invalid domain的错误提示,这说明你js安全域名不对,注意这里是tm的域名不是url。

7、微信jssdk有官方demo,挺好用的但是其中一些事件根本不是什么点击事件,我们看看function里面的内容就好了,外面的点击事件不用太关心。

8、新浪sae的使用中,有时候需要使用其他应用的数据比如你想建两个应用一个用来处理前台逻辑,一个用来给当做数据管理统计后台,这时候就需要使用新浪sae提供的应用授权功能,完成授权以后,在另外那个应用通过主库地址和数据库名用户名秘密就可以访问了,phpthink是在模块conf文件夹里的config.php里设置就可以了。

9、有大量的默认参数在使用新浪sae时会被自动设置,比如comman里的数据库设置一般是无效的,需要通过home或其他自定义模块内的config配置来进行,相关的配置优先级在phpthink手册里都有说。

通过JQ的contents往iframe中添加内容

前提:引用JQ  支持JQ的浏览器(不要用ie)

今天被一个很烦人的问题给困扰了很久。就是怎么通过JQ来修改iframe标签的内容,你问我js处理iframe的方法?而且还要处理ie浏览的情况?出门左拐不送。说正经的,通过JQ处理iframe内容的关键是contents()方法。假如我们直接使用如下代码

1
2
$("#iframeID").html("你好");
$("#iframeID").html("你好");</code></pre>

发现都不能修改iframe中的内容,都不好使。

1
2
3
var a = "测试者inner";
var b = "测试者部门inner";
$("#container02").contents().find("body").html("&lt;div>" + "&lt;span>" + a + "&lt;/span>" + "&lt;span>" + b + "&lt;/span>" + "&lt;/div>"); &lt; /script>/</code></pre>

则可以顺利的给iframe中添加标签。JQ这contents帮我节约了几小时的生命。。。当然还可以反过来用,通过contents()来获取iframe中的内容然后进行修改。

1
2
3
4
5
6
7
8
$(function() {
$("#container02").contents().find("span").each(function() {
if ($(this).html() == "测试者inner") //使用text()对ie无效
{
$(this).parent("div").remove(); //把包含条件内容的span的父亲div删除
}
})
});

通过以上来完成检索iframe中所有span标签然后删除盛放这个span的div容器。

python实现简单验证码识别

  1. 安装python和pip不作介绍,保证打开cmd输入pip和python有反应。需设置环境变量。python3.6安装包
  2. 在cmd中执行以下命令(怎么启动cmd)
1
2
3
pip install PIL
pip install Pillow
pip install pytesseract
  1. 目标图片
    验证码

  2. 识别代码(python3)
    如果出现无法导入需要自己解决依赖问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    from PIL import Image
    from pytesseract import *


    im = Image.open('index.png')

    im = im.convert('L')
    def initTable(threshold=140):
    table = []
    for i in range(256):
    if i < threshold:
    table.append(0)
    else:
    table.append(1)

    return table

    binaryImage = im.point(initTable(), '1')
    #binaryImage.show()

    print(image_to_string(binaryImage, config='-psm 7'))
  3. 结果截图
    结果

其它

参考链接

select、poll、epoll详解

转载链接

select,poll,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制使一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

  select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的

  异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

  sellect、poll、epoll三者的区别 :

  select:

  目前支持几乎所有的平台

  默认单个进程能够监视的文件描述符的数量存在最大限制,在linux上默认只支持1024个socket

    可以通过修改宏定义或重新编译内核(修改系统最大支持的端口数)的方式提升这一限制

  内核准备好数据后通知用户有数据了,但不告诉用户是哪个连接有数据,用户只能通过轮询的方式来获取数据

    假定select让内核监视100个socket连接,当有1个连接有数据后,内核就通知用户100个连接中有数据了

    但是不告诉用户是哪个连接有数据了,此时用户只能通过轮询的方式一个个去检查然后获取数据

    这里是假定有100个socket连接,那么如果有上万个,上十万个呢?

    那你就得轮询上万次,上十万次,而你所取的结果仅仅就那么1个。这样就会浪费很多没用的开销

  只支持水平触发;每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

  同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也会很大

poll:

  与select没有本质上的差别,仅仅是没有了最大文件描述符数量的限制

  只支持水平触发

  只是一个过渡版本,很少用

  epoll:

  Linux2.6才出现的epoll,具备了select和poll的一切优点,公认为性能最好的多路IO就绪通知方法

  没有最大文件描述符数量的限制

  同时支持水平触发和边缘触发

  不支持windows平台

  内核准备好数据以后会通知用户哪个连接有数据了

  IO效率不随fd数目增加而线性下降

  使用mmap加速内核与用户空间的消息传递

水平触发与边缘触发:

  水平触发:将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用epoll时将再次报告这些文件描述符,这种方式称为水平触发

  边缘触发:只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发

  理论上边缘触发的性能要更高一些,但是代码实现相当复杂。

 select和epoll的特点

  select:

  select通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。

  由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。

  epoll:

  epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。

  另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。

select

select(rlist,wlist,xlist,timeout=None)

 select函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。

 调用后select函数会阻塞,直到有描述符就绪(有数据可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。

使用ts-protoc-gen编译proto获得typescript提示文件

目的:

为了使用typescript语法调用gRPC.

过程

  1. 各种找,也试过用thrift输出typescript代码,各种错误依赖都错.
    然后尝试用使用gRPC.

  2. 然后我找到一个名字叫ts-protoc-gen的包,感觉找到了救星
    https://github.com/agreatfool/grpc_tools_node_protoc_ts

  3. 3.官网那个配置是机遇linux操作的在windows10下跑不了,有以下这几种错误

  4. 官网命令(自己跑不起来)

    script
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    npm install grpc_tools_node_protoc_ts --save-dev

    # generate js codes via grpc-tools
    grpc_tools_node_protoc \
    --js_out=import_style=commonjs,binary:./your_dest_dir \
    --grpc_out=./your_dest_dir \
    --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` \
    -I ./proto \
    ./your_proto_dir/*.proto

    # generate d.ts codes
    protoc \
    --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts \
    --ts_out=./your_dest_dir \
    -I ./proto \
    ./your_proto_dir/*.proto
  5. 自己修改后的命令(需要你自己修改plugin路径)

    1
    2
    3
    protoc --grpc_out=./   --js_out=import_style=commonjs,binary:./  --plugin=protoc-gen-grpc=D:/comany_project/monster_farm/server/node_modules/.bin/grpc_tools_node_protoc_plugin.cmd index.proto

    protoc --grpc_out=./ --plugin=protoc-gen-grpc=D:/comany_project/monster_farm/server/node_modules/.bin/grpc_tools_node_protoc_ts_plugin.cmd index.proto

两条命令使用的插件名不同grpc_tools_node_protoc_ts_plugin.cmd 中间有个ts

  • window下 protoc-gen-ts后面要加个cmd, 且–plugin对应的参数要用绝对路径,如果不用绝对路径,则需要使用window特定的相对路径书写方式,例如 .\**\这样.
  1. 环境依赖
    package.json文件内容:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    {
    "name": "ts",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "",
    "license": "ISC",
    "devDependencies": {
    },"dependencies": {
    "google-protobuf": "^3.0.0",
    "grpc": "^1.11.0"
    },
    "devDependencies": {
    "@types/node": "^11.11.4",
    "grpc-tools": "latest",
    "grpc-tools-ts": "latest",
    "grpc_tools_node_protoc_ts": "^2.4.2",
    "mocha": "latest",
    "ts-node": "^8.0.3",
    "ts-protoc-gen": "^0.9.0",
    "typescript": "^3.3.4000",
    "typings": "latest"
    }
    }

protoc版本
protoc-3.7.0-win64

671-二叉树中第二小的节点

给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2或 0。如果一个节点有两个子节点的话,那么这个节点的值不大于它的子节点的值。
给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1 。

示例 1:

1
2
3
4
5
6
输入:      2   
/ \
2 5
/ \
5 7
输出: 5 说明: 最小的值是 2 ,第二小的值是 5 。

示例 2:

1
2
3
4
输入:      2 
/ \
2 2
输出: -1 说明: 最小的值是 2, 但是不存在第二小的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int min = -1;
int subMin = -1;

public int findSecondMinimumValue(TreeNode root) {
if (root == null)
return -1;
if (min == -1)
min = root.val;
else if ((subMin==-1 && root.val!=min) ||(root.val < subMin && root.val > min))
subMin = root.val;
findSecondMinimumValue(root.left);
findSecondMinimumValue(root.right);
return subMin;
}
}

这道题一开始我看成求第二大,这里是第二小..
根节点肯定最小,所以只要记录根节点值,然后遍历查找,大于根节点的最小值即可..
还是笨,边看游戏边写一大早上才一题t.t

674-最长连续递增序列

给定一个未经排序的整数数组,找到最长且连续的的递增序列。

示例 1:

输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1,3,5], 长度为3。 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开。

示例 2:

输入: [2,2,2,2,2] 输出: 1 解释: 最长连续递增序列是 [2], 长度为1。

注意:数组长度不会超过10000。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int findLengthOfLCIS(int[] nums) {
if(nums.length<=1)
return nums.length;
int maxCnt = 0;
int tmpCnt = 1;
for (int i = 1; i < nums.length; i++) {
if(nums[i]>nums[i-1])
tmpCnt ++;
else{
maxCnt = tmpCnt>maxCnt?tmpCnt:maxCnt;
tmpCnt = 1;
}
}
maxCnt = tmpCnt>maxCnt?tmpCnt:maxCnt;
return maxCnt;
}
}

没注意到切断连续以后 tmpCnt 应该从1开始,错误提交一次.别问为啥这么简单的题也放上来,这不是文章少嘛

680-验证回文字符串-Ⅱ

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:

输入: “aba”
输出: True

示例 2:

输入: “abca”
输出: True

解释: 你可以删除c字符。

注意:

字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
int chance = 1;
public boolean validPalindrome(String s) {
chance = 1;
return help(s, 0, s.length() - 1);
}

boolean help(String s, int left, int right) {
for (int i = left; i < s.length(); i++) {
if (left >= right)
break;
char lc = s.charAt(i);
char rc = s.charAt(right);
if (lc == rc) {
left++;
right--;
} else {
if (chance == 0)
return false;
chance--;
boolean leftRes = help(s, left + 1, right);
boolean rightRes = help(s, left, right - 1);
return leftRes || rightRes;
}
}
return true;
}
}

本来想着用一个for循环处理,然后两个指针从两边往中间走,如果指向的字符不一致,则尝试移动其中一边的指针,如果移动后一致两个指针就继续一起向中间移动.提交后总有错误,我又没搞懂哪些例子会错.一气之下改成递归的,只取两边同时逼近时彻底相同的情况输出,其他情况就递归查找,然后约束一下递归次数.整体看上去给人清楚多了.