This repository has been archived by the owner on Jun 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DB.sql
250 lines (219 loc) · 660 KB
/
DB.sql
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
-- MySQL dump 10.13 Distrib 5.6.48, for Linux (x86_64)
--
-- Host: localhost Database: fyblog
-- ------------------------------------------------------
-- Server version 5.6.48-log
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `typecho_comments`
--
DROP TABLE IF EXISTS `typecho_comments`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `typecho_comments` (
`coid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cid` int(10) unsigned DEFAULT '0',
`created` int(10) unsigned DEFAULT '0',
`author` varchar(200) DEFAULT NULL,
`authorId` int(10) unsigned DEFAULT '0',
`ownerId` int(10) unsigned DEFAULT '0',
`mail` varchar(200) DEFAULT NULL,
`url` varchar(200) DEFAULT NULL,
`ip` varchar(64) DEFAULT NULL,
`agent` varchar(200) DEFAULT NULL,
`text` text,
`type` varchar(16) DEFAULT 'comment',
`status` varchar(16) DEFAULT 'approved',
`parent` int(10) unsigned DEFAULT '0',
PRIMARY KEY (`coid`),
KEY `cid` (`cid`),
KEY `created` (`created`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `typecho_comments`
--
LOCK TABLES `typecho_comments` WRITE;
/*!40000 ALTER TABLE `typecho_comments` DISABLE KEYS */;
/*!40000 ALTER TABLE `typecho_comments` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `typecho_contents`
--
DROP TABLE IF EXISTS `typecho_contents`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `typecho_contents` (
`cid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) DEFAULT NULL,
`slug` varchar(200) DEFAULT NULL,
`created` int(10) unsigned DEFAULT '0',
`modified` int(10) unsigned DEFAULT '0',
`text` text,
`order` int(10) unsigned DEFAULT '0',
`authorId` int(10) unsigned DEFAULT '0',
`template` varchar(32) DEFAULT NULL,
`type` varchar(16) DEFAULT 'post',
`status` varchar(16) DEFAULT 'publish',
`password` varchar(32) DEFAULT NULL,
`commentsNum` int(10) unsigned DEFAULT '0',
`allowComment` char(1) DEFAULT '0',
`allowPing` char(1) DEFAULT '0',
`allowFeed` char(1) DEFAULT '0',
`parent` int(10) unsigned DEFAULT '0',
PRIMARY KEY (`cid`),
UNIQUE KEY `slug` (`slug`),
KEY `created` (`created`)
) ENGINE=MyISAM AUTO_INCREMENT=319 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `typecho_contents`
--
LOCK TABLES `typecho_contents` WRITE;
/*!40000 ALTER TABLE `typecho_contents` DISABLE KEYS */;
INSERT INTO `typecho_contents` VALUES (3,'关于我们','3',1404247200,1409753698,'<!--markdown-->四川大学飞扬俱乐部是成都高校界罕有的专业IT公益社团。我们致力于用最诚恳的态度,最完善的管理,最专业的知识,为广大师生提供免费的IT服务,优化校园生活体验。\r\n\r\n飞扬俱乐部自2003年创立以来,已经走过了十一年的风雨征程。在这十一年中,我们多次获得校园十佳社团称号。凭借着创新实践、服务川大的宗旨,在师生间获得了极好的口碑。\r\n\r\n我们的主要服务包括免费电脑维修、大型电脑义诊(一月一次)、系列讲座、IT知识咨询等。此外我们还做一些网站以及校园实用工具的开发(如绩点计算器等),以及关于川大生活的调研。\r\n\r\n目前飞扬俱乐部主要由5个部门组成:维修部、研发部、行政部、设计部、网媒部。\r\n\r\n我们将以一如既往的脚踏实地的态度,为创造一个更加科学、便捷的校园生活环境而不断努力。\r\n\r\n飞扬俱乐部期待您的加入。\r\n\r\n联系方式请戳:[这里](http://log.fyscu.com/index.php/12.html)\r\n\r\nNever stop flying high!',1,1,NULL,'page','publish',NULL,0,'0','0','0',0),(67,'Javascript 闭包与作用域','67',1410409980,1415952324,'<!--markdown-->####1.Javascript的作用域是函数作用域而非块级作用域\r\n\r\n //C语言\r\n #include <stdio.h>\r\n void main()\r\n {\r\n int i=2;\r\n i--;\r\n if(i)\r\n {\r\n int j=3;\r\n }\r\n printf(\"%d/n\",j); \r\n //use an undefined variable:j\r\n }\r\n\r\n这是因为c中的作用域是块级的,j是在if后的{ }中定义的,所以无法访问,然而在js中会是什么情况?\r\n (function(){\r\n var i=1;\r\n if(i==1){\r\n var j=3;\r\n }\r\n console.log(j); //3\r\n })()\r\n\r\n在这里,j是可以访问的,也就是说在一个函数中的任何位置定义的变量在该函数中的任何地方都是可见的\r\n\r\n这里提及一句Javascript的作用域链(` scope chain `),每个函数 定义 时都会将他的作用域链定设为他定义的环境\r\n\r\n function a(){\r\n function b(){\r\n //code\r\n }\r\n }\r\n\r\n这段代码中,b的环境为a,a的环境为全局(`window`),在b中查找变量时会先搜索自身函数内部,如果不存在就去a的内部查找,还不存在就去全局中查找,若还是找不到就是undefined,这就构成一条链\r\n\r\n####2.Javascript中变量的作用域分为全局变量和局部变量\r\n\r\n在函数内部可以访问全局变量和函数内的局部变量,而在函数外部访问不到函数内的变量,看代码\r\n\r\n var p=11;\r\n function f1(){\r\n console.log(p);\r\n }\r\n f1(); //11\r\n\r\n function f1(){\r\n var p=11;\r\n }\r\n f1();\r\n console.log(p); //ReferenceError: p is not defined\r\n\r\n通过这俩段代码可以理解全局变量和局部变量,但是定义局部变量时`一定要注意加上 var` ,如果不加上其实定义的是一个全局变量,看代码\r\n\r\n function f1(){\r\n p=11;\r\n }\r\n f1();\r\n console.log(p); //11\r\n\r\n####3.那如何访问函数内部的变量并对它进行操作呢?这里就需要用到闭包\r\n\r\n先看看闭包的官方解释:` 闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分`\r\n\r\n看到这句户我不禁想问,这是个啥?\r\n\r\n后来参考了一些博客和《Javascript秘密花园》才开始理解,闭包大概就是函数内部的一个函数被外部调用,这样就可以调用内部变量了,比如下面这段\r\n\r\n function f1(){\r\n var p=11;\r\n return {\r\n increment: function() {\r\n p++;\r\n },\r\n \r\n show: function() {\r\n alert(p)\r\n }\r\n }\r\n }\r\n var f=f1();\r\n f.show(); //11\r\n f.increment();\r\n f.show(); //12\r\n\r\n\r\n\r\n这里可以看到,f包含increment和show两个函数,而这两个函数是f1的内部函数所以可以访问p这个变量,在我理解,这里的increment和show就是f1()的两个闭包,用他们就可以从外部调用这个变量\r\n\r\n####4.闭包可以做些什么?\r\n\r\n首先我觉得可以模拟`private`,就像上面那段代码,这个变量只能在这个函数内部访问,也只有使用了闭包才能访问\r\n\r\n第二,和Javascript的垃圾回收有关,这里我还不是很清楚,等到搞明白了再来补上\r\n\r\n5.这里有一个要注意的就是循环中使用闭包的问题,这里借用《`Javascript秘密花园`》里的一个例子\r\n\r\n function f1(){\r\n for(var i = 0; i < 10; i++) {\r\n setTimeout(function() {\r\n console.log(i); \r\n }, 1000);\r\n }\r\n }\r\n f1();\r\n\r\n这段代码输出的是10个10而不是期望的0到9,因为闭包内是对i的引用,然后函数执行时i已经变成了10,这里可以使用自执行的匿名函数\r\n\r\n function f1(){\r\n for(var i = 0; i < 10; i++) {\r\n (function(e) {\r\n setTimeout(function() {\r\n console.log(e); \r\n }, 1000);\r\n })(i); \r\n }\r\n }\r\n f1();\r\n\r\n这里的匿名函数将i作为参数,这里的e会有i的一个拷贝,而引用时是对e的引用,这就避免了上述的问题\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(27,'Linux折腾笔记','27',1409767380,1409854932,'<!--markdown-->在此记录一些小问题小感想,不定期更新。如有疏漏,欢迎批评指出。\r\n版本:ubuntu14.04\r\n\r\n一.ubunut开启wifi热点,供手机使用\r\n这里手机系统为android。暂未测试ios。\r\n1.一般开启方式:\r\n右键点击Network Manager图标->Edit Connections->add->wifi->creat->General,取消勾选Automatically connect to this network...->Wi-Fi,填写SSID(Wi-Fi名称),讲Model设置为Ad-hoc->Wi-Fi Security,选择WPA&WPA2 Personal->IPV4 Settinds,Method设置为Shared to other computer->IPV6 Settings,设置Model为Ignore->Save->再次回到Network Manager图标,选择connect to hidden Wi-Fi Network,连接之前设置的Wi-Fi。\r\n完成这些步骤之后,一个Ad-hoc模式的Wi-Fi热点就创建了。但手机却不能查找到这个热点。这是为什么呢?\r\n原生的安卓系统并不支持adhoc信号,因此就需要对安卓系统打补丁。\r\n\r\n2.为手机打Ad-hoc补丁\r\n\r\n\r\n二.ubuntu安装goagent【转】\r\n官方文档十分详尽,但现在不翻墙就无法查看。于是笔者简单讲官方文档复制粘贴过来,仅供参考。\r\n\r\n',0,5,NULL,'post','hidden',NULL,0,'1','1','1',0),(64,'FYSCU 2.0做什么','64',1410328440,1414138035,'<!--markdown-->##互联网\r\n- 前端\r\n 1. 用户体验、交互设计等(基本靠感觉)\r\n 2. HTML+CSS+JS (浅层)\r\n 3. 前端MVC,SPA (待开发)\r\n- 后端\r\n 1. 持久层 MYSQL(浅)\r\n 2. 缓存、队列(不明)\r\n 3. PHP,Node (需要加强)\r\n- 系统服务\r\n 1. C/C++,socket (加强操作系统知识,网络知识)\r\n\r\n##端应用\r\n- (水哥补充)',0,2,NULL,'post','publish','184331942',0,'1','0','0',0),(7,'Express怎么获取用户IP','7',1404330120,1410327385,'<!--markdown-->如果是直接启动node程序的\r\n\r\n req.connection.remoteAddress\r\n\r\n如果是使用了nginx反向代理,在nginx相关配置地方加上\r\n\r\n proxy_set_header X-Real-IP $remote_addr;\r\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\r\n\r\n然后代码里使用\r\n\r\n var headers = req.headers;\r\n console.log(headers[\'x-real-ip\'] || headers[\'x-forwarded-for\']);',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(9,'研发要做的一些事(1)','9',1404842640,1404842671,'<!--markdown-->因为怕思路理的不清楚,所以题目是带有(1),后面可能会继续写,也可能不写了。\r\n\r\n写出来,主要是为了理清下自己的思路,还有给大家伙看下,我们的一个整体的思路。\r\n\r\n目标:走向全中国。用互联网带领飞扬走向新的高度。\r\n\r\n首先我们要做出来一批应用。这些应用既是要锻炼2.0的代码能力,也是为飞扬去赢得一些用户,以及为飞扬内部管理带来质的效益的提升。这些应用包括我们的:报修系统,绩点计算,川大百科,新官网,博客,以及可能要做的问答社区等,以上是面向用户的应用,还会有很多好玩,刚需的面向用户的应用被开发出来。还要开发提升飞扬内部管理效率的应用出来,比如,一键邮件通知反馈系统,以及排班系统,VIP会员中心系统,微博自动发送系统等等,这些是面向飞扬内部进行高效运作管理的系统。当然,如果有时间,我们甚至会接外包的应用项目来练手。\r\n\r\n以上只是第一步。应用层面。\r\n\r\n我们的第二步的计划是:做开放平台。用飞扬的开放平台,来共享飞扬的大数据。具体会有:飞扬单点登录系统(类似QQ登录一样的东西),其他校内,甚至是校外应用可以用我们的给的用户接口去作为他们的用户入口,用我们的开放平台用户系统会给他提供他想要的一些数据,不如说邮箱,手机号,地址这些我们独有的,面向川大的数据。接下来是做一个整个川大的应用入口,用户可以从这个入口看到所以接入的应用,并且可以直接进入去访问该应用提供的服务.并且整合我们所有的应用在这里,我们所有的应用使用的都是我们开放平台的接口。\r\n\r\n第二步的这个平台只是我理解的一个思维,不知道表达对没有。最终解释权在@小蓝\r\n\r\n再说下研发已经做了哪些改变:\r\n\r\n1.成立研发2.0,完全保留研发想继续留下来的孩子,成立研发的2.0团队,继续在研发学习,成长。\r\n\r\n2.成立研发的PM制度,为每一个已经立项的项目,自愿站出来做这个项目的PM,全权负责此项目的所有统筹工作,对部长负责。 部长对会长负责。\r\n\r\n3.建立研发的code day 活动。每周日为研发的codeday,每个2.0坐在一起码代码一天,自愿参加,但是没事要参加。\r\n\r\n4.例会idea时间。例会复盘时间。例会分享时间。\r\n\r\n\r\n以上是这个学期已经实行过的一些东西,效果非常非常棒。下个学期会继续保持下去。\r\n\r\n下面是一些想做的,应该下个学期会做的事情:\r\n\r\n1.租个房子,作为研发的实验室,平时和codeday的地点都在这里,甚至例会?房子里要有水,有电,有wifi,有舒服的椅子和桌子 就够了。有空调最好。没有也行。房子这个学期已经出去看了,但是还没有特别满意的,就没有定下来,AA去租房子,作为实验室。有了这个产出会非常非常,房子一定要近一点,逼格稍微高一点,我个人觉得这个投资非常非常值得。反正已经给2.0说了,下个学期多带点钱过来。哈哈。\r\n\r\n2.注重代码,现在做的应用,都是只要实现功能就行,但是,下个学期后,要考虑代码,代码相互审核,以及在例会上挑一些不好与好的代码 给所有人分享,这样很能提高代码水平。\r\n\r\n3.能赚一桶金,这样就不用编程了。\r\n\r\n嗯以上的要实现的。\r\n\r\n目前做了的项目有:\r\n\r\n报修系统。\r\n\r\n新官网。http://fyscu.cn\r\n\r\n绩点计算。\r\n\r\n博客。http://log.fyscu.com\r\n\r\n一键邮件通知系统。\r\n\r\n以上有些项目还没部署上去,部署了之后,我再更新网址。\r\n\r\n就这些。\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(10,'nodejs学习笔记(一)','10',1434778320,1434778818,'<!--markdown-->先占个坑。\r\n\r\n## 让你的nodejs开发变得更easy\r\n\r\n1. 当安装一个新的模块的时候请使用: ```npm i express --save```\r\n```i```代表 ```install``` ```--save```代表在你的项目的package.json文件里面加入这个模块。\r\n\r\n2. nodejs的开发阶段是,一有改动就需要重启,重启非常的烦,使用webstorm之类的ide还好,但是如果使用普通编辑器的话,请安装更好的工具来做重启。比如:nodemon,安装: ```npm i nodemon -g```运行该命令即可全局安装nodemon,以后启动node程序的时候只需要:```nodemon app.js```,如果要重启的话,直接在命令行里输入```rs```,回车即可。省去了ctrl+c,方向上键,回车的步骤。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(12,'联系我们','12',1405961040,1410321844,'<!--markdown-->如有需要,请联系我们。我们将尽快给予您回复。\r\n\r\n新浪微博:[@四川大学飞扬俱乐部][1]\r\n腾讯微博:[@四川大学飞扬俱乐部][2]\r\n人人:[四川大学飞扬俱乐部][3]\r\n微信:四川大学飞扬俱乐部\r\n![飞扬俱乐部微信][4]\r\n\r\n\r\n\r\n [1]: http://weibo.com/u/1862724881?wvr=5&\r\n [2]: http://e.t.qq.com/fyclub\r\n [3]: http://page.renren.com/600452773?id=600452773&ref=opensearch_normal\r\n [4]: http://t1.qpic.cn/mblogpic/ac1471484d82d2fbd446/460',2,1,NULL,'page','publish',NULL,0,'1','1','1',0),(13,'关于ThinkPHP重写URL的一些事','13',1407993960,1408001314,'<!--markdown--> 背景:这是一个月黑风高的夜晚,电脑屏幕闪闪发光,他,满脸阴沉,眉头紧锁。\r\n 我用的是ThinkPHP 3.1.3 的版本。在本地调试自己的程序,完全没有问题;上传到服务器,却只能访问首页。访问其他页面的时候,出现 **404 NOT FOUND (nginx)**的错误。也就是服务器找不到文件。\r\n 造成这个问题的原因是,某些版本的nginx不支持PATH_INFO模式。要想能正常访问就得重写路由。主要有两个步骤,缺一不可。\r\n \r\n **1.开启ThinkPHP路由的REWRITE模式。**\r\n 这是比较容易忽视的地方。我当时就是忽视了这里, 白白浪费了很多时间。开启REWRITE模式很简单,只需在你的项目配置文件中加如下代码:\r\n `\'URL_MODEL\' => 2,`\r\n\r\n 默认情况下 URL_MODEL 为 1,默认情况下使用PATHINFO模式。0为普通模式,采用传统的URL传参模式。2为rewrite模式,重写URL时必须设置为rewrite。3为兼容模式,是传统传参和PATHINFO的结合。\r\n \r\n \r\n 2.重写URL\r\n 在服务器中打开nginx的配置文件。\r\n 以我自己的博客为例:\r\n `sudo vi /etc/nginx/conf.d/jianghang.name.conf`\r\n 然后添加如下代码:\r\n location / {\r\n //...省略部分代码\r\n if(!-e $request_filename) {\r\n rewrite ^(.*)$ /index.php?s=$1 last;\r\n break;\r\n }\r\n }\r\n\r\n 如果项目文件在二级目录的话,就得修改一下路径。代码如下,yourdomai是项目二级目录名称:\r\nlocation /yourdomin/ { \r\n// …..省略部分代码\r\nif (!-e $request_filename) {\r\nrewrite ^/yourdomin/(.*)$ /index.php?s=$1 last;\r\n }\r\n\r\n 如果只是重写了路由,而不开启ThinkPHP路由的REWRITE模式,则会出现“***无法加载\r\nindex.php模板***”的错误。这时候你将URL地址中的 ***/index.php*** 去掉就会发现可以正常访问了。所以重写路由的时候,得先开启路由重写模式。\r\n\r\n\r\n **3.下一步,重启nginx**\r\nsudo /etc/init.d/nginx restart\r\n 不出意外的话,就没问题啦。\r\n\r\n\r\n **4.something else**\r\n\r\n 不会使用vim? 那再贴几个简单的使用命令:\r\n\r\n a 进入insert 模式,这个时候才可以进行编辑;\r\n esc 退出insert 模式;\r\n : 进入控制台\r\n : q 退出\r\n :wq 保存并退出。\r\n 更多的就自行百度吧...\r\n\r\n最后,欢迎关注我的个人主页 [http://jianghang.name][1]啦啦啦\r\n \r\n\r\n\r\n [1]: http://jianghang.name',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(14,'在ubuntu下搭建Node+Express+Mongodb环境','14',1408094760,1408132619,'<!--markdown-->http://finalhome.org/2014/05/19/Nodejs/%E6%90%AD%E5%BB%BANode+Express+Mongodb%E7%8E%AF%E5%A2%83/\r\n这个文档里面说的很清楚。可以照做。\r\n\r\n安装完记得要\r\n`Run apt-get install nodejs-legacy`\r\n\r\n因为默认的nodejs是用的nodejs命令来访问,而我们需要用node来访问,所以 要安装这个工具。\r\n\r\n安装mongodb可以参考以下。\r\n官方文档:\r\nhttp://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/\r\n\r\n参照该链接里面的内容即可非常友好的安装成功。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(15,'JS计算二维数组中数据之和','15',1408122660,1408124694,'<!--markdown-->先贴出一个例子的完整代码:\r\n\r\n var array = new Array([\"1.2\",\"1.3\",\"1.5\",\"1.7\"],[\"2.1\",\"2.3\",\"2.4\"]);\r\n var sum = new Array();\r\n for (var i=0;i<array.length;i++){\r\n sum[i] = 0;\r\n }\r\n for (var count1=0;count1<array.length;count1++){\r\n for (var count2=0;count2<array[count1].length;count2++){\r\n sum[count1] += parseFloat(array[count1][count2]);\r\n } \r\n }\r\n console.log(sum);\r\n\r\n接下来简单说一下计算中容易忽视的问题:\r\n\r\n1.未将sum数组元素的值初始化\r\n若没有代码:`for (var i=0;i<array.length;i++){\r\n sum[i] = 0;\r\n }`\r\nFireBug的控制台会提示 `detailed error: ReferenceError: sum is not defined\r\nsum[count1] += parseFloat(array[count1][count2]);`\r\n因为sum[count1]没有初始值。\r\n\r\n2.未将array[count1][count2]中的元素转化为浮点型\r\n若没有用 parseFloat将array[count1][count2]转化为浮点型,则计算结果会是一个一维数组[\"01.21.31.51.7\", \"02.12.32.4\"]。这是因为JS 的加号在数值之间是加法运算,字符串之间是字串连接。 `sum[count1] += (array[count1][count2]);`其中的“+”是后者。\r\n\r\n3.未统一变量类型\r\n若没有统一变量类型,当运算无法返回正确的数值时,就会返回“NaN”值。\r\n\r\n \r\n \r\n\r\n ',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(16,'JS保留小数点','16',1408133058,1408133058,'<!--markdown--> <script type=\"text/javascript\"> \r\n //保留两位小数 \r\n //功能:将浮点数四舍五入,取小数点后2位 \r\n function toDecimal(x) { \r\n var f = parseFloat(x); \r\n if (isNaN(f)) { \r\n return; \r\n } \r\n f = Math.round(x*100)/100; \r\n return f; \r\n } \r\n \r\n \r\n //制保留2位小数,如:2,会在2后面补上00.即2.00 \r\n function toDecimal2(x) { \r\n var f = parseFloat(x); \r\n if (isNaN(f)) { \r\n return false; \r\n } \r\n var f = Math.round(x*100)/100; \r\n var s = f.toString(); \r\n var rs = s.indexOf(\'.\'); \r\n if (rs < 0) { \r\n rs = s.length; \r\n s += \'.\'; \r\n } \r\n while (s.length <= rs + 2) { \r\n s += \'0\'; \r\n } \r\n return s; \r\n } \r\n \r\n function fomatFloat(src,pos){ \r\n return Math.round(src*Math.pow(10, pos))/Math.pow(10, pos); \r\n } \r\n //四舍五入 \r\n alert(\"保留2位小数:\" + toDecimal(3.14159267)); \r\n alert(\"强制保留2位小数:\" + toDecimal2(3.14159267)); \r\n alert(\"保留2位小数:\" + toDecimal(3.14559267)); \r\n alert(\"强制保留2位小数:\" + toDecimal2(3.15159267)); \r\n alert(\"保留2位小数:\" + fomatFloat(3.14559267, 2)); \r\n alert(\"保留1位小数:\" + fomatFloat(3.15159267, 1)); \r\n \r\n //五舍六入 \r\n alert(\"保留2位小数:\" + 1000.003.toFixed(2)); \r\n alert(\"保留1位小数:\" + 1000.08.toFixed(1)); \r\n alert(\"保留1位小数:\" + 1000.04.toFixed(1)); \r\n alert(\"保留1位小数:\" + 1000.05.toFixed(1)); \r\n \r\n //科学计数 \r\n alert(3.1415.toExponential(2)); \r\n alert(3.1455.toExponential(2)); \r\n alert(3.1445.toExponential(2)); \r\n alert(3.1465.toExponential(2)); \r\n alert(3.1665.toExponential(1)); \r\n //精确到n位,不含n位 \r\n alert(\"精确到小数点第2位\" + 3.1415.toPrecision(2)); \r\n alert(\"精确到小数点第3位\" + 3.1465.toPrecision(3)); \r\n alert(\"精确到小数点第2位\" + 3.1415.toPrecision(2)); \r\n alert(\"精确到小数点第2位\" + 3.1455.toPrecision(2)); \r\n alert(\"精确到小数点第5位\" + 3.141592679287.toPrecision(5)); \r\n </script>',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(18,'研发部的以后如果有奖励我想好了','18',1408252620,1408252807,'<!--markdown-->###做得好的奖励一个月的付费VPN,让你无论在手机还是电脑上都能无限畅游互联网。\r\n\r\n####嗯由吴会个人出资赞助。\r\n\r\n> 不顶不是中国人。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(19,'mongodb 在windows的开启与正常关闭','19',1408254300,1408254363,'<!--markdown--> 最近在学习mongodb,每次shell下操作完成后直接关闭命令窗口,下次启动的时候总是报出无法连接到数据库的错误,这是因为没有正常关闭mongodb,数据库在db文件夹下生产了mongod.lock锁文件,只有删除了该锁文件才能连接到数据库。\r\n\r\n解决方法:\r\n另外打开一个cmd窗口,键入命令\r\n mongo\r\n进入mongo界面后\r\n1. use admin\r\n2. db.shutdownServer()\r\n3. exit\r\n\r\n就行了。第二步操作的时候会出现一些错误信息,可以忽略掉。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(29,'2.png','2-png',1409823088,1409823088,'a:5:{s:4:\"name\";s:5:\"2.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/4228731919.png\";s:4:\"size\";i:49497;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',64),(21,'curl模拟登录川大教务处网站时记得一定要把post数据http_build_query一下。','21',1409329680,1409642855,'<!--markdown-->这是一个大坑呀。每次在windows本地可以正常post的数据,一部署在服务器就出错。\r\n\r\n这个坑前后一共被坑了至少8个小时吧。\r\n\r\n切记。。\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(22,'1.png','1-png',1409639697,1409639697,'a:5:{s:4:\"name\";s:5:\"1.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3862783752.png\";s:4:\"size\";i:30819;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',23),(23,'说一下EPP3使用中的注解','23',1409639700,1429899940,'<!--markdown-->![1.png][1]\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/09/3862783752.png\r\n\r\n如图\r\n\r\n 在function或class前面,输入\" /** +enter \",就能形成一个具有注解功能的多行注释。\r\n 注意,一定要两个*,不然出来的是绿色的,不是蓝色的,蓝色自然是萌萌哒。\r\n\r\n\r\n----------\r\n割\r\n\r\n\r\n----------\r\n在这个注释块里,你输入 \'@\' 就能看到很多注解的提醒,比如param、return,下面列举一下:\r\n@access\r\n使用范围:class,function,var,define,module\r\n该标记用于指明关键字的存取权限:private、public或proteced\r\n@author\r\n指明作者\r\n@copyright\r\n使用范围:class,function,var,define,module,use\r\n指明版权信息\r\n@deprecated\r\n使用范围:class,function,var,define,module,constent,global,include\r\n指明不用或者废弃的关键字\r\n@example\r\n该标记用于解析一段文件内容,并将他们高亮显示。Phpdoc会试图从该标记给的文件路径中读取文件内容\r\n@const\r\n使用范围:define\r\n用来指明php中define的常量\r\n@final\r\n使用范围:class,function,var\r\n指明关键字是一个最终的类、方法、属性,禁止派生、修改。\r\n@filesource\r\n和example类似,只不过该标记将直接读取当前解析的php文件的内容并显示。\r\n@global\r\n指明在此函数中引用的全局变量\r\n@ingore\r\n用于在文档中忽略指定的关键字\r\n@license\r\n相当于html标签中的<a>,首先是URL,接着是要显示的内容\r\n例如<a href=”http://www.baidu.com”>百度</a>\r\n可以写作 @license http://www.baidu.com 百度\r\n@link\r\n类似于license\r\n但还可以通过link指到文档中的任何一个关键字\r\n@name\r\n为关键字指定一个别名。\r\n@package\r\n使用范围:页面级别的-> define,function,include\r\n类级别的->class,var,methods\r\n用于逻辑上将一个或几个关键字分到一组。\r\n@abstrcut\r\n说明当前类是一个抽象类\r\n@param\r\n指明一个函数的参数\r\n@return\r\n指明一个方法或函数的返回指\r\n@static\r\n指明关建字是静态的。\r\n@var\r\n指明变量类型\r\n@version\r\n指明版本信息\r\n@todo\r\n指明应该改进或没有实现的地方\r\n@throws\r\n指明此函数可能抛出的错误异常,极其发生的情况 \r\n\r\n\r\n----------\r\n注解用好了,文档都不用写。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(28,'[翻译] M3U 和M3U8 详解_from wiki','28',1409795640,1429899910,'<!--markdown-->文件格式\r\nm3u文件是用来描述一个或多个媒体文件地址的纯文本文件,通常以 M3U 或 m3u 作为扩展名。\r\n\r\nm3u文件里描述的最小单位(元素/行/记录),可以是一下三者之一:\r\n\r\n 1.一个文件的绝对路径\r\n 2.相对于m3u文件的相对路径\r\n 3.一个网络url\r\n\r\n以#好开头的,是m3u的注释,而一些m3u扩展指令也是由#号开头\r\n\r\nm3u的一个常见用途是作为一个指向网络中一个流媒体的播放列表,比如在线视频、广播等等。\r\n\r\n你可以直接用文本编辑器编写一个m3u文件,但需要保存为 window-1252格式(ASCII的一个扩展集)。\r\n\r\nM3U指令的扩展\r\n\r\n #EXTM3U 文件头,必须出现在第一行 如:略\r\n #EXTINF 引导信息,包含播放时间(时长)和标题 如:#EXTINF:191,Artist Name - Track Title\r\n\r\nM3U8\r\n所谓的M3U8就是用unicode编写的M3U文件,这最初是用在IOS设备上播放http实时流的基础格式。\r\n\r\n例子1:\r\n这是一个在window系统下的 扩展m3u 文件。其中包含sample.mp3和Example.ogg两个媒体文件。\r\n123和321是文件时长,单位是秒,但如果这里用-1的话,表示的是一个媒体流,而不是真正的时长。\r\n接下来的是要显示的标题,用来描述下一行的这个媒体文件。\r\n----------------------------------------------------\r\n\r\n #EXTM3U\r\n \r\n #EXTINF:123, Sample artist - Sample title\r\n C:\\Documents and Settings\\I\\My Music\\Sample.mp3\r\n \r\n #EXTINF:321,Example Artist - Example title\r\n C:\\Documents and Settings\\I\\My Music\\Greatest Hits\\Example.ogg\r\n\r\n---------------------------------------------------\r\n\r\n例子2:\r\n下面这个例子是用m3u文件来指向一个给定的目录(比如U盘或者光驱)。\r\n这个m3u文件只能包含一行语句:就是指向的这个路径。\r\n这样,播放器就能自动播放这个目录下的全部文件。\r\n\r\n-------------------\r\n\r\n C:\\Music\r\n\r\n--------------------\r\n\r\n例子3\r\n这个例子当中我们使用了相对路径。m3u文件和媒体文件放在同一个目录下,\r\n而当你要把文件转移的时候,必须保持m3u文件和媒体文件的目录结构不改变。\r\n这种方式比较弹性,不必要求媒体文件永远放在一个固定的地方。\r\n还是刚才的文件,我们修改一下:\r\n-----------------------------------------------------\r\n\r\n #EXTM3U\r\n \r\n #EXTINF:123, Sample artist - Sample title\r\n Sample.mp3\r\n \r\n #EXTINF:321,Example Artist - Example title\r\n Greatest Hits\\Example.ogg\r\n\r\n-----------------------------------------------------\r\n\r\n例子4:\r\n下面是一个全面的例子\r\n-----------------------------------------------------\r\n\r\n Alternative\\Band - Song.mp3\r\n Classical\\Other Band - New Song.mp3\r\n Stuff.mp3\r\n D:\\More Music\\Foo.mp3\r\n ..\\Other Music\\Bar.mp3\r\n http://emp.cx:8000/Listen.pls\r\n http://www.example.com/~user/Mine.mp3\r\n\r\n-----------------------------------------------------\r\n备注:\r\n· “Alternative”和“Classical”是m3u文件所在位置的子目录(一看就明白吧)\r\n· “Song”和“New Song”两个文件都在m3u文件所在位置的子目录里(外国人都那么细致)\r\n` “Stuff”这个文件就在m3u文件当前目录\r\n· \"Foo\"这个文件就在一个绝对路径,跟当前目录无关。\r\n· “Bar”这个文件,在当前目录的上一层的子目录下(拗口。。)\r\n· “Listen”这个是个Shoutcast在线地址(貌似是国外一个出名的在线播放产品?)\r\n· “Mine”是个纯粹的在线音频地址\r\n\r\n\r\n例子5:\r\nm3u同样支持嵌套引用\r\n-----------------------------------------------------\r\n\r\n AnotherPlayList.m3u\r\n\r\n-----------------------------------------------------\r\n\r\n例子6:\r\n(一些MP3标签的写法,暂不翻译)\r\n\r\n软件:\r\n支持m3u的播放器有很多,此处不表。\r\n\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(31,'Screenshot from 2014-09-05 16:46:13.png','Screenshot-from-2014-09-05-16-46-13-png',1409906899,1409906899,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-09-05 16:46:13.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2034498818.png\";s:4:\"size\";i:181489;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',32),(32,'发现一件很神奇的事情','32',1409906880,1409938689,'<!--markdown-->我再ubuntu下连接CMCC-EDU,未输入账号密码即可成功上网!有图有真相!尚不清楚是什么原因,先用了再说。待更新!\r\n',0,5,NULL,'post','hidden',NULL,0,'1','1','1',0),(33,'QQ图片20140906000529.jpg','QQ图片20140906000529-jpg',1409933352,1409933352,'a:5:{s:4:\"name\";s:26:\"QQ图片20140906000529.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/452968601.jpg\";s:4:\"size\";i:63615;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',8,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(34,'QQ图片20140906000629.jpg','QQ图片20140906000629-jpg',1409933437,1409933437,'a:5:{s:4:\"name\";s:26:\"QQ图片20140906000629.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/166474125.jpg\";s:4:\"size\";i:124928;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',7,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(35,'QQ图片20140906000550.jpg','QQ图片20140906000550-jpg',1409933465,1409933465,'a:5:{s:4:\"name\";s:26:\"QQ图片20140906000550.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3585076068.jpg\";s:4:\"size\";i:39438;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',6,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(36,'QQ图片20140906000716.jpg','QQ图片20140906000716-jpg',1409933499,1409933499,'a:5:{s:4:\"name\";s:26:\"QQ图片20140906000716.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2915171706.jpg\";s:4:\"size\";i:90110;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',5,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(37,'QQ图片20140906000838.jpg','QQ图片20140906000838-jpg',1409933537,1409933537,'a:5:{s:4:\"name\";s:26:\"QQ图片20140906000838.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/410271054.jpg\";s:4:\"size\";i:118082;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',4,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(38,'QQ图片20140906000842.jpg','QQ图片20140906000842-jpg',1409933546,1409933546,'a:5:{s:4:\"name\";s:26:\"QQ图片20140906000842.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2482170320.jpg\";s:4:\"size\";i:62265;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',3,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(317,'three.js 学习之自转的地球','317',1523943392,1523943392,'<!--markdown-->\r\n首先需要知道什么是 three.js。 简单的说,three.js 是一个非常优秀的 WebGL 开源框架, three(3d) + js(javaScript)。其开源项目的地址:\r\n\r\n> github: https://github.com/mrdoob/three.js\r\n\r\n而 WebGL 是在浏览器中实现三维效果的一套规范。\r\n\r\n在 three.js 中有几大重要的概念需要先了解一下:\r\n\r\n- 场景(scene)\r\n- 相机(camera)\r\n- 渲染器(renderer)\r\n\r\n**关键**:有了这三样东西,我们才能够使用相机将场景渲染到网页上去`\r\n\r\n#### 1、scene\r\n在 WebGL 世界里,场景是一个非常重要的概念,它是存放所有物体的容器。在 three.js 里面新建一个场景很简单,new THREE.Scene 实例就好了。代码如下:\r\n> var scene = new THREE.Scene(); // 场景只有一种\r\n\r\n#### 2、camera\r\n- 相机(camera)\r\n\r\n> var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000) ;\r\n\r\n`PerspectiveCamera( fov, aspect, near, far )`\r\n\r\n- fov(Number): 仰角的角度\r\n- aspect(Number): 截平面长宽比,多为画布的长宽比。\r\n- near(Number): 近面的距离\r\n- far(Number): 远面的距离\r\n\r\n图解 THREE.PerspectiveCamera 参数,如下:\r\n![](https://tse3-mm.cn.bing.net/th?id=OIP.3Jjn7ZAyk9IZUQWgLklF2AHaDn&w=300&h=300&p=0&o=5&pid=1.7)\r\n\r\n#### 3、renderer\r\n渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制。\r\n\r\n```\r\n var renderer = new THREE.WebGLRenderer();\r\n renderer.setSize(window.innerWidth, window.innerHeight);\r\n document.body.appendChild(renderer.domElement);\r\n```\r\n\r\n\r\n好了,几大概念简单的说了,还不是很明白也不打紧,先看下最终的效果:\r\n\r\n![](http://bluestest.oss-cn-shanghai.aliyuncs.com/earth.gif)\r\n\r\n#### 开始画地球\r\n\r\n1、导入 `three.min.js` 文件,可以下载到本地,也可以采用 cdn, 我这里采用的是下载下来的方式:\r\n\r\n\r\n> \\<script src=\"assets/plus/threejs/three.min.js\">\\</script>\r\n\r\n或者\r\n\r\n> \\<script src=\"https://cdn.bootcss.com/three.js/r83/three.min.js\">\\</script>\r\n\r\n2、准备渲染器 renderer 的 domElement 元素\r\n\r\n> \\<div id=\"canvas-frame\">\\</div>\r\n\r\n`<style></style>` 中加入 css:\r\n\r\n```\r\n div#canvas-frame {\r\n border: none;\r\n cursor: pointer;\r\n width: 100%;\r\n height: 100vh;\r\n background-color: #EEEEEE;\r\n}\r\n```\r\n3、实例化一个 scence 对象, 用来存放我们的地球实体。\r\n\r\n```\r\n// 场景\r\nvar scene;\r\nfunction initScene() {\r\n scene = new THREE.Scene();\r\n}\r\n```\r\n4、准备搭建 camera 的位置,和调节角度,在 three.js 里面采用给的是`右手坐标系`:\r\n\r\n```\r\n// 相机\r\nvar camera;\r\nfunction initCamera() {\r\n camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);\r\n camera.position.x = -500;\r\n camera.position.y = 500;\r\n camera.position.z = -500;\r\n}\r\n```\r\n这里采用的是透视相机。 视角越大,看到的场景越大,那么中间的物体相对于整个场景来说,就越小了。\r\n\r\n5、准备渲染器 renderer\r\n\r\n```\r\n// 渲染器\r\nvar renderer;\r\nfunction initThree() {\r\n width = document.getElementById(\'canvas-frame\').clientWidth;\r\n height = document.getElementById(\'canvas-frame\').clientHeight;\r\n // 实例化 THREE.WebGLRenderer 对象。\r\n renderer = new THREE.WebGLRenderer({\r\n antialias: true,\r\n alpha: true,\r\n canvas: renderer\r\n });\r\n // 设置 renderer 的大小\r\n renderer.setSize(width, height);\r\n // 挂载到准备的 domElement 上\r\n document.getElementById(\'canvas-frame\').appendChild(renderer.domElement); \r\n // Sets the clear color and opacity.\r\n renderer.setClearColor(0x000000, 1.0);\r\n}\r\n```\r\n这里对 THREE.WebGLRenderer 实例的参数进行讲解。\r\n\r\n- `canvas ` - 渲染器绘制输出的那个 canvas, 这对应于下面的 domElement 属性。如果没有在设置,则会创建一个新的画布元素。\r\n- `antialias ` - 抗锯齿化\r\n- `alpha ` - alpha 缓冲区\r\n\r\n\r\n6、画地球啦,这里的地球其实就是在一个球体上贴上带有地球纹路的贴纸。\r\n\r\n```\r\n// 地球\r\nvar earthMesh;\r\nfunction initEarth() {\r\n // 实例化一个半径为 200 的球体\r\n var earthGeo = new THREE.SphereGeometry(200, 100, 100);\r\n var earthMater = new THREE.MeshPhongMaterial({\r\n map: new THREE.TextureLoader().load(\'./assets/earth.jpg\')\r\n });\r\n earthMesh = new THREE.Mesh(earthGeo, earthMater);\r\n scene.add(earthMesh);\r\n}\r\n```\r\n7、给地球加上云层;\r\n\r\n```\r\n// 云\r\nvar cloudsMesh;\r\nfunction initClouds() {\r\n\r\n // 实例化一个球体,半径要比地球的大一点,从而实现云飘咋地球上的感觉\r\n var cloudsGeo = new THREE.SphereGeometry(201, 100, 100);\r\n \r\n // transparent 与 opacity 搭配使用,设置材质的透明度,当 transparent 设为 true 时, 会对材质特殊处理,对性能会有些损耗。\r\n var cloudsMater = new THREE.MeshPhongMaterial({\r\n alphaMap: new THREE.TextureLoader().load(\'./assets/clouds.jpg\'),\r\n transparent: true,\r\n opacity: 0.2\r\n });\r\n \r\n cloudsMesh = new THREE.Mesh(cloudsGeo, cloudsMater);\r\n scene.add(cloudsMesh);\r\n}\r\n```\r\n到这里地球就画完了,但是,就像现实的世界一样,如果你不给它打点光,世界就是漆黑一片的,所以接下来给我们的 scene 加点光吧。\r\n\r\n8、给世界来点光,世界还你一片彩。\r\n\r\n```\r\n// 光源\r\nvar light;\r\nfunction initLight() {\r\n // A light source positioned directly above the scene, with color fading from the sky color to the ground color. \r\n // 位于场景正上方的光源,颜色从天空颜色渐变为地面颜色。\r\n // var light = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);\r\n // scene.add(light);\r\n \r\n // 环境光\r\n light = new THREE.AmbientLight(0xFFFFFF);\r\n light.position.set(100, 100, 200);\r\n scene.add(light);\r\n \r\n // 平行光\r\n // 位置不同,方向光作用于物体的面也不同,看到的物体各个面的颜色也不一样\r\n // light = new THREE.DirectionalLight(0xffffbb, 1);\r\n // light.position.set(-1, 1, 1);\r\n // scene.add(light);\r\n}\r\n```\r\n这里采用的是环境光,其它注释了的两种光的效果也不错哦~\r\n直到这里,地球就画出来了,但是我们的题目是画一颗自转的地球,那我们如何让它自己转起来呢?我们继续往下看。\r\n\r\n9、引入一个控制器,这里如果你足够厉害自己写也可以哦,我采用的开源的。\r\n\r\n```\r\n <script src=\"assets/plus/threejs/js/controls/OrbitControls.js\"></script>\r\n```\r\n```\r\n // 载入控制器\r\n var controls = new THREE.OrbitControls(camera, renderer.domElement);\r\n```\r\n10、定义地球和云层自转的动画,速度不一样会更像哦。这里说说为什么循环动画使用的是 `requestAnimationFrame`, 而不是更熟知的 `setInterval`?`setInterval` 是到点就往任务队列里插,是 JS 引擎的定时器方法;`requestAnimationFrame` 是跟着浏览器的绘制走,浏览器每次重绘的时候调用,是 DOM 引擎提供的方法。\r\n\r\n```\r\nfunction animate() {\r\n controls.update();\r\n // 地球自转\r\n earthMesh.rotation.y -= 0.002;\r\n // 漂浮的云层\r\n cloudsMesh.rotation.y -= 0.005;\r\n cloudsMesh.rotation.z += 0.005;\r\n renderer.render(scene, camera);\r\n requestAnimationFrame(animate);\r\n}\r\n```\r\n自转的地球到这里就大功告成啦~\r\n\r\n完整的代码见:https://github.com/jiangyuzhen/three-earth\r\n\r\n```\r\nTips: 有的小伙伴克隆上面的代码后, 用双击 index.html 的方式看不到效果,可以自己搭一个静态服务或者试试 anywhere (随启随用的静态文件服务器):\r\n```\r\n\r\n步骤如下:\r\n\r\n```\r\n// 全局安装\r\nnpm i anywhere -g \r\n\r\n// 文件根目录下执行\r\nanywhere\r\n```\r\n\r\n\r\n#### 相关资料\r\n- https://threejs.org/\r\n- https://github.com/omni360/three.js.sourcecode\r\n- http://www.hewebgl.com/article/articledir/3',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(312,'daily_waka.png','daily_waka-png',1520353578,1520353578,'a:5:{s:4:\"name\";s:14:\"daily_waka.png\";s:4:\"path\";s:34:\"/usr/uploads/2018/03/637394479.png\";s:4:\"size\";i:67026;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',315),(313,'leader.png','leader-png',1520353597,1520353597,'a:5:{s:4:\"name\";s:10:\"leader.png\";s:4:\"path\";s:35:\"/usr/uploads/2018/03/1817434637.png\";s:4:\"size\";i:125377;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,2,NULL,'attachment','publish',NULL,0,'1','0','1',315),(314,'WordArt.png','WordArt-png',1520353626,1520353626,'a:5:{s:4:\"name\";s:11:\"WordArt.png\";s:4:\"path\";s:34:\"/usr/uploads/2018/03/748102548.png\";s:4:\"size\";i:141696;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,2,NULL,'attachment','publish',NULL,0,'1','0','1',315),(315,'趣闻 - 过去一周,程序员都在写什么语言?','315',1520353646,1520353646,'<!--markdown-->一直以来我在使用一个叫**wakatime**的工具来记录每天的编码情况。\r\n\r\n比如:\r\n![daily_waka.png][1]\r\n\r\n想要了解**wakatime**的, 自己去[https://wakatime.com](https://wakatime.com)了解一下。\r\n\r\n\r\n除了这个以外,**wakatime**还提供一个公开的排行榜,展示了**最近七天**用户的编码排名情况。\r\n\r\n![leader.png][2]\r\n\r\n\r\n### 于是机会来了。\r\n\r\n- 把这个排名的数据抓取下来,只要前40页\r\n- 把每一个用户使用的语言列表、每个语言的时长记录统计起来\r\n- 按语言归类, 看看哪个语言最近7天的使用时间最多。\r\n\r\n\r\n### 第一步,数据爬下来,目标40页\r\n我当然是不希望抓页面的,这样太没趣,更重要的是\r\n\r\n**人家有提供接口!!!**\r\n\r\n> https://wakatime.com/api/v1/leaders?page=1\r\n\r\n这下事情就简单多了,代码如下:\r\n\r\n \'use strict\';\r\n const request = require(\'request-agent\').init();\r\n const fs = require(\'fs\');\r\n \r\n (async () => {\r\n let data = {};\r\n for (let i = 0; i < 40; i++) {\r\n data = await request\r\n .method(\'get\')\r\n .url(`https://wakatime.com/api/v1/leaders?page=${i + 1}`)\r\n .send();\r\n fs.writeFileSync(`./waka_stat/${i + 1}.json`, data.body);\r\n }\r\n })().then((v) => {\r\n console.log(v); process.exit(0);\r\n }).catch((e) => {\r\n console.log(e);\r\n });\r\n\r\n### 第二步,统计\r\n你可能要问, 为什么不一遍请求接口一遍统计呢?\r\n\r\n原因是这个接口速度有点蛋疼(翻墙好点), 先把数据拉下来, 这样我统计的部分调试也方便。\r\n\r\n贴代码:\r\n\r\n \'use strict\';\r\n const fs = require(\'fs\');\r\n let result = {};\r\n \r\n for (let i = 1; i <= 40; i++) {\r\n let data = require(`./${i}.json`).data;\r\n let len = data.length;\r\n for (let k = 0; k < len; k++) {\r\n let languages = data[k].running_total.languages;\r\n for (let index in languages) {\r\n result[languages[index].name] = result[languages[index].name] || 0;\r\n result[languages[index].name] += languages[index].total_seconds;\r\n }\r\n }\r\n }\r\n \r\n let unsort = [];\r\n for (let k in result) {\r\n unsort.push({\r\n name: k,\r\n seconds: Number.parseInt(result[k] / 3600),\r\n });\r\n }\r\n unsort.sort((a, b) => {\r\n if (a.seconds > b.seconds) return -1;\r\n return 1;\r\n })\r\n fs.writeFileSync(\'./waka_stat/result.json\', JSON.stringify(unsort, null, 2));\r\n \r\n### 结果\r\n\r\n贴一部分:\r\n![WordArt.png][3]\r\n\r\n [\r\n {\r\n \"name\": \"JavaScript\",\r\n \"hours\": 15112\r\n },\r\n {\r\n \"name\": \"PHP\",\r\n \"hours\": 9366\r\n },\r\n {\r\n \"name\": \"Java\",\r\n \"hours\": 4164\r\n },\r\n {\r\n \"name\": \"TypeScript\",\r\n \"hours\": 3262\r\n },\r\n {\r\n \"name\": \"Python\",\r\n \"seconds\": 3119\r\n },\r\n {\r\n \"name\": \"HTML\",\r\n \"hours\": 3054\r\n },\r\n {\r\n \"name\": \"C#\",\r\n \"hours\": 2662\r\n },\r\n {\r\n \"name\": \"Ruby\",\r\n \"hours\": 1981\r\n },\r\n {\r\n \"name\": \"Vue.js\",\r\n \"hours\": 1698\r\n }...\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2018/03/637394479.png\r\n [2]: http://log.fyscu.com/usr/uploads/2018/03/1817434637.png\r\n [3]: http://log.fyscu.com/usr/uploads/2018/03/748102548.png',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(316,'多条件短路优化实测','316',1520585160,1520586254,'<!--markdown-->### 什么是多条件短路\r\n\r\n型如 **if (A && B && C)** 这样的多个条件组成的逻辑语句,\r\n\r\n通过调整每个因子的顺序,利用**短路**来实现执行效率的优化。\r\n\r\n> [知乎:逻辑运算符特有的短路效应是什么](https://www.zhihu.com/question/39209736/answer/80208676)\r\n> \r\n\r\n### 口说无凭,真实场景模拟测试\r\n\r\n首先定义三个逻辑单元:\r\n\r\n const conditionA = ()=>{\r\n return Math.random() > 0.25;\r\n }\r\n \r\n const conditionB = ()=>{\r\n return Math.random() > 0.5;\r\n }\r\n \r\n const conditionC = ()=>{\r\n return Math.random() > 0.75;\r\n }\r\n\r\n显而易见, 以上三个逻辑, 返回 **true**的概率是逐渐递减的。\r\n\r\n我们以此来做实验样本。\r\n\r\n\r\n const Benchmark = require(\'benchmark\');\r\n const suite = new Benchmark.Suite;\r\n \r\n suite.add(\'A || B || C\', function () {\r\n if(conditionA() || conditionB() || conditionC()){\r\n // A或B或C, 大概率true的放前面\r\n }\r\n }).add(\'C || B || A\', function () {\r\n if(conditionC() || conditionB() || conditionA()){\r\n // C或B或A, 小概率true的放前面\r\n }\r\n }).add(\'A && B && C\', function () {\r\n if(conditionA() && conditionB() && conditionC()){\r\n // A且B且C, 大概率true的放前面\r\n }\r\n }).add(\'C && B && A\', function () {\r\n if(conditionC() && conditionB() && conditionA()){\r\n //C且B且A, 小概率true的放前面\r\n }\r\n }).on(\'cycle\', function (event) {\r\n console.log(String(event.target));\r\n }).on(\'complete\', function () {\r\n console.log(\'Fastest is \' + this.filter(\'fastest\').map(\'name\'));\r\n }).run({ \'async\': true });\r\n \r\n\r\n以上代码应该比较好懂, 测试 `||``&&` 两种情况下,不同的排列顺序对执行效率的影响,\r\n\r\n**如果实在思路转不过来, 多看几遍代码。**\r\n\r\n#### 结果:\r\n\r\n A || B || C x 29,734,965 ops/sec ±1.42% (88 runs sampled)\r\n \r\n C || B || A x 19,663,159 ops/sec ±0.57% (90 runs sampled)\r\n \r\n A && B && C x 19,865,675 ops/sec ±0.63% (89 runs sampled)\r\n \r\n C && B && A x 30,679,108 ops/sec ±0.52% (88 runs sampled)\r\n\r\n**结论:**\r\n\r\n- 多个 **||** 条件,把大概率**true**的条件写最前面,效率更高。\r\n- 多个 **&&** 条件,把小概率**true**的条件写最前面,效率更高。\r\n\r\n\r\n#### 为什么?\r\n\r\n**||**遇到**true**就会短路, 反之, **&&**遇到**false**也会短路。\r\n\r\n明白了吗?\r\n\r\n> 完整代码:将上面两段合在一起就是。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(311,'package.json里的一些属性讲解','311',1519290180,1519295054,'<!--markdown-->> 内容来自 [npm官方文档](https://docs.npmjs.com/files/package.json) , 本文做中文解释.\r\n> \r\n\r\n### name, version\r\n首先, 包名字是**必须的**. 版本号也是**必须的**.\r\n\r\n**npm**规定了, 一个**package**是由**名字**加**版本号**作为唯一标识的.\r\n\r\n比如 `[email protected]` , `[email protected]` , 不同的包名或者版本号, 对应的内容是不一样的.\r\n\r\n以上内容比较好理解, 接下来我补充几点: \r\n\r\n- 包名必须少于等于 **214** 字符, \r\n- 包名不能以 `.`或`_`开头\r\n- 包名不能含有大写字母 (历史原因, 有的老包还有大写字母,新的已经不能用大写字母)\r\n- 另外, 一些`URL`规范里不允许的字符也不能用(具体哪些字符就需要大家自己查查了)\r\n- 建议不要在包名里包含`js``node`等字眼, 因为**npm**默认就是**js**或**node**的\r\n- 因为包名最终会用在`require`语句里, 所以尽可能短一些,但要注意能明确表达自己的用途\r\n- 你开发一个包之前, 最好自己上 [npm官网]( https://www.npmjs.com/)看看名字是不是已经被占用了(很重要)\r\n\r\n对于版本号, **npm**使用业界标准的 `{major}.{feature}.{patch}` 模式\r\n\r\n所以 `1.4.1`到`1.4.2`可能是修复个小bug\r\n\r\n`1.4.1`到`1.5.0`可能是加了新功能\r\n\r\n`1.4.1`到`2.0.0`的话, 可能就是变化很大的两个东西了.\r\n\r\n> Tips\r\n> \r\n> 如果你要发布包到**npm**, 相同的包名, 相同的版本号, 只能发布一次,\r\n> \r\n> 所以如果你修改了代码, 需要更新版本号才能**publish**,\r\n> \r\n> 具体修改哪一位, 要看你修改了多少东西.\r\n\r\n### description, keywords\r\n\r\n这两个放在一起讲.\r\n\r\n这两个字段都是用来在**npm官网**上搜索的, 区别是一个是字符串, 一个是字符串数组.\r\n\r\n不难理解, **npm**会对`description`做分词搜索, 而对于 `keywords`会做精准搜索.\r\n\r\n>Tips\r\n>\r\n>官方并未说明, 以上关于分词与否, 纯属猜测.\r\n\r\n### homepage\r\n\r\n如果你有时间, 可以为你的包做一个官网之类的, 大型的项目常见.\r\n\r\n### bugs\r\n\r\n这个字段并不是说这个包还有 **bug**, 首先我们看看例子 \r\n\r\n\r\n { \r\n \"url\" : \"https://github.com/owner/project/issues\",\r\n \"email\" : \"[email protected]\"\r\n }\r\n\r\n这个字段其实是提供给使用者上报 **bugs**的途径, 可以填一个**email**或者一个**issue地址**\r\n>Tips\r\n>\r\n>如果你只想提供一个**issue地址**, 那么**bugs**可以只是一个字符串\r\n\r\n###license\r\n\r\n这个......不想多说, 自行了解吧\r\n\r\n###author, contributors\r\n\r\n这是关于作者或者其他开发人员信息的字段, 含义很好理解, 我们看一个例子:\r\n\r\n\r\n { \r\n \"name\" : \"Barney Rubble\", \r\n \"email\" : \"[email protected]\", \r\n \"url\" : \"http://barnyrubble.tumblr.com/\"\r\n }\r\n\r\n**author**和**contributors**就是放置型如上面这样的对象来描述人物信息的, 区别是, **author**是单个, 而**contributors**是数组.\r\n\r\n>Tips\r\n>\r\n>非必须信息, 可以出名以后再加.\r\n\r\n### files\r\n\r\n这个不是必选项, 也并不常见, 但是很重要, 因为有配置这个信息会显得非常专业.\r\n\r\n**files**是一个数组, 它描述了你 `npm publish`的时候推送到**npm**服务器的文件列表,支持目录和通配 比如\r\n\r\n\r\n \"files\": [\r\n \"LICENSE\",\r\n \"History.md\",\r\n \"Readme.md\",\r\n \"index.js\",\r\n \"lib/\"\r\n ],\r\n\r\n反过来, 你可以通过一个 `.npmignore` 文件来排除一些文件, 防止大量的垃圾文件推送到**npm**, 规则上和你用的`gitignore`是一样的.\r\n> Tips\r\n> \r\n> 如果你的项目下有 **.gitignore** 文件, 那么它也能充当**.npmignore**的功能.\r\n> \r\n> 这意味着, 如果没有特别的需求, 一个**.gitignore**就行了.\r\n\r\n### main\r\n\r\n这个是一个重要属性,原文对这个描述比较绕, 实际上可以理解为 **入口文件**\r\n\r\n \"main\":\"./src/index.js\",\r\n\r\n以上面的例子来说, 如果你的包名是`foo`, 当用户代码`require(\'foo\')`时,\r\n\r\n相当于**require**了你包目录下的 `./src/index.js`文件.\r\n\r\n如果没有提供这个字段, 默认是项目根目录下的`index.js`\r\n\r\n### bin\r\n这也是一个重要属性, 它定义了一系列可执行命令, 在全局安装的命令行包里尤其多见.\r\n\r\n这里提供一个**pm2**的`bin`例子:\r\n\r\n \r\n \"bin\": {\r\n \"pm2\": \"./bin/pm2\",\r\n \"pm2-dev\": \"./bin/pm2-dev\",\r\n \"pm2-docker\": \"./bin/pm2-docker\",\r\n \"pm2-runtime\": \"./bin/pm2-runtime\"\r\n },\r\n\r\n上面这个对象的意思是, 安装完以后, 输入`pm2`实际上是运行`{模块所在目录}/bin/pm2`, 以此类推.\r\n\r\n带有`bin`信息的包, 在局部安装后, 可执行文件会在`./node_modules/.bin`下,\r\n\r\n如果是全局安装, 可执行文件会在 `$PATH` 里对应`npm`那个目录下.\r\n\r\n>Tips\r\n>\r\n>有些朋友安装node环境的方式比较奇怪, 没有把全局安装nodule的路径加到 $PATH里,\r\n>\r\n> 导致 npm install -g 以后提示命令找不到, 最好检查一下自己的$PATH\r\n\r\n### man\r\n\r\n这里是`manuel`, 是**手册**的意思, 不是男人, 也不是上面说到的**main**\r\n\r\n这个是指定一个(或多个)文件, 用于执行`man {包名}`时, 展现给用户的手册内容.\r\n\r\n稍微有点**linux**基础都懂, 不细说.\r\n\r\n### directories\r\n\r\n这个字段挺无语的, 它是一个**object**, 包含了`lib``bin``man``doc``example``test`等属性, \r\n\r\n主要是用来告诉用户我的某些功能目录放在哪里, 也是一个**显得专业**的功能.\r\n\r\n除此以外暂时没有实际应用.\r\n\r\n\r\n \"directories\": {\r\n \"bin\": \"./bin\",\r\n \"doc\": \"./doc\",\r\n \"lib\": \"./lib\",\r\n \"man\": \"./man\"\r\n },\r\n\r\n\r\n### repository\r\n\r\n这个属性很明显, 是放置你的`git`地址的, 格式如下:\r\n\r\n \r\n \"repository\" :{ \r\n \"type\" : \"git\", \r\n \"url\" : \"https://github.com/npm/npm.git\"\r\n },\r\n\r\n\r\n>Tips\r\n>\r\n>这个部分有一些缩写的方式, 自己看原文吧.\r\n\r\n### scripts\r\n这个是重点!\r\n\r\n \r\n \"scripts\": {\r\n \"start\": \"node app.js\",\r\n \"any\": \"any command && exit 0\",\r\n },\r\n\r\n以上两个配置, 提供了 `npm start`和`npm run any`两个命令对应的实际操作.\r\n\r\n至于什么时候需要`run`什么时候不需要, \r\n\r\n可以详细看 [npm scripts](https://docs.npmjs.com/misc/scripts), 这个够单独开一章来说明.\r\n\r\n>Tips \r\n>\r\n>除了定义一些快捷命令, scripts 还有一些钩子性质的预定义命令,\r\n>\r\n>如 preinstall , postinstall 可以在包安装前后 **自动** 执行一些操作\r\n>\r\n>详细还是看上面的链接.\r\n\r\n### config\r\n这是一个`object`结构, 定义了一些执行`scripts`时的配置参数之类, 和`scripts`属性关系很大, 个人目前还没用过, 等我研究好了再补充.\r\n\r\n目前可以参考 [npm-config](https://docs.npmjs.com/misc/config)\r\n\r\n###dependencies, devDependencies, peerDependencies\r\n\r\n前两个大家很熟悉了, 不用展开讲了, 唯一需要提醒的是, 要自己判断什么包安装在**dev**就行.\r\n\r\n值得注意的是 **peerDependencies** 这个并不常见的属性, \r\n\r\n它是用于你这个包并不依赖模块**A**, 但是要使用你这个包, 必须当前项目装了**A**.\r\n\r\n比如你的 `my-project` , 已经引入了`people`模块, 而还有一个`people-fly`, 必须你的`my-project`有用到`people`才可以用, 但是`people-fly`的源码里并没有直接使用`people`.\r\n\r\n这时候, `people-fly`的**package.json** 里就会声明`peerDependencies`包含`people `\r\n\r\n以上这一段多读几次应该能理解的.\r\n\r\n### bundledDependencies\r\n这个是一个特定场景的属性, 我个人没用过.\r\n\r\n**bundledDependencies**是一个字符串数组, 内容只能是在**dependencies, devDependencies**两个里面声明过的包才行.\r\n\r\n这样可以在`npm publish`和`npm pack`的时候将一些依赖打包进去.\r\n\r\n>Tips:\r\n>\r\n>单纯声明在dependencies里的包, 会在安装的时候, 再从npm那边安装一遍.\r\n>\r\n>而打包了的, 就会在当前模块安装的时候, 就一并下载下来了.\r\n>\r\n>具体怎么应用就自己想想吧, 我没用过.\r\n\r\n### optionalDependencies\r\n可有可无的依赖?\r\n\r\nnpm通常会在某些依赖安装失败时报错, 中断操作, 而写在**optionalDependencies**的依赖则不会.\r\n\r\n要妥善支持这个功能, 你的源码里面也要注意判断这些特定的依赖是否存在.\r\n\r\n其实是很麻烦很扯淡的操作.\r\n\r\n### engines\r\n\r\n \r\n \"engines\" : { \r\n \"node\" : \">=0.10.3 <0.12\" \r\n }\r\n\r\n\r\n这个属性可以声明你的包需要在怎样的`node`环境下运行 (`npm`也一样可以声明)\r\n\r\n只不过,\r\n\r\n只有在用户配置 **npm** 的`engine-strict`后, 才会有意义, 不然只会冒出一个 `warning` (程序员看不到 `warning`)\r\n\r\n### engineStrict\r\n忽略, 最新的 `npm`已经废弃这个了.\r\n\r\n###os\r\n\r\n看两个例子\r\n\r\n\r\n \"os\" : [ \"darwin\", \"linux\" ]\r\n\r\n.\r\n\r\n \"os\" : [ \"!win32\" ]\r\n\r\n\r\n显然意见就是操作系统的黑白名单, \r\n\r\n比如你开发了一个工具, 只支持**OSX**, 不支持**Windows** (这合情合理!)\r\n\r\n就可以通过这个来声明.\r\n\r\n###cpu\r\n\r\n看两个例子\r\n\r\n\r\n \"cpu\" : [ \"x64\", \"ia32\" ]\r\n\r\n.\r\n\r\n\r\n \"cpu\" : [ \"!arm\", \"!mips\" ]\r\n\r\n不想解释了, 能玩到这个属性的人, 已经不需要看这个了.\r\n\r\n### private\r\n\r\n这个设置为`true`, 就会无法`npm publish`,\r\n\r\n怎么说呢, 有用的吧.',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(309,'zhankai.png','zhankai-png',1517651980,1517651980,'a:5:{s:4:\"name\";s:11:\"zhankai.png\";s:4:\"path\";s:34:\"/usr/uploads/2018/02/630749732.png\";s:4:\"size\";i:67965;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',310),(310,'前后分离真的可以提高效率吗?','310',1517652000,1517652358,'<!--markdown-->>Q:传统的服务端渲染静态HTML返回,与现在流行的前后端分离相比,谁的效率更高?\r\n\r\n>提问者:AkagiInc\r\n>\r\n\r\n#### 0x00 当我在说效率的时候, 我们在说什么?\r\n![请输入图片描述][1]\r\n\r\n既然我们说到**效率**, 今天就一次过满足你两个愿望.\r\n\r\n- 开发效率\r\n- 运行效率\r\n\r\n讨论前后分离带来的效率变化, 为了更好地在团队里推(qiang)行(zhi)前后分离,\r\n就需要从这两个角度去说服(dui)开发人员.\r\n\r\n#### 0x01 开发效率\r\n\r\n\r\n我们先假设一种理想情况\r\n\r\n> 1.前期的需求设计接口定义已经非常完善.\r\n> \r\n> 2.前后端对分离后的技术手段都已经非常熟练\r\n\r\n在这个大背景下, 跟过去同样的工作量(假设工作量本质上是相同的),\r\n\r\n那么 **前后分离** 可以让任务更加多地并行开发, 无疑这个时候开发效率是能得到显著的提高的. 同时, 前后分离可以让一套系统的不同部分可以分别迭代, 分别进化, 这对于敏捷开发要求的小步快跑,快速迭代是有与生俱来的好感的, 这无疑是不断优化系统的路上的强大推力.\r\n\r\n**但现实中的情况却不是这样.**\r\n\r\n通常来说团队更习惯于过去已经掌握的技巧, 前端写完静态页面, 再由后端套模板引擎标签, 最后一体化发布.\r\n\r\n他们已经在这个体系下非常熟练地开发各种项目, 如果强行推行新的技术手段, 显然在当下是会牺牲掉一些开发效率.\r\n\r\n**那么结论到底是如何?**\r\n\r\n来自个人的一些见解:\r\n\r\n> 着眼于长远考虑, 前后分离可以让开发效率有很大的提升, 并且开发质量也会因为更多的**专业化**,**工程化**而得到前所未有的提高.\r\n> \r\n> 2016年是前端工程化重要的一年,相信没有人会质疑工程化带来的优势.\r\n> \r\n> 回顾前文阐述的一种理想情况, 也并不是遥不可及, 想要蜕变就要付出阶段性代价. 争取早日达到\"理想情况\"才是一个技术团队的终极追求.\r\n> \r\n> 所以, 从**开发效率**的角度来考虑, 建议早日走上前后分离的道路.\r\n\r\n\r\n#### 0x02 运行效率\r\n\r\n我们把 **计算效率** 和 **传输效率** 都归到这个环节里来讨论.\r\n\r\n对于老一套的方法, 所有页面看到的都要通过后端程序根据模板渲染出一个html文档.\r\n\r\n所谓的**渲染**, 就是字符串的查找,替换,拼接. \r\n\r\n这种操作是非常消耗计算资源的, 那么同样的千万次请求, 是分发到客户端本地做渲染, 还是在服务器统一渲染, 相信大家已经能明白个中的差别.\r\n\r\n同时, 后端只提供数据接口, 可以非常有效地减少网络传输量\r\n\r\n```\r\n 过去: ----( <p class=\"tit xxx\"><a href=\"/123\">标题</a></p> ) --->\r\n \r\n 现在: ----( {id:123,title:\"标题\"} ) ----> \r\n```\r\n以上只是一个例子, 实际情况中渲染后的内容会比这个更多.\r\n\r\n**如果说前后分离还有一个缺点的话, 那就是首屏体验**\r\n\r\n所谓的首屏, 就是用户访问网站地址后, 不做任何操作的情况下看到的第一个界面的样子.\r\n\r\n那么如果浏览器复杂渲染, 服务器负责给数据, 必然会引起一个问题: \r\n\r\n**网络不佳的情况下, 会出现白屏.**\r\n\r\n原因就是页面准备好了, 而数据未准备好, 又或者因为其他外部资源未就绪, 导致渲染迟迟未进行, 用户只能看着白屏干等.\r\n\r\n**这必然会让用户很不爽啊.**\r\n\r\n解决这个问题有两个思路\r\n\r\n- 做一个加载中的动效盖过去\r\n- 首屏交还给服务端渲染\r\n\r\n很难受哪一种方案目前更受欢迎, 从观察的角度看, 内容为主的站点会倾向**首屏服务端渲染**, 而动效更多的站点更常见有一个**加载中的动画**, 比如一些web游戏.\r\n\r\n所以, 来自个人一点见解:\r\n\r\n> 选择一种合适的方案解决首屏体验问题\r\n> \r\n> 首屏之后的网络交互使用前后分离, 既能提高服务器效能, 又能提高前端体验, 也节省了用户的流量.\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2018/02/630749732.png',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(308,'从一个页面开关, 说说有限状态机','308',1516850982,1516850982,'<!--markdown-->> 故事起源于最近看一位朋友在实现一个 播放/暂停 按钮时, 一些思路上的碰撞,\r\n> 于是整理出本文, 讲解一下如何用 有限状态机 使代码更简洁可靠.\r\n\r\n![](http://bluestest.oss-cn-shanghai.aliyuncs.com/on_off.png)\r\n\r\n我们想实现上面这样的按钮交互, 先看看原版实现:\r\n\r\n $(\'#botton\').on(\'click\', function(){\r\n if ( $(this).text() === \'OFF\' ){\r\n //把按钮的文案改变一下\r\n $(this).text(\'ON\');\r\n //开始播放\r\n $(\'#player\').start();\r\n } else {\r\n $(this).text(\'OFF\');\r\n $(\'#player\').stop();\r\n }\r\n });\r\n \r\n这是一个基本的实现方式, 也是一个最简单的方式.\r\n\r\n不过,\r\n\r\n按照这个方式来做有几个不太优雅的地方:\r\n\r\n- 如果点击按钮之后, 需要做的操作增加, 会让`if / else`里面的代码越来越臃肿.\r\n- 如果按钮的变化不止 `on/off`两种, 我们可能需要些一堆 `else if`或者用`switch / case`\r\n\r\n#### 针对以上状况, 我提议试试使用**有限状态机**来解决问题\r\n\r\n先看代码:\r\n\r\n var fsm = (function(){\r\n //初始状态\r\n var status = 1; \r\n \r\n //状态对应的操作\r\n var mapping = {\r\n \'1\': {\r\n text:\'ON\',\r\n action: $(\'#player\').start\r\n },\r\n \'-1\': {\r\n text:\'OFF\',\r\n action: $(\'#player\').stop\r\n },\r\n };\r\n \r\n return function(btn){\r\n //通过 *-1 实现status从 1/-1 切换\r\n status *= -1;\r\n btn.text( mapping[status].text );\r\n var fn = mapping[status].action;\r\n fn();\r\n }\r\n })();\r\n \r\n $(\'#botton\').click(function(){\r\n fsm(this);\r\n });\r\n \r\n阅读上面代码能发现, 对`botton`的点击事件处理, 只需要调用`fsm`函数即可, 内部的变化和操作, 都不需要暴露出来.\r\n\r\n`fsm`内部, 通过`mapping`来定义和限制行为, 唯一能够改变的只有`status`,\r\n\r\n这样的好处在于, 能够避免在编码过程中人为的错误, 因为事件响应部分只能有限的操作状态机的`status`,而不是直接参与`botton`的行为与表现.\r\n\r\n同时, 功能的扩展, 状态的增减, 都只需要在`mapping`里面定义好, 非常利于扩展与维护.\r\n\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(306,'深究JS引用類型傳參','306',1490338140,1490338463,'<!--markdown-->## 深究JS引用類型傳參\r\n\r\n先看一段代碼:\r\n\r\n var obj = {\r\n name: \'Tom\'\r\n };\r\n \r\n function foo (o) {\r\n o.name = \'Jack\';\r\n }\r\n \r\n foo(obj);\r\n \r\n console.log(obj); //{ name: \'Jack\' }\r\n \r\n \r\n是不是說明,在 `foo` 調用的過程中, `obj`是按引用傳參的呢?\r\n\r\n我們不妨再看一段代碼:\r\n\r\n var obj = {\r\n name: \'Tom\'\r\n };\r\n \r\n function foo2 (o) {\r\n o = {\r\n name: \'Jack\'\r\n };\r\n }\r\n \r\n foo2(obj);\r\n \r\n console.log(obj); //{ name: \'Tom\' }\r\n \r\n仔細對比上面的代碼,到底參數 `o` 是不是以 `obj` 的引用的形式傳進去的呢?\r\n\r\n\r\n## 解釋:\r\n\r\n1.將一個對象賦值給一個變量的含義:\r\n\r\n`var obj = { name: \'Tom\' } ; `\r\n\r\n這裡首先是通過 `{}`操作,建立這個對象的內存空間,然後將地址賦值給 `obj` ,這個很關鍵,反復讀三遍。\r\n\r\n2.當這個變量作為參數傳給一個函數\r\n\r\n`foo(obj);`\r\n\r\n正如上面所說,這個時候傳進去的,是一個對象的地址。\r\n\r\n所以,如果我們改變 `o.name`,實際上是改變 `obj.name`,\r\n\r\n於是最後打印出來的是 `{ name: \'Jack\' }`。\r\n\r\n**相比之下**\r\n\r\n在 `foo2` 里,我們直接 `o = { name: \'Jack\' }` 操作,參考第一條解釋,我們是給“Jack”建立了新的內存空間,然後把地址賦值給 `o`, 那這個時候`o`跟`obj`的關聯的斷開了,\r\n\r\n於是,`obj`還是原來的樣子 `{ name: \'Tom\' }`',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(307,'gitlab-ci 坑后感与指北','307',1514636100,1514642654,'<!--markdown-->>本文的目的:\r\n>\r\n> 最主要是备忘, 其次是分享\r\n> \r\n> 疗效:\r\n> \r\n> 并不能让你一下子掌握CI/CD, 这只是一个比较完整的解决方案,其他基础知识,自行补充.\r\n\r\n\r\n----\r\n#### 基调\r\n\r\n>首先,这不是屠龙刀,不要奢望一篇文章可以走遍天下.这里只是提供一个具体的落地方案, 一个具体的技术选型.\r\n\r\n\r\n\r\n----\r\n#### 阶段1: 代码仓库\r\n\r\n关于 **代码仓库**, 本文选取的方案是 `gitlab`\r\n\r\n`gitlab`的搭建:\r\n\r\n以目前的情况来说, 推荐使用`docker`来搭建你的系统, 不然你会陷入各种膜明其妙的问题.\r\n> docker的知识, 请自行补充一下,篇幅有限不能展开细说.\r\n\r\n在这里我推荐一个:\r\n\r\n`https://hub.docker.com/r/sameersbn/gitlab/`\r\n\r\n打开以后直接搜索`Quick Start`, 按照`docker-compose`的方式启动你的`gitlab`. \r\n\r\n\r\n> 不要对英文心存恐惧 ---- 孔子\r\n\r\n下载好 `docker-compose.yml`之后不要急着启动, 需要修改几个参数:\r\n>需要学习一点点yml的知识, 大约5分钟, 自行google\r\n\r\n- `GITLAB_SECRETS_DB_KEY_BASE`, \r\n- `GITLAB_SECRETS_SECRET_KEY_BASE`, \r\n- `GITLAB_SECRETS_OTP_KEY_BASE`\r\n\r\n上面三个是`gitlab`用于加密时用的key, 随便给个长度64的字符串, 这块不做 深究.\r\n\r\n- `GITLAB_ROOT_EMAIL`\r\n- `GITLAB_ROOT_PASSWORD`\r\n\r\n上面两个就是初始化时管理员账号的`账号密码`, 按自己的需要填写\r\n\r\n- `GITLAB_HOST`\r\n\r\n这是 **gitlab** 内部使用的地址, 这关系到你gitlab页面上的项目地址,没设置的话, 到时候显示的是`127.0.0.1`, 这个鬼才能`clone`下来.\r\n> 这个 host 一旦设置, 初始化完就改不了了, 所以一定要在第一次启动之前 就设置好.\r\n> \r\n\r\n##### 启动\r\n\r\n`docker-compose up`\r\n\r\n一系列的初始化信息以后, 你就能访问你的gitlab了.\r\n\r\n默认是 `http://{你的IP}:10080`\r\n\r\n```\r\n其他关于gitlab的使用技巧, 就不深入了.\r\n能关注这篇文章的都不是萌新了,这些内容自己补充吧.\r\n```\r\n\r\n----\r\n#### 阶段2: 提交触发\r\n\r\n接上文.\r\n\r\n`gitlab-ci`在最新版的`gitlab`已经是内置的了, 只要项目里有`.gitlab-ci.yml`,同时有对应的`gitlab-runner`, 就能实现`CI`, 相比之下不需要太多的配置.\r\n\r\n>名词解释:\r\n>\r\n> .gitlab-ci.yml:\r\n> \r\n> 这是gitlab-ci使用的任务描述文件, 里面主要是定义CI的过程需要执行哪些行为, 简单说就是, 要进行哪几个步骤, 每个步骤是哪些命令.\r\n> \r\n> gitlab-runner:\r\n> \r\n> 另一个程序, 也可以用docker启动, 就是负责执行 CI 任务的机器人, runner这块后面会展开讲.\r\n\r\n----\r\n**启动并注册`gitlab-runner`**\r\n\r\n我们还是使用`docker`来启动,这是一个大方向\r\n\r\n docker run -d --name gitlab-runner --restart always \\\r\n\r\n -v /srv/gitlab-runner/config:/etc/gitlab-runner \\\r\n \r\n -v /var/run/docker.sock:/var/run/docker.sock \\\r\n \r\n gitlab/gitlab-runner:latest\r\n\r\n\r\n\r\n> 想深入了解的话, 请看 \r\n> \r\n> https://docs.gitlab.com/runner/install/docker.html\r\n\r\n**敲黑板!!**\r\n\r\n在这里, 我们将宿主机的`docker.sock`映射进去,让`runner`可以跟宿主用同一个`daemon`, (意味着你进去runner内部执行`docker images`是可以看到外面的镜像列表的), 这样做是埋下一个**伏笔**, 以便后面阶段使用`dind`(docker in docker)时, 获得更好的体验.\r\n\r\n\r\n----\r\n\r\n**继续**\r\n\r\n好了, 这个时候你启动了一个`runner`, 你要告诉它应该到哪里去\"服役\",\r\n\r\n这一步叫做: **注册**\r\n\r\n> 注册runner的方式请看 \r\n> \r\n> https://docs.gitlab.com/runner/register/index.html#docker\r\n\r\n不过, 还是请你使用以下命令来注册:\r\n\r\n\r\n\r\n docker exec -it gitlab-runner gitlab-runner register \\\r\n \r\n --docker-volumes /var/run/docker.sock:/var/run/docker.sock \\\r\n \r\n --docker-privileged\r\n\r\n\r\n这里使用了两个参数, 都是为了 **docker in docker** 能得到更好的体验而服务的.\r\n\r\n输入以上命令后, 根据提示填写信息, 其中:\r\n\r\n- host,token 这些, 请打开你刚装好的gitlab, 进入 `Admin area`-`Runners `,然后照着填写就是了\r\n- 特别注意期间会让你选一个`executor `类型, 个人推荐最好的方式是`docker `, 至于`shell`这种方式, 玩玩可以,实际使用时副作用太多.\r\n- 更多参数的细节, 自行研究.\r\n\r\n完成以上步骤之后, 你在`gitlab` - `Admin area`-`Runners `页面就能看到注册好的`runner`了, 当然你现在还是感觉不到它的作用.\r\n\r\n\r\n 这个环节内容比较多, 操作比较多, 走到这里建议休息一下喝杯茶.\r\n\r\n\r\n\r\n----\r\n#### 阶段3: Runner Job\r\n\r\n这个阶段, 是指代码提交以后, `gitlab-runner`会自动读取项目的`.gitlab-ci.yml`, 运行里面定义的每个`Job`.\r\n\r\n这里给出一个极简的`.gitlab-ci.yml`例子,\r\n\r\n它做的就是, 在提交代码以后, 自动的**测试**, 自动的**构建**, 自动的**发布** :\r\n\r\n\r\n\r\n stages:\r\n - test\r\n - build\r\n - deploy\r\n \r\n job_01:\r\n stage: test\r\n image: dev_tool/node_builder:1.0.0\r\n script: \r\n - npm install --registry=https://registry.npm.taobao.org\r\n - node server.js &\r\n - node test_api.js\r\n \r\n job_02:\r\n stage: build\r\n image: gitlab/dind\r\n script:\r\n - docker build -t ci-demo:latest .\r\n \r\n job_03:\r\n stage: deploy\r\n image: dev_tool/rancher-cli:latest\r\n script:\r\n - rancher-tool init\r\n - rancher up -d --pull --force-upgrade --confirm-upgrade\r\n\r\n\r\n一目了然, 上面的第一个定义: `stages` 数组,\r\n\r\n意思是这个项目的`CI/CD`过程要执行三个步骤(`stage`),\r\n\r\n分别是`test测试`-`build编译`-`deploy发布`\r\n\r\n\r\n然后下面的三个`job_*`,名字是随意的, 重点是里面的`stage`属性,\r\n\r\n告诉`gitlab-ci`这个任务是在哪个`stage`执行的,\r\n\r\n一个`stage`你可以写很多个`job`\r\n\r\n**敲黑板!!!** \r\n\r\n需要注意的是, 我们之前选择了`docker executor`, `job`里面就要声明`image`属性,指定这个`Job`的`scripts`要在哪个`image`里面运行.\r\n\r\n**重点说明!! 再次大力敲黑板!!**\r\n\r\n这里第二步使用了`gitlab/dind` , 仔细看`script`, 这是在一个容器里面去构建一个镜像, 为了**整体体验**与**构建效率**着想, 我们之前注册`runner`的时候,将宿主机的`docker.sock`映射进去是十分必要的!!\r\n(重新翻上去看吧)\r\n\r\n\r\n\r\n**看到这里, 聪明的朋友已经发现了,**\r\n\r\n我们需要自己**打造**一批用于运行`Job`的基础镜像, 这些镜像里要预先安装好我们需要的依赖环境.\r\n\r\n举个栗子:\r\n\r\n你要在`build`这一步做`webpack`打包的话, 你要准备好一个内部安装好`webpack`的镜像(相关的`node`,`npm`之类就更不用说了)\r\n\r\n**听起来好麻烦?**\r\n\r\n也不是, 这是个 **功在当代,利在千秋** 的行为, 前期打造好基础镜像, 后面的项目就可以很容易写`CI Job`了.\r\n\r\n\r\n>更多 gitlab-ci.yml 的高级写法,还是建议看官方文档\r\n> https://docs.gitlab.com/ee/ci/yaml/README.html\r\n\r\n\r\n----\r\n#### 阶段4: 坐享其成 && 总结\r\n\r\n如果按照上面的步骤把这个系统搭建起来以后, 你应该已经能够感受到`gitlab-ci`带来的好处了.\r\n\r\n现在你只管提交代码, 就能快速看到新功能集成到相应的环境了.\r\n\r\n此后, 你只要写好每一步的`Job` 就可以了.\r\n\r\n尤其是**测试**这个环节.\r\n\r\n尤其是**测试**这个环节. \r\n\r\n尤其是**测试**这个环节.\r\n\r\n\r\n----\r\n### 后记\r\n\r\n- `gitlab` 真的很吃资源, 虚拟机玩够呛, 团队用的话, 建议装一台PC来搭建.\r\n- `基础镜像`别偷懒, 多打磨,让你的`scripts`可以更简洁\r\n- 更进一步的话, 自己开发一系列的命令行工具, 让你的`scripts`更强大. \r\n- 有事找我, 包教会.\r\n\r\n\r\n\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(305,'记一次结构化数据的经历','305',1485174420,1485176123,'<!--markdown-->#### 0.背景\r\n故事的背景,是源于要为第三方提供一套接口,而这套接口又是依赖于其他内部数据API。\r\n\r\n这看起来好像有点平常,不过事情通常没有想象中那么顺利。\r\n\r\n这问题在于,内部的API接口,正在处于一个动荡的年代,结构说变就变。有时候可能只是属性名变了,有时候甚至整块数据都不见了。\r\n\r\n而对于一套给第三方用的接口,这是致命的。我们需要保持数据模型的绝对稳定性。\r\n\r\n![](http://lanhao.name/img/upload/fake_api.png)\r\n\r\n#### 1.有哪些需要做的?\r\n\r\n从内部API拿到数据,剔除部分敏感信息,调整一下属性名,简化一下层次结构,这就是我们这套接口需要做的东西。\r\n\r\n\r\n以上的事情,都可以直接在代码里做的,反正简单`unset`一下,`array_*`一下,又不会太累,只要对照结构写就行。\r\n\r\n**但是开发者小蓝不会这么做!**\r\n\r\n这么做有以下不爽的地方:\r\n\r\n- 底层API每次变动,都需要跟进编码,编码意味着可能出BUG\r\n- 对于要产出的结构,没有一个明确的描述,只能靠代码\r\n- 为了解决第二个问题,需要专门维护这个文档,告诉你产出是怎样的,时间长了,很容易“文(档)不对(代)码”\r\n\r\n#### 2.应该怎么做\r\n\r\n针对以上几个问题的思考,我希望能实现以下的指标:\r\n\r\n- 最大限度地不受底层API的影响,即使底层有迭代,这边接口的输出结构稳定\r\n- 依赖一些`Schema`文件来描述底层数据与输出数据之间的转化关系,以及直接能表达出输出数据的结构\r\n- 有条件的情况下,还能根据`Schema`直接生产数据文档,保证文档与执行结果的统一性\r\n\r\n**综上所述,我需要制定一个描述`Schema`的规范,以及编写一个数据转换的方法**\r\n\r\n#### 3.实际操作\r\n\r\n我们先来放出一个源数据的例子\r\n\r\n $source = [\r\n \'arr\' => [\r\n [\r\n \'a\' => 1,\r\n \'secret\'=>\'hey\'\r\n ],\r\n [\r\n \'a\' => 4,\r\n \'secret\'=>\'jude\'\r\n ]\r\n ],\r\n \'hello\' => \'!\'\r\n ];\r\n\r\n\r\n首先是`Schema`部分,为了简单易用,目前直接使用编程语言内部的数据类型来描述。\r\n\r\n $schema = [\r\n \'arr=array\' => [\r\n [\r\n \'a=c\' => \'\'\r\n ]\r\n ]\r\n ];\r\n \r\n 这个`Schema`的含义就是:\r\n \r\n - 首先`arr`这样的描述不清楚,要重命名为`array`\r\n - 其次,`array`是个数组,里面的元素的模型只展示一个`a`属性,并且重命名为`c`\r\n - `hello`这个属性,直接干掉\r\n\r\n 然后输出的结果就是:\r\n \r\n {\r\n \"array\" : [\r\n {\r\n \'a\' : 1\r\n },\r\n {\r\n \'a\' : 4\r\n }\r\n ]\r\n }\r\n \r\n当然,`Schema`规则肯定不止这两条,这里只挑比较直接的说明一下。\r\n\r\n同样的,规则可以慢慢添加,重要的是,整个体系的依托,要建立起来。\r\n\r\n**接下来就差一个转换函数了**\r\n\r\n代码就不贴了,无非就是根据`Schema`来读取`Source`的数据,\r\n\r\n遇到数组,就让`Source`循环起来,\r\n\r\n遇到对象,就让`Source`和`Schema`递归进去,\r\n\r\n对,递归是重点。\r\n\r\n写这个函数的过程就是,慢慢调bug,抓头发,拍大腿的过程,反正就是越来越健壮就是了。\r\n\r\n#### 4.立竿见影的好处\r\n\r\n转换函数初步可用后,尝试着编写一个数据接口,包括编写`Schema`的时间,10分钟不到就出来了,还可靠。(按照对数据手写的话,估计半小时以上)\r\n\r\n而且写`Schema`的时候,可用将大脑切换到**数据模式**,一门心思地想数据,这样出错的可能也低许多。\r\n\r\n到运行稳定后甚至可以让其他人员来维护`Schema`,我们专心做其他技术细节。\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(304,'总结一些最近写Command Line Tool 的一些心得','304',1484897520,1512093781,'<!--markdown-->> 总结一些最近写Command Line Tool 的一些心得\r\n> \r\n\r\n## yargs\r\n\r\n npm install yargs --save\r\n\r\n`yargs`是优雅地接受命令行输入参数的模块,功能非常强大且易用,免去了很多重复的工作,一段代码足以证明:\r\n\r\n \r\n const argv = require(\'yargs\').argv; \r\n \r\n // argv 会自动接受所有输入参数 ,比如 demo_command -a hello\r\n \r\n console.log(argv.a); \r\n //hello\r\n \r\n当然可以对 `a` 做更多的配置 \r\n\r\n const yargs = require(\'yargs\');\r\n \r\n let argv = yargs.\r\n options(\'a\', {\r\n alias: \'api\',\r\n default: \'all\',\r\n }).argv;\r\n //这样可以给 argv.a设置一个默认值,同时有一个别名,如:demo --api hello\r\n \r\n更多的配置方式看[github](https://github.com/yargs/yargs)\r\n\r\n***\r\n\r\n## colors\r\n\r\n npm install colors --save\r\n\r\n`colors`是用来控制命令行输出文本颜色的, 还有更多功能如 `背景色`、`字体特效` 等我用得比较少,需要学全的请看[github](https://github.com/Marak/colors.js)。\r\n\r\n //用起来也是特别简单,\r\n const colors = require(\'colors\');\r\n \r\n //输出绿色的hello , 黄色的 world\r\n console.log(colors.green(\'hello \') + colors.yellow(\'world\'));\r\n \r\n更多预设颜色:black、red、green、yellow、blue、magenta、cyan、white、gray、grey\r\n\r\n主要是用于命令行输出提示信息,如红色的`error message`\r\n\r\n***\r\n\r\n## readline-sync\r\n\r\n npm install readline-sync --save\r\n \r\n`readline-sync`是同步获取用户输入的模块,主要用于带交互的基本输入。\r\n\r\n常见的有询问用户是否同意 ,同意输入`yes`, 或者需要用户填写什么信息之类。\r\n\r\n const readline = require(\'readline-sync\');\r\n\r\n let name = readline.question(\'What is your name? \', {defaultInput: \'Tom\'});\r\n \r\n console.log(\'Oh! I got it! You are \'+name);\r\n \r\n输出:\r\n\r\n $ node test.js \r\n What is your name? Gay \r\n Oh! I got it! You are Gay\r\n \r\n`readline-sync`的功能远远不止这样,还有很多交互方式,详情看[github](https://github.com/anseki/readline-sync)\r\n\r\n***\r\n\r\n## 关于目录的一些问题\r\n#### HOME\r\n`HOME`目录在Command Line 中也比较常用,可以让你生成一些本地文件,或者配置文件。\r\n`Linux` 和 `OSX`中,可以通过环境变量来获取。\r\n \r\n process.env[\'HOME\'];\r\n // 当前用户的目录\r\n\r\n而`windows`的话,我就没研究了。\r\n\r\n#### 命令所在的源码目录\r\n\r\n __dirname\r\n \r\n 当前执行的脚本的目录,不管你在哪个目录下调用,这个返回的都是源码所在目录\r\n \r\n这个指的是你当前命令的执行文件源码的目录(或理解为 `安装目录`)。\r\n\r\n它的作用是,你可能需要从你开发的命令的源码里加载一些文件,或者模板。\r\n\r\n比如 一些框架的脚手架 ,需要生产代码 ,自然就是从脚手架的目录里copy一份模板。\r\n\r\n#### 当前目录\r\n\r\n process.cwd()\r\n\r\n这个是指你输入命令的当前目录。\r\n\r\n**要活用以上两个目录,在写 Command Line Tool 的时候会经常用到。**\r\n\r\n### 注意 EOL 的坑\r\n\r\n require(\'os\').EOL\r\n\r\n这是一个很方便的功能,它会抹平操作系统的差异性,返回一个换行符。\r\n在你打印信息的时候十分常用。\r\n\r\n**不过注意有一个坑**\r\n\r\n如果你需要生产一些文本文件,那你需要特别注意里面用的换行符。\r\n\r\n比如我在`linux`下生成的配置文件,弄到 `windows`下就解释不出来了。\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(303,'js中的内部属性与delete操作符','303',1481620980,1481627548,'<!--markdown-->在讲解 `configurable` 之前,先来看一道面试题:\r\n\r\n```\r\na = 1;\r\nconsole.log( window.a ); // 1\r\nconsole.log( delete window.a ); // true\r\nconsole.log( window.a ); // undefined\r\n\r\nvar b = 2;\r\nconsole.log( window.b ); // 2\r\nconsole.log( delete window.b ); // false\r\nconsole.log( window.b ); // 2\r\n```\r\n\r\n从上面的这道题可以看出两个的区别:在没有使用var声明变量时,使用delete关键词是可以进行删除的,再次获取时值就是undefined了;在使用var声明的变量,使用delete是不能删除的,再获取时值依然是2。\r\n\r\n## 1. delete 操作符\r\n\r\ndelete 操作符用来删除一个对象的属性。在严格模式中,如果属性是一个不可配置(non-configurable)属性,删除时会抛出异常,非严格模式下返回 false。其他情况都返回 true。如上面的例子中,delete无法删除变量a时,则返回false;而delete能成功删除变量b,则返回true。\r\n\r\n+ delete 操作符与直接释放内存(只能通过解除引用来间接释放)没有关系。可查看[内存管理](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management)页面。\r\n\r\n+ 你可以使用 delete 操作符来删除一个隐式声明的全局变量,也就是没有使用 var 定义的全局变量.全局变量其实是global对象(window)的属性.\r\n\r\n+ 如果 delete 操作符删除成功,则被删除的属性将从所属的对象上彻底消失。然后,如果该对象的原型链上有一个同名属性,则该对象会从原型链上继承该同名属性。\r\n\r\n```\r\nfunction Person() {\r\n this.name = \'nodejh\';\r\n}\r\nPerson.prototype.name = \'小蒋\';\r\nvar student = new Person();\r\nconsole.log(student.name); // nodejh\r\nconsole.log(delete student.name); // true, 删除成功\r\nconsole.log(student.name); // 小蒋\r\nconsole.log(delete student.name); // true, 但无法删除原型中的 name 属性\r\nconsole.log(student.name); // 小蒋\r\nconsole.log(delete Person.prototype.name); // true, 删除成功\r\nconsole.log(student.name); // undefined\r\n```\r\n\r\n## 2. JS 的内部属性\r\n\r\nECMAScript中有两种属性:数据属性和访问器属性。\r\n\r\n### 2.1 数据属性\r\n\r\n数据属性指包含一个数据值的位置,可在该位置读取或写入值,该属性有4个供述其行为的特性:\r\n\r\n[[configurable]]:表示能否使用delete操作符删除从而重新定义,或能否修改为访问器属性。默认为true。\r\n[[enumerable]]:表示是否可通过for-in循环返回属性。默认true。\r\n[[writable]]:表示是否可修改属性的值。默认true。\r\n[[value]]:包含该属性的数据值。读取/写入都是该值。默认为undefined;如上面实例对象 Person 中定义了 name 属性,其值为 ’nodejh\', 对该值的修改都在这个位置。\r\n\r\n要修改对象属性的默认特征(默认都为 `true` ),可调用 `Object.defineProperty()` 方法,它接收三个参数:属性所在对象,属性名和一个描述符对象(必须是:`configurable`、`enumerable `、`writable ` 和 `value `,可设置一个或多个值)。\r\n\r\n如:\r\n\r\n```\r\nvar person = { name: \'nodejh\' };\r\nObject.getOwnPropertyDescriptor(person, \'name’); \r\n// { configurable:true, \r\n// enumerable:true, \r\n// value: \"nodejh\", \r\n// writable: true }\r\n\r\nObject.defineProperty(person, \'name\', {\r\n configurable: false,\r\n enumerable: false,\r\n writable: false,\r\n value: \'nodejh\',\r\n});\r\nObject.getOwnPropertyDescriptor(person, \'name’);\r\n// { configurable:false, \r\n// enumerable:true, \r\n// value: \"nodejh\", \r\n// writable: false}\r\n\r\nconsole.log(delete person.name); // false \r\nperson.name = \'nodejh2\';\r\nconsole.log(person.name); // nodejh \r\n```\r\n\r\n值得注意的是,一旦 `configurable` 和 `writable` 一旦被设置为 `false`,就不能再通过 `Object. defineProperty` 将其设置为 `true`(执行会报错:`Uncaught TypeError: Cannot redefine property:`)。 \r\n\r\n\r\n### 2.2 访问器属性\r\n\r\n它主要包括一对 `getter` 和 `setter` 函数,在读取访问器属性时,会调用 `getter` 返回有效值;写入访问器属性时,调用 `setter` ,写入新值;该属性有以下4个特征:\r\n\r\n+ [[configurable]]:是否可通过delete操作符删除重新定义属性;\r\n+ [[numberable]]:是否可通过for-in循环查找该属性;\r\n+ [[get]]:读取属性时自动调用,默认:undefined;\r\n+ [[set]]:写入属性时自动调用,默认:undefined。\r\n\r\n访问器属性不能直接定义,必须使用defineProperty()来定义,如下:\r\n\r\n```\r\nvar person = {\r\n _age: 18\r\n};\r\nObject.defineProperty(person, \'isAdult\', {\r\n Configurable : false,\r\n get: function () {\r\n if (this._age >= 18) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n});\r\nconsole.log( person.isAdult ); // true\r\nObject.getOwnPropertyDescriptor(person, \'isAdult’);\r\n// { configurable: false, \r\n// enumerable: false,\r\n// get: (),\r\n// set: undefined }\r\n```\r\n\r\n\r\n\r\n还有一点需要额外注意一下,`Object.defineProperty()` 方法设置属性时,不能同时声明访问器属性(`set` 和 `get`)和数据属性(`writable` 或者 `value` )。意思就是,某个属性设置了 `writable` 或者 `value` 属性,那么这个属性就不能声明 `get` 和 `set` 了,反之亦然。\r\n\r\n如若像下面的方式进行定义,访问器属性和数据属性同时存在:\r\n\r\n```\r\nvar o = {};\r\nObject.defineProperty(o, \'name\', {\r\n value: \'wenzi\',\r\n set: function(name) {\r\n myName = name;\r\n },\r\n get: function() {\r\n return myName;\r\n }\r\n});\r\n\r\n// Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, \r\n```\r\n\r\n上面的代码看起来貌似是没有什么问题,但是真正执行时会报错。\r\n\r\n+ 对于数据属性,可以取得:configurable,enumberable,writable和value;\r\n+ 对于访问器属性,可以取得:configurable,enumberable,get和set。\r\n\r\n由此我们可知:一个变量或属性是否可以被删除,是由其内部属性 `configurable` 进行控制的,若 `configurable` 为 `true`,则该变量或属性可以被删除,否则不能被删除。\r\n\r\n\r\n## 3. 总结\r\n\r\n回到最初的面试题,其中 a 是隐式声明的全局变量,也就是没有使用 var 定义的全局变量。全局变量其实是 global 对象 (window) 的属性。\r\n\r\n```\r\na = 1;\r\nconsole.log( window.a ); // 1\r\nObject.getOwnPropertyDescriptor(window, \'a’);\r\n// { configurable:true, \r\n// enumerable:true, \r\n// value: 1, \r\n// writable: true }\r\n\r\nconsole.log( delete window.a ); // true\r\nconsole.log( window.a ); // undefined\r\n\r\n\r\nvar b = 2;\r\nconsole.log( window.b ); // 2\r\nObject.getOwnPropertyDescriptor(window, \'b\');\r\n// { configurable:false, \r\n// enumerable:true, \r\n// value: 1, \r\n// writable: true }\r\nconsole.log( delete window.b ); // false\r\nconsole.log( window.b ); // 2\r\n```\r\n\r\n— \r\n\r\n[MDN: delete](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/delete)\r\n[js中的内部属性与delete操作符](http://www.xiabingbao.com/javascript/2015/08/03/javascript-delete-configurable/)\r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(302,'致杨先生,关于《javascript到底是如何运行的》','302',1475820357,1475820357,'<!--markdown-->### 致杨先生:\r\n#### 前言\r\n>引用 [javascript到底是如何运行的?--杨先生](http://xiaomingplus.com/full-stack/how-to-run-for-javascript/)\r\n\r\n当我们讨论`javascript`运行机制这种问题,有别于语法,语法我们有标准可以参考,对于运行机制,我们应该明确是什么引擎。\r\n\r\n在这我以V8为例,猜想杨先生大概也是V8,从node源码的角度,补充一二。\r\n行文没有顺序,只是针对一些观点的补充。\r\n\r\n\r\n#### 正文\r\n***\r\n> 在js中,有多种类型的观察者,包括文件I/O观察者,网络请求观察者等(其实这里的观察者一般来讲就是宿主环境提供的API)\r\n\r\n观察者其实不是什么API,而是一种结构。\r\n\r\n举个例子,如果是网络IO观察者,它的结构是这样的:\r\n\r\n {\r\n fd,\r\n callback\r\n }\r\n这个是`uv__io_s `类型的对象,而我们常说的`事件循环`里的一个个单元,就是这样的对象。\r\n\r\n而文件IO观察者,想必也是差不多,待我进一步研读源码再来求证。\r\n\r\n\r\n\r\n***\r\n>一个JavaScript运行时包含一个待处理的任务队列,该队列是先进先出的,队列里的每一个任务都与一个函数相关联(一般是调用API时指定的回调函数)。当[执行栈]为空时,[执行栈]会从[任务队列]中取出队列里最前面的一个任务进行处理。\r\n\r\n任务队列一直一个值得我们深刻研究的话题,在杨先生的描述里,js有一个“执行栈”,一个任务队列。执行栈 先执行一次,然后从队列里取出一个,如此往复,直到结束。\r\n\r\n某个程度上可以这么描述,不过对于杨先生的水平,我认为是要有更高的要求的,这里面,有很多不太严谨的地方。\r\n\r\n我将从几个问题来展开:\r\n\r\n**1.什么是任务队列?**\r\n \r\n任务队列是 `default_loop_struct`,来自结构体定义 `uv_loop_s`。正如前面所说,里面存放的是观察者。\r\n \r\n**2.什么是 `Tick`**\r\n\r\n我们知道有一个 `process.nextTick` 方法,但是 `Tick` 到底是什么,要从任务队列的运行机制去了解。\r\n \r\n`default_loop_struct` 里面的观察者是以链表的结构存储的。而 `Tick` 里是以 数组 的方式存储的。\r\n \r\n杨先生之前的描述只是 执行栈 与 `Tick` 之间的交互,实际上,每次取出一个任务,都是从`Tick`里取的。而`Tick`其实是 `default_loop_struct`的全量镜像。\r\n>注:是不是全量,我还需要继续考证,在此仅供参考。\r\n\r\n所以真正的关系链是:\r\n\r\n main() <--- Tick <--- default_loop_struct\r\n\r\n在这里顺便说一下,`process.nextTick` 会让一个callback加到`Tick`里,而其他的 timer 之类(setTimeout,setImmediate),只会加到 `default_loop_struct ` 。此中区别,还需细细品味。\r\n\r\n**3.任务队列的时机**\r\n\r\n在杨先生文中的那个图,我不能说它是错的,但是并没有表达出一个关键信息,就是执行轨迹。\r\n\r\n真实的情况是 `main()`执行完所有JS代码后,进入`uv_run()`,再去看看 `default_loop_struct `有没有观察者,没有则程序结束,如果有,则进入`epoll_wait()`。\r\n\r\n以上不理解没关系,可以日后细细研究,在此我只想表达一点,JS不会一边执行代码一边跟任务队列做互动。不信你可以试试,连续一堆 `setTimeout `,然后直接`process.exit()`,那么还没来得及进入`uv_run()`,程序就结束了,这些任务自然一个都执行不了。\r\n\r\n#### 其他\r\n\r\n以上还有一些用语不太严谨,不过为了行文连贯,做出一定的牺牲,需要考究准确性的地方,我们还需要私下讨论为佳。\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(300,'PHP设计模式(一)工厂模式','300',1470812940,1470813104,'<!--markdown-->PHP设计模式(一)工厂模式\r\n====\r\n\r\n> 最近会简单的自我总结一些php当中的一些设计模式,当然个人才疏学浅,可能些不对的地方望各位看官见谅指正\r\n\r\n## 是什么?\r\n\r\n工厂模式是一种创建型的模式,简单的说就是用来创建对象的\r\n\r\n## 为什么?\r\n\r\n我们一般最普通的创建对象的方式是这样`new classname()`,但是换位想一下,这样创建对象的时候我们必须要知道类名,但是我们考虑一下下面几个情况:\r\n1. 如果我们不知道类名呢?\r\n2. 如果我在很多个文件当中都用到了这个类创建对象,new了很多次,但是在重构或者其他什么情况的时候我要修改类名怎么办?当然有人会说怎么会修改类名,这是有可能会遇到的,那说一一下常见一点的,如果我给这个类的构造方法加了,或者是少了一个参数?那岂不是得一个个的去改\r\n3. 我现在有一个抽象的基类,由它派生了很多子类,我不知道后面还会不会添加其他的子类\r\n\r\n上面几个都是可能会遇到的一些情况之一,使用工厂模式可以比较好的解决上面的问题\r\n\r\n## 怎么办?\r\n\r\n### 简单工厂模式\r\n\r\n```php\r\n<?php\r\n class Food{\r\n //todo\r\n }\r\n\r\n class FoodFactory{\r\n\r\n static public function create(){\r\n return new food();\r\n }\r\n }\r\n\r\n $food= FoodFactory::create();\r\n```\r\n上面实现简单工厂模式,`FoodFactory`这个类很简单只有一个创建方法,返回food类的实例,当然也可以发现这个方法很笨拙,只能实现一个对象的创建,感觉比直接new一个对象好不了多少,只是方便改动而已。不过这是工厂模式最基本的思路,后面再怎么改进其实都是按照这个思路来的\r\n\r\n### 工厂方法模式\r\n\r\n```php\r\nclass FoodFactory{\r\n\r\n static public function create($classname){\r\n \r\n if(include_once \'class/\' . $classname . \'.php\'){\r\n return new $classname;\r\n } else {\r\n throw new Exception(\'Driver not found\');\r\n }\r\n\r\n }\r\n }\r\n```\r\n通过上面的方法我们发现我们已经可以不局限于,创建一个固定的类的对象了\r\n**但是要注意的是:**\r\n*如果我们使用了命名空间的话,在动态实例化类的时候必须包含完整的命名空间,提前use或者处于统一命名空间都是没有用的*\r\n\r\n```php\r\n<?php\r\n namespace Mohuishou\\Lib;\r\n\r\n class FoodFactory{\r\n\r\n static public function create($classname){\r\n \r\n if(include_once \'class/\' . $classname . \'.php\'){\r\n $classname=\"Mohuishou\\Lib\\\\\".$classname;\r\n return new $classname;\r\n } else {\r\n throw new Exception(\'Driver not found\');\r\n }\r\n\r\n }\r\n }\r\n```\r\n如果我们还想传入参数呢?\r\n```php\r\n<?php\r\n namespace Mohuishou\\Lib;\r\n\r\n class FoodFactory{\r\n\r\n static public function create($classname,$params){\r\n \r\n if(include_once \'class/\' . $classname . \'.php\'){\r\n $classname=\"Mohuishou\\Lib\\\\\".$classname;\r\n return new $classname($params);\r\n } else {\r\n throw new Exception(\'Driver not found\');\r\n }\r\n\r\n }\r\n }\r\n ```\r\n 如果我们不知道类名,不知道方法,怎么办?怎么实现一个一般的工厂模式?\r\n 这里可能需要用到反射的概念了,这篇就不过多赘述\r\n \r\n',0,30,NULL,'post','publish',NULL,0,'1','1','1',0),(298,'PHP pdo 事务,代码里的一个容易踩的坑','298',1470300483,1470300483,'<!--markdown-->PHP pdo 在支持事务的存储引擎(innoDB)下,可以使用以下代码实现事务\r\n\r\n $pdo->beginTransaction();\r\n\r\n try{\r\n $pdo->exec(\'insert into tt set s=11,t=99 \');\r\n $pdo->commit();\r\n // 注意!!\r\n }catch (Exception $e){\r\n var_dump($e);\r\n $pdo->rollback();\r\n }\r\n \r\n上面的逻辑,在数据库插入失败时,会执行`rollback`,本次事务结束。\r\n\r\n表面上看这段代码没有问题,\r\n\r\n但是,如果你在上面【注意】的地方,还有其他代码的话。比如:\r\n\r\n $pdo->beginTransaction();\r\n\r\n try{\r\n $pdo->exec(\'insert into tt set s=11,t=99 \');\r\n $pdo->commit();\r\n // 注意!!\r\n throw new Exception(\'boom\');\r\n }catch (Exception $e){\r\n var_dump($e);\r\n $pdo->rollback();\r\n }\r\n \r\n这样一来,数据库插入没有问题,顺利`commit` ,但是catch到了一个其他的异常,\r\n\r\n导致`rollback`也被执行了一次,这时候 `pdo` 会报一个错误\r\n\r\n Uncaught PDOException: There is no active transaction in ...\r\n\r\n这是因为 `beginTransaction` 会让这个事务状态为 `active`,\r\n\r\n而 `commit` 或 `rollback` 会让事务变成 `inactive` 。\r\n\r\n显而易见,当然不能执行了 `commit` 后又执行 `rollback` 了。\r\n\r\n\r\n### 所以, commit 应该写在 try 语句块的最后一行。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(299,'【PHP】比较 exit 和 die','299',1470378670,1470378670,'<!--markdown-->> 无意中在网上看到 `exit` 和 `die` 的区别,歪果仁一言不合就讨论开了,其中不乏一些有趣的结论。\r\n\r\n#### 官方:`exit` 和 `die` 是一样的\r\n\r\nPHP Manual for exit:\r\n\r\n Note: This language construct is equivalent to die().\r\nPHP Manual for die:\r\n\r\n This language construct is equivalent to exit().\r\n\r\n\r\nPHP官方明确指明这两个是一样的,并且有以下佐证:\r\n\r\n[List of Function Aliases (函数别名列表)](http://php.net/manual/en/aliases.php)\r\n,在这个列表里,`exit` 是主函数,`die`是别名,PHP官方不推荐用别名,因为这有可能会在将来的版本里被干掉。(可能性不大)\r\n\r\n另一个证据更充分,有人分析了 `parser token`, 两者解释出来都是 `T_EXIT`\r\n\r\n意思就是,php解释这两个的时候,对应的是同一个东西。\r\n\r\n\r\n#### 坊间,两者还是有一些区别的\r\n\r\n- 起源不一样\r\n \r\n php的诞生是参考了很多语言的, 可以参考 [这里](https://exploringdata.github.io/vis/programming-languages-influence-network/#PHP) 。\r\n \r\n php主要受 `Perl`, `C`, `Python`, `C++`, `C#`, `Tcl`, `Java`, `Smalltalk` 影响。\r\n \r\n 而 `exit`是来源于 `C`语言中的 exit(),`die`是来源于`Perl`中的 die 。\r\n \r\n- 角度刁钻,解释起来效率不一样\r\n\r\n 有一位歪果仁,没学过php,但是从脚本语言解释的角度分析了两者的区别。\r\n \r\n 大体意思就是,php被解释的时候, 一些函数、变量之类会被翻译成`TOKEN`,\r\n \r\n 如果在你的项目里 `d`开头的函数比较多,那`die`解释起来就慢,反之亦然。\r\n \r\n 我觉得这个也是有一定的道理的,至少在解释阶段确实是存在差异。\r\n\r\n- 从语义的角度看\r\n\r\n 也有的朋友从语义的角度分析, \r\n \r\n `die`是程序挂了,一般用于出错的场合:\r\n \r\n if( $data === false ) {\r\n die( \"Failure.\" ); // something wrong\r\n }\r\n \r\n `exit`表示程序退出,一般是正常退出\r\n \r\n // start\r\n // all thing done\r\n // and exit as normal\r\n exit(0);\r\n \r\n 这个观点是相当有建设性的,我一贯坚持代码首先是给人看的,\r\n \r\n 这样的区分使用是对代码可读性的很好实践。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(297,'一些笔记 , Elasticsearch','297',1469612040,1469612971,'<!--markdown-->- 开始\r\n\r\n安装\r\n \r\n 访问ES官方网站\r\n https://www.elastic.co/downloads/elasticsearch\r\n 获取最新版,当前本班2.1.1 。\r\n ES对运行环境唯一要求为JAVA 1.6以上,\r\n 同样推荐官方最新版。(www.java.com)\r\n \r\n配置\r\n \r\n ES的配置文件 ./config/elasticsearch.yml\r\n network.host: 0.0.0.0 #地址绑定\r\n \r\n index.number_of_shards: 10 #默认主分片个数\r\n index.number_of_replicas: 0 #默认从分片个数\r\n \r\n启动\r\n\r\n ES解压即用,\r\n ./bin/elasticsearch -d \r\n \r\n -d 参数表示在后台运行,注意ES不允许使用root用户运行,\r\n 所以你需要为ES专门分配用户,并且确保该用户对ES的数据\r\n 目录、日志目录具有写入权限。\r\n 默认数据目录在ES目录下的data\r\n\r\n- 运行时\r\n\r\nhead插件\r\n\r\n 安装方式参看\r\n ./bin/plugin install mobz/elasticsearch-head\r\n \r\n 访问地址:\r\n http://hostname:9200/_plugin/head\r\n \r\n head插件可以查看集群概况,删除、关闭Indices,\r\n 浏览数据,发送http请求操作数据等。\r\n 上线时注意修改ES配置不能让外部网络访问。\r\n \r\nkibana\r\n\r\n 下载地址(最新4.x变化比较大,推荐)\r\n https://www.elastic.co/downloads/kibana\r\n \r\n kibana也是解压即可用,直接运行即可\r\n nohup ./bin/kibana >log.txt &\r\n (由于没有 -d 参数,要用nohup保持运行)\r\n \r\nkibana-marvel\r\n\r\n marvel是kibana的一个插件,是一个动态监控ES运行状态的工具,\r\n 安装方式请看 \r\n https://www.elastic.co/downloads/marvel\r\n 访问地址: \r\n http://hostname:5601/app/marvel\r\n\r\n- 集群\r\n\r\n发现\r\n \r\n ES配置文件默认集群名字是elasticsearch,在同一个局域网中,\r\n 多个实例(不限主机)使用相同的集群名字,会自动发现并组成集群。\r\n 2.0版本后,使用 multicast 自动发现的用户,需要单独安装:\r\n bin/plugin install discovery-multicast\r\n 然后配置文件加上 \r\n discovery.zen.ping.multicast.enabled: true\r\n \r\n ES也支持指定IP列表的集群,但灵活性和自动化不如上一种方式,\r\n 所以在具备局域网组建条件的情况下推荐使用自动发现。\r\n\r\n主从\r\n \r\n 每个运行的ES实例,称为一个节点。\r\n 当集群中运行了两个节点时(可以是单台主机上的两个节点),我们就\r\n 实现了主从功能,后启动的节点会复制一份数据,意味着磁盘空间成倍增加。\r\n\r\n![](https://raw.githubusercontent.com/looly/elasticsearch-definitive-guide-cn/master/images/elas_0203.png)\r\n\r\n \r\n第三个节点\r\n\r\n 当有第三个节点介入时,ES集群会重新组织自己,重新分配数据分片。\r\n 数据分片(shard)是Indices存储的逻辑空间,ES以分片为单位转移数据,如图:\r\n \r\n![](https://raw.githubusercontent.com/looly/elasticsearch-definitive-guide-cn/master/images/elas_0204.png)\r\n \r\n 这样,每个节点上维护的分片减少,整个集群的吞吐量和容量都得到提升。\r\n \r\n***从节点会增加搜索速度,但是降低写入效率;\r\n而主节点能提高写入速度,轻微降低搜索速度,所以要权衡好数量***\r\n \r\n* RESTFUL 接口\r\n \r\n \r\n ES\r\n- 维护\r\n\r\n分片与节点\r\n \r\n 对于目前的应用场景,单机情况下,建议开启10个shard,0个从节点\r\n \r\n 索引方面,建议每天一个,kibana支持跨索引做局和图表,\r\n 如:log-20160105,log-20160106\r\n \r\n内存与磁盘\r\n \r\n 通过rest接口,可以删除指定的index,按时间创建index以后尤其方便删除:\r\n curl -x delete http://hostname:9200/log-20160105\r\n \r\n 建议创建计划任务,每天固定时间删除一个月前的index\r\n \r\n\r\n \r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(296,'php就不能认真一点对待数组?!','296',1467868413,1467868413,'<!--markdown-->> php 数组,对象混搭的现象由来已久,不过小心一点也就可以了,但是有些地方,真的是坑死你不偿命\r\n\r\n### 黑 is cheap ,show you my code \r\n\r\n $arr = [\r\n 0 => \'a\',\r\n 1 => \'b\',\r\n 2 => \'c\',\r\n ];\r\n echo json_encode($arr);\r\n \r\n // [\"a\",\"b\",\"c\"]\r\n\r\nOK\r\n\r\n没有任何问题,但是……\r\n\r\n $arr = [\r\n //0 => \'a\',\r\n 1 => \'b\',\r\n 2 => \'c\',\r\n ];\r\n echo json_encode($arr);\r\n \r\n // {\"1\":\"b\",\"2\":\"c\"}\r\n\r\n\r\n## WHAT THE FUCK!! \r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(295,'yield方式的异步代码什么原理?(刨根向)','295',1467257644,1467257644,'<!--markdown-->\r\n\r\n> 江湖上流传着一个说法,说是通过 yield 和 generator ,就是用同步的方式写出异步的代码。\r\n> \r\n> 真的是这样吗?\r\n> \r\n> 也许你可以从网上搜到很多相关教程,照着样例代码,你也能写出这样的代码。但是你是否真的已经明白,这背后到底发生了什么?\r\n\r\n### 第一集,他是谁?\r\n\r\n这就是一个 `generator`,\r\n\r\n var gen = function* (){\r\n return 1;\r\n }\r\n看上去像个函数,浑身有一种莫名其妙的的罪恶感,对了,他让我想起那恶心的指针。\r\n\r\n我们看看运行起来会怎么样?\r\n\r\n gen();\r\n // {}\r\n \r\n看来只是长得像,跟函数没啥关系呢。\r\n\r\n我想他还有其他不为人知的地方,比如,`next()`\r\n\r\n var a = gen();\r\n console.log( a.next() );\r\n \r\n // { value: 1, done: true } duang!!\r\n \r\n我明白了,要调用`next`才能让他执行起来。\r\n\r\n### 第二集,yield ?\r\n\r\n如果 `generator` 遇上 `yield` 会怎样?\r\n\r\n var gen = function* (){\r\n yield 2;\r\n return 1;\r\n }\r\n var a = gen();\r\n console.log( a.next() );\r\n // { value: 2, done: false }\r\n他并没有返回1,而是2 ,一个被 `yield`了的2 。\r\n\r\n那么这个`done`的值,应该就是告诉我还没执行完的意思吧。\r\n\r\n那我能不能多`next`几次?\r\n\r\n var a = gen();\r\n console.log( a.next() );\r\n // { value: 2, done: false }\r\n console.log( a.next() );\r\n // { value: 1, done: true }\r\n console.log( a.next() );\r\n // { value: undefined, done: true }\r\n\r\n果然,只要`done`没返回 `true` 就可以一直 `next`下去。(注:`false`也可以继续`next`,不过已经没有什么意义了 )\r\n\r\n**一个典型的迭代器呼之欲出 !**\r\n\r\n没错,`generstor`就是一个迭代器,暂时来说和异步编程没有任何关系\r\n \r\n var item = null;\r\n while( item = a.next() ){\r\n if(item.done === true){\r\n break;\r\n }\r\n // do anything with {item}\r\n console.log(item.value);\r\n }\r\n \r\n // 2 , 1\r\n \r\n\r\n### 第三集,Promise 和 CO\r\n\r\n`generator`的诞生就是为了成为一个伟大的迭代器,阴差阳错之下,被用来写异步代码。\r\n这得从他遇上 `promise` 说起。\r\n\r\n\r\n**`generator`,或者说 `yield`有一个很特别的能力——移花接木。**\r\n\r\n![](http://lanhao.name/img/upload/yield1.png)\r\n\r\n一个 `yield` 表达式包含很丰富的操作,一行代码包含了两个阶段逻辑\r\n\r\n- 执行最右边的操作 `2+3` ,把结果通过`value`带出去。(`next` 的返回值)\r\n- 再次调用`next`时,可以接受参数,将外面的值传进来,赋值给 `a`\r\n\r\n\r\n\r\n**君子无罪,怀璧其罪**\r\n\r\n这种特异功能被眼尖的程序员发现了,一个伟大的设想诞生了。\r\n\r\n- 先将异步操作用`promise`实现,通过`yield`带出去\r\n- 然后执行`then`函数,获取异步处理结果\r\n- 再次执行`next`,将异步结果传回 `generator`内部,赋值给`yield`左边的表达式\r\n\r\n![](http://lanhao.name/img/upload/yield2.png)\r\n\r\n**如此一来,这一行代码看起来就像同步代码一样!**\r\n\r\n我们看看成品代码:\r\n\r\n \r\n var gen = function* () {\r\n let content = yield httpGet(\'http://lanhao.name\');\r\n return content;\r\n };\r\n\r\n var myCo = (fn) => {\r\n let state = null;\r\n let g = fn();\r\n return (function next(data){\r\n state = g.next(data);\r\n if(state.done){\r\n return state.value;\r\n }else{\r\n return state.value.then( val => next(val) );\r\n }\r\n })();\r\n };\r\n\r\n\r\n var a = myCo(gen);\r\n\r\n a.then(val=>console.log(val));\r\n \r\n //{\"code\":200,\"data\":[],\"message\":\"\"}\r\n\r\n而且我们发现,不管`generator`逻辑如何,`Co`的写法都是一样的,不会重复编码。\r\n\r\n只要通过`Co`来执行`generator`,我们就能像同步代码一样写异步操作。\r\n\r\n**以上就是 yield方式的异步代码 原理解释**\r\n\r\n(未完)',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(294,'当我们说 Promise ,我们在说什么?(刨根向)','294',1467022980,1513778792,'<!--markdown-->当我要组织文章内容的时候,我感到十分的吃力。\r\n\r\n这是源于一个困惑:我们现在是否还需要探讨什么是`Promise `?\r\n\r\n我们很容易就能 “使用” `Promise `,已经有很多优秀的模块实现了不同标准的`Promise `。\r\n而随着ES6原生 `Promise ` 的落实,我们更容易写出 `Promise ` 风格的异步代码。\r\n\r\n // ES6 下的原生Promise\r\n var httpGet = (url) => {\r\n return new Promise( (resolved,rejected)=>{\r\n request.get(url,(err,res)=>{\r\n if(!err){\r\n resolved(res);\r\n }else{\r\n rejected(err);\r\n }\r\n });\r\n });\r\n }\r\n \r\n httpGet(\'http://abc.com\').then(...);\r\n \r\n但是,治学这东西,知其然,还要知其所以然。\r\n\r\n尤其是现在很多声音还存在对 `Promise ` 的曲解的情况下。\r\n\r\n### 那么,Promise到底是什么东西?\r\n\r\n\r\n有一种说法是用了`Promise `就不需要callback的写法了,实际上是不是这样,我们看一段代码\r\n \r\n \r\n func(arg ,(err,ret)=>{\r\n //pass\r\n });\r\n \r\n func(arg).then( (err,ret)=>{\r\n //pass\r\n });\r\n实际上只是callback写的位置不一样而已,并没有什么实际的改变。\r\n\r\n**是不是这样呢?我们层层深入地理解一下 Promise 到底是什么。**\r\n\r\n对于上面这个问题, `Promise ` 是不是只是把callback换个地方写呢?\r\n\r\n我从《深入浅出Nodejs》 4.3.2 中的一段话收到了启发\r\n> 上面的异步调用中,必须严谨地设置目标。那么是否有一种先执行异步调用,延迟传递处理的方式呢?\r\n\r\n说的就是传统的callback写法,必须在异步调用的时候,明确地声明回调处理的逻辑。\r\n\r\n httpGet(\'/api\',{\r\n success:onSuccess,\r\n error:onError\r\n });\r\n\r\n就是说,你必须明确指明了异步调用结束时的各种回调,然后才会执行异步操作\r\n\r\n (声明异步操作)---> (注册回调) ---> (执行异步操作)\r\n\r\n\r\n反过来看看 `Promise ` 是不是就不一样呢?先看一段代码\r\n\r\n var p = httpGet(\'/api\');\r\n \r\n p.then(onSuccess , onError);\r\n \r\n你猜到底在哪一步发起了http请求?\r\n\r\n正如你猜测的一样,在 `p` 初始化的时候,这个异步操作就执行了。\r\n所以对于`Promise `来说,流程是这样的\r\n\r\n (声明异步操作)---> (执行异步操作) ---> (注册回调)\r\n\r\n \r\n >原来真的存在一种方法,先执行异步调用,延迟传递处理的方式。这就是`Promise `与传统callback一个很显著的区别。\r\n \r\n \r\n \r\n \r\n### 状态机\r\n\r\n如果 `Promise ` 只是对callback在逻辑顺序及书写方式上面的一点改动的话,\r\n\r\n那你就小看它了。\r\n\r\n有没有想过,为什么 `Promise ` 能先执行异步操作,再指明回调逻辑呢?下面这段代码又会如何?\r\n\r\n var p = httpGet(\'/api\');\r\n \r\n // do something\r\n \r\n p.then(onSuccess , onError);\r\n \r\n // do something\r\n \r\n p.then(onSuccess , onError);\r\n\r\n请问,第二个`then`是否正常执行 ?\r\n\r\n#### Promise 下的状态\r\n\r\n `Promise ` 定义了其内部的几个状态\r\n\r\n- pending\r\n- resolved (fullfilled)\r\n- rejected \r\n\r\n`Promise ` 初始化后 内部状态为 `pending` ,然后开始执行异步操作,\r\n当异步操作完成,内部状态转换为 `resolved` 或 `rejected` (失败时)。\r\n\r\n一旦状态改变,就会被固化,不会再改变。\r\n\r\n所以就很好解释,一个状态已经确定的 `Promise ` ,无论你调动多少次`then`,它都会返回正确且唯一的结果,因为 `Promise `的结果,是完全依赖它自己的内部状态。\r\n\r\n#### 这个时候我们有必要说一下`then` 方法到底做了什么?\r\n\r\n不去深入探究的话,你大概会认为`then`只是注册了一系列回调函数。\r\n\r\n其实 `then` 除了注册回调函数,还会检查 `Promise ` 状态,只要不是`pending`状态,就回调用相应状态的回调。\r\n\r\n同样的,当状态改变的时候,也会检查对应状态是否有已经绑定的回调函数,再按照`Promise `的方式去执行回调。\r\n\r\n正因为这种机制,才能真正实现了`Promise `的异步操作与回调声明分离,并且通过维护状态变化,更好地控制异步操作结果中的不同情况。\r\n\r\n> 注:为了降低理解成本,本文的实现里一个状态默认只处理一个回调函数\r\n\r\n \r\n### 一字长蛇阵\r\n\r\n以上便是一个独立的 `Promise` 的运行机理,在这之上灵活运用才是`Promise`的终极玩法。\r\n\r\n那么我们经常听到的用 `Promise` 解决回调地狱,是怎么回事呢?看看最终代码:\r\n\r\n loadPic(\'/path/of/picture.jpg\')\r\n .then(...) //图片压缩\r\n .then(...) //生成缩略图\r\n .then(...); //存储到指定地方\r\n \r\n想想用`callback`的时候你是怎么写的。\r\n\r\n它的原理就是,每个`then`的 resolved 部分,返回一个新的 `Promise`,\r\n这么一来就能继续 `then` 下去,只要每一个环节都遵守`Promise`规范,就能将一个回调地狱梳理成**串行**的**链式调用**。\r\n\r\n#### 最后附上两种手写 `Promise` 的参考\r\n>http://www.lanhao.name/article/293\r\n\r\n(未完)\r\n\r\n\r\n\r\n\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(293,'两种方式手写实现Promise(基本版)','293',1467022560,1467116983,'<!--markdown--># Promise / deferred 分开的版本\r\n\r\n \'use strict\';\r\n let myPromise = (deferred) => {\r\n this._resolved = null;\r\n this._rejected = null;\r\n this.then = (resolve,reject) => {\r\n switch (deferred.state){\r\n case \'pending\':\r\n this._resolved = (typeof resolve === \'function\') ? \r\n resolve \r\n : null;\r\n this._rejected = (typeof reject === \'function\') ? \r\n reject \r\n : null;\r\n break;\r\n case \'rejected\':\r\n (typeof reject === \'function\') \r\n && reject.call(null,deferred.reason);\r\n break;\r\n case \'resolved\':\r\n (typeof resolve === \'function\') \r\n && resolve.call(null,deferred.result);\r\n break;\r\n }\r\n };\r\n };\r\n\r\n let myDeferred = () => {\r\n let _self = this;\r\n this.state = \'pending\';\r\n this.reason = null;\r\n this.result = null;\r\n this.promise = new myPromise(_self);\r\n\r\n this.resolved = (val) => {\r\n this.state = \'resolved\';\r\n this.result = val;\r\n if(this.promise._resolved){\r\n this.promise._resolved.call(null,val);\r\n }\r\n };\r\n\r\n this.rejected = (err) => {\r\n this.state = \'rejected\';\r\n this.reason = err;\r\n if(this.promise._rejected){\r\n this.promise._rejected.call(null,err);\r\n }\r\n };\r\n };\r\n\r\n### USAGE\r\n\r\n const fs = require(\'fs\');\r\n let getFileSync = function (path) {\r\n\r\n let df = new myDeferred();\r\n\r\n fs.readFile(path, (e, r) => {\r\n if(e){\r\n df.rejected(e);\r\n }else{\r\n df.resolved(r);\r\n }\r\n });\r\n return df.promise;\r\n };\r\n\r\n let r =getFileSync(\'./README.md\');\r\n //pending\r\n r.then(\r\n //resolved\r\n (val) => console.log(val),\r\n\r\n //rejected\r\n (err) => console.log(err)\r\n );\r\n\r\n# 一体化的版本\r\n\r\n\r\n\r\n let myPromise = (fn) => {\r\n let _self = this;\r\n this.state = \'pending\';\r\n this.result = null;\r\n this.reason = null;\r\n this.resolvedHandler = null;\r\n this.rejectedHandler = null;\r\n\r\n this.resolved = (val) => {\r\n _self.state = \'resolved\';\r\n _self.result = val;\r\n if(typeof _self.resolvedHandler === \'function\'){\r\n _self.resolvedHandler(val);\r\n }\r\n };\r\n\r\n this.rejected = (err) => {\r\n _self.state = \'rejected\';\r\n _self.reason = err;\r\n \r\n if(typeof _self.rejectedHandler === \'function\'){\r\n _self.rejectedHandler(err);\r\n }\r\n };\r\n\r\n this._promise = {};\r\n\r\n this._promise._p = _self;\r\n\r\n this._promise.then = (resolvedHandler, rejectedHandler) => {\r\n switch (_self.state){\r\n case \'pending\':\r\n _self.resolvedHandler = (typeof resolvedHandler === \'function\') ? \r\n resolvedHandler \r\n : null;\r\n _self.rejectedHandler = (typeof rejectedHandler === \'function\') ? \r\n rejectedHandler \r\n : null;\r\n break;\r\n \r\n case \'resolved\':\r\n (typeof resolvedHandler === \'function\') \r\n && resolvedHandler(_self.result);\r\n break;\r\n case \'rejected\':\r\n (typeof rejectedHandler === \'function\') \r\n && rejectedHandler(_self.reason);\r\n }\r\n };\r\n\r\n fn(this.resolved,this.rejected);\r\n \r\n return this._promise;\r\n };\r\n\r\n### USAGE\r\n\r\n const fs = require(\'fs\');\r\n\r\n let getFileSync = (path) => {\r\n return new myPromise( (resolved, rejected) => {\r\n fs.readFile(path, (e, r) => {\r\n if(!e){\r\n resolved(r);\r\n }else{\r\n rejected(e);\r\n }\r\n });\r\n });\r\n };\r\n\r\n let r = getFileSync(\'./README.md\');\r\n //pending\r\n \r\n r.then(\r\n //resolved\r\n (val) => console.log(val), \r\n //rejected\r\n (err) => console.log(err)\r\n );\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(292,'[总结] ES6中的变量和作用域','292',1466590020,1466592711,'<!--markdown-->[原文地址][1]\r\n\r\n### 通过let和const确定块作用域\r\n使用 `let` 和 `const` 创建块作用域,他们声明的变量只存在块内。\r\n比如下面的示例, `let` 声明的变量 `tmp` 只存在于 `if` 语句块,也只有在 `if` 语句块内有效。\r\n\r\n\r\n function func () {\r\n if (true) {\r\n let tmp = 123;\r\n }\r\n console.log(tmp); // ReferenceError: tmp is not defined\r\n }\r\n\r\n\r\n相比之下,使用 `var` 声明的变量,在整个函数域内都有效:\r\n\r\n function func () {\r\n if (true) {\r\n var tmp = 123;\r\n }\r\n console.log(tmp); // 123\r\n }\r\n\r\n块作用域也可以存在于整个函数内:\r\n\r\n\r\n function func () {\r\n let foo = 5;\r\n if (...) {\r\n let foo = 10;\r\n console.log(foo); // 10\r\n }\r\n console.log(foo); // 5\r\n }\r\n\r\n\r\n\r\n### const创建不可变的变量(常量)\r\n\r\nlet 创建的变量是可变的:\r\n\r\n let foo = \"abc\";\r\n foo = \"def\";\r\n console.log(foo); // def\r\n\r\n而使用 `const` 创建的变量是不可变量,其是一个常量:\r\n\r\n const foo = \"abc\";\r\n foo = \"def\"; // TypeError\r\n\r\n注意: `const` 并不影响一个常数是否可变,如果一个常数是一个对象,那它总是一个引用对象,但仍然可以改变对象的本身(如果它是可变的)。\r\n\r\n const obj = {};\r\n obj.prop = 123;\r\n console.log(obj.prop); // 123\r\n obj = {}; // TypeError\r\n\r\n如果你想让 `obj` 是一个真正的常数,可以使用 `freeze` 方法 来冻结其值:\r\n\r\n const obj = Object.freeze({});\r\n obj.prop = 123; // TypeError\r\n\r\n### 循环体内的 const\r\n\r\n一旦通过 `const` 创建的变量它就是一个常量,它是不能被改变的。但这也并不意味着你不能重新给其设置一个新值。例如,可以通过一个循环来操作:\r\n \r\n function logArgs (...args) {\r\n for (let [index, elem] of args.entries()) {\r\n const message = index + \'. \' + elem;\r\n console.log(message);\r\n }\r\n }\r\n logArgs(\"Hello\", \"everyon\");\r\n\r\n输出的结果\r\n\r\n 0. Helloe\r\n 1. everyone\r\n\r\n### 什么应该使用 let ,什么时候应该使用 const\r\n\r\n如果你想改变一个变量保存其原始值,你就不能使用 `const` 来声明:\r\n\r\n const foo = 1;\r\n foo++; // TypeError\r\n\r\n然而,你可以使用 `const` 声明变量,来引用可变量的值:\r\n\r\n const bar = [];\r\n bar.push(\"abc\"); // array是一个可变的\r\n\r\n我还在仔细考虑使用什么方式才是最好的方式,但是目前情况使用的都是像前面的示例,因为 `bar` 变量是可变的。我使用 `const` 表明变量和值是不可变的:\r\n\r\n const EMPTY_ARRAY = Object.freeze([]);\r\n\r\n### 暂时性死区\r\n\r\n使用 `let` 或 `const` 声明的变量有一个所谓的暂时性死区(`TDZ`):当进入作用域范围,它就不能接受( get 或 set )访问,直到其被声明。\r\n\r\n我们来来看一个有关于 `var` 变量的生命周期,它没有暂时性死区:\r\n\r\n- 当 `var` 声明了一个变量,其就有一个存储空间(创建一个所谓的绑定)。变量就初始化了,其默认值为 `undefined`\r\n- 当执行的范围到达声明处,变量设置为指定的值(如果有赋值的话),如果变量没有赋值,其值仍然是 `undefined`\r\n\r\n通过 `let` 声明变量存在暂时性死区,这意味着他们的生命周期如下:\r\n\r\n- 当使用 let 创建一个变量,其就有一个块作用域,也具有一个存储空间(也就是创建一个所谓的绑定)。其值仍未初始化变量\r\n获取或设置一个未初始化的变量,得到一个错误ReferenceError\r\n- 当执行范围内到达声明的变量处,如果有赋值的话,变量的初始值为指定的初始化值。如果没有,变量的值仍为 undefined\r\n\r\n使用 `const` 声明的变量工作类似于 `let` ,但它必须要有一个初始化值,而且不能被改变。\r\n\r\n在一个`TDZ`内,通过 `if` 语句秋设置或获取一个变量将会报错:\r\n\r\n if (true) { // TDZ开始\r\n // 未初始化tmp变量\r\n tmp = \"abc\"; // ReferenceError\r\n console.log(tmp); // ReferenceError\r\n let tmp; // TDZ结束,tmp已初始化,其初始值为undefined\r\n console.log(tmp); // undefined\r\n tmp = 123;\r\n console.log(tmp); // 123\r\n }\r\n\r\n下面的例子演示了死区是时间(基于时间),而不是空间(基于位置):\r\n\r\n if (true) { // 进入新作用域,TDZ开始\r\n const func = function () {\r\n console.log(myVar); // OK\r\n }\r\n //在TDZ内访问myVar,会引起ReferenceError错误\r\n let myVar = 3; // TDZ结束\r\n func (); // 调用外面的TDZ\r\n }\r\n\r\n### typeof和TDZ\r\n\r\n一个变量在难以接近TDZ时,这也意味着你不能使用 `typeof` :\r\n\r\n if (true) {\r\n console.log(typeof tmp); // ReferenceError\r\n let tmp;\r\n }\r\n\r\n在实践中我不认为这是一个问题,因为你不能有条的通过 `let` 声明变量范围。相反,你可以使用 `var` 声明变量,而且可以通过 window 创建一个全局变量:\r\n\r\n if (typeof myVarVariable === \'undefined\') {\r\n // `myVarVariable` does not exist => create it\r\n window.myVarVariable = \'abc\';\r\n }\r\n\r\n### 循环头中的 `let`\r\n\r\n在循环中,你可以通过 `let` 声明变量,为每次迭代重新绑定变量。比如在 `for` 、 `for-in` 和 `for-of` 循环中。\r\n\r\n看起来像下面:\r\n\r\n let arr = [];\r\n for (let i = 0; i < 3; i++) {\r\n arr.push(() = > i);\r\n }\r\n console.log(arr.map(x => x())); // [0,1,2]\r\n\r\n相比之下,使用 `var` 声明的变量将在整个循环中都可以工作:\r\n\r\n let arr = [];\r\n for (var i = 0; i < 3; i++) {\r\n arr.push(() => i);\r\n }\r\n console.log(arr.map(x => x())); // [3,3,3]\r\n\r\n每次迭代得到一个新的绑定似乎有些奇怪,但当你使用循环创建功能(比如回调事件处理),它显得就非常有用。\r\n\r\n## 参数\r\n\r\n### 参数和局部变量\r\n\r\n如果使用 `let` 声明变量,它有一个相同的名称,称作参数。静态加载会出错:\r\n\r\n function func (arg) {\r\n let arg; // Uncaught SyntaxError: Identifier \'arg\' has already been declared\r\n }\r\n\r\n同样的,将其放在一个作用块里:\r\n\r\n function func (arg) {\r\n {\r\n let arg; // undefined\r\n }\r\n } \r\n\r\n相比之下,使用 `var` 声明一个和参数相同变量,其作用范围在同一个范围内:\r\n\r\n function func (arg) {\r\n var arg;\r\n }\r\n\r\n或者\r\n\r\n function func (arg) {\r\n {\r\n var arg;\r\n }\r\n }\r\n\r\n### 参数默认值和`TDZ`\r\n\r\n如果 参数有默认值 ,他们会当作一系列的 `let` 语句,而且存在`TDZ`。\r\n\r\n // OK: `y` accesses `x` after it has been declared\r\n function foo(x=1, y=x) {\r\n return [x, y];\r\n }\r\n foo(); // [1,1]\r\n \r\n // Exception: `x` tries to access `y` within TDZ\r\n function bar(x=y, y=2) {\r\n return [x, y];\r\n }\r\n bar(); // ReferenceError\r\n\r\n### 默认参数不知道其自身的范围\r\n\r\n参数默认值的范围是独立于其自身范围。这意味着内部定义的方法或函数参数的默认值不知道其内部的局部变量:\r\n\r\n let foo = \'outer\';\r\n function bar(func = x => foo) {\r\n let foo = \'inner\';\r\n console.log(func()); // outer\r\n }\r\n bar();\r\n\r\n### 全局对象\r\n\r\nJavaScript全局对象(浏览器中的window,Node.js中的global)存在的问题比他的特性多,尤其是性能。这也是为什么ES6中不引用的原因。\r\n\r\n全局对象的属性都是全局变量,在全局作用域下都有效,可以通过 `var` 或 `function` 方式声明。\r\n\r\n但现在全局变量也不是全局对象。在全局作用域下,可以通过 `let` 、 `const` 或者 `class` 声明。\r\n\r\n### 函数声明和class声明\r\n\r\nfunction 声明:\r\n\r\n- 像 let 一样,声明的是一个块作用域\r\n- 像 var 一样,在全局对象创建属性(全局作用域)\r\n- 存在生命提升:独立于一个函数声明中提到它的范围,它总是存在于开始时创建的范围内\r\n\r\n下面的代码演示了函数声明的提升:\r\n\r\n { // Enter a new scope\r\n \r\n console.log(foo()); // OK, due to hoisting\r\n function foo() {\r\n return \'hello\';\r\n }\r\n }\r\n\r\n#### 类声明:\r\n\r\n- 是一个块作用域\r\n- 不能在全局对象上创建属性\r\n- 不存在生命提升\r\n\r\n`class` 不存在生命提升可能令人惊讶,那是因为其存在于引擎下,而不是一个函数。这种行为的理由是,他们扩展表达式。这些表达式在适当的时间内被执行。\r\n\r\n { // Enter a new scope\r\n \r\n const identity = x => x;\r\n \r\n // Here we are in the temporal dead zone of `MyClass`\r\n let inst = new MyClass(); // ReferenceError\r\n \r\n // Note the expression in the `extends` clause\r\n class MyClass extends identity(Object) {\r\n }\r\n }\r\n\r\n\r\n\r\n [1]: http://www.w3cplus.com/javascript/variables-and-scoping-in-es6.html?utm_source=tuicool&utm_medium=referral',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(291,'八一八HTTP的一些事情','291',1463211600,1511941874,'<!--markdown--># 八一八HTTP的一些事情\r\n\r\n> 如果想了解全面的,请自己看[RFC](http://www.rfc-editor.org/search/rfc_search_detail.php?title=http&pubstatus%5B%5D=Any&pub_date_type=any)\r\n\r\n## 从0.9到1.0\r\n\r\n0.9是第一个版本,有以下几个显著特点。\r\n \r\n 1.实现了 get 请求,没有协议头,整个请求只有一行:GET /index.html \r\n \r\n 2.它只定义了请求(Request),返回(Response)没有任何定义。\r\n 所以,服务端只能返回纯文本。\r\n \r\n 3.典型的无状态请求,每一个事务都重新建立并关闭 一次TCP连接。\r\n \r\n 4.如果请求的资源不存在,或是服务器不可用,不会有任何的返回。\r\n0.9的时代大家都很单纯,由于各种客观原因,能够从网络上拿到纯文本信息,\r\n已经能为互联网提供很大的想象空间。\r\n\r\n但是很明显的,以我们现在的眼光来看http0.9,这是一个非常直接非常单薄的发明。\r\n\r\n而真正到了接近我们现在理解的http,就是1.0的时代了。\r\n\r\n1.0是一个相对完善的版本,所以跟0.9比较起来,内容多了很多,其中比较值得关注的是\r\n\r\n 1.多了post的方法,这是web2.0的基础\r\n \r\n 2.有了http headers的概念,这是最伟大的部分,后面细说\r\n \r\n 3.有了状态码\r\n\r\n## http 1.0 让世界有了色彩\r\n\r\n由于1.0相对对0.9增加的内容太多,后来的很多client(如浏览器),都强制从1.0开始支持。\r\n\r\npost方法带来变化,相信大家都比较能理解,在这里不细说。\r\n\r\n这里我想重点说一下为什么 headers 是最伟大的部分。\r\n \r\n1.多媒体的支持\r\n\r\n 在0.9时代,从网络上传回来的数据,我们只能按照纯文本来处理,\r\n 因为我并不知道这些内容是什么含义。\r\n \r\n 而从1.0开始,为了能告诉客户端数据类型,http返回头里会包含 content-type 属性。\r\n \r\n content-type的格式是 \r\n “主类型/子类型” ( [type]/[subtype])\r\n 如 : text/html\r\n \r\n 常见的content-type请看 http://tool.oschina.net/commons\r\n \r\n 有了这个信息,服务器可以明确告诉客户端,这是音频、视频、图片、ppt等,\r\n 客户端也就可以根据这个属性,调用本地的解释器来执行返回的内容。\r\n \r\n 于是就有了多媒体。\r\n \r\n2.缓存\r\n \r\n 缓存部分通过几个机制来完成,层层递进,分别是\r\n \r\n Expires : \r\n 例子:Expires: Thu, 01 Dec 2016 16:00:00 GMT\r\n 返回头包含这个信息,告诉client在这个时间之前,你都可以使用本地的副本。\r\n 这个机制可以直接 免除 网络请求,效果明显,\r\n 但是问题是当服务器时间跟客户端时间不一致时,会出现一些问题。\r\n \r\n Last-Modified、If-Modified-Since (精确到秒)\r\n 当Expires过期,客户端就重新请求资源,并且请求头在带上If-Modified-Since\r\n (而上一次请求得到资源时,返回头会包含 Last-Modified 表明资源的修改时间),\r\n 服务器收到请求,会检查本地资源在If-Modified-Since之后是否有变化,\r\n 如果有,返回200,更新Last-Modified系信息,返回资源实体。\r\n 如果没有变化,返回304 ,由于没有返回实际数据,这个请求很快,\r\n 然后客户端就还是使用本地的副本。\r\n \r\n ETag (http 1.1)\r\n ETag是1.1补充到,在这样顺便说明一下。\r\n Etag是服务器对资源的一个特征值校验,一旦资源发生变化,Etag也会变化。\r\n 它是弥补Last-Modified的一个缺陷,就是当资源在一秒内发生变化,\r\n Last-Modified是无法察觉的。\r\n \r\n \r\n3.状态码\r\n\r\n 每一个状态码都有它的含义,在一些实现得好的http环境下,能够表达很多的含义。\r\n 虽然我们没法记住全部状态码,但是可以通过码段区分:\r\n 1XX 是传达一些信息的\r\n 2XX 是成功一类的状态,不过也分很多种,received,understood, and accepted\r\n 3XX 重定向一类,只有头部返回信息\r\n 4XX Client Error ,这个错误是由客户端产生的,比如uri写错的404\r\n 5XX Server Error ,说明是服务端的问题,必要时报警通知管理员\r\n \r\n4.其他\r\n\r\n http1.0还有很多丰富的进步,有兴趣的可以去看 rfc1945\r\n \r\n## http 1.1\r\n1.1是对1.0的一个补充,所以现在的client基本上都同时支持1.0/1.1,\r\n实际上我们玩得6的基本都在1.0,而1.1也有以下一些振奋人心的东西:\r\n\r\n1. host\r\n\r\n 1.1要求请求头加入host信息,表明目前请求的域名,这样web服务器(nginx等)就能\r\n 根据头部信息,分发内容到VirtualHost,实现了一台主机多个应用。\r\n (1.0以前,一个IP只能部署一个应用)。\r\n2. keepalive\r\n\r\n keepalive是客户端与服务端在一个超时范围内,可以重复使用tcp链接,\r\n (过去是一次请求一次返回就断开)\r\n 其实在1.0就已经支持keepalive,不过要手动设定,\r\n 而到了1.1,默认所有请求都加入keepalive选项。\r\n3. range\r\n\r\n range技术多用于下载,它允许分段传输文件。\r\n 在请求头中加入:Range: bytes 0-800 表示下载前800bytes的内容,\r\n 服务器会返回前800bytes并且状态是206 。\r\n 有了这个技术,可以实现断点续传、多线程下载等。\r\n4. session/cookie\r\n\r\n 这个我们最熟悉的东西,居然不是http里定义的。\r\n \r\n\r\n \r\n \r\n\r\n \r\n\r\n ',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(289,'redis 3.2 vs 3.0','289',1462780470,1462780470,'<!--markdown-->## 命令:\r\n\r\n> redis-benchmark -h 127.0.0.1 -p 6379 -q -d 100\r\n\r\n## 结果(谨代表本机情况,数据仅供参考):\r\n\r\n\r\n### reids 3.0\r\nSET: 66577.90 requests per second\r\nGET: 78740.16 requests per second\r\nINCR: 69252.08 requests per second\r\nLPUSH: 75018.76 requests per second\r\nRPUSH: 51150.89 requests per second\r\nLPOP: 73152.89 requests per second\r\nRPOP: 68119.89 requests per second\r\nSADD: 78926.60 requests per second\r\nSPOP: 66622.25 requests per second\r\nLPUSH (needed to benchmark LRANGE): 56369.79 requests per second\r\nLRANGE_100 (first 100 elements): 17857.14 requests per second\r\nLRANGE_300 (first 300 elements): 8238.59 requests per second\r\nLRANGE_500 (first 450 elements): 5544.47 requests per second\r\nLRANGE_600 (first 600 elements): 4256.59 requests per second\r\nMSET (10 keys): 22055.58 requests per second\r\n\r\n### redis 3.2\r\nSET: 67750.68 requests per second\r\nGET: 76569.68 requests per second\r\n**INCR: 78864.35 requests per second** 13% up\r\nLPUSH: 72992.70 requests per second\r\n**RPUSH: 75815.01 requests per second** 47% up\r\nLPOP: 75301.21 requests per second\r\n**RPOP: 78308.54 requests per second** 14% up\r\nSADD: 78308.54 requests per second\r\n**SPOP: 77942.32 requests per second** 16% up\r\n**LPUSH (needed to benchmark LRANGE): 71994.23 requests per second** 28% up\r\nLRANGE_100 (first 100 elements): 18996.96 requests per second\r\nLRANGE_300 (first 300 elements): 8262.41 requests per second\r\nLRANGE_500 (first 450 elements): 5717.88 requests per second\r\nLRANGE_600 (first 600 elements): 4255.32 requests per second\r\n**MSET (10 keys): 31776.29 requests per second** 41% up\r\n\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(290,'快速体验redis地理信息API','290',1462863851,1462863851,'<!--markdown-->近日 redis 发布了3.2版本,期待已久的GEO Api终于能够使用,我们第一时间体验一下\r\n\r\n### GEOADD\r\n> GEOADD key longitude latitude member [longitude latitude member ...]\r\n\r\n例子:\r\n\r\n GEOADD user_location 103.1123 30.676 \"Tom\"\r\n 参数讲解:\r\n GEOADD 添加地理信息\r\n user_location 定义一个地理信息点的集合,叫做 用户位置\r\n 103.1123 经度,X坐标\r\n 30.676 纬度,Y坐标\r\n \"Tom\" 名字,用户名之类\r\n (后3个参数作为一组信息,可以无线重复多个,一次录入多个点)\r\n 比如:\r\n GEOADD user_location 103.1123 30.676 \"Tom\" 111.27 44.566 \"Jack\"\r\n \r\n>注意的是,很多时候我们看到的经纬度单位 **度|分|秒**,GEOADD里要转换成小数。\r\n同时,有效的经度从-180度到180度,有效的纬度从-85.05112878度到85.05112878度。\r\n所以,地球两极是处理不了的。\r\n\r\n>具体原因是,GEO将球形转换成平面的XY矩形,极点无法转化。\r\n(参考 EPSG:900913 / EPSG:3785 / OSGEO:41001 )\r\n\r\n### GEODIST\r\n>GEODIST key member1 member2 [unit]\r\n\r\n例子:\r\n\r\n GEODIST user_location Jack Tom km\r\n 参数讲解:\r\n GEODIST 计算两点距离\r\n user_location 地理信息集合,目前只能计算同一个集合下的点\r\n Jack Tom 两个点的名字\r\n km 单位,m 表示米,km 表示千米,mi 表示英里,ft 表示英尺。\r\n 返回:\r\n \"1701.7446\" 表示两点距离1701.74 km\r\n\r\n>GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。\r\n\r\n\r\n### 附近的人 GEORADIUS , GEORADIUSBYMEMBER\r\n >GEORADIUS key longitude latitude radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]\r\n\r\n 例子:\r\n GEORADIUS user_location 100 35 1000 km \r\n 表示从指定集合里,查找 (100,35)这个点附近1000km的点,\r\n 返回: Tom ,说明Jack不在1000km内。\r\n \r\n 参数说明:\r\n user_location 指定的地理信息集合\r\n 100 35 经纬度\r\n 1000 距离\r\n km 距离单位,m|km|ft|mi \r\n 以下可选开关:\r\n WITHCOORD 返回坐标\r\n WITHDIST 返回距离\r\n WITHHASH 返回GeoHash\r\n COUNT count 表示只返回多少个结果,如:COUNT 10 \r\n ASC 按距离正序\r\n DESC 按距离倒序\r\n \r\n 所以,假如是要获取附近1公里的人,就是\r\n GEORADIUS user_location {X} {Y} 1 km WITHDIST ASC\r\n \r\n>值得注意的是,使用 WITHDIST 来返回距离时,使用的单位和radius的单位是一致的,所以,尽量使用小单位,给自己更多的操作空间。\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(288,'[转]阻止UPDATE语句没有添加WHERE条件的发生','288',1462272480,1491557696,'<!--markdown-->支持原创请访问:[原文地址][1]\r\n\r\n如果在生产环境中使用UPDATE语句更新表数据,此时如果忘记携带本应该添加的WHERE条件,那么。。\r\n\r\nOh,no…后果可能不堪设想。。。\r\n\r\n之前就遇到一个同事在生产环境UPDATE忘记携带WHERE条件。。\r\n于是只能从binlog日志中找到相关数据,然后去恢复。。宝宝当时表示心好累。。。\r\n那么有没有什么办法可以阻止这样的事情发生,又不使用任何的审核工具呢。。。\r\n办法当然是有的,请听我说~\r\n\r\nsql\\_safe\\_updates\r\n\r\nsql\\_safe\\_updates这个MySQL自带的参数就可以完美的解决我们的问题,并且该参数是可以在线变更的哦~\r\n当该参数开启的情况下,你必须要在UPDATE语句后携带WHERE条件,否则就会报出ERROR。。\r\n\r\n举个栗子\r\n \r\n # sql_safe_updates=0,即未开启\r\n [email protected] : test 07:58:34> set sql_safe_updates=0;\r\n Query OK, 0 rows affected (0.00 sec)\r\n \r\n [email protected] : test 07:58:43> show variables like \'sql_safe_updates\';\r\n +------------------+-------+\r\n | Variable_name | Value |\r\n +------------------+-------+\r\n | sql_safe_updates | OFF |\r\n +------------------+-------+\r\n 1 row in set (0.00 sec)\r\n\r\n [email protected] : test 07:58:55> select * from t;\r\n +-------+\r\n | pd |\r\n +-------+\r\n | hello |\r\n | mysql |\r\n +-------+\r\n 2 rows in set (0.00 sec)\r\n \r\n [email protected] : test 07:58:59> begin;\r\n Query OK, 0 rows affected (0.00 sec)\r\n \r\n [email protected] : test 07:59:04> update t set pd=\'MySQL\';\r\n Query OK, 2 rows affected (0.00 sec)\r\n Rows matched: 2 Changed: 2 Warnings: 0\r\n \r\n [email protected] : test 07:59:12> select * from t;\r\n +-------+\r\n | pd |\r\n +-------+\r\n | MySQL |\r\n | MySQL |\r\n +-------+\r\n 2 rows in set (0.00 sec)\r\n\r\n # sql_safe_updates=1,即开启\r\n [email protected] : test 08:00:00> set sql_safe_updates=1;\r\n Query OK, 0 rows affected (0.00 sec)\r\n \r\n [email protected] : test 08:00:11> show variables like \'sql_safe_updates\';\r\n +------------------+-------+\r\n | Variable_name | Value |\r\n +------------------+-------+\r\n | sql_safe_updates | ON |\r\n +------------------+-------+\r\n 1 row in set (0.00 sec)\r\n \r\n [email protected] : test 08:00:16> select * from t;\r\n +-------+\r\n | pd |\r\n +-------+\r\n | hello |\r\n | mysql |\r\n +-------+\r\n 2 rows in set (0.00 sec)\r\n\r\n [email protected] : test 08:00:25> begin;\r\n Query OK, 0 rows affected (0.00 sec)\r\n \r\n [email protected] : test 08:00:27> update t set pd=\'MySQL\';\r\n ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column\r\n\r\n如上属的栗子所示,当参数sql\\_safe\\_updates开启的时候,UPDATE语句不携带WHERE条件将会爆出一个错误。。所以小心使用UPDATE语句是真的很重要哇。。。\r\n\r\n\r\n [1]: http://wing324.github.io/2016/05/01/%E5%A6%82%E4%BD%95%E5%9C%A8MySQL%E4%B8%AD%E9%98%BB%E6%AD%A2UPDATE%E8%AF%AD%E5%8F%A5%E6%B2%A1%E6%9C%89%E6%B7%BB%E5%8A%A0WHERE%E6%9D%A1%E4%BB%B6%E7%9A%84%E5%8F%91%E7%94%9F/',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(301,'PHP PSR2 与 PHPCS 相关','301',1475168880,1475168930,'<!--markdown-->## PSR2 is ?\r\n[github上一个中文介绍的项目](https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-2-coding-style-guide.md)\r\n\r\n## phpcs (php_codesniffer)\r\n\r\n- Install : composer global require \"squizlabs/php_codesniffer=*\"\r\n\r\n- PSR-1 的程式出現在 1.3.5 ,PSR-2 出現在 1.4.0 \r\n\r\n- phpcs --config-set default_standard PSR2\r\n\r\n## IDE\r\n\r\n- sublime text [参考配置](https://my.oschina.net/u/130139/blog/290638)\r\n \r\n- phpstorm \r\n \r\n preferences -> Editor -> Code Style -> PHP \r\n \r\n -> set from...(右上角) -> Predefined Style -> PSR1/PSR2\r\n \r\n## git hook\r\n- 安装 phpcs \r\n \r\n composer global require \"squizlabs/php_codesniffer=*\"\r\n- Link\r\n\r\n ln -s ~/.composer/vendor/bin/phpcs /usr/local/bin/phpcs\r\n\r\n- edit hook\r\n\r\n1.\r\n\r\n vi {project_root}/.git/hooks/pre-commit\r\n\r\n2.\r\n \r\n #!/bin/sh\r\n PHPCS_BIN=/usr/local/bin/phpcs\r\n PHPCS_CODING_STANDARD=PSR2\r\n PHPCS_FILE_PATTERN=\"\\.(php)$\"\r\n\r\n FILES=$(git diff --name-only --cached)\r\n\r\n if [ \"$FILES\" == \"\" ]; then\r\n exit 0\r\n fi\r\n\r\n for FILE in $FILES\r\n do\r\n echo \"$FILE\" | egrep -q \"$PHPCS_FILE_PATTERN\"\r\n RETVAL=$?\r\n if [ \"$RETVAL\" -eq \"0\" ]\r\n then\r\n \r\n PHPCS_OUTPUT=$($PHPCS_BIN --standard=$PHPCS_CODING_STANDARD $FILE)\r\n PHPCS_RETVAL=$?\r\n \r\n if [ $PHPCS_RETVAL -ne 0 ];\r\n then\r\n echo $PHPCS_OUTPUT\r\n exit 1\r\n fi\r\n fi\r\n done\r\n exit 0\r\n\r\n3.\r\n\r\n chmod +x {project_root}/.git/hooks/pre-commit\r\n\r\n- all',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(283,'对象的成员函数,不要偷偷地修改一些数据','283',1460084762,1460084762,'<!--markdown-->请看一段代码:\r\n\r\n $this->setTitle(\'title\');\r\n\r\n\r\n //in class Article\r\n public function setTitle($title){\r\n $this->title = $title;\r\n \r\n $this->keywords = $this->getKeywords();\r\n $this->descriptions = $this->getDescriptions();\r\n }\r\n \r\n这里的setTitle 就偷偷地修改了这个成员的 keyword和descriptions,\r\n就算这样的代码运行起来没有错,但这个做法都是不推荐的。然而很多人都有犯这样的错误,偷懒、无原则地封装逻辑。\r\n\r\n记住一个函数,不要做超出自己范围的行为,不要做自己名字没有交代的事情。\r\n\r\n代码首先是给人看的,其次才是计算机。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(284,'Firefox_Screenshot_2016-04-14T07-04-16.982Z.png','Firefox_Screenshot_2016-04-14T07-04-16-982Z-png',1460617532,1460617532,'a:5:{s:4:\"name\";s:47:\"Firefox_Screenshot_2016-04-14T07-04-16.982Z.png\";s:4:\"path\";s:35:\"/usr/uploads/2016/04/1049222048.png\";s:4:\"size\";i:113075;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',286),(285,'QQ20160414-0.png','QQ20160414-0-png',1460620769,1460620769,'a:5:{s:4:\"name\";s:16:\"QQ20160414-0.png\";s:4:\"path\";s:34:\"/usr/uploads/2016/04/908170112.png\";s:4:\"size\";i:39543;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,2,NULL,'attachment','publish',NULL,0,'1','0','1',286),(286,'从一段代码剖释PHP foreach做了什么','286',1461308820,1461315325,'<!--markdown-->## 从一段代码剖释PHP foreach做了什么\r\n\r\n当我们使用 foreach 的时候,php到底在做什么?我们看一段代码\r\n \r\n $arr = [ 1 , 2 , 3 ];\r\n \r\n foreach($arr as $key => &$value){\r\n $value *= 2;\r\n }\r\n // [2,4,6]\r\n \r\n foreach($arr as $key => $value){\r\n echo $value;\r\n }\r\n // 2,4,4 why ?\r\n \r\n为什么不是输出 2 , 4 , 6 ? 要解决这个谜题,我们需要搞清楚foreach到底做了什么。\r\n以下均为伪代码:\r\n\r\n foreach($arr as $key => &$value){\r\n /* \r\n 1.首先 php 会内部执行 \r\n $key = key($arr);\r\n $value = & current($arr); \r\n 注,因为上面代码使用 &$value 所以此处也是引用\r\n */\r\n $value *= 2;\r\n }\r\n //第一部分没有问题,正如你理解一样\r\n //但是重点来了,这个时候 $value 仍然是 $arr 最后一个元素的引用\r\n \r\n foreach($arr as $key = $value){\r\n /* \r\n 1.首先 php 会内部执行 \r\n $key = key($arr);\r\n $value = current($arr); \r\n 注,结合上面的情况,第一循环相当于\r\n ( $arr[2] = $arr[0] )\r\n 所以第一循环以后,数组变成 2 , 4 , 2 ;想想为什么?\r\n 同理,第二循环相当于 $arr[2] = $arr[1],\r\n 数组变成 2 , 4 , 4\r\n 第二循环相当于 $arr[2] = $arr[2],\r\n 数组还是 2 , 4 , 4\r\n */\r\n }\r\n\r\n \r\n疑难得解,那么怎么解决?\r\n\r\n方法一,不用引用\r\n \r\n foreach($arr as $key => $value){\r\n $arr[$key] = $value * 2;\r\n }\r\n\r\n方法二,unset引用变量\r\n\r\n foreach($arr as $key => &$value){\r\n $value *= 2;\r\n }\r\n unset($value);',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(287,'2016/4/30飞扬研发实验室会议记录(修改代发)','287',1462073040,1462162598,'<!--markdown-->发者表示,看了于宏洋同学的会议记录后,感觉同学对例会高度重视,认真听讲;就是感觉会议记录写得太正式了,其实会议记录写得有意思一点,以后读起来很怀念的,下面是正文:\r\n\r\n概况:\r\n---\r\n\r\n* 会议:飞扬研发实验室招新后第二次例会 \r\n>发者评论:第一次呢?\r\n\r\n* 时间:2016年4月30日星期六 晚上7点半 \r\n* 地点:无(线上例会::群视频) \r\n>发者评论:一次形式比较新颖的例会\r\n\r\n与会人员:\r\n-----\r\n\r\n* 参与的包括三个部长在内的共计30人: \r\n苏苏、赖林、许曼、\r\n巩娜、车畅、于宏洋、金双平、黄映博、张策、郑琪光、陈佳琦、陈红霖、董鑫、魏欣桐、贾宇、曹蓉、姬云飞、卢奇、李宸强、郑光璨、徐涵玉、唐奥林、杨京蕾、巫正为、周翔鸿、李举磊、朱飞扬、杨尚昆、田定、邹可欣 \r\n> 发者评论:人好多\r\n\r\n* 请假:\r\n姚慧敏 \r\n> 理由未记录\r\n\r\n* 缺席:无\r\n> 不错!\r\n\r\n会议记录:\r\n=====\r\n\r\n1. 分别对各个项目进行了思路讲解并对问题进行了解答。\r\n> 项目比较难确实,但是目的是为了让你们选清方向(这个很重要)和让你们体验一下什么叫面向deadline编程(这个也很重要) \r\n\r\n2. 为零基础同学推荐了学习方法。\r\n\r\n> 能带你们入门\r\n\r\n3. 明天有出去玩的同学上午十点在校车站集合。\r\n\r\n> 吃得好玩得好才能码得好\r\n\r\n会议重点:\r\n=====\r\n\r\n* 大家注意以后按时完成各项任务,不要拖延。\r\n> 不知道说了有没有用\r\n\r\n* 以后(包括本周)每周日晚12点前汇报一次任务进度。\r\n> 希望不是应付...\r\n\r\n* 建议零基础同学先看书、找视频,最后再进行谷歌搜索。\r\n> 原文是百度\r\n\r\n* 做安卓端项目的同学有问题可以问邹兵学长。\r\n> 超级厉害\r\n\r\n* 自然语言项目需要能够在Linux系统上使用。\r\n> linux的命令行多用用,以后肯定会接触到\r\n\r\n* 注意任务时间其实很紧张,开始做之后需要一两周的时间才能完成,希望大家抓紧时间。\r\n> 估计说了也会拖到deadline\r\n\r\n* 有同学需要资料什么的可以私戳许曼,记得带上百度云账号。\r\n\r\n* 没有投票、例会没请假的同学记得向部长解释一下原因。\r\n> 估计觉得难然后退却了\r\n\r\n记录人:于宏洋\r\n-------',0,7,NULL,'post','publish',NULL,0,'1','1','1',0),(282,'Git-flow 带你飞起','282',1459615140,1499497390,'<!--markdown-->## 简单介绍\r\n### git-flow,是一个工具,是一种规范\r\n \r\n> Git Flow是构建在Git之上的一个组织软件开发活动的模型,是在Git之上构建的一项软件开发最佳实践。Git Flow是一套使用Git进行源代码管理时的一套行为规范和简化部分Git操作的工具。\r\n\r\n> ( http://www.ituring.com.cn/article/56870 )\r\n\r\n所以说,git-flow 是一个规则,一种约定,一种规范,并不是什么洪水猛兽,\r\n是提高你使用git技术的一个进阶实践。\r\n\r\n\r\n### git-flow 基于git本身的分支管理机制\r\n所以,你必须先了解什么是git的分支(branch).请看图\r\n\r\n![](https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-2feature.png)\r\n\r\n因为时间关系,我们假设你已经知道什么是branch,\r\ngit-flow就是通过在一个项目里划分不同的分支,来实现功能开发、bug修复、版本发布,以及开发过程中的冲突处理等。\r\n\r\n(如果觉得这个描述有点绕,那么暂时不用理解它。)\r\n\r\n### git-flow把分支划分了几个类别\r\nMaster\r\n \r\n 就是平时我们看到的master,项目的主要分支,对外的第一门面。\r\n 所有外人浏览你的项目,使用你的项目,第一时间都是看到master。\r\n 你可以把它理解成 稳定无bug发布版 。(任何时候都ready to deploy)\r\n 所以,git-flow 要求我们不能在master下做开发。\r\n \r\nDevelop\r\n\r\n 处于功能开发最前线的版本,查看develop分支就能知道下一个发布版有哪些功能了。\r\n develop一开始是从master里分出来的,并且定期会合并到master里,\r\n 每一次合并到master,表示我们完成了一个阶段的开发,产生一个稳定版。\r\n 同样的,develop下也不建议直接开发代码,develop代表的是已经开发好的功能\r\n 的回归版本(为什么说回归?)\r\n \r\nFeature\r\n\r\n 带着develop处的疑问,我们在feature里为你解答。(有点长,别不看)\r\n feature的作用是为每一个新功能从develop里创建出来的一个分支。\r\n 例如小明和小白分别做两个不相干的功能,就应该分别创建两个分支,\r\n 各自开发完以后,先后合并到develop里,这就叫做回归。\r\n 在这个过程里,小明小白不需要任何的沟通,分别并行地开发,\r\n git-flow能很好的处理好分支间并行开发的关系。\r\n \r\n 而develop,则会在适当的时候,由合适的人,合并到master,作为下一个稳定版本。\r\n \r\nHotfix\r\n\r\n 以上3种以外,还有一个很重要的类型,hotfix。\r\n 它是用来修复紧急bug的,而bug通常是来自线上的,\r\n 所以hotfix分支是从master里创建出来的,并且,在bug修改好以后,\r\n 要同时合并到master和develop,这一点需要特别注意。\r\n \r\nRelease\r\n\r\n release更多倾向与版本发布,项目上线前的一些全面测试以及上线准备。\r\n 同样也肩负着版本归档,回滚支持等。\r\n\r\n## 开始使用\r\n上面说到了,git-flow本质只是一个约定,所以你完全可以在现行的git命令行里,\r\n手动地完成全部git-flow操作,(手动创建、合并分支等),\r\n重点是遵守git-flow规范,遵守命名约定和分支管理流程。\r\n\r\n不过,git-flow早就有插件了。参看这个文章:\r\n> http://blog.163.com/tod_zhang/blog/static/1025522142012913113957679/\r\n> \r\n> 安装了这个插件,你的git就多了一系列方便的命令,比如:\r\n\r\n> git flow init\r\n> \r\n> git flow feature start\r\n> \r\n> git flow feature finish \r\n> \r\n> 等等。\r\n\r\n\r\n不过,我觉得这个插件还是不够方便,我墙裂推荐你们都用 SourceTree 。\r\n\r\n![](https://www.sourcetreeapp.com/dam/jcr:4c4d9b59-1049-4abc-b773-cc052c17f73c/sourcetree_rgb_slate.png?cdnVersion=fi)\r\n\r\n如果我要推荐一个git-flow客户端,我会推荐SourceTree。\r\n\r\n如果我要推荐一个git客户端,那我还是推荐SourceTree。\r\n\r\n没错,SourceTree是专门为git-flow开发的git客户端,它涵盖了所有git本身的功能,\r\n\r\n所以即使你不flow,你也可以使用SourceTree来管理你的git项目。\r\n\r\n官方网站:\r\n> https://www.sourcetreeapp.com/\r\n\r\n至于如何下载、安装、/* 破解 */ ,这些内容就交给各位自行baidu了。\r\n\r\n## 详细说明\r\n\r\n那么下面我们来实际操作一次,看看SourceTree如何帮助我们使用git-flow\r\n\r\n**1.小明创建了一个新项目,就做 Demo,并且用SourceTree来打开它。如果这一步都\r\n不会,你还是别做开发了。**\r\n\r\n(一个新的项目,就不发图了)\r\n\r\n**2.小明为了使用git-flow,需要为git项目做一次初始化。**\r\n\r\n![](http://lanhao.name/img/upload/1.png)\r\n\r\n这些可以改动的地方,为了方便其他协作人员,还是用默认好了。\r\n\r\n\r\n**3.初始化后,会自动切换到develop分支,接下来,小明要发一个新功能**\r\n\r\n![](http://lanhao.name/img/upload/2.png)\r\n\r\n注意那个 **Git Flow** 按钮,所有flow的功能都是从那里开始操作的。\r\n在弹出的窗口里输入功能的名字即可,小明决定开发一个 test1 功能。\r\n\r\n这时,左侧的菜单已经看到分支切换到test1了(有加粗效果)\r\n\r\n![](http://lanhao.name/img/upload/3.png)\r\n\r\n**4.然后小明开始了暗无天日的编码过程,千辛万苦后写了一行readme**\r\n\r\n接下来我们演示一下如何提交修改\r\n\r\n![](http://lanhao.name/img/upload/4.png)\r\n\r\n这个界面十分清晰地告诉你本地没有commit的代码,\r\n\r\n当然了,这仅仅是commit到本地,因为这始终是git,我们还需要push到远端。\r\n\r\n![](http://lanhao.name/img/upload/5.png)\r\n\r\n可以在左侧看到,我们暂存了多少个commit。\r\n按照图上流程,选择你要push 的分支,你也可以一次选择多个,\r\n在这里我们先push 功能分支test1 。\r\n\r\n\r\n\r\n**5.提交过几次代码之后,小明认为功能已经开发完毕,可以回归到develop了**\r\n\r\n注意,这个时候,只有test1的代码是改变了的,develop还是停留在小明创建feature时的状态。\r\n\r\n为了安全起见,每次合并之前,最好pull一下develop,再次不表。(SourceTree拉取)\r\n\r\n那么我们现在把开发好的test1合并到develop:\r\n\r\n![](http://lanhao.name/img/upload/6.png)\r\n\r\n整个界面很简单,就一个操作,实际上,它背后做了很多。 (@ -_-)\r\n\r\n如无意外,test1里的改动会合并到develop里,并且会删除**本地**的test1,\r\n\r\n然后把分支切换到develop,这时候我们应该能看到整个test1期间的变动数目:\r\n![](http://lanhao.name/img/upload/7.png)\r\n\r\n接下来你应该立即把develop的改动push到远端!\r\n\r\nOK,这就是一个功能开发的完整流程,就算有多个功能在并行开发,\r\n\r\n通过git-flow的协调,都能互不干扰地开发,最终全部作用到develop上。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(280,'replace into 真的好使吗?','280',1458284662,1458284662,'<!--markdown-->## replace into 真的好使吗?\r\n\r\n### 关于replace into\r\n\r\n 我们常用insert into ,你肯定也经历过,插入错误,提示duplicate key,\r\n 这就是你的表结构里包含了一个唯一键,这个时候,你可能会先删除再插入,或者\r\n 改用update,或者放弃。\r\n \r\n 其实可以试试replace。\r\n \r\n replace的语法和insert基本一样,大部分情况下把insert 换成replace即可。\r\n 其原理是,如果插入不成功,自动删除上一条记录,然后再进行插入。\r\n \r\n \r\n### 那么问题来了\r\n\r\n replace在它适用的场景十分方便,但是会引起一个问题。\r\n 由于是先删除后插入,如果有自增ID,也会被重新分配。\r\n 这对于一些业务系统,是不能忍受的,比如 user_id。\r\n 总不能说,更改了密码,uid都变了,其他关联表也乱了。\r\n \r\n### 怎么办?\r\n\r\n 我们有一种不改变自增ID的方法。一颗赛艇\r\n \r\n ON DUPLICATE KEY UPDATE\r\n \r\n insert into table1(A, B, C) values(1,2,3) \r\n on duplicate key update A=1,B=2,C=3;\r\n \r\n 以上语句,就是捕获duplicate错误,然后执行update,\r\n 如此如此,就不会改变自增ID了。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(281,'[转]GET和POST有什么区别?及为什么网上的多数答案都是错的','281',1459277040,1459277233,'<!--markdown-->> 原文地址:http://www.cnblogs.com/nankezhishi/archive/2012/06/09/getandpost.html\r\n\r\n### 我的经历\r\n\r\n前几天有人问我这个问题。我说GET是用于获取数据的,POST,一般用于将数据发给服务器之用。\r\n\r\n这个答案好像并不是他想要的。\r\n\r\n于是他继续追问有没有别的区别?\r\n\r\n我说这就是个名字而已,如果服务器支持,他完全可以把GET改个名字叫GET2。\r\n\r\n他反问道,那就是单纯的名字上的区别喽?\r\n\r\n我想了想,我觉得如果说再具体的区别,只能去看RFC文档了,还要取决于服务器(指Apache,IIS)的具体实现。但我不得不承认,我的确没有仔细看过HTTP的RFC文档。于是我说,我对HTTP协议不太熟悉。这个问题也就结束了。\r\n\r\n### 最普遍的答案\r\n\r\n回来之后寻思了很久,他到底是想问我什么?我一直就觉得GET和POST没有什么除了语义之外的区别,自打我开始学习Web编程开始就是这么理解的。\r\n\r\n可能很多人都已经猜到了,他要的答案是:\r\n\r\n1. GET使用URL或Cookie传参。而POST将数据放在BODY中。\r\n\r\n2. GET的URL会有长度上的限制,则POST的数据则可以非常大。\r\n\r\n3. POST比GET安全,因为数据在地址栏上不可见。\r\n\r\n#### 但是很不幸,这些区别`全是错误`的,更不幸的是,这个答案还是[Google搜索的头版头条][1],然而我根本没想着这些是答案,因为在我看来他们都是错的。我来一一解释一下。\r\n\r\n\r\n### GET和POST与数据如何传递没有关系\r\n\r\n GET和POST是由[HTTP协议定义][2]的。\r\n在HTTP协议中,Method和Data(URL, Body, Header)是`正交`的两个概念,也就是说,使用哪个Method与应用层的数据如何传输是没有相互关系的。\r\n\r\n HTTP没有要求,如果Method是POST数据就要放在BODY中。也没有要求,如果Method是GET,数据(参数)就一定要放在URL中而不能放在BODY中。\r\n\r\n 那么,网上流传甚广的这个说法是从何而来的呢?我[在HTML标准中,找到了相似的描述][3]。这和网上流传的说法一致。但是这只是`HTML标准对HTTP协议的用法的约定`。怎么能当成GET和POST的区别呢?\r\n\r\n 而且,现代的Web Server都是支持GET中包含BODY这样的请求。虽然这种请求不可能从浏览器发出,但是现在的Web Server又`不是只给浏览器用`,已经完全地超出了HTML服务器的范畴了。\r\n\r\n 知道这个有什么用?我不想解释了,有时候就得自己痛一次才记得住。\r\n\r\n### HTTP协议对GET和POST都没有对长度的限制\r\n\r\n HTTP协议明确地指出了,HTTP头和Body都没有长度的要求。而对于URL长度上的限制,有两方面的原因造成:\r\n\r\n 1. 浏览器。据说早期的浏览器会对URL长度做限制。据说IE对URL长度会限制在2048个字符内(流传很广,而且无数同事都表示认同)。但我自己试了一下,我构造了90K的URL通过IE9访问live.com,是正常的。网上的东西,哪怕是Wikipedia上的,也不能信。\r\n\r\n 2. 服务器。URL长了,对服务器处理也是一种负担。原本一个会话就没有多少数据,现在如果有人恶意地构造几个几M大小的URL,并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是,把告诉服务器Content-Length是一个很大的数,然后只给服务器发一点儿数据,嘿嘿,服务器你就傻等着去吧。哪怕你有超时设置,这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此,多数服务器出于安全啦、稳定啦方面的考虑,会给URL长度加限制。但是这个限制是针对所有HTTP请求的,与GET、POST没有关系。\r\n\r\n#### 安全不安全和GET、POST没有关系\r\n\r\n 我觉得这真是中国特色。我讲个小段子,大家应该可以体会出这个说法多么的可笑。\r\n\r\n 觉得POST数据比GET数据安全的人会说\r\n\r\n “防君子不防小人;中国小白多,能防小白用户就行了。”\r\n\r\n “哼,”我不以为然,“那你怎么不说,URL参数都Encode过了,或是Base64一下,小白也看不懂啊。”\r\n\r\n 那人反驳道,“Encode太简单了,聪明点儿的小白很容易就可以Decode并修改掉。”\r\n\r\n 我笑道,“五十步笑百步耳,再聪明点儿的小白还会截包并重发呢,Opera就有这功能。”\r\n\r\n 那人阴险地祭出神器——最终解释权,说,“这个不算小白。”\r\n\r\n 我日啊。\r\n\r\n### 最后一点儿感想\r\n\r\n 我之前一直做Windows桌面应用,对Web开发无甚了解,直到一年多前转做服务器端开发,才开始接触到HTTP。(注意,我说的是HTTP,不是HTML。服务器开放接口是基于REST理念设计的,使用的协议是HTTP,但是传输的内容不是HTML。这不是Web Server,而是一个Web Service)\r\n\r\n 所以我对于GET和POST的理解,是纯粹地来源于HTTP协议。他们只有一点根本区别,简单点儿说,一个用于获取数据,一个用于修改数据。具体的请参考RFC文档。\r\n\r\n `如果一个人一开始就做Web开发,很可能把HTML对HTTP协议的使用方式,当成HTTP协议的唯一的合理使用方式。`\r\n\r\n`从而犯了以偏概全的错误。`\r\n\r\n 可能有人会觉得我钻牛角尖。我只是不喜欢模棱两可,不喜欢边界不清、概念不明,不喜欢“拿来主义”,也不喜欢被其它喜欢钻牛角尖的人奚落得无地自容。\r\n\r\n #### “知之为知之,不知为不知,是知也。”\r\n\r\n\r\n [1]: https://www.google.com/search?q=get%E5%92%8Cpost%E7%9A%84%E5%8C%BA%E5%88%AB&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:zh-CN:official&client=firefox-a&channel=fflb\r\n [2]: http://www.w3.org/Protocols/rfc2616/rfc2616.html\r\n [3]: http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.1',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(278,'链接 a 及其伪类','278',1454762820,1454823000,'<!--markdown--># 链接 \\<a\\> 及其伪类\r\n\r\na 标签有多种伪类,而且浏览器默认样式实在是丑到爆,一不小心没有覆盖到露出来就蛋疼无比。\r\n\r\n## 区分 active ♂ focus\r\n\r\n`:hover` `:first-child` `last-child` 之类的伪类,想必大家都很熟悉,我就不在此饶舌了。不过我相信有不少人和我一样长时间弄不清楚 active 和 focus 伪类的含义。\r\n\r\n### active 伪类\r\n\r\n适用于激活状态的元素。所谓激活状态,通常是指鼠标在 a 元素上按下并保持的状态,详细的定义说明见 w3c :\r\n\r\n> 定义和用法\r\n> \r\n> :active 伪类向激活(在鼠标点击与释放之间发生的事件)的元素添加特殊的样式。\r\n> \r\n> 这个伪类应用于处于激活状态的元素。\r\n> \r\n> **最常见的例子就是在 HTML 文档中点击一个超链接:在鼠标按钮按下期间,这个链接是激活的。还有其他一些方式来激活元素,另外从理论上讲其他元素也可以被激活,不过 CSS 对此没有定义。**\r\n\r\n### focus 伪类\r\n\r\n**只适用于可获得焦点的元素**,为获得焦点的元素添加新的样式。一般像输入元素 input、textarea 可获得焦点,正在向其输入时,处于聚焦状态。\r\n\r\n**链接 a 也可获得焦点**: \r\n\r\n1. **tab-focus** 通过 tab 键在可获得焦点的元素间切换时获得焦点\r\n2. I don\'t know...\r\n\r\n> 定义和用法\r\n> \r\n> :focus 伪类在元素获得焦点时向元素添加特殊的样式。\r\n> \r\n> 注释:IE 浏览器不支持此属性。\r\n> \r\n> 说明\r\n> \r\n> **这个伪类应用于有焦点的元素。例如 HTML 中一个有文本输入焦点的输入框,其中出现了文本输入光标;也就是说,在用户开始键入时,文本会输入到这个输入框。其他元素(如超链接)也可以有焦点,不过 CSS 没有定义哪些元素可以有焦点。**\r\n\r\n## 链接 a 的伪类及默认的样式\r\n\r\n适用于 a 标签的伪类较多,能应付一些复杂的需求,但是也像前面所说的写样式的时候尼玛都要覆盖到啊!\r\n\r\n一不小心就漏掉了!!!\r\n\r\n处理特殊链接的时候注意下一般链接伪类选择器的权重!!!\r\n\r\n| | a:link | a:visited | a:hover | a:active | a:focus |\r\n| ------ |--------| --------- | ------- | -------- | ------- |\r\n| 状态 | 未访问的链接 | 已访问过的链接 | 鼠标在链接上悬停 | 鼠标在链接上按下并保持 | tab 键选中,使链接获得焦点 |\r\n| 默认样式 | 蓝色,下划线 | 紫色,下划线 | 下划线 | 红色,下划线 | outline | \r\n\r\n## 正确的书写顺序\r\n\r\n根据 CSS 的优先级规则,当两个规则的优先级相同时,应用后定义的样式;而几个伪类所表示的交互状态有所重叠,所以在书写 a 的样式时需要保证一定的顺序,才能达到预期的效果:\r\n\r\n1. `a:hover` 必须位于 `a:link` 和 `a:visited` 之后!!\r\n2. `a:active` 必须位于 `a:hover` 之后!!\r\n\r\n## my snippets\r\n\r\n比较喜欢简书里的<a href=\"http://www.jianshu.com/p/1e402922ee32/\">链接</a>样式,蓝色就好,不要下划线,不需要区分已访问,一切ok\r\n\r\n```scss\r\na {\r\n transition: .3s;\r\n\r\n // 使访问过与未访问样式一致\r\n &:link, &:visited {\r\n color: #4094c7; // 浅蓝\r\n text-decoration: none;\r\n }\r\n \r\n // 写在后面 & 去掉下划线 ...\r\n &:hover,\r\n &:active {\r\n color: #075b8d; // 深蓝\r\n text-decoration: none;\r\n }\r\n \r\n // 处女座福利 我相信你们和我一样不想见到 outline\r\n &:focus {\r\n outline: none;\r\n }\r\n \r\n /*\r\n detail style here\r\n */\r\n}\r\n```',0,10,NULL,'post','hidden',NULL,0,'1','1','1',0),(275,' 详解spl_autoload_register()函数','275',1452835440,1452835501,'<!--markdown--> 在了解这个函数之前先来看另一个函数:__autoload。 \r\n\r\n一、__autoload \r\n\r\n这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数。看下面例子: \r\n\r\n printit.class.php \r\n \r\n <?php \r\n \r\n class PRINTIT { \r\n \r\n function doPrint() {\r\n echo \'hello world\';\r\n }\r\n }\r\n ?> \r\n \r\n index.php \r\n \r\n <?\r\n function __autoload( $class ) {\r\n $file = $class . \'.class.php\'; \r\n if ( is_file($file) ) { \r\n require_once($file); \r\n }\r\n } \r\n \r\n $obj = new PRINTIT();\r\n $obj->doPrint();\r\n ?>\r\n\r\n \r\n\r\n运行index.php后正常输出hello world。在index.php中,由于没有包含printit.class.php,在实例化printit时,自动调用__autoload函数,参数$class的值即为类名printit,此时printit.class.php就被引进来了。 \r\n\r\n在面向对象中这种方法经常使用,可以避免书写过多的引用文件,同时也使整个系统更加灵活。 \r\n\r\n二、spl_autoload_register() \r\n\r\n再看spl_autoload_register(),这个函数与__autoload有与曲同工之妙,看个简单的例子: \r\n \r\n \r\n <?\r\n function loadprint( $class ) {\r\n $file = $class . \'.class.php\'; \r\n if (is_file($file)) { \r\n require_once($file); \r\n } \r\n } \r\n \r\n spl_autoload_register( \'loadprint\' ); \r\n \r\n $obj = new PRINTIT();\r\n $obj->doPrint();\r\n ?>\r\n\r\n将__autoload换成loadprint函数。但是loadprint不会像__autoload自动触发,这时spl_autoload_register()就起作用了,它告诉PHP碰到没有定义的类就执行loadprint()。 \r\n\r\nspl_autoload_register() 调用静态方法 \r\n \r\n \r\n <? \r\n \r\n class test {\r\n public static function loadprint( $class ) {\r\n $file = $class . \'.class.php\'; \r\n if (is_file($file)) { \r\n require_once($file); \r\n } \r\n }\r\n } \r\n \r\n spl_autoload_register( array(\'test\',\'loadprint\') );\r\n //另一种写法:spl_autoload_register( \"test::loadprint\" ); \r\n \r\n $obj = new PRINTIT();\r\n $obj->doPrint();\r\n ?>\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(276,'今天我们来说说[函数依赖的参变量对调用方全部可见]','276',1453714529,1453714529,'<!--markdown-->### 函数依赖的参变量对调用方全部可见\r\n\r\n这句话什么意思?\r\n\r\n就是,当你需要写一个函数时,你应该遵守一个原则,让调用函数的主体,知晓影响函数执行结果的一切参变量。\r\n\r\n比如 ,我输入 “面粉”,“糖”,“鸡蛋”,你应该返回甜味的馒头,你不能偷偷往里加盐,而又不让我知道也不让我阻止。\r\n\r\n\r\n而实际上,很多时候我们写的代码,都没有很好遵守这个原则,\r\n\r\n function renderHtml($veiw){\r\n $style = \'2016newyear\';\r\n return $this->template($view,$style)\r\n }\r\n\r\n看吧,强行使用了2016newyear风格,调用方完全无可奈何。\r\n\r\n function renderHtml($veiw,$style=\'default\'){\r\n return $this->template($view,$style)\r\n }\r\n\r\n这样就好多了。\r\n\r\n不要小看这些原则,这是高质量代码的一小步。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(277,'Javascript 对象之 Object.defineProperty','277',1453862040,1453862732,'<!--markdown-->平时我们定义一个对象,给它添加属性,通常会这样做\r\n\r\n var o = {};\r\n o.foo = function(){\r\n console.log(\'foo\');\r\n }\r\n o.foo(); // print \'foo\'\r\n\r\n这是可行的,但是如果我们这样\r\n\r\n o.foo = null;\r\n\r\nfoo就被改变了,然后引起 TypeError: o.foo is not a function 的错误。\r\n\r\n## 于是,Object.defineProperty 就进入我们视野\r\n\r\n var a = {};\r\n Object.defineProperty(a,\'foo\',{\r\n value:function(){\r\n console.log(\'foo..\');\r\n }\r\n });\r\n\r\n这样,foo就不会被改变,强行赋值(o.foo = null;)在严格模式下会出 TypeError: \"foo\" is read-only 错误\r\n\r\n## 解读:\r\n\r\n Object.defineProperty 接受三个参数,\r\n 第一个为对象,要添加属性的对象;\r\n 第二个为属性的名字,字符串;\r\n 第三个是一个对象,是对新添加的属性的一些设置,\r\n\r\n重点讲第三个参数,它有以下设置项:\r\n\r\n \r\n\r\n value:属性的值,可以是基本属性、对象、函数等等\r\n\r\n writable:是否可以写,默认false,所以上面的foo是readonly\r\n\r\n configurable:是否可以修改设置,默认false,即定义过以后是否能再次修改设置项\r\n\r\n enumerable:是否能被枚举,关系到for in 或者 Object.keys的时候会不会被列出来\r\n\r\n get、set:设置了get、set就不能设置 writable 或 value,不然会报错,这是对属性读写时的钩子,下面有栗子\r\n\r\n var b = 1;\r\n var a = {};\r\n Object.defineProperty(a,\'foo\',{\r\n set:function(v){\r\n b = v;\r\n console.log(\'set\');// you can do any thing here\r\n },\r\n get:function(){\r\n console.log(\'get\'); // you can do any thing here\r\n return b;\r\n }\r\n });\r\n a.foo; // print \'get\' ,return 1\r\n a.foo = 2; // print \'set\' ,return 2\r\n a.foo; // print \'get\' ,return 2\r\n\r\n## 是不是很棒?\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(274,'编写 DAO / 数据模型 时,切勿做这些犯傻的封装','274',1452679680,1460084859,'<!--markdown--> \r\n 以下是最近看一些项目中 ,对DAO层面、数据模型的类的编写中,挖掘出来的一些不合理的部分。\r\n 大致原因来源于 面向对象 方面的基本功薄弱,设计模式知识的缺乏,对 数据 这个抽象概念的理解错误。\r\n 总结下来雨以下干货:\r\n\r\n## get* 类型函数,读取数据里某一个属性(字段)的,坚决不要\r\n \r\n 这个case,比如我封装了一个 Article 的类,就给它写一个 getTitle ,getCreateTime 这样的一系列函数,\r\n 表面上是在读取这些属性时非常方便,实际上是没什么意义的,应该统一为 getAttribute ,从参数里决定读取个别字短或读取全部。\r\n set* 函数同理\r\n\r\n## is* 类型函数,请不要出现在DAO模型里\r\n\r\n 很多朋友喜欢这样做,比如用户表里有个 role 字短,就写一个 isAdmin 函数来判断 role是否等于 admin,\r\n 从而判断是不是管理员。 \r\n 你可能会觉得,这很好啊,很直观啊。\r\n 但是请记住一点,模型里,这个类只关心数据本身,而不应该包含对数据的判断,不然,就被业务层污染了。\r\n 要做这样的判断,请放在上一层(service)里,既灵活,又合理。\r\n\r\n## 请不要在一个模型里操作与之不相干的模型\r\n\r\n 这一条很难描述,需要借助一个例子。\r\n 还是 Article 类, 有错误的做法,给它写了一个 flushCache() 的方法,以便操作memcache、redis等以刷新缓存,\r\n 逻辑上说得通,但是缓存这一层,是超出于这个模型本身的(自己琢磨)。\r\n 正确的做法是,封装一个 Cache类,实现一个接收 articleId作参数的flush函数。\r\n\r\n## 函数逻辑里不需要实例化对象的,请弄成static\r\n\r\n 就是说,如果操作不是针对指定某个实例,理应写成静态。举个例子:\r\n $a = new Article($articleId);\r\n $count = $a->count();\r\n 这里的count实现就是不对的,虽然你可以让结果看起来是正确的,但是这样的代码,显然不能让人幸福。\r\n \r\n## 模型别包含常量\r\n\r\n 请使用其他途径管理你的常量,模型应该是个绝对抽象的概念,原则上是只得到数据,也能表达出全部意义,\r\n 不能让数据跟模型捆绑在一起。\r\n 举个例子,你的Article模型里有一个 type 属性,是个数字,而这个type对应的 字符串,你用一个map写在\r\n 模型里,这样就不对了,尽管很多人还是这样做,应该用配置文件活着另一个常量模型来管理这些数据。\r\n\r\n## 不要专门为一个业务功能实现一个方法\r\n\r\n 这种也十分常见,比如我要得到 一周内发表的技术文章 ,往往就造成一个 getTechArticleThisWeek 这样的函数,\r\n 时间一长,这类型方法就充斥在模型类里,我见过一个模型超过了 一万 行代码。\r\n 这又是典型的业务污染现象,你应该时刻明白一个原则,让你的模型迁移到别的项目也能全部发挥作用,只要数据没有变化。\r\n\r\n## 只实现最小功能单元,别做无谓的附加操作\r\n\r\n 弄清楚当前的功能,不要合并功能。举个例子,\r\n 把 读取article详情 这个功能,和 让访问记录加一 这个功能,写在一个函数里,这就是附加操作,你应该把两个功能分开,\r\n 该如何组合,交给业务层决定。(比如,管理后台不需要访问记录加一)\r\n\r\n## 不要有不为人知的反馈\r\n\r\n 这个case主要说的是,在你封装的函数里,不要秘密地改动 [全局变量]、[类的静态属性]等,\r\n 如果必须改,请以 引用参数 传进去,让掉用的人知道发生了什么。\r\n 比如这样的代码:\r\n function doLogin(){\r\n /* do sth */\r\n $_SESSION[\'user\'] = something ;\r\n return true;\r\n }\r\n 这段代码,调用方根本不知道操作了session,不看源码还不让人安心写业务了。\r\n 而下面的就好多了,清楚的告诉我,会操作一下session,并且改变它()\r\n function doLogin(& $session){\r\n /* do sth */\r\n $session[\'user\'] = something ;\r\n return true;\r\n }\r\n\r\n## 未完待续\r\n\r\n ',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(272,'【原创】Docker LAMP 入门','272',1447732440,1463024702,'<!--markdown-->**LAMP 服务器套件**(Linux + Apache + MySQL + PHP)早已成为 **Web 应用开发者** 最常用的**部署环境**,几乎是入门必修课,但它的搭建、维护也是对初学者很艰难的一课。虽然有 **XAMPP** 这样的跨平台一键安装包,但它们主要是为了方便搭建开发环境,并不适合直接用在**线上生产环境**。\r\n\r\n自己辛辛苦苦写好的网站上线都费事,简直太沮丧了…… 于是,各种各样的**云计算服务**应运而生,从各个层面解决不同水平 Web 应用开发者的部署需求。下面是从服务底层到用户顶层依次列出的常见**云计算服务模式** ——\r\n\r\n - **IaaS**(**基础设施** 即 服务)—— 云主机/服务器\r\n - **CaaS**(**应用容器** 即 服务)—— Docker\r\n - **PaaS**(**技术平台** 即 服务)—— AWS、GAE、SAE 等\r\n - **BaaS**(**后端 API** 即 服务)—— LeanCloud 等\r\n - **SaaS**(**应用软件** 即 服务)—— Tower、Worktile 等\r\n\r\n> 在云计算时代到来之前,还有几种常见的部署环境 ——\r\n>\r\n> - 类似 PaaS 的**网站空间** —— 本质上是一个操作系统中用 Apache 之类的 HTTP 服务器,对不同的域名 指向不同的**网站根目录**,所以上传网站文件只能用 FTP 读写你自己的目录,网站程序也不能读写本站之外的服务器目录,同机的所有网站共享一个 IP 地址\r\n> - 类似 IaaS 的 **VPS(虚拟主机)** —— 同样是独享一个操作系统的虚拟机,但究其**宿主环境**,一个 VPS 只能运行在一个真实的服务器主机上,而云主机则运行在一群真机协作抽象成的一个超级服务器(**服务器集群**)。后者的硬件资源 超高利用率、真机热插拔(便于扩展、容错)等特性,是前者望尘莫及的;但对它们的用户来说,包括 **独享 IP**、**SSH**(远程登录命令行)等关键特性在内的使用方法几乎完全一样\r\n\r\n至于 **Docker**,它旨在**把 Web 应用程序和它的标准运行环境(由一个配置文件描述)打包为一个虚拟机镜像**,让部署、迁移、扩展一键搞定,无需开发人员、运维人员手动配置云主机,因“开发与部署的环境不完全相同”而产生的 Bug 也没有了。\r\n\r\n---\r\n\r\n构建一个 **Ubuntu + LAMP** 镜像的 **Dockerfile** 配置文件 ——\r\n\r\n FROM ubuntu:14.04\r\n \r\n MAINTAINER test_32 \"[email protected]\"\r\n \r\n \r\n RUN apt-get update; \\\r\n apt-get install -y lamp-server^;\r\n \r\n COPY . /var/www\r\n EXPOSE 80\r\n \r\n CMD /etc/init.d/apache2 restart\r\n\r\n\r\n【参考文档】\r\n 1. http://blog.csdn.net/we_shell/article/details/38445979\r\n 2. http://blog.sina.com.cn/s/blog_7380598c0100wdl5.html\r\n 3. http://segmentfault.com/q/1010000000693754\r\n 4. http://dockerfile.github.io/#/ubuntu\r\n 5. http://www.alauda.cn/2015/07/12/dockerfiledemo/\r\n 6. http://dockerpool.com/static/books/docker_practice/\r\n 7. https://docs.docker.com/\r\n 8. http://www.aixq.com/post-328.html\r\n 9. http://blog.sina.com.cn/s/blog_4dc988240102vj8a.html\r\n 10. http://www.docker.org.cn/book/docker.html\r\n 11. http://my.oschina.net/ylchou/blog/522381\r\n 12. https://github.com/docker/kitematic/issues/1037\r\n 13. http://www.oschina.net/question/1171658_2177501',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(271,'几句话理解javascript中的执行上下文、this、作用域、闭包','271',1446571440,1446571440,'<!--markdown-->这几个问题是javascript问题中的老大难的几个问题,很多文章都有讲过这几个问题,但总也讲不清楚,希望可以尝试用最简单明了的语言把这几个事儿给说清楚了,部分内容并不是官方的定义,而是用简单易懂的语言表达出我所理解的概念。\r\n\r\n### 概念\r\n\r\n\r\n#### 执行上下文\r\n\r\n首先明确一点,所有的js代码都是在某个执行上下文中运行的。\r\n\r\n执行上下文可以看成以下对象:\r\n\r\n executionContextObj = {\r\n scopeChain: { /* 作用域链:变量对象+ 所有父执行上下文的变量对象*/ }, \r\n variableObject: { /*变量对象:函数 arguments/参数,内部变量和函数声明 */ }, \r\n this: { /*运行这个函数的对象(动态的) */ } \r\n }\r\n \r\njs解释器实现了一个执行上下文堆栈,并且总是在栈顶的执行上下文中执行代码。\r\n\r\n当js解释器初始化执行代码时,它首先默认压入一个全局执行上下文到栈中,在此基础上任何一次函数的调用都将压入一个新的执行上下文到栈中,函数执行结束后该执行上下文被弹出。\r\n\r\n![test](http://ww3.sinaimg.cn/large/d9f8fd81gw1exnvbj1v68j20ff080my4.jpg)\r\n\r\n创建执行上下文是根据按照以下步骤创建的(有先后顺序):\r\n\r\n1. 创建当前执行上下文的变量对象(在函数中称为活跃对象):\r\n 1. 创建arguments对象(如果是函数调用的话),初始化参数名称和值并创建引用的复制。其属性名就是形参的名字,其值就是实参的值;对于没有传递的参数,其值为undefined\r\n 2. 扫描当前执行上下文内的所有函数声明:为发现的每一个函数,在变量对象上创建一个属性,属性名是函数的名字,并且指向函数在内存中的引用,如果变量对象已经包含了相同名字的属性,则替换他的值为当前函数在内存中的引用。(这里的函数扫描只扫描用函数声明定义的函数,不包括函数表达式定义的函数)\r\n 3. 扫描当前执行上下文内的所有变量声明:为发现的每个变量声明,在变量对象上创建一个属性,属性名就是变量的名字,并且将变量的值初始化为undefined,如果变量的名字已经在变量对象里存在,则不会进行任何操作并继续扫描,\r\n2. 求出执行上下文内部“this”的值:在全局运行上下文中(在任何函数体外部),this 指代全局对象,无论是否在严格模式下;在函数内部,this的值取决于函数是如何调用的。(关于求this的值,本文后面再讲)\r\n3. 初始化作用域链:作用域链对执行上下文中的变量对象的有序访问的链表,包括当前执行上下文的变量对象,以及包含了所有上层变量对象的分层链(在函数创建时静态保存在函数中的)\r\n\r\n整个js代码的执行机制就是上面所说的,上面的内容其实包括了执行上下文、作用域链、提升机制,有了以上知识储备,我们再来理解这些难懂的概念就比较容易了:\r\n\r\n#### 作用域\r\n\r\n作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在js中,变量的作用域有全局作用域和局部作用域两种。\r\n\r\n- 全局作用域:在代码中任何地方都能访问到的对象拥有全局作用域,有以下几种:\r\n - 在最外层定义的变量;\r\n - 全局对象的属性;\r\n - 任何地方隐式定义的变量(未定义直接赋值的变量),在任何地方隐式定义的变量都会定义在全局作用域中,即不通过 var 声明直接赋值的变量。\r\n- 局部作用域:JavaScript的作用域是通过函数来定义的,在一个函数中定义的变量只对这个函数内部可见,称为函数(局部)作用域\r\n\r\n#### this\r\n\r\n在函数执行时,this 总是指向调用该函数的对象。要判断 this 的指向,其实就是判断 this 所在的函数属于谁。\r\nthis 出现的场景分为四类,简单的说就是:\r\n\r\n- 有对象就指向调用对象\r\n- 没调用对象就指向全局对象\r\n- 用new构造就指向新对象\r\n- 通过 apply 或 call 或 bind 来改变 this 的所指。\r\n\r\n#### 闭包\r\n\r\n闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。闭包是指函数有自由独立的变量。换句话说,定义在闭包中的函数可以“记忆”它创建时候的环境。定义在闭包中的函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。\r\n\r\n### 例子\r\n\r\n//todo\r\n\r\n### 总结\r\n\r\n//todo\r\n\r\n\r\n\r\n参考链接:\r\n\r\n- http://yanhaijing.com/javascript/2014/04/29/what-is-the-execution-context-in-javascript/\r\n- http://segmentfault.com/a/1190000002692982\r\n- http://blog.5ibc.net/p/17359.html\r\n- http://yanhaijing.com/javascript/2014/04/30/JavaScript-Scoping-and-Hoisting/\r\n- https://github.com/alsotang/node-lessons/tree/master/lesson11\r\n- http://segmentfault.com/a/1190000000533094\r\n- http://www.k68.org/?p=1831\r\n- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(260,'V8引擎几个常见无法优化的点','260',1436866500,1436866559,'<!--markdown-->## 1. try-catch(-final)\r\n 但凡在函数中有try-catch语句的,会导致整个函数无法优化。\r\n 所以,应该把try-catch语句封装到一个独立的函数里。\r\n \r\n //不能优化\r\n function(){\r\n /**\r\n **一些业务\r\n **/\r\n try{\r\n //do sth\r\n }catch(ex){\r\n //handle\r\n }\r\n }\r\n\r\n //能被优化\r\n var foo = function(){\r\n try{\r\n //do sth\r\n }catch(ex){\r\n //handle\r\n }\r\n }\r\n function(){\r\n /**\r\n **一些业务\r\n **/\r\n\r\n foo();\r\n\r\n }\r\n## 2. with语句\r\nwith语句可以少写很多对象名,但是不值得,因为它也会导致整个函数无法优化\r\n\r\n function(){\r\n with(object1){\r\n name = \'tom\';\r\n }\r\n /**\r\n * 应该写成\r\n * object1.name = \'tom\';\r\n */\r\n }\r\n## 3. For-In\r\nfor-in 并不是不能优化,只是有比它效率更高的便利对象方式\r\n\r\n var keys = Object.keys(object1);\r\n for (var i = 0; i < keys.length; i++) {\r\n //do sth with object1[i]\r\n //这种方式会优化得很好\r\n }\r\n## 4. Yield\r\n这个我不太了解就不说了,作为这么重要的东西,V8后续版本应该会给它做优化的吧\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(261,'Redis 的 GEO还没来到,也可以自己实现的 ','261',1437448020,1462783579,'<!--markdown-->听说GEO快要出来了,还没了解到具体原理,\r\n不过在这之前,我倒是用redis实现了基于地理位置的处理。\r\n# 有点绕,有更好办法的欢迎指出。\r\n\r\n**zset** 、 **sinter**\r\n\r\n### 基础一\r\nzset是set的一个特殊表现,它可以给每个成员附加一个score排序,从小到大。\r\nzset的一个灵活应用在于范围查询,比如你存储的member是uid,score是年龄,\r\n那你可以用 `ZRANGEBYSCORE key 18 22` 来查询18到22岁的uid集合\r\n\r\n### 基础二\r\nsinter 文档只看到对set的操作,它是取两个集合的交集,(有看到支持zset的请通知我一下)。\r\n比如,集合test1 = [ 1 , 2 , 3 ],集合test2 = [ 2 , 3 , 4], (test1、 test2是两个set,这里用数组表示)\r\n那么,sinter test1 test2 就会返回 [2,3]\r\n\r\n### 实现\r\n1.参考基础一,以 uid(用户) 或 place(地点) 作为member,**经度**作为 score 存储一个zset set1,\r\n2.同样,参考基础一,以 uid(用户) 或 place(地点) 作为member,**纬度**作为 score 存储一个zset set2,\r\n3.根据基础一的范围查询,分别查询两个zset在某个经度(纬度)范围内的结果,得到两个临时结果 **无序set**\r\n3.1 (把两个临时结果存放在 set 里,用完后自行删除)\r\n4.这两个临时set做交集,就能得到既在某经度范围内,也在某纬度范围内的坐标了',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(262,'nodejs中exports和module.exports的区别','262',1439396940,1439397020,'<!--markdown-->**用一句话来说明就是,require方能看到的只有module.exports这个对象,它是看不到exports对象的,而我们在编写模块时用到的exports对象实际上只是对module.exports的引用**\r\n\r\n\r\n如果你能理解上面这句话,那么下面的都是废话,可以不用看了,因为是用来解释上面这句话的。\r\n\r\n关于引用,可以用下面的例子来让你搞得请清楚楚的:\r\n\r\n\r\n首先说一个概念:\r\n\r\nECMAScript的变量值类型共有两种:\r\n\r\n基本类型 (primitive values) : 包括Undefined, Null, Boolean, Number和String五种基本数据类型;\r\n\r\n引用类型 (reference values) : 保存在内存中的对象们,不能直接操作,只能通过保存在变量中的地址引用对其进行操作。\r\n\r\n我们今天要讨论的exports和module.exports属于Object类型,属于引用类型。\r\n\r\n看下面的例子:\r\n\r\n var module = {\r\n exports:{\r\n name:\"我是module的exports属性\"\r\n }\r\n };\r\n var exports = module.exports; //exports是对module.exports的引用,也就是exports现在指向的内存地址和module.exports指向的内存地址是一样的\r\n \r\n console.log(module.exports); // { name: \'我是module的exports属性\' }\r\n console.log(exports); // { name: \'我是module的exports属性\' }\r\n \r\n \r\n exports.name = \"我想改一下名字\";\r\n \r\n \r\n console.log(module.exports); // { name: \'我想改一下名字\' }\r\n console.log(exports); // { name: \'我想改一下名字\' }\r\n //看到没,引用就是a和b都操作同一内存地址下的数据\r\n \r\n \r\n //这个时候我在某个文件定义了一个想导出的模块\r\n var Circle = {\r\n name:\"我是一个圆\",\r\n func:function(x){\r\n return x*x*3.14;\r\n }\r\n };\r\n \r\n exports = Circle; // 看清楚了,Circle这个Object在内存中指向了新的地址,所以exports也指向了这个新的地址,和原来的地址没有半毛钱关系了\r\n \r\n console.log(module.exports); // { name: \'我想改一下名字\' }\r\n console.log(exports); // { name: \'我是一个圆\', func: [Function] }\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n回到nodejs中,module.exports初始的时候置为```{}```,exports也指向这个空对象。\r\n\r\n那么,这样写是没问题的:\r\n\r\n exports.name = function(x){\r\n console.log(x);\r\n };\r\n \r\n //和下面这个一毛一样,因为都是修改的同一内存地址里的东西\r\n \r\n \r\n module.exports.name = function(x){\r\n console.log(x);\r\n };\r\n\r\n但是这样写就有了区别了:\r\n\r\n exports = function(x){\r\n console.log(x);\r\n };\r\n \r\n //上面的 function是一块新的内存地址,导致exports与module.exports不存在任何关系,而require方能看到的只有module.exports这个对象,看不到exports对象,所以这样写是导不出去的。\r\n \r\n //下面的写法是可以导出去的。说句题外话,module.exports除了导出对象,函数,还可以导出所有的类型,比如字符串、数值等。\r\n module.exports = function(x){\r\n console.log(x);\r\n };\r\n\r\n我讲清楚了吧?',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(264,'编写一个原生的Promise封装函数','264',1442999976,1442999976,'<!--markdown--> ## Show Code First\r\n\r\n var Promised = function (fn) {\r\n return function () {\r\n var args = [];\r\n for(var k in arguments){\r\n args.push(arguments[k]);\r\n }\r\n //console.log(args);\r\n return new Promise(function (resolve, reject) {\r\n var done = function (e,r) {\r\n if(!e){\r\n resolve(r);\r\n }else{\r\n reject(e)\r\n }\r\n };\r\n args.push(done);\r\n fn.apply(this,args);\r\n });\r\n }\r\n\r\n## How To Use\r\n\r\n var getAjax = Promised(req.get);\r\n getAjax(\'http://121.41.85.236:33002/beating\').then(function (ret) {\r\n console.log(ret.body);\r\n }).catch(function (err) {\r\n console.log(err);\r\n });\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(265,'开发者的macbook开始配置指南','265',1443191280,1443203632,'<!--markdown-->买了个32寸的大屏幕没想到与macbook的连接总是不稳定,今天终于狠下心来准备重新安装下全新的10.10.5的系统。我把安装和配置的过程记录一下。\r\n\r\n在这之前用移动硬盘备份里我的重要数据。然后开始弄:\r\n\r\n1.制作u盘启动盘 参考的这篇文章:http://get.jobdeer.com/6074.get ,使用磁盘工具抹去了硬盘的全部资料,待会儿安装。\r\n\r\n2.安装过程很简单,按照提示一步步来就ok。然后开始配置mac,我是参考这篇文章做的配置:https://www.gitbook.com/book/aaaaaashu/mac-dev-setup/details\r\n\r\n\r\n没什么了。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(266,'docker学习资料','266',1443431220,1443438554,'<!--markdown-->1. [Docker简明教程](http://blog.saymagic.cn/2015/06/01/learning-docker.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io)\r\n\r\n\r\n2. [Docker for PHP Developers](http://www.newmediacampaigns.com/blog/docker-for-php-developers)\r\n\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(267,'react和webpack的学习资料汇总','267',1443902039,1443902039,'<!--markdown-->[react小书 ](https://fakefish.github.io/react-webpack-cookbook/index.html)\r\n\r\n待更新',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(268,'理解http中的幂等','268',1444902504,1444902504,'<!--markdown-->Http中对幂等最准确、最易理解的定义是:不用担心重复执行会对系统造成改变的行为就是幂等的。而不是说结果一定是一样的。\r\n\r\n以HTTP GET、DELETE、PUT、POST四种方法为主进行语义和幂等性的介绍:\r\n\r\n来源: http://www.i3geek.com/archives/841\r\n\r\n> HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。\r\n\r\n> HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。\r\n\r\n> HTTP POST方法用于创建资源,所对应的URI并非创建的资源本身,而是去执行创建动作的操作者,有副作用,不满足幂等性。比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。\r\n\r\n>HTTP PUT方法用于创建或更新操作,所对应的URI是要创建或更新的资源本身,有副作用,它应该满足幂等性。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(269,'减少switch case语句的使用','269',1446446199,1446446199,'<!--markdown-->上次在程序中使用了switch case的语句,被一群大大们嘲笑了。所以还是在这记一下将switch case的结构如何更改。\r\n\r\n为什么被嘲笑呢,因为switch...case结构要求,在每一个case的最后一行必须是break语句,否则会接着运行下一个case。这样不仅容易忘记,还会造成代码的冗长。\r\n\r\n而且,switch...case不使用大括号,不利于代码形式的统一。此外,这种结构类似于goto语句,容易造成程序流程的混乱,使得代码结构混乱不堪,不符合面向对象编程的原则。\r\n\r\n用js的语法示例如下\r\n\r\n function doAction(action) {\r\n switch (action) {\r\n case \'hack\':\r\n return \'hack\';\r\n break;\r\n \r\n case \'slash\':\r\n return \'slash\';\r\n break;\r\n \r\n case \'run\':\r\n return \'run\';\r\n break;\r\n \r\n default:\r\n throw new Error(\'Invalid action.\');\r\n break;\r\n }\r\n }\r\n上面的代码建议改写成对象结构。\r\n\r\n function doAction(action) {\r\n var actions = {\r\n \'hack\': function () {\r\n return \'hack\';\r\n },\r\n \r\n \'slash\': function () {\r\n return \'slash\';\r\n },\r\n \r\n \'run\': function () {\r\n return \'run\';\r\n }\r\n };\r\n \r\n if (typeof actions[action] !== \'function\') {\r\n throw new Error(\'Invalid action.\');\r\n }\r\n \r\n return actions[action]();\r\n }\r\n因此,避免使用switch...case结构,用对象结构代替。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(270,'读《减少switch case语句的使用》有感','270',1446552360,1446552485,'<!--markdown-->### 原文地址\r\n\r\n http://log.fyscu.com/index.php/archives/269/\r\n\r\n#### 现在我是作为一个长者,给你们一些人生经验 \r\n\r\n\r\n----------\r\n\r\n\r\n\r\n\r\n#### 原文\r\n 因为switch...case结构要求,在每一个case的最后一行必须是break语句\r\n#### 评:\r\n 并不是“必须break”,反而在实际编码中,经常少写一些break,以实现分类、聚合的功能\r\n 比如:\r\n switch (day){\r\n case \'星期一\':\r\n case \'星期二\':\r\n case \'星期三\':\r\n case \'星期四\':\r\n case \'星期五\':\r\n return \'工作日\';\r\n break;\r\n case \'星期六\':\r\n case \'星期日\':\r\n return \'假日\';\r\n break;\r\n }\r\n\r\n#### 结论\r\n 啪!\r\n\r\n\r\n----------\r\n\r\n\r\n\r\n\r\n#### 原文\r\n 建议改写成对象结构\r\n#### 评\r\n 太恶心了!\r\n 用原本case的字符串来做对象成员,如果是 \'baidu\',\'腾讯\',\'360\' 呢?\r\n switch本来的作用就是匹配变量不同的字符串,分流到不同的逻辑,可以说是这个个案里最理想的解决办法,\r\n 而用原文中的“面向对象”的方法,主要有如下问题:\r\n 1.总不能用中文key吧\r\n 2.不能聚合,除非先定义function,多个key指向同一个function,那样实际上更乱\r\n 3.当输入枚举增加,你就要修改object,违反了\"开-闭 原则\"(http://log.fyscu.com/index.php/archives/60/),不是一种好现象\r\n 4.垃圾回收的时候,如果返回值没有被释放,那么doAction即使已经执行完了,也会因此而不被回收,这种习惯有OOM的风险\r\n 5.如果有需要处理上下文中的变量,返回的function的参数表就会和业务耦合得很厉害(这一点自己领会)\r\n 6.凑数\r\n\r\n#### 结论\r\n 啪!啪!\r\n\r\n\r\n----------\r\n\r\n\r\n\r\n\r\n#### 小蓝说\r\n 其实switch...case 作为几乎所有语言基本语法的一部分,肯定是千锤百炼的,无需怀疑的,\r\n 一些忘记写break之类的问题,一方面多从自己身上找原因,理清思路才是真,\r\n 此外也可以换个好点的IDE,比如webstorm,设置一些代码模板,自动break。\r\n\r\n 而对于原文中的 object 方法,属于JS比较有特点的对象声明方式,我们尽量还是用比较通用化的办法,\r\n 积累的经验以后在其他语言也能用。\r\n \r\n\r\n\r\n [1]: http://log.fyscu.com/index.php/archives/60/',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(259,'[JS]对象复制的奇技淫巧一则','259',1433748882,1433748882,'<!--markdown-->Javascript的对象操作,直接用 “=” 结果是对象的一个引用,任意一个引用的改变都会让原对象产生变化。\r\n\r\n而很多时候我们需要对一个对象进行“复制”,最直观的方法是遍历原对象,这也是最实际的方法。\r\n\r\n而在这我们给出一个“奇技淫巧”,仅适用于对象成员都是基本数据类型。\r\n(适用于诸如 `对象模板` 等应用场景)\r\n\r\n var a = {\r\n \'a\':1\r\n };\r\n\r\n var b = JSON.parse(JSON.stringify(a));\r\n b.a=2;\r\n\r\n console.log(a); //Object { a=1}\r\n console.log(b); //Object { a=2}\r\n\r\n可以发现,经过序列化/反序列化操作,原对象被“简单”的复制了一遍(主要是因为序列化以后是string简单类型)。\r\n这个方法代码简单,具体`时间效率`还需要实际测试一下。\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(253,'屏幕快照 2015-05-15 下午4.07.31.png','屏幕快照-2015-05-15-下午4-07-31-png',1431677527,1431677527,'a:5:{s:4:\"name\";s:41:\"屏幕快照 2015-05-15 下午4.07.31.png\";s:4:\"path\";s:35:\"/usr/uploads/2015/05/2597052319.png\";s:4:\"size\";i:92156;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,2,NULL,'attachment','publish',NULL,0,'1','0','1',256),(254,'屏幕快照 2015-05-15 下午4.12.52.png','屏幕快照-2015-05-15-下午4-12-52-png',1431677585,1431677585,'a:5:{s:4:\"name\";s:41:\"屏幕快照 2015-05-15 下午4.12.52.png\";s:4:\"path\";s:35:\"/usr/uploads/2015/05/3026282544.png\";s:4:\"size\";i:79464;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,2,NULL,'attachment','publish',NULL,0,'1','0','1',256),(255,'屏幕快照 2015-05-15 下午4.14.20.png','屏幕快照-2015-05-15-下午4-14-20-png',1431677675,1431677675,'a:5:{s:4:\"name\";s:41:\"屏幕快照 2015-05-15 下午4.14.20.png\";s:4:\"path\";s:35:\"/usr/uploads/2015/05/1983620911.png\";s:4:\"size\";i:51133;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',256),(256,' 实测 对数字字符串转成数字的效率比较','256',1431750008,1431750008,'<!--markdown-->代码:\r\n\r\n var a = \'1\' ;\r\n for (var i = 0; i < 100000000; i++) {\r\n parseInt(a); //方案一\r\n // a * 1; //方案二\r\n }\r\n console.log(process.uptime());\r\n \r\n结果,单位秒:\r\n方案一: 1.559 , 1.492 , 1.523\r\n方案二:3.841 , 3.899 , 3.877',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(257,'接口的简单介绍和fm.scuinfo.com的实现','257',1431770100,1431770247,'<!--markdown-->接口的简单介绍和fm.scuinfo.com的实现\r\n\r\n**我说的可能都是错的,希望给你带来思考。**\r\n\r\n## 接口是什么?\r\n\r\n定义:应用程序接口(英语:Application Programming Interface,简称:API)\r\n\r\n通俗的解释就是:提供转接的口子,遵循同一个规则的多个程序之间交换数据的一种方式。\r\n\r\n\r\n####网络接口。\r\n\r\n例如以 HTTP GET 方式请求 `http://fm.scuinfo.com/api/posts` 并获取返回值, `http://fm.scuinfo.com/api/posts` 就可以视为一个接口。\r\n\r\n####程序内部接口\r\n\r\n比如函数,也可以算是接口。\r\n\r\n\r\n**可以这样说: `返回值 方法名(参数1, 参数2 ...)` 长得像这样的都是接口。**\r\n\r\n通过调用接口,可以获取,提交数据->从而去操作数据。\r\n\r\n## 接口传递数据的数据格式\r\n\r\n#### json\r\n\r\n {\r\n code:200,\r\n message:\"ok\",\r\n data:{\r\n title:\"这里是标题\"\r\n }\r\n }\r\n\r\n\r\n\r\n#### xml\r\n\r\n <result>\r\n <code>200</code>\r\n <message>ok</message>\r\n <data>\r\n <title>这里是标题<title/>\r\n </data>\r\n </result>\r\n\r\n## 一个活生生的例子\r\n\r\n我们来看最近刚刚上线的神奇海螺的例子:\r\n\r\n我们先来访问一下: [http://fm.scuinfo.com](http://fm.scuinfo.com) \r\n\r\n\r\n#### 帖子列表接口定义:\r\n\r\n {\r\n method:\"get\",\r\n url:\"/api/posts\"\r\n params:{\r\n pageSize:10 //请求的文章数\r\n fromId:5488 //从第5488个文章id往前的10篇文章\r\n }\r\n }\r\n\r\n return:{\r\n \"code\": 200,\r\n \"message\": \"success\",\r\n \"data\": [\r\n {\r\n \"id\": 5488,\r\n \"title\": \"我要零食……\",\r\n \"gender\": 1,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww4.sinaimg.cn/mw690/a958717cgw1erw70ntdhuj20fs0fsdh9.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 0,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 0,\r\n \"like\": 0,\r\n \"date\": 1431747866,\r\n \"more\": 0\r\n },\r\n {\r\n \"id\": 5480,\r\n \"title\": \"#海螺#缘分真是神奇的东西 拿给我吧\",\r\n \"gender\": 2,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww1.sinaimg.cn/mw690/a958717cgw1erw6zm4z9qj20fs0fs0tx.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 0,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 0,\r\n \"like\": 0,\r\n \"date\": 1431734448,\r\n \"more\": 0\r\n },\r\n {\r\n \"id\": 5479,\r\n \"title\": \"#海螺#第一次写,我觉得男女主播应该是一对,大家觉得咋样?记得翻我牌啊,还有怎么点歌啊?\",\r\n \"gender\": 1,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww4.sinaimg.cn/mw690/a958717cgw1erw6ueyjnnj20fs0fst9x.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 1,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 2,\r\n \"like\": 0,\r\n \"date\": 1431714369,\r\n \"more\": 0\r\n },\r\n {\r\n \"id\": 5478,\r\n \"title\": \"上个月我找到了一台平板电脑,到现在为止找不到主任,那我怎么办呐?\\n如果有弄丢平板电脑的人话,跟18280063697联系。\\n我叫马木提江。\",\r\n \"gender\": 1,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww3.sinaimg.cn/mw690/a958717cgw1erw6xvhywjj20fs0fsq48.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 0,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 2,\r\n \"like\": 0,\r\n \"date\": 1431713829,\r\n \"more\": 0\r\n },\r\n {\r\n \"id\": 5477,\r\n \"title\": \"#海螺#海螺海螺告诉我,如何拐到男主播?\",\r\n \"gender\": 2,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww2.sinaimg.cn/mw690/a958717cgw1erw710tlblj20fs0fswfp.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 0,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 1,\r\n \"like\": 0,\r\n \"date\": 1431713541,\r\n \"more\": 0\r\n },\r\n {\r\n \"id\": 5476,\r\n \"title\": \"想找一个性格开朗素颜也很美的女朋友,你在哪?\",\r\n \"gender\": 1,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww3.sinaimg.cn/mw690/a958717cgw1erw6z87przj20fs0fs0u5.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 0,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 1,\r\n \"like\": 0,\r\n \"date\": 1431710522,\r\n \"more\": 0\r\n },\r\n {\r\n \"id\": 5475,\r\n \"title\": \"超想知道在电台听到自己的名字会是什么感觉!叫谁呢……额……叫一个不熟的吧……额,会不会被打呀……这……好吧,我只是逗比来了\",\r\n \"gender\": 2,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww2.sinaimg.cn/mw690/a958717cgw1erw710tlblj20fs0fswfp.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 0,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 1,\r\n \"like\": 0,\r\n \"date\": 1431709419,\r\n \"more\": 0\r\n },\r\n {\r\n \"id\": 5474,\r\n \"title\": \"爱上一个学渣……没关系,我也是学渣~重点是,没人爱\",\r\n \"gender\": 2,\r\n \"secret\": 1,\r\n \"avatar\": \"http://ww1.sinaimg.cn/mw690/a958717cgw1erw6zm4z9qj20fs0fs0tx.jpg\",\r\n \"nickname\": \"某同学\",\r\n \"commentCount\": 0,\r\n \"author\": 0,\r\n \"userId\": 0,\r\n \"likeCount\": 0,\r\n \"like\": 0,\r\n \"date\": 1431709308,\r\n \"more\": 0\r\n }\r\n ]\r\n }\r\n \r\n \r\n### 前端ajax获取数据,并渲染。\r\n\r\n $.get(\'http://fm.scuinfo.com/api/posts\',function(data){\r\n \r\n if(data.code==200){\r\n //把数据组装成html,打印到 浏览器里\r\n }else{\r\n alert(data.message);\r\n }\r\n \r\n });\r\n\r\n\r\nok,恩,整个fm.scuinfo.com 就是这样咯。\r\n ',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(251,'Nodejs开发环境搭建','251',1431667800,1431690010,'<!--markdown--># Nodejs开发环境搭建\r\n\r\n## 安装Nodejs\r\n[Nodejs官网](https://nodejs.org/)\r\n\r\n[Nodejs下载](https://nodejs.org/download/)\r\n\r\n### Windows\r\n1. 官方提供了Windows的安装包(.msi)。二进制文件,npm,环境变量一站式服务轻松搞定。简单、傻瓜、一劳永逸,你值得拥有。按提示next就行了。\r\n2. 万恶的官方还提供了单独的编译好的二进制文件(.exe)供不安分的骚年作死。\r\n\r\n#### 正确的折腾方法\r\n下载好的node.exe就是node的可执行文件,直接运行可进入命令行模式。\r\n\r\n1. 建立node的目录,以 **D:\\nodejs** 为例。将node.exe放到D:\\nodejs下\r\n2. 将 **D:\\nodejs** 添加到PATH环境变量: cmd执行`set Path=%Path%;D:\\nodejs`。接下来就可以直接在cmd中执行node了。\r\n3. 安装npm: 下载[npm源码](https://github.com/npm/npm/tags)并解压。 打开命令行进入其目录执行`node cli.js install -gf`完成之后,D:\\nodejs目录会多出node_modules、npm.cmd等等就算是安装成功了。压缩包和解压的东西完事后自行处理.\r\n\r\n使用命令查看版本号\r\n```\r\nnode -v // v0.12.2\r\nnpm -v // 2.7.4\r\n```\r\n可检查安装是否正确\r\n\r\n两种方式没有区别,推荐使用.msi安装... 以上属于瞎折腾\r\n\r\n### Linux\r\n\r\n#### 1. 二进制文件安装\r\n\r\n直接下载编译好的二进制文件。命令可直接运行。\r\n```\r\ncd node-v0.12.2-linux-x64/bin\r\n./node -v\r\nv0.12.2\r\n./npm -v\r\n2.7.4\r\n```\r\n\r\n设置连接\r\n```\r\nln -s /path/to/node-v0.12.2-linux-x64/bin/node /usr/local/bin/node\r\nln -s /path/to/node-v0.12.2-linux-x64/bin/npm /usr/local/bin/npm\r\n```\r\n\r\n#### 2. 源码编译安装\r\n\r\n安装条件:\r\n- python2.6或2.7\r\n- gcc和g++\r\n- make\r\n\r\n编译前,请先确保这些已安装\r\n```\r\n// 下载源码\r\nwget http://nodejs.org/dist/v0.12.2/node-v0.12.2.tar.gz\r\n\r\n// 解压包\r\ntar -xvf node-v0.12.2.tar.gz\r\n\r\n// 进入目录\r\ncd node-v0.12.2\r\n\r\n// configure\r\nsudo ./configure\r\n\r\n// 编译安装\r\nsudo make && make install\r\n```\r\n\r\n时间稍长,耐心等待~\r\n\r\n\r\n#### 3. 使用包管理工具安装\r\n具体情况视包管理工具而定,例如 `sudo apt-get install nodejs npm`。\r\n通常这种方式获得的node版本不是最新的,看自己喜好喽。\r\n\r\n## IDE\r\n推荐使用[WebStorm :: The smartest JavaScript IDE](http://www.jetbrains.com/webstorm/),谁用谁知道。\r\n\r\n如果已安装nodejs,WS会自己根据环境变量自动配置node和npm。若先安装的WS,可在安装好nodejs后在 Configure(File) -> Default Settings -> Language & Frameworks -> Node.js and NPM 中按路径设置 Node(.exe) 。\r\n\r\nPS:WS使用java开发,安装前请确保有java环境。',0,10,NULL,'post','publish',NULL,0,'1','1','1',0),(250,'[模块分享] nodemon','250',1431498404,1431498404,'<!--markdown-->\r\n# http://nodemon.io/\r\n nodemon 可以在node程序开发阶段,自动监测代码变化,自动重启程序,\r\n 让你可以像写php一样,保存一下,刷新页面就有效果。\r\n\r\n# 安装\r\n`npm install nodemon -g`\r\n\r\n 安装在全局,所有项目都能用。\r\n\r\n# 使用\r\n\r\n nodemon app.js 代替原来的 node app.js\r\n 值得注意的是,nodemon是监控当前启动nodemon的目录,\r\n 所以,如果你在 / 下启动 nodemon /path/of/app.js\r\n 它将监控整个 / 的变化。细思极恐\r\n\r\n# 建议\r\n 建议启动nodemon时,加上 -i 参数,忽略掉views目录和public目录,\r\n nodemon app.js -i views -i public \r\n -i 参数表示忽略指定目录或文件的变化。\r\n 这样做的好处是,单纯改改html、css、js这种文件的时候,不用自动重启,\r\n 导致session丢失的问题。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(247,'jquery给新加的元素绑定事件的最佳方法','247',1430499567,1430499567,'<!--markdown-->曾看见过发过一篇文章里面洋洋洒洒写了jquery新建的元素事件绑定问题的4个方法,地址是:http://log.fyscu.com/index.php/archives/180/,看完后差点被骗了。因为我发现了更好用的方法,且是官方非常推荐的。 我得出的结论是,该文章的方法比较适合2010年的web。\r\n\r\n解决新增元素最佳的方法是:\r\n\r\n\r\n使用jquery的on来监听,\r\n\r\n $(\"selector\").on( events [, selector ] [, data ], handler(eventObject) )\r\n\r\non方法接收4个参数,第一个是事件名称,第二个是可选的 一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素,我们可以在第二个参数里面去寻找我们新增的元素。例如:\r\n\r\n\r\n $(\"#posts\").append(\'<article><div class=\"content\">dsgygb</div></article>\')\r\n\r\n $(\"#post\").on(\"click\",\".content\",function(){\r\n \r\n console.log(\'dsgygb被点到了\');\r\n }\r\n\r\n这里有一个前提是,```#post```需在原来的dom中存在。\r\n\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(248,'移动网页开发的几个手指点击、拖动等的事件的英文和中文','248',1430565943,1430565943,'<!--markdown-->Tap 单指点击、点击\r\nPinch 双指缩放,双指聚拢\r\nUnpinch 双指缩放,双指张开\r\nPan 拖动,慢速多动\r\nSwipe 滑动,快速拖动\r\nRotation 双指旋转,旋转\r\nLong Press 长按',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(249,'[ Javascript探究 ] delete','249',1431399454,1431399454,'<!--markdown-->1,对象属性删除\r\n\r\n function fun(){\r\n this.name = \'mm\';\r\n }\r\n \r\n var obj = new fun();\r\n \r\n console.log(obj.name);//mm\r\n \r\n delete obj.name;\r\n \r\n console.log(obj.name); //undefined\r\n\r\n2,变量删除\r\n \r\n var name = \'lily\';\r\n delete name;\r\n console.log(name); //lily\r\n\r\n`直接用delelte删除不了变量`\r\n\r\n3,删除不了原型链中的变量\r\n \r\n fun.prototype.age = 18;\r\n delete obj.age;\r\n console.log(obj.age) //18',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(246,'在PHP中使用包管理器composer安装react/http','246',1429776240,1429776295,'<!--markdown-->想不想在php中使用类似nodejs的npm的包管理工具?\r\n\r\ncomposer给了我们几乎一毛一样的体验。如何开始?听我娓娓道来:\r\n\r\n## 1.安装Composer\r\n\r\nComposer需要PHP 5.3.2+才能运行。\r\n\r\n curl -sS https://getcomposer.org/installer | php\r\n\r\n这个命令会将composer.phar下载到当前目录。PHAR(PHP 压缩包)是一个压缩格式,可以在命令行下直接运行。\r\n\r\n你也可以使用--install-dir选项将Composer安装到指定的目录,例如:\r\n\r\n curl -sS https://getcomposer.org/installer | php -- --install-dir=bin\r\n\r\n当然也可以进行全局安装:\r\n\r\n curl -sS https://getcomposer.org/installer | php\r\n mv composer.phar /usr/local/bin/composer\r\n\r\n在Mac OS X下可以使用brew安装:\r\n\r\n brew tap josegonzalez/homebrew-php \r\n brew install josegonzalez/php/composer \r\n\r\n不过通常情况下只需将composer.phar的位置加入到PATH环境变量就可以,不一定要全局安装。\r\n\r\n## 2.声明依赖\r\n在项目目录下创建一个composer.json文件,指明依赖,比如,你的项目依赖 monolog:\r\n\r\n {\r\n \"require\": {\r\n \"monolog/monolog\": \"1.2.*\"\r\n }\r\n }\r\n\r\n## 3.安装依赖\r\n安装依赖非常简单,只需在项目目录下运行:\r\n\r\n composer install \r\n\r\n如果没有全局安装的话,则运行:\r\n\r\n php composer.phar install \r\n## 4.引入包\r\n\r\nComposer提供了自动引入的特性,只需在你的项目代码的初始化部分中加入下面一行:\r\n\r\n require \'vendor/autoload.php\'; \r\n\r\n你的当前php文件就自动引入了所有的包。\r\n\r\n\r\n好的,如果你到这一步了,那么恭喜你已进入composer的世界!接下来,我将创建一个调用composer包里面的非常著名的```react/http```包来做一个示例。这个包号称是用nodejs来写php。\r\n\r\n1. 先创建一个新的文件夹来放这个项目,假设文件夹名叫```app```\r\n\r\n2. 在```app```下创建一个名为```composer.json```的文件夹,并写入以下依赖:\r\n \r\n \r\n {\r\n \"require\": {\r\n \"react/http\": \"*\"\r\n }\r\n }\r\n\r\n\r\n3.在命令行```app```项目下,运行```composer install```\r\n\r\n\r\n4.安装好之后,新建一个```app.php```文件,作为项目的入口文件,并写入以下代码:\r\n\r\n <?php\r\n\r\n require \'vendor/autoload.php\';\r\n\r\n $loop = React\\EventLoop\\Factory::create();\r\n $socket = new React\\Socket\\Server($loop);\r\n\r\n $http = new React\\Http\\Server($socket);\r\n $http->on(\'request\', function ($request, $response) {\r\n $response->writeHead(200, array(\'Content-Type\' => \'text/plain\'));\r\n $response->end(\"Hello World!\\n\");\r\n });\r\n\r\n $socket->listen(1337);\r\n $loop->run();\r\n\r\n\r\nok,一切皆已完成,现在就用你的浏览器访问:localhost:1337 ,你会发现\'hello world\'将会射入你眼中。\r\n\r\n这是react/http的例子,安装其他的包的方法都一样,下面给一些常用的链接:\r\n\r\n1.[composer包浏览(官方)](https://packagist.org/) https://packagist.org/\r\n\r\n2.[composer中文站](http://www.phpcomposer.com/) http://www.phpcomposer.com/\r\n\r\n3.[composer官网](https://getcomposer.org/) https://getcomposer.org/\r\n\r\n请phper尽快转换思路,来到包管理的新世界吧。\r\n\r\n\r\n\r\n\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(245,'[nodejs]并发条件下,写入导致数组内数据相同','245',1429735140,1429756879,'<!--markdown-->//dsgygb更新版\r\n\r\n今天写的一个东西大概是这样:\r\n\r\n var arr =[\r\n \'a\',\'b\',\'c\',\'d\'\r\n ]\r\n var data = [];//定义存放数据的数组\r\n var item = {};//定义应该存放在data里的格式为对象\r\n async.each(arr,function(v,callback){\r\n item.name = v;\r\n data.push(item);\r\n callback(null);\r\n },function(err){\r\n console(err);\r\n })\r\n console.log(data);\r\n //data=[\'d\',\'d\',\'d\',\'d\']\r\n\r\n然后就出了问题:返回的`data`内的数据一样;\r\n在某宝的帮助下,解决了问题(将`var item = {};`定义在`async.each()`第二个参数里)\r\n并理解了原理(`data`里存放的为`item`的地址,在外面定义导致4个并发的线程不断修改`item`指向的地址里的值,但是`data.push`进去的总是那一个地址,就得到了4个一模一样的数组值,而把`item`定义在`asycn.each`里面,每一次都重新初始化item,使得4个并发的线程中`item`中存放的地址不同,也就达到了预期效果).\r\n\r\n所以正确的姿势是:\r\n\r\n\r\n var arr =[\r\n \'a\',\'b\',\'c\',\'d\'\r\n ]\r\n var data = [];//定义存放数据的数组\r\n async.each(arr,function(v,callback){\r\n var item = {};//定义应该存放在data里的格式为对象\r\n item.name = v;\r\n data.push(item);\r\n callback(null);\r\n },function(err){\r\n console(err);\r\n })\r\n console.log(data);\r\n //data=[\'d\',\'d\',\'d\',\'d\']\r\n\r\n在此感谢dsg.',0,7,NULL,'post','publish',NULL,0,'1','1','1',0),(235,'屏幕快照 2015-03-24 下午2.18.38.png','屏幕快照-2015-03-24-下午2-18-38-png',1427177934,1427177934,'a:5:{s:4:\"name\";s:41:\"屏幕快照 2015-03-24 下午2.18.38.png\";s:4:\"path\";s:35:\"/usr/uploads/2015/03/2566330320.png\";s:4:\"size\";i:90693;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',236),(234,'node 对中文字符MD5加密的问题','234',1425473580,1429897776,'<!--markdown-->\r\n //错误做法,不支持中文\r\n function(data){\r\n var md5sum = crypto.createHash(\'md5\');\r\n md5sum.update(data);\r\n data = md5sum.digest(\'hex\');\r\n return data;\r\n };\r\n\r\n\r\n\r\n //正确做法,支持中文\r\n function(data){\r\n var Buffer = require(\"buffer\").Buffer;\r\n var buf = new Buffer(data);\r\n var str = buf.toString(\"binary\");\r\n var md5sum = crypto.createHash(\'md5\');\r\n md5sum.update(str);\r\n data = md5sum.digest(\'hex\');\r\n return data;\r\n };\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(236,'PHP实现 HTML5数据推送SSE原理','236',1427178060,1442481084,'<!--markdown-->SSE是一种允许服务器端向客户端推送新数据(简称数据推送)的HTML5技术。\r\n\r\n![请输入图片描述][1]\r\n\r\n\r\n当数据源有新数据时,服务器端能立刻发送给一个或多个客户端,而不用等客户端来请求,这些新数据可能是突发新闻、最新股票、上线朋友的聊天信息、新的天气预报、策略游戏中的下一步等。\r\n\r\n\r\nSSE适用于更新频繁、低延迟并且数据都是从服务端到客户端。它和WebSocket的区别:\r\n\r\n\r\n1)便利,不需要添加任何新组件,用任何习惯的后端语言和框架就能继续使用,不用为新建虚拟机弄一个新的IP或新的端口号而劳神。\r\n\r\n\r\n2)服务器端的简洁。因为SSE能在现有的HTTP/HTTPS协议上运作,所以它能够直接运行于现有的代理服务器和认证技术。\r\n\r\n\r\nWebSocket相较SSE最大的优势在于它是双向交流的,这意味着服务器发送数据就像从服务器接受数据一样简单,而SSE一般通过一个独立的Ajax请求从客户端向服务端传送数据,因此相对于WebSocket使用Ajax会增加开销。因此,如果需要以每秒一次或者更快的频率向服务端传输数据,就应该用WebSocket。\r\n\r\n## 浏览器端:\r\n\r\n\r\n <!doctype html>\r\n <html>\r\n <head>\r\n <meta charset=\"UTF-8\">\r\n <title>basic SSE test</title>\r\n </head>\r\n <body>\r\n <pre id = \"x\">initializting...</pre>\r\n <!--之所以使用pre标签而不是p或者div是为了确保数据能以它被接受时的格式呈现,而不会修改或格式化-->\r\n\r\n </body>\r\n <script>\r\n var es = new EventSource(\"basic_sse.php\");\r\n es.addEventListener(\"message\",function(e){\r\n //e.data\r\n document.getElementById(\"x\").innerHTML += \"\\n\"+e.data;\r\n },false);//使用false表示在冒泡阶段处理事件,而不是捕获阶段。\r\n </script>\r\n </html>\r\n\r\n\r\n## 服务器端:\r\n\r\n <?php\r\n header(\'Content-Type: text/event-stream\');\r\n header(\'Cache-Control: no-cache\');\r\n $time = date(\'Y-m-d H:i:s\');\r\n\r\n echo \'retry: 1000\'.PHP_EOL;\r\n echo \'data: The server time is: \'.$time.PHP_EOL.PHP_EOL;\r\n ?>\r\n\r\n\r\n效果截图\r\n![屏幕快照 2015-03-24 下午2.18.38.png][2]\r\n\r\n# 注意事项:\r\n> 1.“Content-Type: text/event-stream”是专门为SSE设计的MIME类型`\r\n> \r\n> 2.retry可以定义推送间隔,如果不发送这个指令,默认间隔5000毫秒`\r\n> \r\n> 3.每行指令后面要有换行 \\n ,用php的请用兼容方案 PHP_EOL`\r\n> \r\n> 4.最后一条指令要两个换行`\r\n> \r\n> 5.未完,其他详细容后发布`\r\n\r\n\r\n [1]: http://bbs.html5cn.org/data/attachment/forum/201503/23/154252lgtq0fb9ifsggbbt.png\r\n [2]: http://log.fyscu.com/usr/uploads/2015/03/2566330320.png',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(237,'[备忘]两条命令升级node版本','237',1427944500,1450254866,'<!--markdown-->` npm install -g n `\r\n安装 n (神器)\r\n\r\n` n stable `\r\n自动升级到最新版\r\n\r\n\r\n过程中可能需要权限,最好用sudo运行\r\n\r\n` n 4.3.2 `\r\n表示安装4.3.2版本的node,其他版本同理\r\n\r\n` n ` \r\n会列出当前安装了的版本,然后可以用键盘上下来选择切换版本,回车确认\r\n\r\n` 所有操作,都可能设计权限操作,必要时请加sudo`',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(241,'css中选择器的优先级','241',1429588034,1429588034,'<!--markdown-->通常我们用1表示标签名选择器的优先级,比如说```div```\r\n\r\n用10表示类选择器的优先级,比如说 ```.posts```\r\n\r\n用100表示ID选择器的优先级。比如说 ```#posts```\r\n\r\nhtml标签里的style的优先级更高\r\n\r\n!important 的优先级最高。\r\n\r\n\r\n那么html页面的元素的样式如果遇到有多个css的相同属性指向同一个元素时,就会优先展现当前的css中优先级最高的样式。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(242,'再挖一个坑,里面放有用的好用的插件','242',1429598580,1429598959,'<!--markdown-->1.js日期格式化\r\n\r\nhttp://momentjs.com/ \r\n\r\n2.绘制统计图表 \r\n\r\nhttps://github.com/gionkunz/chartist-js\r\n\r\nhttps://github.com/nnnick/Chart.js',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(243,'[mysql]表名字段名大小写问题(windows)','243',1429729440,1429735502,'<!--markdown-->在某宝强烈建议下,mysql表名和字段名全部使用小驼峰命名法。\r\n\r\n问题1:表名支持大写,但是,在导入sql文件的时候,会把所有表名修改为小写\r\n解决方法:修改为下划线命名法\r\n\r\n问题2:字段名支持大小写,但是会发生这种情况:如果我有一个`postId`字段,那么想建立一个`postid`字段,就会报字段名重复的错误.\r\n换句话说,在程序里`SELECT * FROM postId`和`SELECT * FROM postid`得到的结果是一样的.\r\n\r\n只是因为windows里面文件名不区分大小写,mysql在把字段名显示出来之前,后台处理了一下,写成`postId`的形式,其实它的本质还是全部小写.windows下导出的sql文件里面的表名为大写而linux下的mysql表名和字段名默认都是区分大小写的,所以,当把代码传到linux服务器上的时候,注意`SELECT * FROM postId`和`SELECT * FROM postid`现在并不相同.\r\n注:(下面内容摘自网上)\r\n>MYSQL在LINUX下数据库名、表名、列名、别名大小写规则如下: \r\n>数据库名与表名是严格区分大小写的 \r\n>表的别名是严格区分大小写的 \r\n>列名与列的别名在所有的情况下均是忽略大小写的 \r\n>变量名也是严格区分大小写的 \r\n\r\n\r\n通过google相关资料,windows关于设置sql默认区分大小写与否:在my.ini文件[mysqld]节下 添加 lower_case_table_names=\'value\'\r\nvalue = 0 :区分大小写,并在文件中以指定大小写保存.\r\nvalue = 1 :不区分大小写,在文件中以小写保存.\r\nvalue = 2 :在文件中以区分大小写形式保存,但mysql将其转化为小写便于查找.注:只在不区分大小写的文件系统上适用.',0,7,NULL,'post','publish',NULL,0,'1','1','1',0),(244,'[nodejs]空数组[]是true还是false','244',1429733520,1429735490,'<!--markdown--> var a=[];//定义一个数组\r\n console.log (typeof(a));//object\r\n if(a){\r\n console.log(\'a==true\');\r\n }\r\n //a==true\r\n\r\n\r\n if(a==true){\r\n console.log(\'a==true\');\r\n }else{\r\n console.log(\'a!=true\');\r\n }\r\n //a!=true\r\n\r\n\r\n\r\n if(a==false){\r\n console.log(\'a==false\')\r\n }else{\r\n console.log(\'a!=false\');\r\n }\r\n //a==false\r\n\r\n\r\n\r\n那么问题来了,到底[]等于不等于true呢?\r\n根据查阅书籍《JavaScript高级程序设计》得知:\r\n在流控制语句`if()`中,自动执行相应的`Boolean()`转换,并且数组属于的`Object`类型的任意对象转换为`Boolean`均为`true`,而`Object`类型中,只有`null`会转化为`false`.\r\n\r\n所以在`if(a)`中,调用了`Boolean()`方法将a转化为了布尔值`true`,但是,在`if(a==true)`中,为什么`a==true`又是错的呢?\r\n原来,任意值与布尔值比较,都会将两边的值转化为Number类型比较,此时,`a`转化为`0`,而`true`转化为`1`,`a`与`true`并不相等.\r\n\r\n问题又来了:为什么`a`会转化为`0`呢?因为`a`是一个对象,如果对象具有`valueOf()`方法,那么在它转化为数字时,调用此方法,返回一个原始值,js将这个原始值转化为数字返回.否则,调用`toString()`,如果这两个方法都没有,那么报错.数组继承了对象默认的`valueOf`方法,但是数组调用此方法后,返回值为数组本身,所以,还会继续调用`toString()`,此时返回空字符串,转换为`0`.\r\n\r\n总结:`if(a)`,直接返回`true.if(a==true)`,将`a`转化为`0`再比较.\r\n因此确切地知道在流控制语句中使用的是什么变量至关重要.错误地使用一个对象而不是一个`Boolean`值,就有可能彻底改变应用程序的流程.\r\n\r\n在此感谢captainblue\r\n\r\n\r\n',0,7,NULL,'post','publish',NULL,0,'1','1','1',0),(240,'[馬克] http 协议详解','240',1429175340,1429897818,'<!--markdown-->\r\n\r\n 引言 \r\n \r\n HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。\r\n\r\n### HTTP协议的主要特点可概括如下:\r\n#### 1.支持客户/服务器模式。\r\n#### 2.简单快速:\r\n客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。\r\n#### 3.灵活:\r\nHTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。\r\n#### 4.无连接:\r\n无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。\r\n#### 5.无状态:\r\nHTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。\r\n\r\n \r\n\r\n## 一、HTTP协议详解之URL篇\r\n\r\nhttp(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,\r\nHTTP1.1版本中给出一种持续连接的机制,绝大多数的Web开发,都是构建在HTTP协议之上的Web应用。\r\n\r\nHTTP URL (URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息)的格式如下:\r\n\r\nhttp://host[\":\"port][abs_path]\r\n\r\n- http表示要通过HTTP协议来定位网络资源;\r\n- host表示合法的Internet主机域名或者IP地址;\r\n- port指定一个端口号,为空则使用缺省端口80;\r\n- abs_path指定请求资源的URI;\r\n如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,\r\n通常这个工作浏览器自动帮我们完成。\r\n\r\neg:\r\n1、输入:`www.guet.edu.cn`\r\n浏览器自动转换成:`http://www.guet.edu.cn/`\r\n2、`http:192.168.0.116:8080/index.jsp `\r\n\r\n \r\n\r\n## 二、HTTP协议详解之请求篇\r\n\r\n http请求由三部分组成,分别是:请求行、消息报头、请求正文\r\n\r\n1、请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,\r\n格式如下:\r\n`Method Request-URI HTTP-Version CRLF ` \r\n其中 \r\n- Method表示请求方法;\r\n- Request-URI是一个统一资源标识符;\r\n- HTTP-Version表示请求的HTTP协议版本;\r\n- CRLF表示回车和换行\r\n(除了作为结尾的CRLF外,不允许出现单独的CR或LF字符)。\r\n\r\n请求方法(所有方法全为大写)有多种,各个方法的解释如下:\r\n- GET 请求获取Request-URI所标识的资源\r\n- POST 在Request-URI所标识的资源后附加新的数据\r\n- HEAD 请求获取由Request-URI所标识的资源的响应消息报头\r\n- PUT 请求服务器存储一个资源,并用Request-URI作为其标识\r\n- DELETE 请求服务器删除Request-URI所标识的资源\r\n- TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断\r\n- CONNECT 保留将来使用\r\n- OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求\r\n应用举例:\r\nGET方法:在浏览器的地址栏中输入网址的方式访问网页时,浏览器采用GET方法向服务器获取资源,eg:GET /form.html HTTP/1.1 (CRLF)\r\n\r\nPOST方法要求被请求服务器接受附在请求后面的数据,常用于提交表单。\r\neg:POST /reg.jsp HTTP/ (CRLF)\r\nAccept:image/gif,image/x-xbit,... (CRLF)\r\n...\r\n- HOST:www.guet.edu.cn (CRLF)\r\n- Content-Length:22 (CRLF)\r\n- Connection:Keep-Alive (CRLF)\r\n- Cache-Control:no-cache (CRLF)\r\n- (CRLF) //该CRLF表示消息报头已经结束,在此之前为消息报头\r\n- user=jeffrey&pwd=1234 //此行以下为提交的数据\r\n\r\nHEAD方法与GET方法几乎是一样的,对于HEAD请求的回应部分来说,它的HTTP头部中包含的信息与通过GET请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到Request-URI所标识的资源的信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新。\r\n2、请求报头后述\r\n3、请求正文(略) \r\n\r\n \r\n\r\n## 三、HTTP协议详解之响应篇\r\n\r\n在接收和解释请求消息后,服务器返回一个HTTP响应消息。\r\n\r\nHTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文\r\n1、状态行格式如下:\r\n- HTTP-Version Status-Code Reason-Phrase CRLF\r\n其中,\r\n- HTTP-Version表示服务器HTTP协议的版本;\r\n- Status-Code表示服务器发回的响应状态代码;\r\n- Reason-Phrase表示状态代码的文本描述。\r\n\r\n状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:\r\n- 1xx:指示信息--表示请求已接收,继续处理\r\n- 2xx:成功--表示请求已被成功接收、理解、接受\r\n- 3xx:重定向--要完成请求必须进行更进一步的操作\r\n- 4xx:客户端错误--请求有语法错误或请求无法实现\r\n- 5xx:服务器端错误--服务器未能实现合法的请求\r\n常见状态代码、状态描述、说明:\r\n\r\n\r\n- 200 OK //客户端请求成功\r\n- 400 Bad Request //客户端请求有语法错误,不能被服务器所理解\r\n- 401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 \r\n- 403 Forbidden //服务器收到请求,但是拒绝提供服务\r\n- 404 Not Found //请求资源不存在,eg:输入了错误的URL\r\n- 500 Internal Server Error //服务器发生不可预期的错误\r\n- 503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常\r\n- eg:HTTP/1.1 200 OK (CRLF)\r\n\r\n2、响应报头后述\r\n\r\n3、响应正文就是服务器返回的资源的内容 \r\n\r\n \r\n\r\n## 四、HTTP协议详解之消息报头篇\r\n\r\n HTTP消息由客户端到服务器的请求和服务器到客户端的响应组成。\r\n请求消息和响应消息都是由\r\n- 开始行(对于请求消息,开始行就是请求行,对于响应消息,开始行就是状态行),\r\n- 消息报头(可选),\r\n- 空行(只有CRLF的行),\r\n- 消息正文(可选)组成。\r\n\r\nHTTP消息报头包括普通报头、请求报头、响应报头、实体报头。\r\n每一个报头域都是由名字+“:”+空格+值 组成,消息报头域的名字是大小写无关的。\r\n\r\n1、普通报头\r\n在普通报头中,有少数报头域用于所有的请求和响应消息,但并不用于被传输的实体,只用于传输的消息。\r\neg:\r\n- Cache-Control 用于指定缓存指令,缓存指令是单向的(响应中出现的缓存指令在请求中未必会出现),且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制),HTTP1.0使用的类似的报头域为Pragma。\r\n- 请求时的缓存指令包括:no-cache(用于指示请求或响应消息不能缓存)、no-store、max-age、max-stale、min-fresh、only-if-cached;\r\n- 响应时的缓存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage.\r\n- eg:为了指示IE浏览器(客户端)不要缓存页面,服务器端的JSP程序可以编写如下:\r\nresponse.sehHeader(\"Cache-Control\",\"no-cache\");\r\n\r\n//response.setHeader(\"Pragma\",\"no-cache\");作用相当于上述代码,通常两者//合用\r\n这句代码将在发送的响应消息中设置普通报头域:Cache-Control:no-cache\r\n\r\n\r\n- Date普通报头域表示消息产生的日期和时间\r\n\r\n- Connection普通报头域允许发送指定连接的选项。例如指定连接是连续,或者指定“close”选项,通知服务器,在响应完成后,关闭连接\r\n\r\n2、请求报头\r\n请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。\r\n常用的请求报头\r\nAccept\r\n- Accept请求报头域用于指定客户端接受哪些类型的信息。eg:Accept:image/gif,表明客户端希望接受GIF图象格式的资源;Accept:text/html,表明客户端希望接受html文本。\r\n- Accept-Charset\r\n- Accept-Charset请求报头域用于指定客户端接受的字符集。eg:Accept-Charset:iso-8859-1,gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。\r\n- Accept-Encoding\r\n- Accept-Encoding请求报头域类似于Accept,但是它是用于指定可接受的内容编码。eg:Accept-Encoding:gzip.deflate.如果请求消息中没有设置这个域服务器假定客户端对各种内容编码都可以接受。\r\n- Accept-Language\r\n- Accept-Language请求报头域类似于Accept,但是它是用于指定一种自然语言。eg:Accept-Language:zh-cn.如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。\r\n- Authorization\r\n- Authorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。\r\n- Host(发送请求时,该报头域是必需的)\r\n- Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的,eg:\r\n我们在浏览器中输入:http://www.guet.edu.cn/index.html\r\n浏览器发送的请求消息中,就会包含Host请求报头域,如下:\r\n- Host:www.guet.edu.cn\r\n此处使用缺省端口号80,若指定了端口号,则变成:Host:www.guet.edu.cn:指定端口号\r\n- User-Agent\r\n我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上,服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息。User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。不过,这个报头域不是必需的,如果我们自己编写一个浏览器,不使用User-Agent请求报头域,那么服务器端就无法得知我们的信息了。\r\n请求报头举例:\r\n- GET /form.html HTTP/1.1 (CRLF)\r\n- Accept:image/gif,image/x-xbitmap,image/jpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/* (CRLF)\r\n- Accept-Language:zh-cn (CRLF)\r\n- Accept-Encoding:gzip,deflate (CRLF)\r\n- If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF)\r\n- If-None-Match:W/\"80b1a4c018f3c41:8317\" (CRLF)\r\n- User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF)\r\n- Host:www.guet.edu.cn (CRLF)\r\n- Connection:Keep-Alive (CRLF)\r\n- (CRLF)\r\n\r\n3、响应报头\r\n响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。\r\n常用的响应报头\r\n### Location\r\n- Location响应报头域用于重定向接受者到一个新的位置。Location响应报头域常用在更换域名的时候。\r\n### Server\r\n- Server响应报头域包含了服务器用来处理请求的软件信息。与User-Agent请求报头域是相对应的。下面是\r\n- Server响应报头域的一个例子:\r\n- Server:Apache-Coyote/1.1\r\n- WWW-Authenticate\r\n- WWW-Authenticate响应报头域必须被包含在401(未授权的)响应消息中,客户端收到401响应消息时候,并发送Authorization报头域请求服务器对其进行验证时,服务端响应报头就包含该报头域。\r\neg:WWW-Authenticate:Basic realm=\"Basic Auth Test!\" //可以看出服务器对请求资源采用的是基本验证机制。\r\n\r\n\r\n4、实体报头\r\n请求和响应消息都可以传送一个实体。一个实体由实体报头域和实体正文组成,但并不是说实体报头域和实体正文要在一起发送,可以只发送实体报头域。实体报头定义了关于实体正文(eg:有无实体正文)和请求所标识的资源的元信息。\r\n常用的实体报头\r\n### Content-Encoding\r\n- Content-Encoding实体报头域被用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容的编码,因而要获得Content-Type报头域中所引用的媒体类型,必须采用相应的解码机制。Content-Encoding这样用于记录文档的压缩方法,eg:Content-- - - - - Encoding:gzip\r\n- Content-Language\r\n- Content-Language实体报头域描述了资源所用的自然语言。没有设置该域则认为实体内容将提供给所有的语言阅读\r\n者。eg:Content-Language:da\r\n- Content-Length\r\n- Content-Length实体报头域用于指明实体正文的长度,以字节方式存储的十进制数字来表示。\r\n- Content-Type\r\n- Content-Type实体报头域用语指明发送给接收者的实体正文的媒体类型。eg:\r\n- Content-Type:text/html;charset=ISO-8859-1\r\n- Content-Type:text/html;charset=GB2312\r\n- Last-Modified\r\n- Last-Modified实体报头域用于指示资源的最后修改日期和时间。\r\n- Expires\r\n- Expires实体报头域给出响应过期的日期和时间。为了让代理服务器或浏览器在一段时间以后更新缓存中(再次访问曾访问过的页面时,直接从缓存中加载,缩短响应时间和降低服务器负载)的页面,我们可以使用Expires实体报头域指定页面过期的时间。eg:Expires:Thu,15 Sep 2006 16:23:12 GMT\r\nHTTP1.1的客户端和缓存必须将其他非法的日期格式(包括0)看作已经过期。eg:为了让浏览器不要缓存页面,我们也可以利用Expires实体报头域,设置为0,jsp中程序如下:response.setDateHeader(\"Expires\",\"0\");\r\n\r\n \r\n\r\n## 五、利用telnet观察http协议的通讯过程\r\n\r\n 实验目的及原理:\r\n 利用MS的telnet工具,通过手动输入http请求信息的方式,向服务器发出请求,服务器接收、解释和接受请求后,会返回一个响应,该响应会在telnet窗口上显示出来,从而从感性上加深对http协议的通讯过程的认识。\r\n\r\n 实验步骤:\r\n\r\n1、打开telnet\r\n1.1 打开telnet\r\n运行-->cmd-->telnet\r\n\r\n1.2 打开telnet回显功能\r\nset localecho\r\n\r\n2、连接服务器并发送请求\r\n\r\n2.1 open www.guet.edu.cn 80 //注意端口号不能省略\r\n\r\n HEAD /index.asp HTTP/1.0\r\n Host:www.guet.edu.cn\r\n \r\n /*我们可以变换请求方法,请求桂林电子主页内容,输入消息如下*/\r\n open www.guet.edu.cn 80 \r\n \r\n GET /index.asp HTTP/1.0 //请求资源的内容\r\n Host:www.guet.edu.cn \r\n\r\n\r\n2.2 open www.sina.com.cn 80 //在命令提示符号下直接输入telnet www.sina.com.cn 80\r\n HEAD /index.asp HTTP/1.0\r\n Host:www.sina.com.cn\r\n \r\n\r\n3 实验结果:\r\n\r\n3.1 请求信息2.1得到的响应是:\r\n\r\n- HTTP/1.1 200 OK //请求成功\r\n- Server: Microsoft-IIS/5.0 //web服务器\r\n- Date: Thu,08 Mar 200707:17:51 GMT\r\n- Connection: Keep-Alive \r\n- Content-Length: 23330\r\n- Content-Type: text/html\r\n- Expries: Thu,08 Mar 2007 07:16:51 GMT\r\n- Set-Cookie: ASPSESSIONIDQAQBQQQB=BEJCDGKADEDJKLKKAJEOIMMH; path=/\r\n- Cache-control: private\r\n\r\n//资源内容省略\r\n\r\n3.2 请求信息2.2得到的响应是:\r\n\r\n- HTTP/1.0 404 Not Found //请求失败\r\n- Date: Thu, 08 Mar 2007 07:50:50 GMT\r\n- Server: Apache/2.0.54 <Unix>\r\n- Last-Modified: Thu, 30 Nov 2006 11:35:41 GMT\r\n- ETag: \"6277a-415-e7c76980\"\r\n- Accept-Ranges: bytes\r\n- X-Powered-By: mod_xlayout_jh/0.0.1vhs.markII.remix\r\n- Vary: Accept-Encoding\r\n- Content-Type: text/html\r\n- X-Cache: MISS from zjm152-78.sina.com.cn\r\n- Via: 1.0 zjm152-78.sina.com.cn:80<squid/2.6.STABLES-20061207>\r\n- X-Cache: MISS from th-143.sina.com.cn\r\n- Connection: close\r\n\r\n\r\n- 失去了跟主机的连接\r\n\r\n- 按任意键继续...\r\n\r\n4 .注意事项:\r\n- 1、出现输入错误,则请求不会成功。\r\n- 2、报头域不分大小写。\r\n- 3、更深一步了解HTTP协议,可以查看RFC2616,在http://www.letf.org/rfc上找到该文件。\r\n- 4、开发后台程序必须掌握http协议\r\n\r\n## 六、HTTP协议相关技术补充\r\n\r\n 1、基础:\r\n 高层协议有:\r\n 文件传输协议FTP、电子邮件传输协议SMTP、域名系统服务DNS、网络新闻传输协议NNTP和HTTP协议等\r\n中介由三种:代理(Proxy)、网关(Gateway)和通道(Tunnel),一个代理根据URI的绝对格式来接受请求,重写全部或部分消息,通过 URI的标识把已格式化过的请求发送到服务器。网关是一个接收代理,作为一些其它服务器的上层,并且如果必须的话,可以把请求翻译给下层的服务器协议。一 个通道作为不改变消息的两个连接之间的中继点。当通讯需要通过一个中介(例如:防火墙等)或者是中介不能识别消息的内容时,通道经常被使用。\r\n 代理(Proxy):\r\n 一个中间程序,它可以充当一个服务器,也可以充当一个客户机,为其它客户机建立请求。请求是通过可能的翻译在内部或经过传递到其它的 服务器中。一个代理在发送请求信息之前,必须解释并且如果可能重写它。代理经常作为通过防火墙的客户机端的门户,代理还可以作为一个帮助应用来通过协议处 理没有被用户代理完成的请求。\r\n 网关(Gateway):\r\n 一个作为其它服务器中间媒介的服务器。与代理不同的是,网关接受请求就好象对被请求的资源来说它就是源服务器;发出请求的客户机并没有意识到它在同网关打交道。\r\n网关经常作为通过防火墙的服务器端的门户,网关还可以作为一个协议翻译器以便存取那些存储在非HTTP系统中的资源。\r\n 通道(Tunnel):\r\n 是作为两个连接中继的中介程序。一旦激活,通道便被认为不属于HTTP通讯,尽管通道可能是被一个HTTP请求初始化的。当被中继 的连接两端关闭时,通道便消失。当一个门户(Portal)必须存在或中介(Intermediary)不能解释中继的通讯时通道被经常使用。\r\n\r\n2、协议分析的优势—HTTP分析器检测网络攻击\r\n以模块化的方式对高层协议进行分析处理,将是未来入侵检测的方向。\r\nHTTP及其代理的常用端口80、3128和8080在network部分用port标签进行了规定\r\n\r\n3、HTTP协议Content Lenth限制漏洞导致拒绝服务攻击\r\n使用POST方法时,可以设置ContentLenth来定义需要传送的数据长度,\r\n例如ContentLenth:999999999,在传送完成前,内存不会释放,攻击者可以利用这个缺陷,连续向WEB服务器发送垃圾数据直至WEB服务器内存耗尽。这种攻击方法基本不会留下痕迹。\r\nhttp://www.cnpaf.net/Class/HTTP/0532918532667330.html\r\n\r\n4、利用HTTP协议的特性进行拒绝服务攻击的一些构思\r\n服务器端忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求(毕竟客户端的正常请求比率非常之小),此时从正常客户的角度看来,服务器失去响应,这种情况我们称作:服务器端受到了SYNFlood攻击(SYN洪水攻击)。\r\n而Smurf、TearDrop等是利用ICMP报文来Flood和IP碎片攻击的。本文用“正常连接”的方法来产生拒绝服务攻击。\r\n19端口在早期已经有人用来做Chargen攻击了,即Chargen_Denial_of_Service,但是!他们用的方法是在两台Chargen 服务器之间产生UDP连接,让服务器处理过多信息而DOWN掉,\r\n那么,干掉一台WEB服务器的条件就必须有2个:\r\n- 1.有Chargen服务\r\n- 2.有HTTP 服务\r\n方法:\r\n攻击者伪造源IP给N台Chargen发送连接请求(Connect),Chargen接收到连接后就会返回每秒72字节的字符流(实际上根据网络实际情况,这个速度更快)给服务器。\r\n\r\n5、Http指纹识别技术\r\n Http指纹识别的原理大致上也是相同的:记录不同服务器对Http协议执行中的微小差别进行识别.Http指纹识别比TCP/IP堆栈指纹识别复杂许 多,理由是定制Http服务器的配置文件、增加插件或组件使得更改Http的响应信息变的很容易,这样使得识别变的困难;然而定制TCP/IP堆栈的行为 需要对核心层进行修改,所以就容易识别.\r\n 要让服务器返回不同的Banner信息的设置是很简单的,象Apache这样的开放源代码的Http服务器,用户可以在源代码里修改Banner信息,然 后重起Http服务就生效了;对于没有公开源代码的Http服务器比如微软的IIS或者是Netscape,可以在存放Banner信息的Dll文件中修 改,相关的文章有讨论的,这里不再赘述,当然这样的修改的效果还是不错的.另外一种模糊Banner信息的方法是使用插件。\r\n常用测试请求:\r\n- 1:HEAD/Http/1.0发送基本的Http请求\r\n- 2:DELETE/Http/1.0发送那些不被允许的请求,比如Delete请求\r\n- 3:GET/Http/3.0发送一个非法版本的Http协议请求\r\n- 4:GET/JUNK/1.0发送一个不正确规格的Http协议请求\r\nHttp指纹识别工具Httprint,它通过运用统计学原理,组合模糊的逻辑学技术,能很有效的确定Http服务器的类型.它可以被用来收集和分析不同Http服务器产生的签名。\r\n\r\n6、其他:\r\n为了提高用户使用浏览器时的性能,现代浏览器还支持并发的访问方式,浏览一个网页时同时建立多个连接,以迅速获得一个网页上的多个图标,这样能更快速完成整个网页的传输。\r\nHTTP1.1中提供了这种持续连接的方式,而下一代HTTP协议:HTTP-NG更增加了有关会话控制、丰富的内容协商等方式的支持,来提供\r\n更高效率的连接。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(231,'nodejs写mysql语句性能测试记录','231',1425369780,1425370270,'<!--markdown-->1.100000条语句逐条插入 用时98秒\r\n2.100000条语句,每次批量100条,用时 1.8秒\r\n2.100000条语句,每次批量1000条,用时0.5秒',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(239,'【原创】只用 Web 浏览器,实现 图片裁剪(兼容 IE 8+)','239',1429070220,1429604796,'<!--markdown-->【插件主要特性】\r\n--------\r\n 1. 纯前端插件:完全由 Web 前端程序 裁剪图片\r\n 2. 后端零改动:不改变 Web 后端各种技术架构 传统的**文件 POST 表单**(multipart/form-data 内容类型)处理方式\r\n 3. 平台全兼容:IE 10+ **现代浏览器** 基于 **HTML 5 API**,IE 8、9 基于 **ActiveX/WSC**(Windows 脚本组件)\r\n 4. 代码全开源:所有组件基于 **ECMAScript 5** 的 JavaScript 实现,一致、开放\r\n\r\n【参文 - 图片文件处理兼容】\r\n===============\r\n 1. http://www.web-tinker.com/article/20619.html\r\n 2. http://blog.csdn.net/aminfo/article/details/8100436\r\n\r\n【参文 - ActiveX 插件开发】\r\n===================\r\n 1. http://www.cnblogs.com/cilence/archive/2012/08/29/2657279.html\r\n 2. http://my.oschina.net/amath0312/blog/38465\r\n 3. http://www.iteye.com/topic/110834\r\n 4. http://blog.csdn.net/jiangtongcn/article/details/13509633\r\n 5. http://mimmy.iteye.com/blog/512474\r\n 6. http://www.cnblogs.com/Jahom/archive/2010/04/23/1718442.html\r\n 7. http://hi.baidu.com/xuejinglan/item/90bfb3ca2ecdf63d45941644\r\n 8. http://www.cnblogs.com/zhf/archive/2008/12/11/1352582.html\r\n 9. http://www.cnblogs.com/qguohog/archive/2013/01/28/2880276.html\r\n 10. http://www.cnblogs.com/interdrp/archive/2009/05/03/1448382.html\r\n 11. http://www.bathome.net/viewthread.php?tid=11386\r\n 12. http://www.jb51.net/shouce/script56/\r\n 13. https://msdn.microsoft.com/zh-cn/aa751974(v=vs.85)\r\n 14. https://msdn.microsoft.com/zh-cn/library/cc468260(v=vs.71).aspx\r\n 15. https://msdn.microsoft.com/zh-cn/windows/desktop/ff851942.aspx\r\n 16. https://social.msdn.microsoft.com/Forums/en-US/91d28d4b-12ea-468a-bd25-c9f65f40a232/error-message-0x80004005-when-installing-a-wsc-file?forum=jscript\r\n 17. https://social.msdn.microsoft.com/Forums/zh-CN/5da74ba2-9db9-4d94-9a3d-e55efbeb549b/makecert-fails-error-cryptcertstrtonamew-failed?forum=clr\r\n 18. https://social.msdn.microsoft.com/Forums/en-US/b7d1a35f-3759-4217-91ba-e4416ac19d78/how-do-you-fix-error-code-0x80004005?forum=jscript\r\n\r\n【参文 - Flash 程序开发】\r\n-----------------\r\n 1. http://www.adobe.com/cn/devnet/flash/quickstart/filereference_class_as3.html\r\n 2. http://www.cnblogs.com/crkay/archive/2011/10/25/2223726.html\r\n 3. http://www.cnblogs.com/huangxiaolu/p/3473021.html\r\n 4. ',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(227,'js中的arguments对象','227',1422784920,1423972358,'<!--markdown--># js中的arguments对象\r\n一直以来都简单认为function中的arguments是一个数组,但是却看到了`Array.prototype.slice.call(arguments, 1)` 这样诡异的写法。\r\n\r\n1. arguments并非真正的数组实例,不具备数组的slice、push、pop等方法。\r\n\r\n```\r\n(function () {\r\n console.log(arguments.toString()); //[object Arguments]\r\n console.log(arguments instanceof Array); // false\r\n console.log(arguments);// {0: \'Hello\', 1: \'world\', length: 2, callee: function()}\r\n})(\'Hello\', \'world\');\r\n```\r\n\r\n2. arguments是一个类数组对象,以0开始的数字为键,拥有表示长度的属性length,具有和Array相似的结构。所以可以借用Array.prototype的方法,使用call或apply来改变slice的调用对象为arguments,以达到`arguments.slice(1)`的目的。类似的pop、push等也可以使用这种方法调用。',0,10,NULL,'post','publish',NULL,0,'1','1','1',0),(228,'linux 编译安装 PHP','228',1422909240,1422985695,'<!--markdown-->*操作系统: ubuntu 14.04*\r\n*Server version: Apache/2.4.7 (Ubuntu)*\r\n\r\n**1.准备工作**\r\n\r\n+ 下载 PHP 源码包\r\n\r\n直接到官网下载: [http://php.net/downloads.php][1]\r\n\r\n然后进入下载目录,解压源码包: \r\n\r\n tar -zxvf php-5.6.5.tar.gz\r\n\r\n+ 安装依赖包\r\n\r\n\r\n sudo apt-get install libxml2-dev libpcre3-dev libbz2-dev libcurl4-openssl-dev libjpeg-dev libpng12-dev libxpm-dev libfreetype6-dev libmysqlclient-dev libt1-dev libgd2-xpm-dev libgmp-dev libsasl2-dev libmhash-dev unixodbc-dev freetds-dev libpspell-dev libsnmp-dev libtidy-dev libxslt1-dev libmcrypt-dev\r\n\r\n这里只列举了大部分所需要的依赖包.若缺乏依赖,则会直接导致编译失败.更多依赖包查看 [<<编译安装PHP过程中的 CONFIGURE:ERROR>>][2]\r\n\r\n**2.编译安装**\r\n\r\n cd php-5.6.0\r\n \r\n sudo ./configure \\\r\n --prefix=/etc/php5 \\\r\n --with-config-file-path=/etc/php5/config \\\r\n --with-apxs2=/usr/bin/apxs \\\r\n --enable-inline-optimization \\\r\n --disable-debug \\\r\n --disable-rpath \\\r\n --enable-shared \\\r\n --enable-opcache \\\r\n --enable-fpm \\\r\n --with-fpm-user=jh \\\r\n --with-fpm-group=jh \\\r\n --with-mysql=mysqlnd \\\r\n --with-mysqli=mysqlnd \\\r\n --with-pdo-mysql=mysqlnd \\\r\n --with-gettext \\\r\n --enable-mbstring \\\r\n --with-iconv \\\r\n --with-mcrypt \\\r\n --with-mhash \\\r\n --with-openssl \\\r\n --enable-bcmath \\\r\n --enable-soap \\\r\n --with-libxml-dir \\\r\n --enable-pcntl \\\r\n --enable-shmop \\\r\n --enable-sysvmsg \\\r\n --enable-sysvsem \\\r\n --enable-sysvshm \\\r\n --enable-sockets \\\r\n --with-curl \\\r\n --with-zlib \\\r\n --enable-zip \\\r\n --with-bz2 \\\r\n --with-readline\r\n\r\n更多编译参数可以通过 `./configure --help` 查看,下面是更详细的参数说明:\r\n\r\n --prefix=/etc/php //指定 php 安装目录 \r\n --with-apxs2=/usr/bin/apxs //整合apache,apxs功能是使用mod_so中的LoadModule指令,加载指定模块到 apache,要求 apache 要打开SO模块\r\n --with-config-file-path=/usr/local/php/etc //指定php.ini位置\r\n --with-MySQL=/usr/local/mysql //mysql安装目录,对mysql的支持\r\n --with-mysqli=/usr/local/mysql/bin/mysql_config //mysqli扩展技术不仅可以调用MySQL的存储过程、处理MySQL事务,而且还可以使访问数据库工作变得更加稳定。 \r\n --enable-safe-mode 打开安全模式 \r\n --enable-ftp 打开ftp的支持 \r\n --enable-zip 打开对zip的支持 \r\n --with-bz2 打开对bz2文件的支持 \r\n --with-jpeg-dir 打开对jpeg图片的支持 \r\n --with-png-dir 打开对png图片的支持 \r\n --with-freetype-dir 打开对freetype字体库的支持 \r\n --without-iconv 关闭iconv函数,各种字符集间的转换 \r\n --with-libXML-dir 打开libxml2库的支持 \r\n --with-XMLrpc 打开xml-rpc的c语言 \r\n --with-zlib-dir 打开zlib库的支持 \r\n --with-gd 打开gd库的支持 \r\n --enable-gd-native-ttf 支持TrueType字符串函数库 \r\n --with-curl 打开curl浏览工具的支持 \r\n --with-curlwrappers 运用curl工具打开url流 \r\n --with-ttf 打开freetype1.*的支持,可以不加了 \r\n --with-xsl 打开XSLT 文件支持,扩展了libXML2库 ,需要libxslt软件 \r\n --with-gettext 打开gnu 的gettext 支持,编码库用到 \r\n --with-pear 打开pear命令的支持,PHP扩展用的 \r\n --enable-calendar 打开日历扩展功能 \r\n --enable-mbstring 多字节,字符串的支持 \r\n --enable-bcmath 打开图片大小调整,用到zabbix监控的时候用到了这个模块\r\n --enable-sockets 打开 sockets 支持\r\n --enable-exif 图片的元数据支持 \r\n --enable-magic-quotes 魔术引用的支持 \r\n --disable-rpath 关闭额外的运行库文件 \r\n --disable-debug 关闭调试模式 \r\n --with-mime-magic=/usr/share/file/magic.mime 魔术头文件位置\r\n\r\n\r\n指定了`--with-apxs2=/usr/local/apache/bin/apxs`以后, 就不要再激活`--enable-fpm和--enable-fastCGI`, apxs 是一个为 Apache HTTP 服务器编译和安装扩展模块的工具, 以php module的模式加载PHP的. 其中 `/usr/bin/bin/apxs` 是 apxs 的工作文件路径.\r\n\r\n在 ubuntu 中使用 apt-get 按装的 apache2 ,可能没有安装 apxs 模块.这时可通过命令 `sudo apt-get install apache2-dev` 安装,安装完成之后,apxs工具默认会安装在目录 `/usr/bin/` 里面.\r\n\r\n\r\n然后使用 make 命令编译:\r\n\r\n sudo make\r\n sudo make install\r\n\r\n如果想重新安装:\r\n\r\n sudo make clean\r\n sudo make clean all\r\n \r\n sudo ./configure ...\r\n sudo make\r\n sudo make install\r\n\r\n安装过程中可能会出现很多错误,基本你是因为缺乏依赖包.具体请参考之前说到的 [<<编译安装PHP过程中的 CONFIGURE:ERROR>>][2].\r\n\r\n**3.配置PHP**\r\n\r\n编译完成后会显示各种配置路径信息,可以记住这些信息.除此还一个提示: You may want to add: /etc/php5/lib/php to your php.ini include_path.\r\n\r\n+ 配置php.ini :\r\n\r\n\r\n sudo cp php.ini-development /etc/php5/etc/php.ini\r\n\r\n+ 启动 php-fpm 服务\r\n\r\n\r\n sudo cp /etc/php5/etc/php-fpm.conf.default /etc/php5/etc/php-fpm.conf\r\n sudo cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm5\r\n sudo chmod +x /etc/init.d/php-fpm5\r\n service php-fpm5 start\r\n\r\n+ 添加 php 命令到环境变量\r\n\r\n\r\n sudo vim /etc/profile\r\n\r\n在文件末尾加上如下两行代码\r\n\r\n PATH=$PATH:/etc/php5\r\n export PATH \r\n\r\n然后执行命令 `source /etc/profile` 或执行点命令 `./profile` 使其修改生效,执行完可通过echo $PATH命令查看是否添加成功.\r\n\r\n+ 最后通过 php -v 命令查看是否编译成功:\r\n\r\n\r\n php -v\r\n PHP 5.6.5 (cli) (built: Feb 3 2015 01:50:38) \r\n Copyright (c) 1997-2014 The PHP Group\r\n Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies\r\n\r\n\r\n [1]: http://php.net/downloads.php\r\n [2]: http://www.jianghang.name/index.php/archives/38/',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(229,'Apache的多处理模块(MPM)','229',1422982920,1481620561,'<!--markdown-->*操作系统: ubuntu 14.04*\r\n*PHP 版本号: PHP 5.6.5 (cli)*\r\n*Apache 版本号: Server version: Apache/2.4.7 (Ubuntu)*\r\n\r\n## 引入:##\r\n\r\n今天在编译 PHP 的时候遇到一个问题, 配置 ./configure 的时候,出现一个 warning:\r\n\r\n +--------------------------------------------------------------------+\r\n | *** WARNING *** |\r\n | |\r\n | You have built PHP for Apache\'s current non-threaded MPM. |\r\n | If you change Apache to use a threaded MPM you must reconfigure |\r\n | PHP with --enable-maintainer-zts |\r\n +--------------------------------------------------------------------+\r\n | License: |\r\n | This software is subject to the PHP License, available in this |\r\n | distribution in the file LICENSE. By continuing this installation |\r\n | process, you are bound by the terms of this license agreement. |\r\n | If you do not agree with the terms of this license, you must abort |\r\n | the installation process at this point. |\r\n +--------------------------------------------------------------------+\r\n\r\n究其原因是当前的 Apache 的工作模式是 worker 或 event ,而编译 PHP 时的参数却没有设置 PHP 的多进程. \r\n\r\n如果不管这个 warnning 继续编译下去,重启 apache 的时候就会失败:\r\n\r\n Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.\r\n AH00013: Pre-configuration failed\r\n\r\n还是一样的原因. 所以当 Apache 的 MPM 配置为 worker 或 event 时,在编译 PHP 的时候,参数 `--enable-maintainer-zts` 就必不可少. \r\n\r\n## 多处理模块的详细介绍 ##\r\n\r\n无心插柳, 一开始本来没打算编译支持多进程的 PHP, 因为编译过程中不消息配置了 Apache 的多进程模式,索性就让 PHP 支持多线程吧.\r\n\r\n**1. MPM 的介绍**\r\n\r\n1) Apache MPM简介\r\n\r\n Apache 2.X 提供了可以选择的多处理模块(MPM),用来绑定到网络端口上,接受请求,以及调度子进程处理请求.在编译apache时必须选择也只能选择一个MPM.这三种MPM记录于 `/etc/apache2/conf/extra/httpd-mpm.conf` 文件中.其中 `/etc/apache2/` 是 apache 的安装目录.\r\n\r\n 扩展到这一级别的服务器模块化设计,带来两个重要的好处:\r\n \r\n + Apache httpd 能更优雅, 更高效率的支持不同的平台. 尤其是 Apache httpd 的 Windows 版本现在更有效率了, 因为 mpm_winnt 能使用原生网络特性取代在 Apache httpd 1.3 中使用的 POSIX 层.它也可以扩展到其它平台来使用专用的 MPM .\r\n\r\n + Apache httpd 能更好的为有特殊要求的站点定制. 例如,要求更高伸缩性的站点可以选择使用线程的 MPM,即 worker 或 event; 需要可靠性或者与旧软件兼容的站点可以使用 prefork .\r\n\r\n\r\n1) 默认 MPM\r\n\r\n 下表列出了不同系统的默认 MPM .如果你不在编译时选择,那么它就是你将要使用的 MPM .\r\n <table border=\"1\">\r\n <tr><td> Netware </td><td> mpm_netware </td><tr>\r\n <tr><td> OS/2 </td><td> mpmt_os2 </td><tr>\r\n <tr><td> Unix </td><td> prefork,worker 或 event,取决于平台特性 </td><tr>\r\n <tr><td> Windows </td><td> mpm_winnt </td><tr>\r\n </table>\r\n\r\n1) 构建 MPM 为静态模块\r\n \r\n 在全部平台中, MPM 都可以构建为静态模块. 在构建时选择一种 MPM , 链接到服务器中. 如果要改变 MPM, 必须重新构建.\r\n\r\n 为了使用指定的 MPM,请在执行 configure 脚本 时,使用参数 --with-mpm=NAME. NAME 是指定的 MPM 名称.\r\n\r\n1) 查看当前 PMP 模块\r\n\r\n 使用 `apache2ctl -l` 命令进行查看\r\n \r\n ```\r\n erver version: Apache/2.4.7 (Ubuntu)\r\n Server built: Jul 22 2014 14:36:38\r\n Server\'s Module Magic Number: 20120211:27\r\n Server loaded: APR 1.5.1-dev, APR-UTIL 1.5.3\r\n Compiled using: APR 1.5.1-dev, APR-UTIL 1.5.3\r\n Architecture: 64-bit\r\n Server MPM: event\r\n threaded: yes (fixed thread count)\r\n forked: yes (variable process count)\r\n Server compiled with....\r\n ```\r\n\r\n1) 构建 MPM 为动态模块\r\n\r\n 在 Unix 或类似平台中,MPM 可以构建为动态模块,与其它动态模块一样在运行时加载. 构建 MPM 为动态模块允许通过修改 LoadModule 指令内容来改变 MPM,而不用重新构建服务器程序.\r\n\r\n 在执行 configure 脚本时,使用 --enable-mpms-shared 选项可以启用此特性. 当给出的参数为 all 时,所有此平台支持的 MPM 模块都会被安装.还可以在参数中给出模块列表.\r\n\r\n 默认 MPM,可以自动选择或者在执行 configure 脚本时通过 --with-mpm 选项来指定,然后出现在生成的服务器配置文件中. 编辑 LoadModule 指令内容可以选择不同的 MPM . \r\n\r\n**2.Prefork、Worker和Event三种工作模式分析**\r\n\r\n**Prefork MPM**:这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache 1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。\r\n\r\n这个MPM具有很强的自我调节能力,只需要很少的配置指令调整。最重要的是将MaxClients设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。\r\n\r\n**Worker MPM**:此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。\r\n\r\n每个进程可以拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建立。每个子进程可以建立ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答。\r\n\r\n不管是Worker模式或是Prefork 模式,Apache总是试图保持一些备用的(spare)或者是空闲的子进程(空闲的服务线程池)用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。\r\n\r\n**Event MPM**:以上两种稳定的MPM方式在非常繁忙的服务器应用下都有些不足。尽管HTTP的Keepalive方式能减少TCP连接数量和网络负载,但是 Keepalive需要和服务进程或者线程绑定,这就导致一个繁忙的服务器会耗光所有的线程。 Event MPM是解决这个问题的一种新模型,它把服务进程从连接中分离出来。在服务器处理速度很快,同时具有非常高的点击率时,可用的线程数量就是关键的资源限 制,此时Event MPM方式是最有效的。一个以Worker MPM方式工作的繁忙服务器能够承受每秒好几万次的访问量(例如在大型新闻服务站点的高峰时),而Event MPM可以用来处理更高负载。值得注意的是,Event MPM不能在安全HTTP(HTTPS)访问下工作。',0,5,NULL,'post','waiting',NULL,0,'1','1','1',0),(224,'【实用工具】网页用户反馈/客服(E-Mail、QQ 等)','224',1419939660,1420020601,'<!--markdown-->意见反馈(本地电邮软件)\r\n------------\r\n\r\n HTML**`<form />`元素**与**`mailto:`协议**结合,使网页浏览器可以在`submit`(表单提交)时打开用户电脑上的**电邮客户端软件**来发送邮件。电邮软件启动时,可以默认填写一些主要信息,这样就能让用户在大多数情况下只需点击“发送”即可**与站务人员交流**。\r\n\r\n 通常,反馈**电邮的主题、收件人、抄送人**都是定下就不变的(无需用户填写),而**反馈的主要内容、用户基本信息**却会多种多样,但只有 **E-Mail 协议格式中的`body`(正文)字段**可以承载这些内容,这就需要我们在提交前自己**整合各种自定义字段的内容**。\r\n\r\n 把上述常用逻辑封装成插件不仅适用于调用本机电邮软件,也同样能**适配第三方邮件发送 API**,还能一次性绑定更多的提交事件回调、因**用户操作焦点**转移到另一窗口后的事件回调(为焦点切回来的用户一定的**交互反馈**)——\r\n\r\n //\r\n // jQuery.Mail_Form.js v0.2\r\n //\r\n \r\n (function (BOM, $) {\r\n \r\n $.fn.Mail_Form = function (CB_Submit, CB_AppRun) {\r\n return this.submit(function () {\r\n var $_This = $(arguments[0].target), MoreInfo = [];\r\n if (! $_This.is(\'form[action^=\"mailto:\"]\')) return;\r\n var $_Mail_Body = $_This.find(\'textarea[name=\"body\"]\');\r\n var BodyText = $.trim( $_Mail_Body.val() );\r\n if (! BodyText) {\r\n BOM.alert(\'Body Text of this Mail is Empty!\');\r\n return false;\r\n }\r\n \r\n MoreInfo.push( BodyText );\r\n $_This.find(\'textarea:not([name=\"body\"])\').each(function () {\r\n var Value = $.trim(this.value);\r\n if (! Value) return;\r\n \r\n MoreInfo.push([\r\n \'-----------\',\r\n [\'<h3>\', (this.placeholder || this.title), \'</h3>\'].join(\'\'),\r\n Value\r\n ].join(\"\\n\"));\r\n });\r\n $_This.find(\'input, select\').filter(function () {\r\n var Type = (this.type in {\r\n text: 1, number: 1,\r\n search: 1, email: 1, url: 1,\r\n radio: 1, checkbox: 1\r\n }),\r\n Name = (! (this.name in {\r\n subject: 1, body: 1,\r\n cc: 1, bcc: 1\r\n })),\r\n Value = $.trim(this.value);\r\n return Type && Name && Value;\r\n }).each(function () {\r\n if (arguments[0] < 1)\r\n MoreInfo.push(\"<hr />\");\r\n MoreInfo.push([\r\n this.placeholder || this.title,\r\n this.value\r\n ].join(\' : \'));\r\n });\r\n \r\n $_This.attr(\'enctype\', \'text/html\');\r\n $_Mail_Body.val(\r\n MoreInfo.join(\"\\n\\n\").replace(/\\n\\n/g, \"<br /><br />\\n\")\r\n );\r\n if (CB_Submit)\r\n CB_Submit.call($_This[0], arguments[0]);\r\n \r\n $(BOM).one(\'blur.Mail_Submit\', function () {\r\n $_Mail_Body.val( BodyText );\r\n CB_AppRun && CB_AppRun.call(this, arguments[0]);\r\n });\r\n });\r\n };\r\n })(self, self.jQuery);\r\n\r\n【示例代码】\r\n\r\n // 支持“委托式”事件绑定\r\n \r\n $(\'.Float_Layer_Wrapper\').Mail_Form(\r\n function CB_Submit(iEvent) {\r\n // this 指向 触发 submit 的 form\r\n },\r\n function CB_AppRun(iEvent) {\r\n // this 指向 原 window\r\n }\r\n );\r\n\r\n【参考文章】\r\n\r\n 1. http://www.dreamdu.com/xhtml/mailto/\r\n 2. http://hi.baidu.com/prometheus2008/item/0518fa3475e592352f0f817d\r\n\r\n\r\n----------\r\n\r\n\r\n在线客服(弹出 QQ 对话框)\r\n---------------\r\n\r\n function Open_QQ_MessageBox(QQ_UID) {\r\n if (! QQ_UID) return false;\r\n if (typeof QQ_UID != \'string\')\r\n QQ_UID = QQ_UID.toString();\r\n top.open([\r\n \'http://wpa.qq.com/msgrd?v=3&exe=qq&menu=yes\',\r\n \'&uin=\', QQ_UID,\r\n \'&site=\', top.document.title.split(\' \').slice(-1)\r\n ].join(\'\'));\r\n }\r\n\r\n【参考文章】\r\n\r\n 1. http://www.fangfa.net/html/business/business_showinfo_41.html\r\n 2. http://www.cnblogs.com/w-y-f/archive/2012/05/30/2526475.html',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(225,'【收藏】JavaScript 浏览器端 QR 二维码 API','225',1421035920,1421133505,'<!--markdown-->本收录旨在综合 兼容性、易用性、性能,涉及 SVG、HTML 5 Canvas、DataURL、HTTP 等技术。\r\n\r\n本地生成\r\n====\r\n\r\n纯 JavaScript,不依赖 常见 DOM 库(如 jQuery)\r\n-----------------------------------\r\n 1. https://github.com/pinchtools/qrcodesvg(SVG、VML 格式)\r\n 2. https://github.com/davidshimjs/qrcodejs(Canvas、Table 实现)\r\n 3. https://github.com/kazuhikoarase/qrcode-generator(DataURL Image、Table 实现)\r\n 4. https://github.com/siciarek/javascript-qrcode(SVG、PBM,Node.JS 命令行支持)\r\n\r\n远程处理\r\n====\r\n\r\n国外\r\n--\r\n 1. http://www.free-qr-code.net/\r\n 2. http://goqr.me/',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(226,'【原创】网页浏览器 文字输入事件','226',1421613240,1421702069,'<!--markdown-->TextType 事件封装 专注于 具体的用户文字输入内容 ——\r\n\r\n (function (BOM, DOM) {\r\n \r\n var iLoop = { };\r\n \r\n BOM.TextType = function (TypeBox, Callback) {\r\n if (! TypeBox) throw \'No Target TextInput Element !\';\r\n if (! TypeBox.id)\r\n TypeBox.id = \'TextInput_Event_\' + (new Date()).getTime();\r\n if (! Callback) clearInterval( iLoop[TypeBox.id] );\r\n \r\n var lastPosition = TypeBox.selectionStart,\r\n lastLength = TypeBox.value.length;\r\n \r\n function TextInput_Event(iEvent) {\r\n if (iEvent) {\r\n var iKeyCode = iEvent.which;\r\n var isTyping = (\r\n (iKeyCode < 1) || (iKeyCode > 46) ||\r\n ((iKeyCode > 3) && (iKeyCode < 8)) ||\r\n ((iKeyCode > 8) && (iKeyCode < 33)) ||\r\n ((iKeyCode > 40) && (iKeyCode < 46))\r\n );\r\n if ( isTyping ) return;\r\n }\r\n var nowPosition = TypeBox.selectionStart,\r\n nowLength = TypeBox.value.length;\r\n \r\n if (nowLength > lastLength) {\r\n var iType = TypeBox.value.slice(\r\n Math.min(lastPosition, nowPosition),\r\n Math.max(lastPosition, nowPosition)\r\n );\r\n if (iType) Callback.call(iEvent || BOM, iType);\r\n }\r\n lastLength = nowLength;\r\n lastPosition = nowPosition;\r\n }\r\n \r\n iLoop[TypeBox.id] = setInterval(TextInput_Event, 3000);\r\n TypeBox.addEventListener(\'keydown\', TextInput_Event, false);\r\n TypeBox.addEventListener(\'mousedown\', TextInput_Event, false);\r\n TypeBox.addEventListener(\'paste\', function () {\r\n var iText = arguments[0].clipboardData.getData(\'text/plain\');\r\n lastPosition += iText.length;\r\n lastLength += iText.length;\r\n Callback.call(this, iText);\r\n }, false);\r\n };\r\n \r\n })(self, self.document);',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(223,'JavaScript中的几个奇怪操作符','223',1419802440,1419853493,'<!--markdown-->*注:原文出自《JavaScript for PHP developers》,博主只是根据自己的理解增加了一些内容.*\r\n\r\n本文主要介绍几个JavaScript中的几个奇怪的操作符,并与PHP中的类似操作符进行比较.这些操作符又:`in`,`字符串连接`,`类型强制转换`,`void`,`逗号操作符`.\r\n\r\n## 1.in ##\r\n\r\n### 1.1 for-in循环 ###\r\n说in操作符之前,不得不说一下for-in循环.在JavaScrip中当我们需要关联一个数组的时候,我们使用对象.并且,我们使用for-in循环而不是foreach来遍历数组.\r\n\r\n假设我们在PHP中定义了如下的数组:\r\n\r\n //PHP\r\n $clothes = array(\r\n \'shirt\' => \'white\', \r\n \'pants\' => \'blue\',\r\n \'shoes\' => \'black\', //结尾建议加上逗号,这样要添加一个新单元时更方便 \r\n );\r\n\r\n //自PHP5.4起\r\n $clothes = [\r\n \'shirt\' => \'white\',\r\n \'pants\' => \'blue\',\r\n \'shoes\' => \'black\', //结尾建议加上逗号,这样要添加一个新单元时更方便 \r\n ];\r\n在JavaScript中,相同的数据如下所示:\r\n\r\n //JavaScript\r\n var clothes = {\r\n shirt : \'white\',\r\n pants : \'blue\',\r\n shoes : \'black\' //由于旧的IE的存在,结尾放逗号的话会出问题\r\n } \r\n\r\n //上面的JavaScript是直接定义的对象.也可直接定义数组.在JavaScript中,数组也是对象.\r\n //数组定义方式如下:\r\n var clothes = new Array();\r\n clothes[\'shirt\'] = \'white\';\r\n clothes[\'pants\'] = \'blue\';\r\n clothes[\'shirt\'] = \'black\';\r\n typeof clothes;//\"object\"\r\n \r\n在PHP中我们像下面这样遍历数组:\r\n\r\n //PHP\r\n $result = \'\';\r\n foreach ($clothes as $key => $value) {\r\n $result .= $key . \':\' . $value . \'\\n\';\r\n }\r\n\r\n在JavaScript中我们使用for-in循环:\r\n \r\n //JavaScript\r\n var result =\'\';\r\n for (var key in clothes) {\r\n result += key + \':\' + clothes[key] . \'\\n\';\r\n } \r\n\r\n在该循环中,我们不能直接访问下一个属性的值,因此,我们使用方括号表示法clothes[key]来获取值.\r\n\r\n还要注意,枚举属性的顺序不是固定的并且依赖于具体实习.换句话说,shoes可能出现在shirt之前,尽管其在定义中位于后面.如果想要保持这个顺序,我们需要使用一个常规的数组来存储数据.\r\n\r\n这里只是为了说明,如果你暂时忘了PHP中的foreach必须使用=>来访问值,你也可以在PHP中像下面这样做,以模拟JavaScript中的for-in循环:\r\n \r\n $result = \'\';\r\n foreach (array_keys($clothes) as $key) {\r\n $result .= $key . \':\' .$clothes[$key] . \'\\n\';\r\n } \r\n\r\n### 1.2.in ###\r\n在前面in操作符用来遍历一个对象的属性.它也可用来检查一个对象中是否存在某个属性:\r\n\r\n if (\'shirt\' in clothes) { //true\r\n //do something\r\n }\r\n if (\'hat\' in clothes) { //false\r\n //do something\r\n }\r\n\r\n也可用如下代码来进行检查:\r\n\r\n if (clothes[\'shirt\']) { //true\r\n //do something\r\n }\r\n\r\n或者,更常用的方法是使用点表示法\r\n\r\n if (clothes.shirt) { //true\r\n //do something\r\n }\r\n\r\n不同指出在于,in只是检查该属性是否存在,他根本不会查看其值.使用clothes.shirt检查,只是在该属性存在且其值为非假的时候,才返回true.\r\n\r\n例如,如果我们添加一个新的属性:\r\n\r\n clothes.jacket = undefined;\r\n\r\n那么:\r\n \r\n \'jacket\' in clothes; //true\r\n\r\n但是:\r\n \r\n clothes.jacket; //undefined\r\n !!clothes.jacket; //false\r\n \r\n因为clothes.jacket的值是undefined,这是一个假值,并且会强制转换为false.\r\n\r\n这类属于PHP中isset()和empty()的区别.\r\n\r\n此外,更麻烦一点,我们可以四月typeof操作符来只检查属性是否存在二不检查其值:\r\n\r\n typeof clothes.jacket !== \"undefined\"; //true\r\n\r\n //但是请注意,当一个属性是`undefined`值的时候,相应的就会得到false\r\n clothes.i_am_undefined = undefined;\r\n typeof clothes.i_am_undefined === typeof clothes.i_dont_exist; //true\r\n\r\n这种写法的一种更简单的方式是,与undefined值比较:\r\n\r\n clothes.jacket !== undefined; //true\r\n\r\n## 2.字符串连接 ##\r\n在PHP中我们使用`.`操作符来连接字符串.在查看for-in循环的时候,你可能已经注意到了,JavaScript中`+`操作符来连接字符串:\r\n\r\n var alphabet = \'a\' + \'b\' + \'c\';\r\n alphabet; //\"abc\" \r\n\r\n这可能有些奇怪,但是`+`操作符既可用来将数字相加,也可用来连接字符串:\r\n\r\n var numbers = \'1\' + \'2\' + \'3\';\r\n var sum = 1 + 2 + 3;\r\n numbers; //\"123\"\r\n sum; //6\r\n\r\n那么,我们如何知道该执行哪一种操作呢?这取决于操作数的类型.如果操作数是字符串,那么`+`就是连接字符串;如果操作数是数字,那么`+`就是求和.\r\n\r\n不必说,`+`操作符经常会导致错误,因此,记住变量类型就很重要.\r\n\r\n如果在计算和的时候,操作数是字符串,或者不清楚操作数的类型,可使用parseFloat()或parseInt()方法将字符串类型转换为数字类型,然后再求和:\r\n\r\n var a = \'1\', b = \'2\', c = \'3\';\r\n sum = parseFloat(a) + parseFloat(b) + parseFloat(c); //6\r\n\r\n对于连接字符串,一种替代方法是,将要添加的字符串存储到一个数组中,完成之后,再将数组的元素连接起来.这种方式在较早的浏览器例如IE7甚至更早的版本中都能很好的工作:\r\n\r\n [\'R\', \'2\', \'-\', \'D\', \'2\'].join(\'\'); //\"R2-D2\"\r\n\r\n最后,还可以使用contact()方法,该方法不需要我们为了连接字符串二创建临时的数组对象:\r\n \r\n \'\'.contact(\'R\', \'2\', \'-\', \'D\', \'2\'); //\"R2-D2\"\r\n String.prototype.contact(\'R\', \'2\', \'-\', \'D\', \'2\'); //\"R2-D2\"\r\n\r\n## 3.类型强制转换 ##\r\n由于`+`既可用于加法,也可用于字符串连接,我们也可用`+`来快速的转换变量的类型:\r\n\r\n +\'1\'; //将字符串\"1\"转换为数字1\r\n \'\'+1; //将数字1转换为字符串\"1\"\r\n\r\n这样,我们就可以像下面这样连接字符串或者求和:\r\n \r\n var numbers = \'\'+1 + \'\'+2 + \'\'+3; \r\n var sum = +\'1\' + +\'2\' + +\'3\';\r\n numbers; //\"123\"\r\n sum; //6\r\n\r\n说到强制转换,我们可以使用!!将变量转换为布尔类型:\r\n \r\n !!1; //true\r\n !!\'\'; //false\r\n\r\n第一个!取反,并且如果该值是假的话,会返回一个布尔true;第二个!再次取反,得到转换为布尔类型后我们想要的结果.此外,内建的构造函数也可用来执行变量的强制转换:\r\n \r\n Number(\'1\') === 1; //true\r\n String(100) === \'100\'; //true\r\n Boolean(0) === false; //true\r\n Boolean(100) === true; //true\r\n\r\n## 4.void ##\r\n我们可能会遇到的另一个操作符是void,它接受任意的表达式作为操作数,并且返回undefined:\r\n\r\n var a = void 1;\r\n typeof a === \'undefined\'; //true\r\n\r\nvoid操作数很少用到,它会用作链接红的href.和typeof操作符一样,人们常常错误的将其与分组操作符`()`一起使用,这使其看上去像是一个函数调用.\r\n\r\n有时候,typeof()用作一个函数,但是,不建议这么做.记住,typeof不是一个函数,而是一个操作符.在这种用法中,typeof()之所以像一个函数一样使用,是因为`()`也是一个操作符,它叫做分组操作符(grouping operator),通常用来覆盖操作优先级.例如:\r\n\r\n 3 * (2 + 1); //9\r\n 3 * 2 + 1; //7\r\n \r\n <!--这不是一个好的做法-->\r\n <a href=\"javascript:void(0)\">Click and Nothing Happens</a> \r\n \r\n这中糟糕的做法看上去是挺无辜的,但是,你思考一下就会发现,这么做确实很傻.在这个过程中,发生了如下的使其:\r\n\r\n1. 用户单击,计算一个JavaScript表达式\r\n1. 直接量0作为一个操作数发送给分组操作符()\r\n1. 分组操作符返回数组中的最终值0 \r\n1. 现在发送给void操作符\r\n1. void在这里是一个黑洞,它接受操作符并返回undefined\r\n\r\n即便不考虑这种什么也不是的链接的糟糕语义,人们还是会将herf设置为javascript:undefined.\r\n\r\nJavaScript中的`typeof(a)`和`typeof a`的关系,就像PHP中`echo ($a);`和`echo $a;`的关系(尽管使用二者的原因不同).PHP中的`include($a)`和`include $a`也是基于同样的道理.即使这种写法有效,大妈仍然被看做是一种糟糕的写法,因为它有点鱼目混珠.\r\n\r\n## 5.逗号操作符 ##\r\n逗号操作符是另一个奇怪的操作符,它是JavaScript中优先级最低的操作符,它直接返回传递给它的最后一个操作数的值:\r\n \r\n var a = (\'hello\', \'there\');\r\n a; //\"there\"\r\n var a = (\'hello\', \'there\', \'young\', \'one\');\r\n a; //\"one\"\r\n\r\n它类似于&&和||,然而,当结果一目了然的时候,这些表达式会停止计算,但是逗号操作符会继续计算:\r\n\r\n 0 && 2 && 1; //0\r\n 0 || 2 || 1; //2\r\n 0 , 2 , 1, //1 \r\n\r\n当JavaScript只期望一个表达式,而你想要偷偷插入另一个表达式的时候,逗号操作符就很有作用了.\r\n\r\n你是否注意到,前面的例子中,&&和||并不总是像PHP那样返回一个布尔值,.相反,它们返回想要表达式的值.这可能有点令人混淆,特别是在如下的常用模式中,也按照默认情况编写JavaScript的时候:\r\n\r\n //JavaScript\r\n var a = 100;\r\n var b = a || 200;\r\n b; //100\r\n\r\n //PHP\r\n $a = 100;\r\n $b = $a || 200;\r\n var_dump($b); //bool(true)\r\n\r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(222,'[预告]消息队列消费者大赛。','222',1419577800,1419829058,'<!--markdown-->这个是预告,暂时还没确定时间。\r\n\r\n## 科普一下:\r\n### 队列\r\n队列就是先进先出,排队的意思,不懂的可以百度一下或者关注scuinfo。\r\n消息队列,就是一些特定的字符串消息,在一个管子里,每次从菊花进去一个,或从嘴出来一个,也是先进先出。\r\n大概是这个样子的\r\n从这边进 o ----oooooooooooooooooooooo----> o 从这边出\r\n\r\n进一步应用到程序里:\r\n\r\n这边接收请求 o ----oooooooooooooooooooooo----> o 这边处理数据\r\n就算同一时间很多请求,也能放到队列里,慢慢等待,就像买火车票一样快乐,售票员一点都不慌。\r\n\r\n### 生产者 / 消费者\r\n上图左边的角色就是生产者,右边的就是消费者。\r\n所谓生产就是生产消息单元( o 就是这个),\r\n右边把消息一个个处理掉,就是消费者了。\r\n\r\n## 科普完毕,进入正题\r\n1.窝会准备一个有50万个消息的队列(消费掉了可以叫窝补充)\r\n2.然后泥萌用各种语言写消费者,具体为:\r\n 取出消息-->字符串处理-->写数据库-->取下一条消息...(循环)\r\n3.然后比较运行时间,比如你处理1万条活着5万,然后算每1000条点成绩\r\n4.可以使用多进程/多线程等技术,前提是数据不要出错\r\n\r\n## 怎么取消息?消息格式说怎样的?\r\n取消息方式说http请求,说httpsqs留的接口,地址问群里。\r\n消息格式&处理:\r\n比如,取出来的时 dsgygb_13_183_www.scuinfo.com\r\n我们要存到数据库里 name:dsgygb,age:13,height:183,website:www.scuinfo.com\r\n当然这只是个例子,具体安排请关注部长微博。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(216,'飞扬研发20141207会议记录(代发)','216',1417883343,1417883343,'<!--markdown-->(发者表示 这是一次严肃的代发 原作者@苏苏)\r\n笔者表示今天是一次严肃而内容丰富的会议,以会长的爬虫比赛为开端,在经过了漫长的对会长的等待后,会议正式开始……\r\n\r\n首先是部长的总结,总结了研发的几大问题及改善意见(主要关于报修系统):\r\n\r\n1.订单上:之前出现了技术员大量拒绝订单,导致客户满意度下降,现在提出修改可以让管理员设置,每个技术员每月最多拒绝n次订单,每单最多可被拒绝一次。\r\n\r\n同时为了防止技术员过度繁忙,提出每月接单总额上限为50单,超过上限后非会员单不再接。\r\n\r\n最后关于接单:每单分配后技术员如不在30小时内确认或者拒绝,则系统默认接单,同时系统以短信通知技术员。\r\n\r\n2.报修途径上:只有微信报修不够完善,依然需要开通网页报修,可以以手机号为ID绑定手机,做一个网页报修入口。\r\n\r\n3.用户反馈:可改进为用户评价+技术员回复形式;\r\n\r\n4.主页可开辟技术员展示模块:对技术员的订单进行统计并公开,同时公开每单评价。\r\n\r\n5.会员与非会员的区别问题:导入行政部表格,对会员优先;\r\n\r\n修改任务分配:\r\n会员认证系统:部长; \r\n网页报修:部长; \r\n订单短信通知:部长\r\n订单自动确认:狮虎; \r\n技术员数据官网可视化:JH;\r\n\r\n\r\n然后是水哥的一个提议,关于产品经理的问题:\r\n产品经理是负责跟进某个特定项目保证其正常运行的工作。由于我们的产品缺乏产品经理的跟进管理,无法及时的反馈和修复遇到的问题,同时我们的产品虽然是独立的,但是仍然需要改进和继续开发,经讨论,将项目如下划分:\r\n\r\n报修系统:\r\n狮虎,白会负责;\r\n官网:陶钰;\r\nOA/会员/绩点:JH;\r\nUC:部长;\r\n\r\n目前官网需要规划统计入口位置以及其他模块的排版设计;所有项目经理在明天天亮之前给出需求;\r\n\r\n\r\n最后狮虎总结了一下官网的备案问题,之前在陕西备案了两个域名,后来其中一个停用并被其他人注册了。现在我们在四川重新注册出现了信息不符,花了一部分时间才弄好。\r\n\r\n补充:12.21飞扬年会,窝萌部门需要出一个节目……\r\n\r\n\r\n又:下次例会大家需要展示聊天机器人作品:(包括所有在场人员\r\n\r\n语言分配如下:\r\n陶钰姐:PHP ; \r\n\r\n白会:PHP; \r\n\r\n水哥:PHP; \r\n\r\n邹兵学长:PHP;\r\n\r\n蓝神:nodeJS; \r\n\r\n狮虎:nodeJS;\r\n王济元:nodeJS;\r\n\r\n吴宗芸:nodeJS;\r\n \r\n部长:JAVA; \r\n\r\nJH:JAVA; \r\n\r\n崔倩姐:JAVA;\r\n \r\n陈宁学长:C/C++; \r\n\r\n窝:C/C++;\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(217,'聊天机器人需求','217',1417897699,1417897699,'<!--markdown-->说一下聊天机器人的一个需求:\r\n\r\n基本要求:\r\n\r\n1.能和人进行聊天,可以识别预置的关键词,并返回给相应的回答。\r\n2.可以教机器人聊天。(比如设置“@”为关键词,@你是##萌萌哒小花 ,类似这样的格式来交机器人回答)\r\n\r\n进阶要求(鼓励实现):能使用中文分词软件,以及良好的数据结构设计,充分考虑大量的请求,可利用上次的知乎日报的数据去教机器人。\r\n\r\n可使用控制台,UI界面来做输入输出控制。\r\n\r\n参加人员和所使用语言:\r\n\r\n陶钰姐:PHP ; \r\n\r\n白会:PHP; \r\n\r\n水哥:PHP; \r\n\r\n邹兵学长:PHP;\r\n\r\n蓝神:nodeJS; \r\n\r\n狮虎:nodeJS;\r\n王济元:nodeJS;\r\n\r\n吴宗芸:nodeJS;\r\n \r\n部长:JAVA; \r\n\r\nJH:JAVA; \r\n\r\n崔倩姐:JAVA;\r\n \r\n陈宁学长:C/C++; \r\n\r\n窝:C/C++;\r\n\r\n截止时间:2014/12/13 15:00',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(218,'linux用户和用户组','218',1422024000,1422024048,'<!--markdown-->## 一.用户和用户组##\r\n\r\n**1. /etc/group 储存当前系统中所有用户组信息**\r\n\r\n`Group:x:123:abc,def,xyz`\r\n组名称:组密码占位符:组编号:组中用户名列表\r\n\r\n用户组编号1至499是系统预留编号,是用来分配给软件的.安装一个软件就会创建该软件的一个用户组并分配一个用户组编号.越早安装的软件,编号越小.\r\n用户手动创建的用户组编号是从500开始的.\r\n\r\n**2. /etc/gshadow 粗存当前系统中用户组密码信息**\r\n\r\n`group:*: :abc,def,xyz`\r\n组名称:组密码:组管理者:组中用户名列表\r\n\r\n组密码为 `,` `*` 或 `!` ,我们都可以认为组密码为空,也就是组密码是没有密码的.\r\n那个用户可以管理该用户组.一般为空,表示所以用户都可以管理该用户组.\r\n\r\n**3. /etc/passwdn 存储当前系统中所有用户的信息**\r\n\r\n`user:x:123:456:xxxxxx:/home/user:/bin/bash`\r\n用户名:密码占位符:用户编号:用户组编号:用户注释信息:用户主目录:shell类型\r\n\r\n系统添加用户的时候,可以给用户添加备注信息. shell 是用来执行用户输入指令的硬件接口.我们一般使用 `/bin` 目录下的 bash 这个 shell 来下达用户执行的指令.\r\n\r\n用户被创建后,会在相应目录下创建相关的用户主目录.\r\n\r\n**4. /etc/shadow 存储当前系统中所有用户的密码信息**\r\n\r\n`user:vf:/Zus8dk... : : : :`\r\n用户名:密码\r\n\r\n密码是单向加密的,我们无法看出原始密码是什么。后面包含了用户创建时间,用户信息上一次登录的信息等等\r\n\r\n## 二.用户和用户组的基本命令##\r\n\r\n**1. groupadd 创建用户组**\r\n\r\n`groudadd fyyf`\r\n\r\n[ 创建fyyf 这个用户组. ]\r\n\r\n`groupadd -g 667 boss`\r\n[ -g 创建用户组并指定组编号 ]\r\n\r\n创建用户组后,会按照默认顺序创建组编号.通过 `vi /etc/group` 可查看. \r\n\r\n**2. groupmod 改变用户组信息**\r\n\r\n`groupmod -n fyyf2 fyyf`\r\n\r\n[ -n 改变组名称.将 fyyf 组名改为 fyyf2 ]\r\n\r\n`groupmod -g 666 fyyf2`\r\n[-g 改变组编号 ]\r\n\r\n**3. groupdel boss**\r\n\r\n`groupdel boss`\r\n\r\n[ 删除用户组.得先删除用户,才能删除用户组 ]\r\n\r\n**4. useradd**\r\n\r\n`useradd -g fyyf2 jh`\r\n\r\n[ -g 指定用户组,添加用户]\r\n\r\n`useradd -d /data/user/jh jh`\r\n\r\n[ -d 创建用户时,指定用户的个人文件夹.如果不指定,就会在home目录下创建要给和用户名同名的文件夹.不指定用户组,则系统默认创建一个和用户名相同的用户组. ]\r\n\r\n**5. usermod**\r\n\r\n`usermod -c hehe jh`\r\n\r\n[ -c 为用户添加用户信息,即注释.该例子的注释信息为 hehe ]\r\n\r\n`usermod -l nodejh jh`\r\n [ -l 更改用户名.将新的用户名写在前面,旧的用户名写在后面. ]\r\n\r\n`usermod -d /data/user/nodejh nodejh\r\n\r\n[ -d 修改用户的默认路径 ]\r\n\r\n`usermod -g root noedejh`\r\n\r\n[ -g 将某个用户加入用户组.将用户 nodejh 加入 root 用户组 ]\r\n \r\n**6. userdel 删除用户**\r\n\r\nuserdel nodejh\r\n\r\n[ 删除用户 nodejh ,但不会删除个人文件.若要同时删除文件,需要加参数 -r,即 `userdel -r nodejh` ]\r\n\r\n**7. 其他命令**\r\n\r\n1. 禁止普通用户登录 touch /etc/nologin 禁止除了root意外所有用户登录\r\n\r\n1. passwd -l cls 锁定账户\r\n\r\n1. passwd -u cls 解锁用户\r\n1. passwd -d cls 清楚密码,实现无密码登陆\r\n\r\n\r\n## 三.主要组与附属组 ##\r\n\r\n用户可以同时属于多个组:一个主要组,多个附加组.\r\n\r\n`gpasswd -a dsgygb boss`\r\n\r\n[ 将 dsg 账号添加到 boss 附属组;添加多个附属组用逗号隔开. ]\r\n\r\n`usermod -g`\r\n\r\n[ 修改主要用户组 ]\r\n\r\n`newgrp boss`\r\n\r\n [ 切换用户组.在自己的账号下,将当前登录的这个用户切换到 boos 组.当用户需要将身份切换到附属组的时候,若附属组有组密码,则切换的时候需要输入组密码. ]\r\n\r\n`gpasswd -d dsgygb boss`\r\n\r\n [ 删除附属组 ]\r\n\r\n`useradd -g group -G group1,group2`\r\n\r\n[添加用户,并添加主用户组和附属组 ]\r\n\r\n`gpasswd fyyf2`\r\n\r\n[ 给用户组设置组密码.回车后,输入密码即可,需要确认两次 ] \r\n\r\n`su username`\r\n \r\n[ 切换用户.如果不加参数,则切换至root用户.需要输入密码. root 用户切换至普通用户不需要输入密码 ]\r\n\r\n`Whoami` \r\n\r\n[ 我是谁.显示当前登陆用户.不知道这个命令有什么意义,命令行前面明明已经有用户名... ]\r\n\r\n`id nodejh`\r\n\r\n[ 显示指定用户信息.包括用户编号,用户名,主要组编号及名称,附属组列表. ]\r\n\r\n`groups nodejh`\r\n\r\n[ 显示 nodejh 用户所在的用户组 ]\r\n\r\n`chfn nodejh`\r\n \r\n[ 设置用户资料,依次输入用户资料 ]\r\n\r\n`finger nodejh`\r\n\r\n[ 现实用户详细资料 ]',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(219,'su: /bin/bash: Permission denied','219',1418417540,1418417540,'<!--markdown-->在远程服务器上创建了用户之后,通过 `su` 切换用户出现如下错误:\r\n\r\n新建用户:\r\n groupadd coder \r\n useradd -g coder -s /bin/bash jh \r\n\r\n切换用户:\r\n su jh\r\n su: /bin/bash: Permission denied\r\n\r\n解决方式:\r\n\r\n chmod 755 /\r\n chmod 755 /bin\r\n\r\n只通过错误信息来看是没有权限的问题,于是就修改权限,问题得以解决.但具体原因仍然不知,望有人能指出 -.-\r\n ',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(220,'[资源]不用翻墙了,httpsqs相关下载','220',1419482880,1419576218,'<!--markdown-->\r\n[libevent-2.0.12-stable.tar.gz][1]\r\n\r\n\r\n[tokyocabinet-1.4.47.tar.gz][2]\r\n\r\n\r\n[httpsqs-1.7.tar.gz][3]\r\n\r\n\r\n----------\r\n安装介绍请看 [张宴博客][4]\r\n安装过程出现的error自行百度,不难,\r\nconfigure 第二个东西的时候,会提示缺少 zlib,执行 `yum install bzip2-devel` 即可 \r\n\r\n\r\n [1]: http://pan.baidu.com/s/1c0F6wxi\r\n [2]: http://pan.baidu.com/s/1gd3oUKb\r\n [3]: http://pan.baidu.com/s/1o65c8d0\r\n [4]: http://zyan.cc/httpsqs/7/1/',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(221,'jQuery 多元素串行动画','221',1419491160,1419491601,'<!--markdown-->**jQuery** 可以很方便地给**元素集合**(选择符选出的元素)指定一系列动画,因为它的**核心动画方法 animate** 基于其内部实现的**动画队列**。但通常,一次性地给一个元素集合指定动画后,各成员元素的动画都是一同进行的。若有“一个接一个依次进行”的需求呢?\r\n\r\n在此,我们先基于网上对此屈指可数的解答中提到的“animate 方法的 **complete 回调参数**”来实现一个**【元素集合串行动画】**——\r\n\r\n (function ($) {\r\n \r\n var iNO = 0, $_Animate, iCallback;\r\n \r\n function iAnimate($_Element, iArgument) {\r\n var This_Func = arguments.callee;\r\n \r\n $.fn.animate.apply($_Element, [].concat(iArgument, function () {\r\n if (++iNO < $_Animate.length)\r\n This_Func($_Animate.eq(iNO), iArgument);\r\n else iCallback.call(this);\r\n }));\r\n }\r\n \r\n $.fn.iAnimate = function () {\r\n $_Animate = this;\r\n var iArgument = $.makeArray(arguments);\r\n if (typeof iArgument[iArgument.length - 1] == \'function\')\r\n iCallback = iArgument.pop();\r\n \r\n iAnimate($_Animate.eq(iNO), iArgument);\r\n \r\n return this;\r\n };\r\n \r\n })(self.jQuery);\r\n\r\n上述封装方法的参数格式与“原生 animate”完全相同。\r\n\r\n【参考文档】\r\n 1. http://www.cnblogs.com/dolphinX/p/3330174.html\r\n 2. http://zhidao.baidu.com/question/412851030(思路正确,但误解了 jQuery next 方法的含义,失去了普适性)',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(215,'2014.12.04飞扬内部讨论记录','215',1417801260,1417801568,'<!--markdown-->## 一.报修系统##\r\n\r\n**1.订单**\r\n\r\n*issue*\r\n(1)技术员可自由选择接单还是拒绝接单。造成订单分配不及时,和订单积压的问题。\r\n\r\n*discussion*\r\n(1)每个技术员每个月只能拒绝1次订单/设置每月拒绝次数\r\n(2)每个订单只能别拒绝1次/设置可被拒绝次数\r\n(3)开通短信接口,通过短信通知技术员有新订单,开通通过短信回复确认接单\r\n(4)技术员3小时内未确认接单,则不能再拒绝该订单/设置时间\r\n(5)每周总订单数为50,满了之后,会员可继续报修,普通用户不能报修\r\n(6)开发网页版报修接口\r\n\r\n**2.用户界面**\r\n\r\n*issue*\r\n(1)没有用户反馈系统\r\n(2)用户容易误触`取消订单`\r\n(3)会员和非会员区分不明显\r\n\r\n*discussion*\r\n(1)增加用户评论功能。评论为星级评论+内容。两项都必填\r\n(2)重新设计`取消订单`按钮\r\n(3)若是会员登陆,设计一个和普通客户不同的界面\r\n\r\n**3.私活模式**\r\n\r\n*issue*\r\n技术员没有使用私活模式\r\n\r\n*discussion*\r\n给技术员介绍私活模式的使用方法\r\n\r\n**4.大型维修**\r\n\r\n*discussion*\r\n大型维修不适用线上的报修系统。\r\n大修现场没有打印机,没办法打印订单给用户;线上+线下的报修模式更为复杂。\r\n大修最后只统计总报修数字。或者将报修电脑统计后,统一导入到数据库。\r\n\r\n## 二.官网##\r\n\r\n**1.技术员论坛**\r\n增加一个技术员论坛。\r\n(1)用来写电脑小问题的常用解决方式。\r\n(2)写技术员的维修心得。\r\n\r\n**2.技术员展示**\r\n在该页面展示技术员维修订单,维修日志等。\r\n\r\n*discussion*\r\n(1)展示技术员维修的所有订单,并可查看详情\r\n(2)展示客户对技术维修的评分(星级)以及评论\r\n(3)技术员可对用户评论进行追加评论 \r\n(4)展示技术员所写的报修心得\r\n\r\n**3.飞扬报修展示**\r\n增加一个板块,用来展示飞扬报修的总数量,以及各种信息。\r\n\r\n*discussion*\r\n(1)数据可视化\r\n(2)展示总订单数\r\n(3)......\r\n\r\n## 三.会员认证##\r\n\r\n**1.会员认证**\r\n\r\n**issue**\r\n没有会员认证,会员福利不明显。\r\n\r\n*discussion*\r\n(1)开发会员认证,以会员卡卡号+姓名座位身份标识\r\n(2)会员电脑优先分配,每周报修数量满了之后,会员可继续报修\r\n(3)登陆飞扬官网后,可选择绑定教务处。绑定教务处后,可开发和教务处有关的功能。\r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(213,'QQ图片20141205154405.jpg','QQ图片20141205154405-jpg',1417765465,1417765465,'a:5:{s:4:\"name\";s:26:\"QQ图片20141205154405.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/12/2847814876.jpg\";s:4:\"size\";i:6293;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',214),(214,'Linux创建常用SSH帐号','214',1417765500,1417765536,'<!--markdown-->**任何一篇文章都会说,日常使用root操作是很不安全的行为。因此要创建一个日常使用的超级用户。**\r\n\r\n**1.创建常用的账户**\r\n useradd jh\r\n passwd jh\r\n\r\n**2.编辑 sudoer 文件**\r\n vim /etc/sudoer\r\n\r\n将 jh 加入 root 用户组,以便使用sudo命令直接操作一些系统命令,减少对root账户的使用。\r\n\r\n**3.编辑 sshd 配置文件,修改一些默认选项(可选)**\r\n #仅使用SSH2协议\r\n Protocol 2\r\n\r\n #修改密钥生成强度\r\n ServerKeyBits 1024\r\n\r\n #禁止root账户通过ssh登录\r\n PermitRootLogin no\r\n\r\n #禁止使用常规的用户名密码方式登录,此项慎用\r\n #在没有生成好Key,并且成功使用之前,不要设置为no\r\n PasswordAuthentication no\r\n![QQ图片20141205154405.jpg][1]\r\n #禁止空密码登录\r\n PermitEmptyPasswords no\r\n\r\n\r\n**4.重启 sshd **\r\n方法一:\r\n /etc/init.d/sshd restart\r\n方法二:\r\n service sshd restart\r\n\r\n\r\n [1]: http://log.scuinfo.com/usr/uploads/2014/12/2847814876.jpg',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(212,'【浏览器小工具】墙内 Google 划词搜索','@212',1416888060,1417060403,'<!--markdown-->天朝**习大大**继位之后,政坛、社会暗流更加汹涌,各路高官皆有落马者…… **好在江山依然稳固,彭阿姨依然美丽**,但我**大谷歌**却牺牲更大,义务封口近一岁,重放新声遥无期……\r\n\r\n好在我朝素不缺**侠肝义胆之士**,树立数个**海外镜像**来招魂,其魂最真者 —— [某 **V2EX** 大神的一声**天问** —— 路在何方!~][1]\r\n\r\n鄙人不才,仅能**低调地传承侠客的义举** —— 把大神的招魂镜像封装在[我之前做的一个 Bookmarklet][2] 中,并再次优化,方便大家使用 ——\r\n\r\n安装用代码\r\n-----\r\n\r\n javascript: (function(BOM,DOM,SL){function iRegExp(a,b){var c=/ /;return c.compile(a,b),c}var trim=function(){var a=iRegExp(\"(^s*)|(s*$)\",\"g\");return function(b){return b.replace(a,\"\")}}(),SS=function(WF){var TN,TA,N,n,IS=\"\";for(TN in{input:0,textarea:0})try{TA=DOM.getElementsByTagName(TN);for(N in TA)with(TA[N])IS=trim(value.slice(selectionStart,selectionEnd))}catch(EO){}if(\"\"==IS&&(IS=trim(DOM.selection?DOM.selection.createRange().text:DOM.getSelection().toString())),\"\"==IS)for(n=0;n<WF.length;n++){try{IS=arguments.callee(WF[n])}catch(EO){}if(\"\"!=IS)break}return IS}(BOM.frames);\"\"!=SS?BOM.open([\"https://wen.lu/search?newwindow=1&lr=lang_\",SL,\"&q=\",encodeURIComponent(SS)].join(\"\"),\"_blank\"):BOM.confirm(\"您未选中任何网页中的文字……\\n\\n\\n『确定』进入问题反馈;『取消』即退出本工具。\")?(BOM.prompt(\"输入框中的是『运行环境』信息,请直接复制它们,按『确认』即可访问 原作者主页~\",navigator.userAgent),BOM.open(\"http://www.fyscu.com/\",\"_blank\")):BOM.alert(\"【Google 中文搜索助手 v0.9】\\n\\n(C)2013-2014 四川大学·飞扬俱乐部·研发部\")})(top,top.document,\"zh-CN\");\r\n\r\n开发用源码\r\n-----\r\n\r\n (function (BOM, DOM, SL) {\r\n \r\n function iRegExp(Pattern, Mode) {\r\n var RegEx = / /;\r\n RegEx.compile(Pattern, Mode);\r\n return RegEx;\r\n }\r\n var trim = (function () {\r\n var RegEx = iRegExp(\'(^\\s*)|(\\s*$)\', \'g\');\r\n return function (Str) {\r\n return Str.replace(RegEx, \'\');\r\n };\r\n })();\r\n \r\n var SS = (function (WF) {\r\n var IS = \'\';\r\n for (var TN in {input: 0, textarea: 0}) try {\r\n var TA = DOM.getElementsByTagName(TN);\r\n for (var N in TA) with (TA[N])\r\n IS = trim( value.slice(selectionStart, selectionEnd) );\r\n } catch (EO) {};\r\n if (IS == \'\') IS = trim(\r\n DOM.selection ?\r\n DOM.selection.createRange().text :\r\n DOM.getSelection().toString()\r\n );\r\n if (IS == \'\') for (var n = 0; n < WF.length; n++) {\r\n // 以下异常处理 很神奇地 绕过了 IE、Firefox 对 iframe 的跨域安全限制~\r\n // 但可能在它们中运行时会有一瞬间的卡顿……\r\n try { IS = arguments.callee( WF[n] ); } catch (EO) {};\r\n if (IS != \'\') break;\r\n }\r\n return IS;\r\n })(BOM.frames);\r\n \r\n if (SS != \'\')\r\n BOM.open([\r\n \'https://wen.lu/search?newwindow=1&lr=lang_\', SL,\r\n \'&q=\', encodeURIComponent(SS)\r\n ].join(\'\'), \'_blank\');\r\n else if ( BOM.confirm(\r\n \"您未选中任何网页中的文字……\\n\\n\\n『确定』进入问题反馈;『取消』即退出本工具。\"\r\n ) ) {\r\n BOM.prompt(\r\n \"输入框中的是『运行环境』信息,请直接复制它们,按『确认』即可访问 原作者主页~\",\r\n navigator.userAgent\r\n );\r\n BOM.open(\'http://www.fyscu.com/\', \'_blank\');\r\n } else BOM.alert(\r\n \"【Google 中文搜索助手 v0.9】\\n\\n(C)2013-2014 四川大学·飞扬俱乐部·研发部\"\r\n );\r\n })(top, top.document, \'zh-CN\');\r\n\r\n为何还坚持 Google ?\r\n--------------\r\n\r\n 1. **棱镜门丑闻**虽然揭露了**美帝在国际互联网隐藏多年的大木马**,Google 等业界典范也未能幸免…… 但一个**世界最大的移民国家对自由执着的追求**,让那些阴暗面总是不能得逞太久;而**天朝的秘密**大多都躺在几十年后还不一定能解密的档案中……\r\n 2. **百度**这样一个**唯利是图、没啥技术**的搜索引擎,**搜索结果中假冒伪劣、坑蒙拐骗丛生,人为和谐比比皆是** —— 叫“中国黄页”还差不多~\r\n 3. **搜狐搜狗**虽是**中国大陆搜索引擎中最用心、最努力的**,2010年和**腾讯搜搜**一样,接收了一些**谷歌中国危机**中跳槽的人才,2014年又全面合并人才储备不少的搜搜,加上**搜狗输入法**多年积累的**语料数据、技术创新**,已经很棒了~ 但个人近两年对它的持续使用发现 —— **垃圾站屏蔽、小众站抓取** 还有较大进步空间……\r\n 4. **奇虎360搜索** 有点像当年 115搜索 等**结果二次筛选**的网站,虽然它一直力行用户体验第一的产品原则,但作为 3B大战的直接产物,加上360一直屡教不改的“**流氓推广**”方式,让我没法信任它提供的内容……\r\n\r\n [1]: http://v2ex.com/t/117230?r=hourui\r\n [2]: http://bbs.fyscu.com/forum.php?mod=viewthread&tid=3677',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',210),(209,'JavaScript去掉字符串中的空格','209',1416820133,1416820133,'<!--markdown-->**`JavaScript` 中没有 `trim` 函数,所有无法直接去掉空格。**\r\n\r\n**但 `jQuery` 内置了 `trim` 函数,可以很方便的使用。**\r\n<br>\r\n## 1.jQuery trim 函数取空格##\r\n\r\n var str=\' string \';\r\n str = $.trim(string);\r\n \r\n<br>\r\n## 2.使用正则表达式去空格 ##\r\n\r\n var str=\' hello \';\r\n\r\n function trimLeft(s){\r\n return s.replace( /^\\s*/, \"\");\r\n }\r\n \r\n function trimRight(s){\r\n return s.replace( /\\s*$/, \"\");\r\n }\r\n \r\n function trim(s){\r\n return trimRight(trimLeft(s));\r\n }\r\n \r\n str = trimLeft(str);//去左空格;\r\n str = trimRight(str);//去右空格\r\n str = trim(str);//去掉左右空格\r\n \r\n });',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(210,'【浏览器小工具】墙内 Google 划词搜索','210',1416888060,1416980924,'<!--markdown-->天朝**习大大**继位之后,政坛、社会暗流更加汹涌,各路高官皆有落马者…… **好在江山依然稳固,彭阿姨依然美丽**,但我**大谷歌**却牺牲更大,义务封口近一岁,重放新声遥无期……\r\n\r\n好在我朝素不缺**侠肝义胆之士**,树立数个**海外镜像**来招魂,其魂最真者 —— [某 **V2EX** 大神的一声**天问** —— 路在何方!~][1]\r\n\r\n鄙人不才,仅能**低调地传承侠客的义举** —— 把大神的招魂镜像封装在[我之前做的一个 Bookmarklet][2] 中,并再次优化,方便大家使用 ——\r\n\r\n安装用代码\r\n-----\r\n\r\n javascript: (function(BOM,DOM,SL){function iRegExp(a,b){var c=/ /;return c.compile(a,b),c}var trim=function(){var a=iRegExp(\"(^s*)|(s*$)\",\"g\");return function(b){return b.replace(a,\"\")}}(),SS=function(WF){var TN,TA,N,n,IS=\"\";for(TN in{input:0,textarea:0})try{TA=DOM.getElementsByTagName(TN);for(N in TA)with(TA[N])IS=trim(value.slice(selectionStart,selectionEnd))}catch(EO){}if(\"\"==IS&&(IS=trim(DOM.selection?DOM.selection.createRange().text:DOM.getSelection().toString())),\"\"==IS)for(n=0;n<WF.length;n++){try{IS=arguments.callee(WF[n])}catch(EO){}if(\"\"!=IS)break}return IS}(BOM.frames);\"\"!=SS?BOM.open([\"https://wen.lu/search?newwindow=1&lr=lang_\",SL,\"&q=\",encodeURIComponent(SS)].join(\"\"),\"_blank\"):BOM.confirm(\"您未选中任何网页中的文字……\\n\\n\\n『确定』进入问题反馈;『取消』即退出本工具。\")?(BOM.prompt(\"输入框中的是『运行环境』信息,请直接复制它们,按『确认』即可访问 原作者主页~\",navigator.userAgent),BOM.open(\"http://www.fyscu.com/\",\"_blank\")):BOM.alert(\"【Google 中文搜索助手 v0.9】\\n\\n(C)2013-2014 四川大学·飞扬俱乐部·研发部\")})(top,top.document,\"zh-CN\");\r\n\r\n开发用源码\r\n-----\r\n\r\n (function (BOM, DOM, SL) {\r\n \r\n function iRegExp(Pattern, Mode) {\r\n var RegEx = / /;\r\n RegEx.compile(Pattern, Mode);\r\n return RegEx;\r\n }\r\n var trim = (function () {\r\n var RegEx = iRegExp(\'(^\\s*)|(\\s*$)\', \'g\');\r\n return function (Str) {\r\n return Str.replace(RegEx, \'\');\r\n };\r\n })();\r\n \r\n var SS = (function (WF) {\r\n var IS = \'\';\r\n for (var TN in {input: 0, textarea: 0}) try {\r\n var TA = DOM.getElementsByTagName(TN);\r\n for (var N in TA) with (TA[N])\r\n IS = trim( value.slice(selectionStart, selectionEnd) );\r\n } catch (EO) {};\r\n if (IS == \'\') IS = trim(\r\n DOM.selection ?\r\n DOM.selection.createRange().text :\r\n DOM.getSelection().toString()\r\n );\r\n if (IS == \'\') for (var n = 0; n < WF.length; n++) {\r\n // 以下异常处理 很神奇地 绕过了 IE、Firefox 对 iframe 的跨域安全限制~\r\n // 但可能在它们中运行时会有一瞬间的卡顿……\r\n try { IS = arguments.callee( WF[n] ); } catch (EO) {};\r\n if (IS != \'\') break;\r\n }\r\n return IS;\r\n })(BOM.frames);\r\n \r\n if (SS != \'\')\r\n BOM.open([\r\n \'https://wen.lu/search?newwindow=1&lr=lang_\', SL,\r\n \'&q=\', encodeURIComponent(SS)\r\n ].join(\'\'), \'_blank\');\r\n else if ( BOM.confirm(\r\n \"您未选中任何网页中的文字……\\n\\n\\n『确定』进入问题反馈;『取消』即退出本工具。\"\r\n ) ) {\r\n BOM.prompt(\r\n \"输入框中的是『运行环境』信息,请直接复制它们,按『确认』即可访问 原作者主页~\",\r\n navigator.userAgent\r\n );\r\n BOM.open(\'http://www.fyscu.com/\', \'_blank\');\r\n } else BOM.alert(\r\n \"【Google 中文搜索助手 v0.9】\\n\\n(C)2013-2014 四川大学·飞扬俱乐部·研发部\"\r\n );\r\n })(top, top.document, \'zh-CN\');\r\n\r\n为何还坚持 Google ?\r\n--------------\r\n\r\n 1. **棱镜门丑闻**虽然揭露了**美帝在国际互联网隐藏多年的大木马**,Google 等业界典范也未能幸免…… 但一个**世界最大的移民国家对自由执着的追求**,让那些阴暗面总是不能得逞太久;而**天朝的秘密**大多都躺在几十年后还不一定能解密的档案中……\r\n 2. **百度**这样一个**唯利是图、没啥技术**的搜索引擎,**搜索结果中假冒伪劣、坑蒙拐骗丛生,人为和谐比比皆是** —— 叫“中国黄页”还差不多~\r\n 3. **搜狐搜狗**虽是**中国大陆搜索引擎中最用心、最努力的**,2010年和**腾讯搜搜**一样,接收了一些**谷歌中国危机**中跳槽的人才,2014年又全面合并人才储备不少的搜搜,加上**搜狗输入法**多年积累的**语料数据、技术创新**,已经很棒了~ 但个人近两年对它的持续使用发现 —— **垃圾站屏蔽、小众站抓取** 还有较大进步空间……\r\n 4. **奇虎360搜索** 有点像当年 115搜索 等**结果二次筛选**的网站,虽然它一直力行用户体验第一的产品原则,但作为 3B大战的直接产物,加上360一直屡教不改的“**流氓推广**”方式,让我没法信任它提供的内容……\r\n\r\n [1]: http://www.v2ex.com/t/126018\r\n [2]: http://bbs.fyscu.com/forum.php?mod=viewthread&tid=3677',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(211,'【原创】Google 站内搜索小工具(完善重发)','211',1416990720,1416990805,'<!--markdown-->对于**经常在互联网中查资料去开拓自己的未知领域**的人们来说,**搜索引擎**绝对是必备工具 —— 它不但能在全球浩瀚的信息海洋中对我们需要的信息“大海捞针”,也能有针对性地对某个网站的内容进行搜寻,让我们能不受**内容源网站自身内容组织结构**的负面影响,迅速找到需要的内容。\r\n\r\n虽然 **站内搜索** 早已是搜索引擎的标配,但大多做得不好,经常一篇文章已经在某网站发布了比较久了,但就是搜不出来……(特别是 中途调整过**网址结构**的网站,比如 路径格式变更、换子域名、换主域名 等)\r\n\r\n目前为止,**Google** 依然是 难得可用且很好用的**站内搜索引擎**,这一点我在以前原创的[【Google 站内搜索助手】v0.9][1]的发布帖中早有论述~\r\n\r\n因为我对上述工具的[上游代码][2]做了升级,所以也重构了这个工具。而且,我把自己写的所有实用的 **Bookmarklet** 整合成了一个[**开源项目 iBookmarkLet**][3] 发布,所以博文里就只贴出**安装版代码** ——\r\n\r\n javascript: (function(BOM,DOM){function iRegExp(a,b){var c=/ /;return c.compile(a,b),c}var DN,HN,trim=function(){var a=iRegExp(\"(^s*)|(s*$)\",\"g\");return function(b){return b.replace(a,\"\")}}(),SS=function(WF){var TN,TA,N,n,IS=\"\";for(TN in{input:0,textarea:0})try{TA=DOM.getElementsByTagName(TN);for(N in TA)with(TA[N])IS=trim(value.slice(selectionStart,selectionEnd))}catch(EO){}if(\"\"==IS&&(IS=trim(DOM.selection?DOM.selection.createRange().text:DOM.getSelection().toString())),\"\"==IS)for(n=0;n<WF.length;n++){try{IS=arguments.callee(WF[n])}catch(EO){}if(\"\"!=IS)break}return IS}(BOM.frames);\"\"!=SS?(HN=BOM.location.hostname,DN=HN.match(/(edu|net|org|com|gov)\\.\\w+$/)?HN.match(/(\\w+\\.){2}\\w+$/):HN.match(/\\w+\\.\\w+$/),BOM.open(\"https://wen.lu/search?newwindow=1&q=\"+encodeURIComponent([SS,\" site:\",DN[0]].join(\"\")),\"_blank\")):BOM.confirm(\"您未选中任何网页中的文字……\\n\\n\\n『确定』进入问题反馈;『取消』即退出本工具。\")?(BOM.prompt(\"输入框中的是『运行环境』信息,请直接复制它们,按『确认』即可访问 原作者主页~\",navigator.userAgent),BOM.open(\"http://www.fyscu.com/\",\"_blank\")):BOM.alert(\"【Google 站内搜索助手 v1.0】\\n\\n(C)2013-2014 四川大学·飞扬俱乐部·研发部\")})(top,top.document);\r\n\r\n\r\n [1]: http://bbs.fyscu.com/forum.php?mod=redirect&goto=findpost&ptid=2711&pid=58461\r\n [2]: http://log.fyscu.com/index.php/archives/210/\r\n [3]: http://git.oschina.net/Tech_Query/iBookmarkLet/',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(206,'yum安装memcache到CentOS','206',1416535920,1429899687,'<!--markdown-->### 第一步\r\n yum install libevent\r\n\r\n### 第二步\r\n wget http://dag.wieers.com/rpm/packages/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm\r\n rpm -ivh rpmforge-release-0.3.6-1.el5.rf.i386.rpm\r\n\r\n### 第三步\r\n yum -y install –enablerepo=rpmforge memcached php-pecl-memcache\r\n pecl install memcache\r\n### 启动\r\n servive memcached start',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(207,'.net协会年度精品活动:看谁抓的又快又好','207',1416644340,1416671373,'<!--markdown-->**活动时间:2014.11.22-2014.12.6**\r\n\r\n**希望研发2.0全员参加.以及大一大二准备下学期加入研发的同学.以及本校其他大牛们~**\r\n\r\n**活动内容**:选择你喜欢的语言,去抓取指定网站的内容。两个礼拜的时间。\r\n\r\n**语言**:php,python,ruby,c,c++,nodejs,java,易语言等等......\r\n\r\n**抓取网站**:http://zhihudaily.ahorn.me/ [点击进入](http://zhihudaily.ahorn.me)\r\n\r\n**要求:**将该站所有文章,约10000+篇文章,将每一篇文章的标题,题图地址,作者,作者简介,文章内容全文 写入到后缀为.md的文件。\r\n\r\n**文件格式如下:** \r\n\r\n ![题图](题图地址)\r\n ### 标题\r\n *作者:xxx(简介)*\r\n 正文\r\n\r\n\r\n评比标准:所花时间最少者,如果花时间一样,以代码质量为评选标准。\r\n\r\n评比时间:12.6日例会 现场计时跑。\r\n\r\n**请参加者,在本篇文章下,报名参加,说明自己采用的编程语言。**\r\n\r\n**哦,奖品很大。可能是一年的付费VPN。**',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(204,'"闻道有先后"后台需求','204',1416460303,1416460303,'<!--markdown-->经过这半个多月的时间,闻道有先后的前台部分以及搜索模块已基本成型了。现在将后台模块需求列出如下:\r\n\r\n**总览**:后台包括管理员/编辑登录/注销,发布/编辑/删除代码块,为代码块的每一行添加标注功能。管理员有增加/删除编辑权限,以及用户管理。 就酱紫。\r\n\r\n**数据库** Mysql\r\n\r\n**语言** 推荐使用世界上最好的语言PHP来写(如果你熟悉的话,也可以用nodejs来写)\r\n\r\n**详细**:\r\n1.**管理员/编辑登录/注销** 调用飞扬UC(user center:飞扬开发的基于oauth2.0的单点登录平台)进行登录和注销。\r\n\r\n2.**发布/编辑/删除代码块 以及标注** 要求后台编辑器在发布/编辑代码的时候支持语法高亮显示。代码块的标题需要调用中文分词保存在指定数据表,编辑器可使用 特殊标记 来表示对某一行的标注(比如@#这里的内容是对上一行的标注#@),并写入数据库。需要把每一个代码块的总行数提取出来写入数据库。\r\n\r\n3.**用户管理** 管理员特权:可以看到目前的用户的列表/基本信息/最近登录等,也可以搜索用户,并修改用户组(管理员/编辑/普通)\r\n\r\n\r\n列表就是以上,基本就是一个增删改查的后台,登录那块uc已经有demo了,推荐用[fyscu](http://fyscu.lanhao.name) 框架来开发,后台不需要太漂亮,但是一定不能丑,可以使用[妹子UI](http://www.amazeui.org)、或者[bootstrap](http://bootcss.com)来写。编辑器那块 有很多开源的编辑器可以直接用,我大概查了一下,觉得[codeMirror](http://codemirror.net/) 是比较好用的一个。\r\n\r\n以上。\r\n\r\n',0,4,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(202,'【原创】实现一个好用的网页布局系统(栅格、流式)','202',1416273900,1416818904,'<!--markdown-->CSS 2 大行其道的年代,**CSS + Div 布局法**一直是 **Web 前端开发**的核心与重难点之一,让很多初学者、后端程序猿生畏、头疼;而当 **CSS 3** 开始逐渐流行后,**HTML 5 / CSS 开发框架**又如雨后春笋,令人眼花缭乱。于是,很多人会觉得 <font color=\"red\" size=\"3\">**网页布局**</font> 是个高深、蛋疼的活儿~\r\n\r\n## 救世主 BootStrap ##\r\n\r\n用过 Web 前端框架的人想必都对大名鼎鼎的 **Twitter BootStrap** 有所了解,它不但逻辑行为方面完全基于 **jQuery**,在网页布局方面也像 jQuery 一样,用**简洁的 API**(HTML 结构、CSS 类)在较短时间内就能搭建出 **Modern & Responsive View**,方便初学者上手~\r\n\r\n很多人一见“框架”二字,就会觉得很牛逼,高不可攀,特别是这些前端框架的 CSS 还都是 Less、Sass 等高级样式语言编译出来的一大坨紧凑代码。所以,要么就乖乖地用框架,平时盼更新,没了就不会写;要么就自己草草地手敲,一个项目一套写法,永远没个章法~\r\n\r\n## 凡人修仙 ##\r\n\r\n其实在科研、工程领域,“**大道至简**”的道理永不过时,再复杂的理论、技术,其核心原理都是很简练的,然后再由其基本元素按照基本规则随机组合,以致千变万化~\r\n\r\n我把我手写纯 HTML/CSS 提炼出的一个框架 <font color=\"red\" size=\"3\">**EasyLayout.css** (v1.0)</font> 中的**布局系统** 提出来与大家分享我的**自适应网页布局**的心得 —— **结合 `<div />` 简洁的书写结构与 `<table />` 完善的长宽、居中算法**,轻松达成 ——\r\n - 行列式**栅格布局**:列格**宽度自适应**、列格**自动等高**、列格**子元素垂直居中**\r\n - 单位内容框**流式布局**:行列数、总行数自适应屏幕宽度(**自动换行**),且所有内容框可**水平居中**\r\n\r\n\r\n * {\r\n box-sizing: border-box;\r\n }\r\n \r\n /* ----- Toolkit ----- */\r\n .ClearFix:after, body:after,\r\n ul:after, form:after, div:after,\r\n header:after, footer:after, nav:after,\r\n article:after, section:after, aside:after {\r\n content: \" \";\r\n font-size: 0;\r\n line-height: 0;\r\n height: 0;\r\n width: 0;\r\n visibility: hidden;\r\n display: block;\r\n clear: both;\r\n zoom: 1;\r\n }\r\n .CenterX {\r\n text-align: center;\r\n }\r\n .CenterY {\r\n display: table;\r\n }\r\n .CenterY > * {\r\n float: none;\r\n display: table-cell;\r\n vertical-align: middle;\r\n }\r\n .Ellipsis,\r\n .Ellipsis a, .Ellipsis span,\r\n .Ellipsis li, .Ellipsis td {\r\n overflow: hidden;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n }\r\n .Float-L { float: left; }\r\n .Float-R { float: right; }\r\n .Fix-Top {\r\n position: fixed;\r\n z-index: 2147483647;\r\n }\r\n \r\n /* ----- Grid Layout ----- */\r\n .Grid-Row {\r\n display: table;\r\n width: 100%;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n .Grid-Column {\r\n display: table-cell;\r\n /* Patch for iframe child-element */\r\n vertical-align: top;\r\n }\r\n .Grid-Column.CenterY {\r\n float: none;\r\n vertical-align: middle;\r\n }\r\n .Column-1_1 {\r\n width: 100%;\r\n text-align: left !important;\r\n }\r\n .Column-1_2 {\r\n width: 50%;\r\n }\r\n .Column-1_3 {\r\n width: 33.3%;\r\n }\r\n .Column-2_3 {\r\n width: 66.6%;\r\n }\r\n .Column-1_4 {\r\n width: 25%;\r\n }\r\n .Column-3_4 {\r\n width: 75%;\r\n }\r\n .Column-1_5 {\r\n width: 20%;\r\n }\r\n .Column-4_5 {\r\n width: 80%;\r\n }\r\n .Column-2_5 {\r\n width: 40%;\r\n }\r\n .Column-3_5 {\r\n width: 60%;\r\n }\r\n .Column-1_6 {\r\n width: 16.6%;\r\n }\r\n .Column-5_6 {\r\n width: 83.3%;\r\n }\r\n .Column-1_7 {\r\n width: 14.2%;\r\n }\r\n .Column-6_7 {\r\n width: 85.7%;\r\n }\r\n .Column-3_7 {\r\n width: 42.8%;\r\n }\r\n .Column-4_7 {\r\n width: 57.1%;\r\n }\r\n .Column-4_9 {\r\n width: 44.4%;\r\n }\r\n .Column-3_10 {\r\n width: 30%;\r\n }\r\n .Column-11_20 {\r\n width: 55%;\r\n }\r\n\r\n /* ----- Item Box ----- */\r\n .Item-Box {\r\n display: inline-block;\r\n margin: 0 1% 0.5em;\r\n text-align: left;\r\n background: white;\r\n border: 1px solid rgb(215, 215, 215);\r\n box-shadow: 1px 2px 3px rgb(200, 200, 200);\r\n transition: border-color ease-in-out .15s,\r\n box-shadow ease-in-out .15s;\r\n }\r\n .Item-Box:hover {\r\n border-color: rgb(14, 144, 210);\r\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),\r\n 0 0 8px rgba(14, 144, 210, 0.6);\r\n }\r\n\r\n上述代码的核心在于 ——\r\n - 栅格布局:`display: table(-cell)` 与 `vertical-align: middle`\r\n - 流式布局:`display: inline-block` 与 `text-align: center`\r\n\r\n是不是有些“返璞归真”的感觉?在保留 **块级元素 可指定长宽、内外边距、定位坐标**的同时,重新拾起 **行内元素 自动换行/原生水平居中**、**表格单元格 自动等高/自调宽度/原生垂直居中**的优秀特性~\r\n\r\n示例代码\r\n----\r\n\r\n <body>\r\n <header class=\"Grid-Row\">\r\n <div class=\"Grid-Column Column-1_6\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-5_6 CenterY\">\r\n ......\r\n </div>\r\n </header>\r\n <div id=\"Main\" class=\"Grid-Row\">\r\n <div class=\"Grid-Column Column-1_6\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-5_6\">\r\n <div class=\"Grid-Row CenterX\">\r\n <div class=\"Item-Box\">\r\n <div class=\"Grid-Column Column-1_6\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_2 CenterY\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_3 CenterY\">\r\n ......\r\n </div>\r\n <div class=\"Item-Box\">\r\n <div class=\"Grid-Column Column-1_6\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_2 CenterY\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_3 CenterY\">\r\n ......\r\n </div>\r\n <div class=\"Item-Box\">\r\n <div class=\"Grid-Column Column-1_6\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_2 CenterY\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_3 CenterY\">\r\n ......\r\n </div>\r\n <div class=\"Item-Box\">\r\n <div class=\"Grid-Column Column-1_6\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_2 CenterY\">\r\n ......\r\n </div>\r\n <div class=\"Grid-Column Column-1_3 CenterY\">\r\n ......\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </body>',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(195,'iframe 视觉效果融入主页面(一)—— 内容高度自适应','195',1415352420,1415352479,'<!--markdown-->**B/S 应用系统**开发中,`<iframe />` 是一种**兼顾 前后端程序员配合、程序解耦的实用技术**,比较蛋疼的主要在于 —— **视觉效果上让用户感觉不出系统界面是由多个较为独立的网页合成的**……\r\n\r\n一般大家会首先面临 —— **iframe 内容高度自适应,让子页面都不出现滚动条,整个网页只有主页面有滚动条~**\r\n\r\n虽然网上有非常多的技术博客讲过这个问题,也有一两种经典方案,但在实际应用中其实很不理想…… 我自己和与我配合的后端程序猿折腾了很久,在网上经典代码的基础上改了不知多少次,终于整出了**可用性**比较高的程序 ——\r\n\r\n // iFrame 视觉效果 融入父页面 v0.3\r\n\r\n $(document).ready(function () {\r\n function Local_iFrame(Context) {\r\n return $(\'iframe\', Context || self.document).filter(function () {\r\n var _SRC = $(this).attr(\'src\');\r\n if (_SRC && _SRC.match(/^(\\w+:)?\\/\\//)) {\r\n return !! _SRC.match(\r\n RegExp( \'^\' + [location.protocol, \'\', location.host].join(\"\\\\/\"), \'i\' )\r\n );\r\n }\r\n return true;\r\n });\r\n }\r\n function Offset_TopWin(Element) {\r\n var Offset_Sum = {left: 0, top: 0};\r\n for (var Offset_Temp, Wait = 0; Element !== null; ) {\r\n Offset_Temp = $(Element).offset();\r\n Offset_Sum.left += Offset_Temp.left;\r\n Offset_Sum.top += Offset_Temp.top;\r\n try {\r\n Element = Element.ownerDocument.defaultView.frameElement;\r\n } catch (Err) { break; }\r\n }\r\n return Offset_Sum;\r\n }\r\n var iTimer, iFrame_List = [];\r\n function iFrame_DH(){\r\n if (! Local_iFrame().length) {\r\n clearInterval(iTimer);\r\n return;\r\n }\r\n Local_iFrame().each(function () {\r\n var iHeight;\r\n try{\r\n var iMethod = \'min\',\r\n iURL = this.contentWindow.location.href;\r\n if (iURL == \'about:blank\') return;\r\n else if (jQuery.inArray(iURL, iFrame_List) < 0) {\r\n iFrame_List.push(iURL);\r\n iMethod = \'max\';\r\n }\r\n if (parseInt(this.frameBorder) != 0) {\r\n this.frameBorder = 0;\r\n this.allowTransparency = true;\r\n }\r\n var iFrame_DOM = this.contentWindow.document;\r\n var iDocument = iFrame_DOM.documentElement,\r\n iBody = iFrame_DOM.body;\r\n iHeight = Math[iMethod](\r\n iBody.scrollHeight,\r\n iDocument.scrollHeight\r\n ) + 20;\r\n } catch (Error) {\r\n if (this.frameBorder == 0) {\r\n this.frameborder = 1;\r\n this.allowTransparency = false;\r\n }\r\n iHeight = (IE_Ver > 8) ?\r\n $(this.ownerDocument.defaultView).height() - Offset_TopWin(this).top :\r\n 500;\r\n }\r\n if (iHeight != this.height) this.height = iHeight;\r\n });\r\n }\r\n iTimer = setInterval(iFrame_DH, 200);\r\n });\r\n\r\n上述程序在高度自适应方面与经典方案的区别主要在于 —— 不一味地取 document、body 各自 scrollHeight 的最大值,那样会造成 iframe 的高度在重复使用的过程中只增不减。因为 `iframe.height == iframe.contentWindow.document.scrollHeight`,iframe 度过加载初期之后,(除非 `<body />` 的所有子元素都是 `position: absolute / fixed`,)子页的内容高度就是 body 的高度。所有,应该在首次设置高度时取大值,以后都取小值。',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(196,'更改wampserver的默认项目目录','196',1415525880,1421257491,'<!--markdown-->**wampserver安装后,默认的项目目录是按照路径下的`www`目录。**\r\n\r\n**例如我的wampserver是安装在`D:/wamp`,则我的默认项目文件夹路径是`D:/wamp/www`。可以点击wampserver的图标,点击 `www directory` 快捷访问。**。\r\n\r\n**但有时候,这样不利于项目的管理,或者就是看不惯,想改一改默认路径。那请往下看。主要有两步:**\r\n\r\n**例:将默认路径改为 `D:/www`** \r\n\r\n**1.更改默认网站路径**\r\n\r\n打开 `D:\\wamp\\bin\\apache\\Apache2.2.17\\conf \\httpd.conf`\r\n\r\n查找: `DocumentRoot \"D:/wamp/www/\"`\r\n修改为: `DocumentRoot \"D:/www/\"`\r\n\r\n查找: `<Directory \"D:/wamp/www/\">`\r\n修改为: `<Directory \"D:/www/\"> `\r\n\r\n**2.更改 `www directory` 指定的路径**\r\n\r\n**修改D:\\wamp\\wampmanager.ini:**\r\n\r\n(1)打开:`D:\\wamp\\wampmanager.ini`\r\n\r\n(2)查找:`Type: item; Caption: \"www directory\"; Action: shellexecute; FileName: \"D:/wamp/www/\"; Glyph: 2`\r\n\r\n(3)修改为:`Type: item; Caption: \"www directory\"; Action: shellexecute; FileName: \"D:/www/\"; Glyph: 2`\r\n\r\n\r\n**修改 `D:\\wamp\\wampmanager.tpl`:**\r\n\r\n(1)打开:`D:\\wamp\\wampmanager.tpl`\r\n\r\n(2)查找:`Type: item; Caption: \"${w_wwwDirectory}\"; Action: shellexecute; FileName: \"${wwwdir}\"; Glyph: 2`\r\n\r\n(3)修改为:`Type: item; Caption: \"${w_wwwDirectory}\"; Action: shellexecute; FileName: \"d:/www\"; Glyph: 2 `\r\n\r\n**然后退出 wampserver ,再次启动即可。**\r\n\r\n<br>\r\n**注:**\r\n\r\n1.第一步中,要确保修改后的目录是存在的。不然wampserver可能启动不成功。\r\n\r\n2.第二步中,要退出后再启动。不然 `www directory` 无法重新指向新目录。',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(191,'浏览器自定义事件(模仿 jQuery bind、trigger、live 方法)','191',1414985160,1414992192,'<!--markdown-->纯 **JavaScript** 实现的**浏览器事件** **绑定**(可延迟)、**触发**(可自定义)——\r\n\r\n (function (BOM, DOM) {\r\n \r\n var UA = navigator.userAgent;\r\n var IE_Ver = UA.match(/MSIE (\\d+)\\.\\d/i) ||\r\n UA.match(/Trident\\/.+; rv:(\\d+)\\.\\d/i);\r\n IE_Ver = IE_Ver ? Number(IE_Ver[1]) : NaN;\r\n var old_IE = IE_Ver && (IE_Ver < 9);\r\n \r\n BOM.iEvent = {\r\n bind: function (Element, Type, CallBack) {\r\n if (! old_IE)\r\n Element.addEventListener(Type, CallBack, false);\r\n else Element.attachEvent(\'on\' + Type, CallBack);\r\n for (var i = 0, EO; i < this.promise.length; i++) {\r\n EO = this.promise[i];\r\n if (EO && (EO.type == Type)) {\r\n if (! old_IE) Element.dispatchEvent(EO);\r\n else Element.fireEvent(EO.type, EO);\r\n this.promise[i] = null;\r\n }\r\n }\r\n },\r\n trig: function (Element, Type) {\r\n if (! old_IE) {\r\n var EO = DOM.createEvent(\'HTMLEvents\');\r\n EO.initEvent(Type, true, true);\r\n Element.dispatchEvent(EO);\r\n } else {\r\n var EO = DOM.createEventObject();\r\n EO.type = \'on\' + Type;\r\n Element.fireEvent(EO.type, EO);\r\n }\r\n this.promise.push(EO);\r\n },\r\n promise: []\r\n };\r\n })(self, self.document);\r\n\r\n【参考文章】\r\n\r\n 1. http://www.zhangxinxu.com/wordpress/2012/04/js-dom%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6/',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(197,'偶得,跨域也能处理逻辑','197',1415776939,1415776939,'<!--markdown-->印象中,跨域就不是个什么好东西,一提到跨域,就觉得是没办法了,这条路走不通。\r\n`其实不然。`\r\n\r\n跨域的请求,其实也走了一趟目标服务器,检测到服务器没有允许跨域请求(比如 `CORS` )\r\n\r\n那么对于没有允许的跨域请求,就真的没法处理了吗?\r\n\r\n### 当然还是可以处理的。\r\n\r\n当一个请求到达服务器,它请求的`uri`信息,`headers`信息就已经到达了,\r\n即使这个请求被跨域原则驳回,我们服务端已经收到这些信息了,\r\n也就是说\r\n### 我们可以将一些信息放到头部或者uri,然后就能穿过跨域来处理了。\r\n\r\n最后,这个有什么用?\r\n第一,部分接口可以这样传数据,而不用给站点开跨域。\r\n第二,小心别人这样hack你的网站,GET参数防不住啊。\r\n\r\n`其他深入研究,后续展开`\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(198,'【记录】javascript获取页面的referer','198',1415783460,1415951062,'<!--markdown-->服务端自不多说,通过`headers`信息即可,而在浏览器端,也是有办法的。\r\n\r\n var getReferrer=function() {\r\n\r\n var referrer = \'\';\r\n\r\n try {\r\n\r\n referrer = window.top.document.referrer;\r\n\r\n } catch(e) {\r\n\r\n if(window.parent) {\r\n\r\n try {\r\n\r\n referrer = window.parent.document.referrer;\r\n\r\n } catch(e2) {\r\n\r\n referrer = \'\';\r\n\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n if(referrer === \'\') {\r\n\r\n referrer = document.referrer;\r\n\r\n }\r\n\r\n return referrer;\r\n\r\n };\r\n\r\n单纯记录一下,记不起的时候看看',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(201,'[翻译]初创公司,这是设计的原理','201',1416237600,1416469847,'<!--markdown-->译者注:为配合交程序员设计系列翻译中的引用而翻译。\r\n\r\n原文:[https://startupsthisishowdesignworks.com/](https://startupsthisishowdesignworks.com/)\r\n\r\n\r\n像苹果这样的公司使得初创公司不可能去忽略设计。像[github](http://github.com/),[Airbnb](http://airbnb.com/),[Square](http://squareup.com/),和[Fitbit](http://fitbit.com/)已经将设计作为商业核心,并且他们做着非凡的工作。但是“设计”到底是什么?是个logo?wordpress主题?或者是一个创新的UI?\r\n\r\n不,远远不止这些。设计是一种精神状态,是解决问题的途径,是你准备如何去踢你的竞争对手的屁股的方式。这个简要的指南将帮助你理解设计并且提供帮你发现超赞的设计天才的资源。\r\n\r\n### 1.1 **设计是解决问题的方法**\r\n\r\n这是最简单的定义。设计包含了如此多的东西,用许多不同的方法去执行,但是功能总是相同的。它是否是一个蓝图,一个可爱的UI,一个小册子,或者一把椅子——设计可以帮助解决视觉或者物理的问题。\r\n\r\n\r\n### 1.2 **所以,什么是\"好的设计\"?**\r\n\r\n这个不太好定义。最好的设计是大家都知道的:看起来一点也没有设计,或者说\"undesigned\"。\r\n\r\n我们把事情分解一下是很容易理解了,如果你知道去找什么,那么当你看到它的时候或者**可能你看不到它**,就能很容易辨认什么是好的设计。\r\n\r\n\r\n### 1.3Dieter Ram关于“好的设计”的十个原则\r\n\r\n**Dieter Rams**是一位紧密联合消费者的博朗公司与功能主义工业设计的德国工业设计师。\r\n\r\n据Vits说:早在上个世纪80年代初,他就意识到他的设计是对世界非常大的贡献,他问他自己了一个重要的问题:**“什么样的设计才是好的设计?”**\r\n\r\n由于好的设计不能用标准的方法来衡量,他发表了十个他认为的好的设计的重要原则。(简称\"十戒\")。下面是这十个原则:\r\n\r\n1.**创新**:用尽任何手段去创新。科技的发张总是配合着创新的设计,但是设计的革新从来没有跟上科技的革新并且从没有为了设计而去设计。\r\n\r\n2.**做有用的产品**:\r\n\r\n产品做出来就是用的。它必须满足某种标准,不仅仅是实用的,而且兼具心理学和美感。好的设计强调一个产品的有效性,当你使用它的时候没有任何的其他东西可以使你转移注意力。\r\n\r\n3.**美**\r\n\r\n产品的美感对他的有效性有不可或缺的作用,因为我们每天都要用它,它影响着我们每个人以及我们的幸福与否。所以,只有是精心设计的产品才是美好的。\r\n\r\n4.**让一个产品容易理解**\r\n\r\n好的设计必须阐明这个产品的结构。比较好的技巧是,它可以让产品讲话,最好,它是自解释的。\r\n\r\n5.**不引人注意**\r\n\r\n产品就像工具一样实现一个目的。既不是装饰的对象,也不是艺术工作。产品的设计应该兼具中立和克制,留给用户自我表达的空间。\r\n\r\n6.**诚实的**\r\n\r\n好的设计不会让真实的自己看起来更加的创新,强大,有价值。不会试图把他不能做的承诺给消费者。\r\n\r\n7.**持续时间长的**\r\n\r\n好的设计避免时尚性,因此从来不会过时,不像时尚设计,他会持续很多年——甚至在今天的社会。\r\n\r\n\r\n8.**周密的**\r\n\r\n绝逼不能是武断的或者疏忽的。在设计的过程中谨慎和精确是对消费者的尊重。\r\n\r\n9.**环保的**\r\n\r\n设计对环保提出了很大的挑战,好的设计应该在产品的全部生命周期贯穿节约资源,并且最小化物理和视觉污染。\r\n\r\n10.**极简**\r\n\r\n越少,但是越好——因为好的设计关注最重要的方面,而且,该产品不应该有非必需品。\r\n\r\n回到纯粹的,简单的设计。\r\n\r\n\r\n> 我们设计师,不是活在真空里,我们需要和人们打交道。我们不是艺术家,常常有人混淆设计师和技术加。在我看来,如今严肃对待设计的公司很少很少。\r\n> ——Dieter Rams\r\n\r\n\r\n### 1.4 好的设计并不是由光滑的按钮或者高超的线条单独实现。它是这些所有的原则融合而成的,经过深思熟虑的。\r\n\r\n就像伟大的商业计划没有专家来执行什么都没有,一个伟大的Ps模型什么都没有。比如说,没有对UI或用户需求进行谨慎的分析。\r\n\r\n\r\n### 1.5 设计面面观\r\n\r\n是一部以提供者的视角从牙刷到科技产品背后的每一件创造性的纪录片。\r\n\r\n### 1.6\r\n\r\n看一看你身边的产品,是否以一种革新的方式设计出来的?这样的设计是否使得产品变得有用,容易理解,并且美观呢?是否不会过时?或者说它在几年后看起来也不会过时或者坏掉?\r\n\r\n这真的是一个很难回答的问题。设计师使得你在给定的范围内去创造让消费者深爱的产品。爱真的是一个很强烈的情感。\r\n\r\nDieter Rams和他的同时代人在20世纪开始了简而美运动。设计甚至在60年前就已经为企业带来非常重要的价值,在如今商业化的今天,依然如此,设计是一个非常行之有效的方法。\r\n\r\n## 设计分为很多种类\r\n\r\n### 2.1 平面设计\r\n\r\n这是一个描述不同种类设计者的定义。可以把它想象为“企业家”。描述各种各样的像VC,CEO的商人,但是没有全包括。平面设计师主要工作是平面图像,包括插图,印刷,或者图片以及各种印刷和网络媒体。平面媒体是典型的2D渲染——打印在物理表面或者显示在屏幕上。\r\n\r\nI.纸媒设计\r\n\r\n平面设计中工作在纸媒的一种类型,在电脑,软件,网络尚未大范围的普及之前,事实上平面设计师都在做海报,杂志,广告牌和书籍。纸媒设计师是典型的排版、插图大师,传统的印刷工艺,想排字机或凸版印刷机,这些已经使用了500多年的印刷方式由于他的手工制作和传统的感觉如今又流行起来了。\r\n\r\n### 2.2交互设计\r\n\r\n在另一方面来说,交互设计师聚焦在数字产品和软件交互设计。比如说,网络应用facebook和Pinterest,移动应用Tweetbot,操作系统OS X.在平面设计意味着观察,交互设计为了实现目标特性,帮助人们用基于屏幕硬件来体验或操作软件或接口,比如说检测电子邮件,在ATM机取款,或者在你朋友圈点个赞。\r\n\r\n**\"交互设计着重于让使用某种产品的人感到满意\"**\r\n\r\n\r\nI.用户界面设计\r\n\r\n用户界面(UI)设计着重于软件以及网页的用户体验和界面。**用户界面设计的目标是使得用户界面尽可能的简单和高效。**好的用户界面设计从不“把自己画出来” todo\r\n\r\n\"设计的过程一定是平衡技术功能和视觉元素而创作的不仅仅可以运行而且能适应不断改变的用户需求的系统。“\r\n\r\nI.用户体验\r\n\r\n用户体验(UX)由“心理学,人类学,社会学,计算机科学,平面设计,认知科学”组成。由产品的目标决定,用户体验也许涉及内容组织,比如沟通设计,教程设计或者游戏设计。\r\n\r\n用户体验的目标是在用户和产品之间创建无缝、简单有用的交互设计,包括硬件和软件。与用户界面设计相比,用户体验更注重与创建交互设计去满足和促进用户期望和需求。\r\n\r\n\r\n### 2.3 工业设计\r\n\r\n工业设计者创造满足成千上万的大众消费的实体产品。摩托车,iPods,牙刷,以及床头柜等等全部是由工业设计者设计的。他们都是实体货物和在生产线和大机器的些之下的创新大师。\r\n\r\n“他们研究的是功能和形式,以及产品与用户、环境之间的连接。”\r\n\r\n## 数据:业内人士怎么看?\r\n\r\n### 3.1创业公司认为设计最重要的是什么?\r\n\r\n我问了78个CEO,市场营销者,工程师,以及设计师他们对设计的定义是什么。在我提出这个项目之前,我不得不在入门之前重新核定我的假设,并且获得了一些可靠的数据。似乎企业家、工程师和设计师门思考着同样的事情。\r\n\r\n### 3.2 产品设计有多重要?\r\n\r\n产品设计包括虚拟和实体产品,它不仅仅需要美观,而且**它是什么?用户要怎么样用它,以及用户能否很容易的使用它快速处理事情。\r\n\r\n想一想,产品设计对你而言有多重要?对你的消费者来说美观和易用性有多重要?\r\n\r\n### 3.3设计的程度?\r\n\r\n现在我们到这了。在创业公司的文化里,棒的设计是根源,并且看起来很多人拥抱改变。很多企业家,开发者和工程师不仅看到了他们产品还有很大的提升空间,而且他们压倒性的相信设计师在初建团队中的重要性。\r\n\r\n> (译者注:4的部分略去不翻译,主要介绍了美国本土的几个设计师以及本土去寻找设计师的地方,在天朝基本无用,直接上第五点)\r\n\r\n## 资源\r\n\r\n### 5.4 \r\n\r\n这仅仅是初创公司在设计方面的入门东西,有很多信息量,非常多杰出的想法在讨论棒的设计。\r\n\r\n下面是我非常推荐的一些资源:\r\n\r\n[hackDESIGH](http://hackdesign.org/?ref=stihdw) :教程序员学设计的地方\r\n\r\n[designer fund](http://thedesignerfund.com/) 设计师交流社区\r\n\r\n[creativemornings](http://creativemornings.com/) 有若干的主题的演讲,免费的,包括20分钟演讲和咖啡。\r\n\r\n[the design observer group](http://designobserver.com/)设计师和文化写作社区\r\n\r\n[a list apart](http://alistapart.com/)发现设计,开发者以及网络内容运营,注重网页标准以及最好的练习\r\n\r\n[swiss miss](http://swiss-miss.com/)一个设计的博客\r\n\r\n[ilt](http://ilovetypography.com/)我爱印刷排版\r\n\r\n[typekit](http://typekit.com/)在你的网站加一行代码就能在线选择多种字体\r\n\r\n[ga](http://generalassemb.ly/)用于科技,设计以及企业家大学\r\n\r\n[our choice](http://ourchoicethebook.com/)AL Gore和Push Pob Press推出的电子书,将会改变我们阅读的方式。也有可能改变世界\r\n\r\n[kerning game](http://type.method.ac/)字距调整游戏,你只需要把每个字母分配的让用户阅读起来舒服、愉快就行了。\r\n\r\n[dribbble](http://dribbble.com/)Dribbble是一个为设计师展示、讨论、分享他们设计的产品的截图的社区。\r\n\r\n[helvetica](http://amazon.com/Helvetica/dp/B002RIOGI0/ref=sr_1_1?s=instant-video&ie=UTF8&qid=1331186392&sr=1-1)是一部关于排版、平面设计以及视觉文化的长篇独立电影。\r\n\r\n[smashing](http://www.smashingmagazine.com/)为网页设计师和开发者提供有用的、创新的信息。\r\n\r\n[objectified](http://amazon.com/Objectified/dp/B002SOUVKU/ref=pd_sim_mov_aiv_2)关于复杂的工业设计的长篇纪录片,扩展开来,就是设计他们的人。中文名:设计面面观。\r\n\r\n[ted](http://ted.org/)牛逼的人的很吸引人的演讲,免费。实际上,很深刻也很幽默。\r\n\r\n[zerply](http://zerply.com/)招聘电视、电影、游戏方面的人,你可以上传你的简历。\r\n\r\n[core77](http://core77.com/)设计师聚集的社区,发布文章、教程、聚会、展示。\r\n\r\n[500startups](http://500.co/)创业孵化公司,提供基金,指导,在设计,数据,分发上帮助创业者们。\r\n\r\n[aiga](http://aiga.org/)设计职业协会,致力于把设计发展为职业的工艺,战略工具以及重要的文化促进。\r\n\r\n[a type prinner](http://atypeprimer.com/)介绍实用的排版的一本书,分析基本的原则和打字应用。\r\n\r\n[signal noise](http://37signals.com/svn)37个人写的关于商业,设计,体验,朴素,网页,文化的博客。\r\n\r\n[behance](http://behance.net/)认证的职业设计师和团队展示作品的网站。\r\n\r\n[design the new business](http://www.designthenewbusiness.com/)一部纪录片,讲述了设计是如何改变我们的行为方式和商业方式。\r\n\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(200,'[翻译]教程序员学设计第二课:设计是什么?为什么他是重要的?','200',1416226980,1416479536,'<!--markdown-->原文地址:[https://hackdesign.org/lessons/1](https://hackdesign.org/lessons/1)\r\n\r\n\r\n为什么设计?设计的目的是什么?不是纯粹的美学,也不全是分析和功能。当你考虑你的项目的设计时,你必须思考每一个零散的东西要如何和谐的组合在一起,我认为,这是解决问题的唯一最实用的方法。\r\n\r\n就像你在[上一课](http://log.fyscu.com/index.php/archives/199/)中学到的,设计对人们的生活产生了巨大的影响,并且由于他是照顾到每个人的,所以是积极的影响。这个礼拜你将会获得到设计师是怎样思考的,以及设计学科的多样性。下面是你要学的预览:\r\n\r\n1.初创公司,这是设计的原理([原文链接](https://hackdesign.org/tasks/3) [译者翻译链接](http://log.fyscu.com/index.php/archives/201/))\r\n\r\n在这个链接里寻找一些你可以保存为数千和以后自己做的时候的参考的资源。这篇文章有很多来自全世界的有帮助的站点,会议,以及聚焦于设计的组织。设计的第一步就把你自己沉浸在设计的海洋中~\r\n\r\n2.从开发者过渡到设计者([原文链接](https://hackdesign.org/tasks/15) 待翻译)\r\n\r\n通过阅读这些技巧,请注意,这不仅仅是设计师所必需的——这是所有想创造伟大的产品的人所应该具备的通用的技巧。\r\n\r\n顺便说一句,感谢[@gem_ray](http://twitter.com/gem_ray)给我分享这篇文章。\r\n\r\n3.我们不开心,我们是设计师\r\n\r\n\r\n\r\n\r\n\r\n\r\n',0,4,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(188,'【笔记】移动 Web 前端开发 那些蛋疼事儿','188',1414733640,1447397954,'<!--markdown-->**移动 Web 前端开发的设备适配** 现在有种“**兼容老 IE**”的蛋疼感…… 希望刚刚正式颁布的 **HTML 5 标准**可以让这种现在渐渐改变,而不是又一个“Web 噩梦时代”的开始……\r\n\r\n以下是一些**优秀参考文章**的搜集,是**本人肉眼过滤**于 sogou.com;而非 URL 的条目则是 **肉测心得** ——\r\n\r\n响应式设计入门\r\n-------\r\n 1. http://www.cnblogs.com/vajoy/p/3903591.html\r\n 2. http://jinjuan.me/webapp-share-zte/\r\n\r\nUser Agent(网页客户端 标识符)\r\n---------------------\r\n - http://outofmemory.cn/code-snippet/1901/mobile-liulanqi-Us\r\n\r\nMeta/Viewport 标签(移动设备适配元数据)\r\n---------------------------\r\n 1. http://sowm.cn/wpjam/article/5FBDBB430CC9E424299B61EC03BF5C42.html\r\n 2. http://wiki.eoeandroid.com/Targeting_Screens_from_Web_Apps\r\n 3. http://wanglery.iteye.com/blog/1926747\r\n 4. http://www.cnblogs.com/stephenykk/p/3822441.html\r\n\r\n屏幕像素比\r\n-----\r\n - http://www.zhangxinxu.com/wordpress/2012/08/window-devicepixelratio/\r\n\r\nTarget DensityDPI(安卓中等屏幕专用)\r\n-------------------------\r\n - http://blog.csdn.net/fengri5566/article/details/9414599\r\n\r\nWebView 怪癖(***微信内置浏览器*** 等)\r\n-------------------------\r\n 1. **JavaScript 动态设置 Viewport** 时 `device-width` 无效,需手动指定 具体像素值(如 320)\r\n 2. 其 **device-dpi** ≠ medium-dpi(设置无效),最佳效果是手动指定为 `medium-dpi`\r\n 3. **Android** 有些版本的 **WebView 组件**中 `<input type=\"file\" />` 无效,它的调用从底层被拦截,在 JavaScript 层面无异常抛出,程序没被中断\r\n\r\nposition: fixed 大坑\r\n------------------\r\n 1. https://github.com/maxzhang/maxzhang.github.com/issues/11\r\n 2. https://github.com/maxzhang/maxzhang.github.com/issues/2\r\n 3. https://github.com/maxzhang/maxzhang.github.com/issues/7\r\n\r\n移动版网页布局技巧\r\n---------\r\n 1. http://www.w3cplus.com/mobile/mobile-terminal-refactoring-mobile-layout.html\r\n 2. http://blog.csdn.net/hursing/article/details/9186199\r\n\r\nFlex-Box 布局 基本用法、老版兼容\r\n---------------------\r\n\r\n\r\n----------\r\n\r\n\r\n移动端网页调试 —— HTTP\r\n---------------\r\n\r\n## 公网(weinre + 花生壳) ##\r\n 1. http://www.cnblogs.com/lhb25/p/debug-mobile-site-and-app-with-weinre.html\r\n 2. http://segmentfault.com/q/1010000000941321\r\n 3. http://service.oray.com/question/2480.html\r\n\r\n## 内网(UC 浏览器开发者版 + WiFi) ##\r\n 1. http://www.uc.cn/business/developer/\r\n 2. http://plus.uc.cn/document/webapp/doc5.html\r\n\r\n## 内网(Firefox 42 + WiFi) ##\r\n 1. https://developer.mozilla.org/zh-TW/docs/Tools/Remote_Debugging/Debugging_Firefox_for_Android_over_Wifi\r\n\r\n\r\n----------\r\n\r\n\r\n线上网页 JS 日志\r\n----------\r\n 1. http://jslogger.com\r\n\r\n\r\n----------\r\n\r\n\r\n触控事件的蛋疼\r\n-------\r\n 1. http://select.yeeyan.org/view/213582/202991\r\n 2. http://www.cnblogs.com/pifoo/archive/2011/05/23/webkit-touch-event-1.html\r\n 3. http://www.aliued.cn/2013/04/27/%E7%A7%BB%E5%8A%A8%E5%BC%80%E5%8F%91%E4%B9%8Btouch-event%E7%AF%87.html\r\n 4. http://www.web-tinker.com/article/20364.html\r\n\r\nGPU 硬件加速渲染\r\n----------\r\n 1. http://blog.bingo929.com/transform-translate3d-translatez-transition-gpu-hardware-acceleration.html\r\n\r\n(绝对是 **未完待续**……)',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(189,'JavaScript 多组数值比较最大最小','189',1414734180,1414734376,'<!--markdown--> (function (BOM) {\r\n \r\n function NumberMost(Type, iArray) {\r\n var Temp = {\r\n index: -1,\r\n value: (Type == \'min\') ? Infinity : -Infinity\r\n };\r\n for (var i = 0, This; i < iArray.length; i++) {\r\n This = parseFloat(iArray[i]);\r\n if ( isNaN(This) ) continue;\r\n if (This != Temp.value)\r\n Temp.value = Math[Type](This, Temp.value);\r\n if (This == Temp.value)\r\n Temp.index = i;\r\n }\r\n return Temp;\r\n }\r\n function Args2Array(Args) {\r\n return [].concat.apply([], Args);\r\n }\r\n \r\n BOM.iMax = function () {\r\n return NumberMost(\'max\', Args2Array(arguments));\r\n };\r\n BOM.iMin = function () {\r\n return NumberMost(\'min\', Args2Array(arguments));\r\n };\r\n })(self);',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(193,'iframe 通过 src 属性完成的加载不触发 onload','193',1415332924,1415332924,'<!--markdown-->疑难症状\r\n----\r\n我本想在 `<iframe />` 的 **onload 事件**回调中在其子页面中执行一段程序(也可以叫做“**注入上下文**”,即**从父页面注入代码到子页面的上下文中运行**),**让父页面能响应子页面的操作**。搞了好久,就是有一个子页面不行……(即便用 **jQuery** 推荐的**事件委托法**,在文档还在加载 `<head />` 中的元素时就在 `document` 上监听稍后加载的 iframe 冒泡上来的 onload 事件,也完全没有截获……)\r\n\r\n疑难诊断\r\n----\r\n绞尽脑汁很久之后发现,不触发的 iframe 与其它的唯一实质区别在于 —— 在 HTML 源码中有预设的 src 属性,其它的都是靠 `<a target=\"iframe_name\" href=\"./xxx/xxx.xxx?xxx=xxx\"></a>` 或 `<form target=\"iframe_name\" action=\"./xxx/xxx.xxx\"></form>` 来加载子页的~\r\n\r\n这就说明 ——\r\n\r\n> 预设 **src 属性**的 `<iframe />` 不触发 onload 事件\r\n> \r\n> (至少 **Webkit 内核**是这样,其它的内核有空再一一测试)\r\n\r\n解决方案\r\n----\r\n其实 onload 事件在 JavaScript 前端开发中并不是最佳选择,因为它在 HTML 源码中所有内容及其引用的资源加载完之后才触发。通常我们不等图片、插件等加载完就可以操作完整的 HTML DOM 树结构,就可以执行主要的业务逻辑。所以,各种 JS 基础库封装的 DOM Ready 事件(W3C 标准中是 DOMContentLoaded)就是我们的最佳选择~\r\n\r\n但对 iframe 而言,它在父页面 DOM Ready 时正处在加载初期,其 window 对象可能都无法访问,即便用 `try ... catch` 也可能在这种父子页面都处于混沌期的状态下造成 JS 死循环,整个页面都只能强关重启……\r\n\r\n综上,最稳妥的方法是 ——\r\n> 在每个 `<iframe src=\"./xxx/xxx.xxx?xxx=xxx\"></iframe>` 子页面中都自行引用(`<script />` 式)并执行一段 DOM Ready 跨页面冒泡的 JS 脚本,手动触发子页面的外包 iframe 的 onload 事件\r\n',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(187,'【笔记】Web 前端开发疑难','187',1414549500,1463109933,'<!--markdown-->**网页布局** 方方面面**疑难解答**的优秀文章,由本人**肉眼搜集**于 sogou.com(按一般的**技术学习路线**排序;**技术更迭,未完待续**)——\r\n\r\n【CSS 盒模型】元素长宽计算与 padding、border 的关系\r\n-----------------------------------\r\n 1. http://bbs.aau.cn/forum.php/?mod=viewthread&tid=7398\r\n 2. http://www.cnblogs.com/muyun/p/3567235.html\r\n\r\n【浏览器乱象】网页长宽属性\r\n-------------\r\n 1. http://blog.sina.com.cn/s/blog_48e6792c0100z7ge.html\r\n 2. http://blog.csdn.net/u010200222/article/details/10948059\r\n 3. http://www.cnblogs.com/yesw/p/4259727.html\r\n\r\n【CSS】伪元素特性\r\n----------\r\n 1. http://www.cnblogs.com/oooweb/p/css-pseudo-element-before-and-after.html\r\n 2. http://www.hulufei.com/post/about-before-and-after-pseudo-element\r\n\r\n【CSS】content 属性用法详解\r\n-------------------\r\n 1. http://blog.dimpurr.com/css-before-after/\r\n 2. http://www.zhangxinxu.com/wordpress/2010/04/css-content%e5%86%85%e5%ae%b9%e7%94%9f%e6%88%90%e6%8a%80%e6%9c%af%e4%bb%a5%e5%8f%8a%e5%ba%94%e7%94%a8/\r\n 3. http://www.zhangxinxu.com/wordpress/2014/08/css-counters-automatic-number-content/\r\n 4. http://www.w3cplus.com/css3/css-counters.html\r\n\r\n【CSS】文本溢出显示省略号\r\n--------------\r\n 1. http://www.cnblogs.com/lilyimage/p/3653864.html\r\n\r\n【CSS 盒模型】position、float 与 display 关系梳理\r\n--------------------------------------\r\nhttp://www.cnblogs.com/coffeedeveloper/p/3145790.html\r\n\r\n【CSS 盒模型】内容、元素水平、垂直居中\r\n---------------------\r\n 1. http://www.qianduan.net/css-to-achieve-the-vertical-center-of-the-five-kinds-of-methods.html\r\n 2. http://www.zhangxinxu.com/wordpress/2010/10/%e6%88%91%e6%89%80%e7%9f%a5%e9%81%93%e7%9a%84%e5%87%a0%e7%a7%8ddisplaytable-cell%e7%9a%84%e5%ba%94%e7%94%a8/\r\n\r\n【CSS 盒模型】z-index 堆叠规则\r\n---------------------\r\n 1. http://blog.doyoe.com/2014/01/21/css/%E4%BD%A0%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3%E7%9A%84z-index%E4%B8%96%E7%95%8C/\r\n\r\n【CSS 3】IE CSS 滤镜\r\n----------------\r\n 1. http://www.cnblogs.com/shiyangxt/archive/2008/11/16/1334633.html\r\n 2. http://www.javascriptkit.com/filters/filters.shtml\r\n 3. http://www.laoshu133.com/post/css_background_transparence.html?jdfwkey=ggieh1\r\n 4. http://www.cnblogs.com/yushiro/archive/2008/11/26/1341219.html\r\n 5. http://www.75team.com/archives/303\r\n\r\n【动态 CSS】JavaScript 操作 CSS 属性\r\n----------------------------\r\n 1. http://www.cnblogs.com/flyjs/archive/2012/02/20/2360502.html\r\n 2. http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/\r\n\r\n【动态 CSS】JavaScript 操作 CSS 规则\r\n----------------------------\r\n 1. http://blog.csdn.net/renfufei/article/details/39085235\r\n 2. http://javascript.ruanyifeng.com/dom/css.html\r\n 3. http://robinqu.iteye.com/blog/461359\r\n 4. http://www.alloyteam.com/2013/12/powerfuljs-1-to-operate-an-html-document-using-js/\r\n\r\n【DOM 特性】Attribute 与 Property\r\n----------------------------\r\n 1. http://www.cnblogs.com/dolphinX/p/3348582.html\r\n 2. http://www.cnblogs.com/zhwl/p/3520162.html\r\n\r\n【DOM 兼容】innerText、textContent\r\n-----------------------------\r\n 1. http://www.cnblogs.com/sniper007/archive/2012/04/24/2468175.html\r\n 2. http://www.360doc.com/content/14/0414/16/15727046_368828277.shtml\r\n\r\n【DOM 兼容】动态创建元素\r\n--------------\r\n 1. http://www.cnblogs.com/yizihan/p/4386431.html\r\n 2. http://qbaok.blog.163.com/blog/static/101292652013022296590/\r\n\r\n【DOM 监控】Mutation 的 Event 与 Observer\r\n-----------------------------------\r\n 1. http://www.cnblogs.com/rubylouvre/p/3192021.html\r\n 2. http://www.cnblogs.com/rubylouvre/archive/2012/05/28/2520721.html\r\n 3. http://chrisyip.github.io/post/mutation-events-and-mutationobserver/\r\n 4. http://javascript.ruanyifeng.com/dom/mutationobserver.html\r\n 5. https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver\r\n\r\n【浏览器数据流操作】JavaScript 转换 DataURL\r\n------------------------------\r\n 1. http://www.iunbug.com/archives/2012/06/05/254.html\r\n 2. http://www.78oa.com/news/news727.html\r\n 3. http://my.oschina.net/l3ve/blog/300097\r\n 4. http://stackoverflow.com/questions/11335460/how-do-i-parse-a-data-url-in-node\r\n 5. http://stackoverflow.com/questions/6926016/nodejs-saving-a-base64-encoded-image-to-disk\r\n 6. http://segmentfault.com/q/1010000000095621\r\n 7. https://cnodejs.org/topic/4f939c84407edba2143c12f7\r\n 8. https://developer.mozilla.org/zh-CN/docs/Using_files_from_web_applications\r\n 9. http://www.cnblogs.com/boychenney/archive/2011/10/08/2203036.html\r\n\r\n【浏览器数据流操作】JavaScript Base64 编解码\r\n-------------------------------\r\n 1. http://qianduanblog.com/post/js-learning-34-en-decodeuri-en-decodeuricomponent-un-escape-btoa-atob.html\r\n 2. http://www.cnblogs.com/rubylouvre/archive/2010/09/19/1829898.html\r\n\r\n【浏览器数据流操作】JavaScript 二进制数据操作\r\n---------------------------\r\n 1. http://javascript.ruanyifeng.com/htmlapi/file.html\r\n 2. http://javascript.ruanyifeng.com/stdlib/arraybuffer.html#toc7\r\n 3. http://www.douban.com/note/225494734/\r\n 4. http://www.blogjava.net/jidebingfeng/articles/406171.html\r\n 5. http://www.cnblogs.com/axes/p/4603984.html\r\n\r\n【浏览器加密】window.crypto\r\n--------------------\r\n 1. http://blog.csdn.net/emu/article/details/39618297\r\n 2. http://www.cnblogs.com/rubylouvre/p/3462457.html\r\n\r\n【浏览器乱象】键盘事件对象的 keyCode 属性\r\n-------------------------\r\n 1. http://www.tychio.net/tech/2013/06/06/event-keycode.html\r\n\r\n【浏览器乱象】网页文档模式\r\n-------------\r\n 1. http://blog.csdn.net/ennyhong/article/details/8330160\r\n 2. http://blog.csdn.net/justremind/article/details/25913639\r\n 3. http://www.oschina.net/translate/doctype\r\n\r\n【浏览器乱象】Window 对象的识别\r\n-------------------\r\n 1. http://www.w3school.com.cn/jsref/dom_obj_window.asp\r\n 2. http://www.cnblogs.com/rubylouvre/archive/2010/02/20/1669886.html\r\n\r\n【浏览器乱象】鼠标事件兼容\r\n-------------\r\n 1. http://segmentfault.com/a/1190000002499967\r\n 2. http://w3help.org/zh-cn/causes/BT9017\r\n 3. http://blog.csdn.net/ge_yulong/article/details/38924475\r\n 4. http://www.cnblogs.com/_franky/archive/2010/05/01/1725624.html\r\n\r\n【DOM 事件】事件模拟\r\n------------\r\n 1. http://web.jaxedit.com/post/2013/03/30/2990442.html\r\n\r\n【HTML 5 API】鼠标拖拽\r\n----------------\r\n 1. http://www.cnblogs.com/hooray/archive/2012/01/30/2331648.html\r\n\r\n【AJAX】跨域通信\r\n----------\r\n 1. https://segmentfault.com/a/1190000003642057\r\n 2. http://segmentfault.com/a/1190000000702539\r\n 3. https://github.com/luics/storage/wiki/Storage\r\n 4. http://cssha.com/cross-domain-local-storage/\r\n 5. http://stackoverflow.com/questions/1653308/access-control-allow-origin-multiple-origin-domains\r\n 6. http://blog.csdn.net/vivianhope/article/details/46581039\r\n 7. http://www.tuicool.com/articles/3UBzIbb\r\n 8. http://my.oschina.net/blogshi/blog/303758\r\n 9. https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS\r\n 10. https://dev.opera.com/articles/dom-access-control-using-cors/\r\n\r\n【AJAX】跨域 XHR 兼容\r\n---------------\r\n 1. http://segmentfault.com/a/1190000000702550\r\n 2. http://www.vinqon.com/codeblog/?detail/11103\r\n 3. http://www.w3cmm.com/ajax/xdomainrequest.html\r\n 4. https://msdn.microsoft.com/en-us/library/ie/cc288060(v=vs.85).aspx\r\n 5. http://blogs.msdn.com/b/ieinternals/archive/2009/07/23/the-ie8-native-xmlhttprequest-object.aspx\r\n\r\n【HTML 5 API】历史记录 与 AJAX\r\n-----------------------\r\n 1. http://www.zhangxinxu.com/wordpress/2013/06/html5-history-api-pushstate-replacestate-ajax/\r\n 2. http://blog.csdn.net/tianyitianyi1/article/details/7426606\r\n 3. http://blog.csdn.net/fdipzone/article/details/8928202\r\n 4. https://github.com/browserstate/history.js\r\n\r\n【JSON 本地处理】JSON 对象方法的详细用法\r\n-------------------------\r\n 1. http://www.cnblogs.com/mu-mu/p/3394475.html\r\n 2. http://www.cnblogs.com/anychem/archive/2012/04/02/2429785.html\r\n 3. http://www.cnblogs.com/damonlan/archive/2012/03/13/2394787.html\r\n\r\n【JS 技巧】in 操作符\r\n-------------\r\n 1. http://www.linuxfly.org/post/524/\r\n\r\n【JS 技巧】类数组对象\r\n------------\r\n 1. http://www.cnblogs.com/littledu/archive/2012/05/19/2508672.html\r\n 2. http://www.zipeng.info/archives/js-array-like-obj.html\r\n 3. http://www.cnblogs.com/fool/archive/2010/10/09/1846966.html\r\n 4. http://www.zuojj.com/archives/218.html\r\n 5. http://blueion.iteye.com/blog/371861\r\n\r\n【JS 技巧】对象自定义属性的单独处理\r\n-------------------\r\n 1. http://birdshome.cnblogs.com/archive/2005/06/24/GetExpandoAttributes.html\r\n 2. http://fsy0718.com/?p=36\r\n\r\n【SVG】浏览器 JS 网页截图\r\n----------------\r\n 1. http://www.raychase.net/1152\r\n 2. http://www.webhek.com/drawwindow\r\n 3. https://github.com/niklasvh/html2canvas\r\n 4. https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas\r\n\r\n【浏览器性能】JavaScript 函数调用降频\r\n------------------------\r\n 1. http://www.webhek.com/function-debounce\r\n\r\n【Web 前端性能】\r\n----------\r\n - http://www.csdn.net/article/2013-09-23/2817020-web-performance-optimization\r\n\r\n【HTTP 协议】Header 标准\r\n------------------\r\n 1. http://www.cnblogs.com/shanyou/archive/2012/05/06/2486134.html\r\n 2. http://kb.cnblogs.com/page/92320/\r\n 3. https://imququ.com/post/vary-header-in-http.html\r\n\r\n【HTTP 协议】缓存机制\r\n-------------\r\n 1. http://www.cnblogs.com/TankXiao/archive/2012/11/28/2793365.html\r\n 2. http://www.studyofnet.com/news/935.html\r\n 3. http://blog.csdn.net/crazyhacking/article/details/44497293\r\n\r\n【HTTP 协议】ETag 缓存头\r\n-----------------\r\n 1. http://blog.csdn.net/21aspnet/article/details/6604822\r\n 2. http://blog.csdn.net/chenzhiqin20/article/details/10947857\r\n\r\n【实时通讯】HTTP SSE\r\n--------------\r\n 1. http://www.ituring.com.cn/tupubarticle/1408',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(185,' C++调用C函数 ','185',1414488395,1414488395,'<!--markdown-->在C++的源文件中调用了纯C语言编写的函数,虽然正确地引入了头文件,编译时也正确连接了动态链接库,但还是出现\"**未定义的引用xxxxxx**\"(undifined reference to xxx)的错误.\r\n\r\nC++支持了函数重载,在编译时不只简单地前缀个_(或者其他的简单处理)用来当做函数的标识符,而是会对函数名进行一些处理,以使原型不同的同名函数区分开,这点与C不同.当编译cpp文件时,调用的C函数编译后产生的标识符与动态连接库中的不同,于是即使正确引入了动态链接库,也会出现**\"未定义的引用xxxxxx\"**的错误.\r\n\r\n### 解决方法 ###\r\n1.使用`extern \"C\"{}`引入头文件,并将用到的函数重新声明一遍,例如:\r\n\r\n extern \"C\"{\r\n #include <mysql/mysql.h>\r\n extern MYSQL * mysql_init( void );\r\n }\r\n\r\n2..c和.cpp的区别就不用多说了吧\r\n\r\n3.一些项目原本就有C++的api,就不要多此一举了\r\n\r\n**PS**: C++编译器开发商已经对`<stdio.h>`这类的C标准库的头文件作了extern“C”处理,所以一般可以直接在cpp中直接#include引用这些头文件.',0,10,NULL,'post','publish',NULL,0,'1','1','1',0),(184,'【原创】Web 前端脚本文件响应式异步加载器(框架页兼容)','184',1414472760,1414749630,'<!--markdown-->我之前开源了[【JavaScript 文件响应式异步加载器】v0.6][1],用于在 Web 前端统一管理单页开发中的 JS 模块加载,方便、优雅、可靠。\r\n\r\n但若要用框架页的模式来开发较为复杂的 Web 应用,统一管理父子页面的 JS、CSS 又是一件麻烦的事……\r\n\r\n框架页是一种 HTML 模块化的基础技术,我们通常希望整个网页在视觉上浑然一体,而非被框架分割成一块又一块,所以不同的框架页通常使用同一套基础的 JS、CSS 脚本库。一般的做法是在每个框架页的 `<head />` 中都硬编码上完全相同的基础库引用,虽然浏览器缓存会消除文件的重复下载,但 JS 代码会在每个框架页的上下文中再运行一遍,多消耗 N 倍的 CPU 执行时间、多占用 N 份相同大小的内存……\r\n\r\n好在框架页之间有 Window 对象之间的引用,好在 JavaScript 的函数可以用 call/apply 方法轻松改变执行上下文\r\n\r\n框架页稳定版 v0.8\r\n-------------\r\n\r\n //\r\n // >>> EasyImport.js <<<\r\n //\r\n //\r\n // [Version] v0.8 (2014-10-31) Stable\r\n //\r\n // [Usage] Only for loading JavaScript files in All Kinds of Web,\r\n // with JS/CSS-Inherit support for Frames.\r\n //\r\n //\r\n // (C)2013-2014 SCU FYclub-RDD\r\n //\r\n \r\n (function (BOM, DOM) {\r\n // ----------- Private Attribute ----------- //\r\n var UA = navigator.userAgent,\r\n RootPath, JS_List = [], CallBack, NameSpace = [],\r\n EIJS = {\r\n AsyncJS: [],\r\n DOM_Ready: []\r\n };\r\n // ----------- Inner Basic Member ----------- //\r\n var IE_Ver = UA.match(/MSIE (\\d+)\\.\\d/i) ||\r\n UA.match(/Trident\\/.+; rv:(\\d+)\\.\\d/i);\r\n IE_Ver = IE_Ver ? Number(IE_Ver[1]) : NaN;\r\n var old_IE = IE_Ver && (IE_Ver < 9),\r\n is_Pad = UA.match(/Tablet|Pad|Book|Android 3/i),\r\n is_Phone = UA.match(/Phone|Touch|Symbian/i);\r\n var is_Mobile = is_Pad || is_Phone || UA.match(/Mobile/i);\r\n \r\n function DOM_Loaded_Event(DOM_E, CB_Func) {\r\n if (!old_IE) DOM_E.addEventListener(\'load\', CB_Func, false);\r\n else DOM_E.attachEvent(\'onreadystatechange\', function () {\r\n if (DOM_E.readyState.match(/loaded|complete/))\r\n CB_Func.call(DOM_E);\r\n });\r\n }\r\n function DOM_Ready_Event(_CB) {\r\n if (!old_IE) DOM.addEventListener(\'DOMContentLoaded\', _CB, false);\r\n else if (self !== top)\r\n DOM_Loaded_Event(DOM, _CB);\r\n else (function () {\r\n try {\r\n DOM.documentElement.doScroll(\'left\');\r\n _CB.call(DOM);\r\n } catch (Err) { setTimeout(arguments.callee, 1); }\r\n })();\r\n }\r\n function $_TN(HTML_Elements, TagName) {\r\n return HTML_Elements.getElementsByTagName(TagName);\r\n }\r\n function NewTag(TagName, AttrList) {\r\n var NE = DOM.createElement(TagName);\r\n if (AttrList) for (var AK in AttrList)\r\n NE[AK] = AttrList[AK];\r\n return NE;\r\n }\r\n function PagePath_IE(_BOM) {\r\n var _PP = _BOM.document.URL;\r\n _PP = _PP.split(\'/\');\r\n if (_PP.length > 3) _PP.pop();\r\n _PP.push(\'\');\r\n return _PP.join(\'/\');\r\n }\r\n \r\n var DOM_Head = $_TN(DOM, \'head\')[0];\r\n var DOM_Title = $_TN(DOM_Head, \'title\')[0];\r\n try {\r\n var _DOM = parent.document;\r\n } catch (Err) {\r\n var Inherit_Root = true;\r\n }\r\n // ----------- Frame Inherit (JS) ----------- //\r\n if (Inherit_Root || (self === top)) { // Default NameSpaces (Offical Support Libraries)\r\n if (! IE_Ver) NameSpace = [\r\n { jQuery: true },\r\n { $:\r\n function () {\r\n return this.jQuery(\r\n arguments[0],\r\n (arguments.length > 1) ? arguments[1] : this.document\r\n );\r\n }\r\n }\r\n ];\r\n } else {\r\n var _NS;\r\n if (! IE_Ver) {\r\n _NS = parent.ImportJS.NS();\r\n for (var i = 0; i < _NS.length; i++)\r\n for (__NS in _NS[i]) {\r\n var _NS_Shell = _NS[i][__NS];\r\n if (_NS_Shell === true) {\r\n var _NS_ = parent[__NS];\r\n self[__NS] = _NS_;\r\n } else if (typeof _NS_Shell == \'function\')\r\n self[__NS] = (function (_NS_S) {\r\n return function () {\r\n return _NS_S.apply(self, arguments);\r\n };\r\n })(_NS_Shell);\r\n }\r\n } else {\r\n _NS = [];\r\n var _SE = $_TN($_TN(_DOM, \'head\')[0], \'script\');\r\n for (var i = 2, JS_URL; i < _SE.length; i++) {\r\n JS_URL = _SE[i].src;\r\n if ((JS_URL == \'\') || JS_URL.match(/EasyImport.*\\.js/i))\r\n continue;\r\n if (IE_Ver < 8)\r\n JS_URL = PagePath_IE(parent) + JS_URL;\r\n _NS.push(JS_URL);\r\n }\r\n BOM.onbeforeunload = function () {\r\n var SE = $_TN(DOM, \'script\');\r\n for (var i = 0; i < SE.length; i++)\r\n SE[i].parentNode.removeChild(SE[i]);\r\n SE = null;\r\n DOM.write(\'\');\r\n DOM.clear();\r\n BOM.onbeforeunload = null;\r\n BOM.close();\r\n top.CollectGarbage();\r\n };\r\n }\r\n NameSpace = _NS;\r\n }\r\n // ----------- Frame Inherit (CSS) ----------- //\r\n if ((! Inherit_Root) && (self !== top)) {\r\n var _LE = _DOM.styleSheets;\r\n for (var i = 0, CSS_URL; i < _LE.length; i++) {\r\n if (_LE[i].rel.indexOf(\'nofollow\') == -1)\r\n continue;\r\n CSS_URL = _LE[i].href;\r\n if (IE_Ver < 8)\r\n CSS_URL = PagePath_IE(parent) + CSS_URL;\r\n DOM_Head.appendChild(\r\n _LE[i][old_IE ? \'owningElement\' : \'ownerNode\'].cloneNode(true)\r\n ).href = CSS_URL;\r\n }\r\n }\r\n // ----------- Standard Mode Meta Patches ----------- //\r\n if (is_Mobile) {\r\n if (! old_IE) {\r\n var is_WeChat = UA.match(/MicroMessenger/i),\r\n is_UCWeb = UA.match(/UCBrowser|UCWeb/i);\r\n DOM_Head.insertBefore(\r\n NewTag(\'meta\', {\r\n name: \"viewport\",\r\n content: [\r\n [\r\n \'width\',\r\n (is_WeChat || is_UCWeb) ? 320 : \'device-width\'\r\n ].join(\'=\'),\r\n \'initial-scale=1.0\',\r\n \'target-densitydpi=medium-dpi\'\r\n ].join(\',\')\r\n }),\r\n DOM_Title\r\n );\r\n } else DOM_Head.insertBefore(\r\n NewTag(\'meta\', {\r\n name: \'MobileOptimized\',\r\n content: 320\r\n }),\r\n DOM_Title\r\n );\r\n DOM_Head.insertBefore(\r\n NewTag(\'meta\', {\r\n name: \'HandheldFriendly\',\r\n content: \'true\'\r\n }),\r\n DOM_Title\r\n );\r\n }\r\n if (IE_Ver) \r\n DOM_Head.insertBefore(\r\n NewTag(\'meta\', {\r\n \'http-equiv\': \'X-UA-Compatible\',\r\n content: \'IE=Edge, Chrome=1\'\r\n }),\r\n DOM_Title\r\n );\r\n // ----------- Inner Logic Module ----------- //\r\n function xImport(JS_URL, CB_Func) {\r\n var SE = DOM.createElement(\'script\');\r\n with (SE) {\r\n type = \'text/javascript\';\r\n charset = \'UTF-8\';\r\n src = JS_URL;\r\n }\r\n if (CB_Func) DOM_Loaded_Event(SE, CB_Func);\r\n return DOM_Head.appendChild(SE);\r\n }\r\n function LI_Add(LQ, RP, FN) {\r\n if (! FN.match(/^http(s)?:\\/\\//)) FN = RP + FN;\r\n LQ.push( { URL: FN } );\r\n }\r\n function SL_Set(RP, List0) {\r\n for (var i = 0; i < List0.length; i++)\r\n if (!(List0[i] instanceof Array)) List0[i] = [List0[i]];\r\n var List1 = [];\r\n for (var i = 0, k = 0; i < List0.length; i++) {\r\n List1[k] = [];\r\n for (var j = 0, _URL; j < List0[i].length; j++) {\r\n if (typeof List0[i][j] == \'string\')\r\n LI_Add(List1[k], RP, List0[i][j]);\r\n else {\r\n var _Rule = {\r\n old_PC: old_IE,\r\n Mobile: is_Mobile,\r\n Phone: is_Phone,\r\n Pad: is_Pad\r\n }, no_Break = true;\r\n for (RI in _Rule) if (_Rule[RI]) {\r\n if (List0[i][j][RI] === false)\r\n no_Break = false;\r\n else if (List0[i][j][RI])\r\n LI_Add(List1[k], RP, List0[i][j][RI]);\r\n break;\r\n }\r\n }\r\n if (no_Break && !List1[k][j] && List0[i][j].new_PC)\r\n LI_Add(List1[k], RP, List0[i][j].new_PC);\r\n }\r\n if (List1[k].length) k++;\r\n }\r\n return List1;\r\n }\r\n function CB_Set(List, Index) {\r\n var Item = List[Index + 1];\r\n if (Item[0].CallBack) {\r\n var AJSQ = EIJS.AsyncJS;\r\n var AJS_NO = AJSQ.push(0) - 1;\r\n var AJS_CB = function () {\r\n if (++AJSQ[AJS_NO] == Item.length)\r\n Item[0].CallBack();\r\n };\r\n }\r\n return function TF_Import() {\r\n for (var n = 0; n < Item.length; n++)\r\n xImport(Item[n].URL, AJS_CB);\r\n };\r\n }\r\n function CB_Chain(JS_RC, Final_CB) {\r\n var DRQ = EIJS.DOM_Ready;\r\n var DRQ_NO = DRQ.push(0) - 1;\r\n for (var k = JS_RC.length - 2, l = 0; k > -2; k--, l++) {\r\n if (! l) {\r\n if (Final_CB) {\r\n JS_RC[k+1][0][\'CallBack\'] = function (iEvent) {\r\n if (++DRQ[DRQ_NO] == 2) Final_CB.apply(self);\r\n };\r\n DOM_Ready_Event(JS_RC[k+1][0].CallBack);\r\n } else if (k > -1) {\r\n var Last_Script = JS_RC[k+1][0].URL;\r\n JS_RC[k][0][\'CallBack\'] = function (iEvent) {\r\n if (++DRQ[DRQ_NO] == 2) xImport(Last_Script);\r\n };\r\n DOM_Ready_Event(JS_RC[k][0].CallBack);\r\n continue;\r\n }\r\n }\r\n if (k > -1) JS_RC[k][0][\'CallBack\'] = CB_Set(JS_RC, k);\r\n }\r\n }\r\n \r\n // ----------- Open API ----------- //\r\n BOM.ImportJS = function () {\r\n var Func_Args = Array.prototype.slice.call(arguments, 0);\r\n \r\n if (typeof Func_Args[0] == \'string\')\r\n RootPath = Func_Args.shift();\r\n else RootPath = \'./\';\r\n if (Func_Args[0] instanceof Array)\r\n JS_List = Func_Args.shift();\r\n else throw \"Format of Importing List isn\'t currect !\";\r\n if (typeof Func_Args[0] == \'function\')\r\n CallBack = Func_Args.shift();\r\n else CallBack = null;\r\n if ((Func_Args[0] instanceof Array) && (! IE_Ver))\r\n NameSpace = NameSpace.concat(Func_Args[0]);\r\n if (IE_Ver) {\r\n JS_List = NameSpace.concat(JS_List);\r\n NameSpace = [];\r\n }\r\n \r\n var JS_Item = SL_Set(RootPath, JS_List);\r\n CB_Chain(JS_Item, CallBack);\r\n xImport(JS_Item[0][0].URL, JS_Item[0][0].CallBack);\r\n };\r\n \r\n BOM.ImportJS.UA = {\r\n IE: !! old_IE,\r\n Modern: ! old_IE,\r\n Mobile: !! is_Mobile,\r\n Pad: !! is_Pad,\r\n Phone: !! is_Phone\r\n };\r\n BOM.ImportJS.NS = function () {\r\n return NameSpace;\r\n };\r\n })(self, self.document);\r\n\r\n [1]: http://log.fyscu.com/index.php/archives/130/',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(182,'php用curl进行get和post请求函数','182',1414424280,1414424312,'<!--markdown--> /**\r\n * GET 请求\r\n * @param string $url\r\n */\r\n function http_get($url){\r\n $oCurl = curl_init();\r\n if(stripos($url,\"https://\")!==FALSE){\r\n curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);\r\n curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);\r\n }\r\n curl_setopt($oCurl, CURLOPT_URL, $url);\r\n curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );\r\n $sContent = curl_exec($oCurl);\r\n $aStatus = curl_getinfo($oCurl);\r\n curl_close($oCurl);\r\n if(intval($aStatus[\"http_code\"])==200){\r\n return $sContent;\r\n }else{\r\n return false;\r\n }\r\n }\r\n\r\n\r\n /**\r\n * POST 请求\r\n * @param string $url\r\n * @param array $param\r\n * @param boolean $post_file 是否文件上传\r\n * @return string content\r\n */\r\n function http_post($url,$param,$post_file=false){\r\n $oCurl = curl_init();\r\n if(stripos($url,\"https://\")!==FALSE){\r\n curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);\r\n curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);\r\n }\r\n if (is_string($param) || $post_file) {\r\n $strPOST = $param;\r\n } else {\r\n $aPOST = array();\r\n foreach($param as $key=>$val){\r\n $aPOST[] = $key.\"=\".urlencode($val);\r\n }\r\n $strPOST = join(\"&\", $aPOST);\r\n }\r\n curl_setopt($oCurl, CURLOPT_URL, $url);\r\n curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );\r\n curl_setopt($oCurl, CURLOPT_POST,true);\r\n curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);\r\n $sContent = curl_exec($oCurl);\r\n $aStatus = curl_getinfo($oCurl);\r\n curl_close($oCurl);\r\n if(intval($aStatus[\"http_code\"])==200){\r\n return $sContent;\r\n }else{\r\n return false;\r\n }\r\n } ',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(183,'【笔记】最舒服的 Web 中文字体设置(CSS font-family 属性)','183',1414468140,1415178978,'<!--markdown-->参考文章\r\n----\r\n\r\n 1. http://www.uisdc.com/web-page-font-choices\r\n 2. http://www.elonglau.com/119.html\r\n\r\n参考代码\r\n----\r\n 个人觉得,为了让网页上各种**中文纯文本**阅读起来舒服,不但要用**设计比较现代的无衬线字体**,还要用**等宽字体**,最后还要考虑**各种系统平台的优选中文字体**(Windows 的**微软雅黑**、Linux 的**文泉驿微米黑**、Mac OS X 的**华文细黑** 等)~\r\n\r\n body {\r\n font-family: \"Microsoft YaHei\" \"WenQuanYi Micro Hei\" STXihei sans-serif monospace;\r\n }\r\n\r\n 上述代码之所以不用**字体的中文名**,是因为 —— **font-family 属性**中用非英文表示的字体名过多,可能会导致浏览器完全无法应用你所设置的任何字体……(原因未知,但为了同时保证 CSS 文件在没有指定文件编码为 UTF-8 时也能正常解析,这个属性的值还是统统用英文名来写)',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(164,'2014102107.png','2014102107-png',1413872010,1413872010,'a:5:{s:4:\"name\";s:14:\"2014102107.png\";s:4:\"path\";s:34:\"/usr/uploads/2014/10/684354631.png\";s:4:\"size\";i:32341;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',7,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(165,'2014102108.png','2014102108-png',1413872208,1413872208,'a:5:{s:4:\"name\";s:14:\"2014102108.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2984044950.png\";s:4:\"size\";i:48237;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',8,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(166,'2014102109.png','2014102109-png',1413872270,1413872270,'a:5:{s:4:\"name\";s:14:\"2014102109.png\";s:4:\"path\";s:34:\"/usr/uploads/2014/10/253048103.png\";s:4:\"size\";i:27518;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',9,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(167,'201410210101.png','201410210101-png',1413872590,1413872590,'a:5:{s:4:\"name\";s:16:\"201410210101.png\";s:4:\"path\";s:34:\"/usr/uploads/2014/10/112273718.png\";s:4:\"size\";i:49841;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',10,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(168,'2014102101011.png','2014102101011-png',1413872643,1413872643,'a:5:{s:4:\"name\";s:17:\"2014102101011.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2659802268.png\";s:4:\"size\";i:129861;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',11,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(169,'201410210213.png','201410210213-png',1413874347,1413874347,'a:5:{s:4:\"name\";s:16:\"201410210213.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2045955589.png\";s:4:\"size\";i:37073;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',174),(170,'201410210101231.png','201410210101231-png',1413874387,1413874387,'a:5:{s:4:\"name\";s:19:\"201410210101231.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2282326882.png\";s:4:\"size\";i:63394;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,5,NULL,'attachment','publish',NULL,0,'1','0','1',174),(171,'2014102101013421324.png','2014102101013421324-png',1413874526,1413874526,'a:5:{s:4:\"name\";s:23:\"2014102101013421324.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2523093893.png\";s:4:\"size\";i:109198;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,5,NULL,'attachment','publish',NULL,0,'1','0','1',174),(172,'2014102144.png','2014102144-png',1413874658,1413874658,'a:5:{s:4:\"name\";s:14:\"2014102144.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2734436628.png\";s:4:\"size\";i:21924;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',4,5,NULL,'attachment','publish',NULL,0,'1','0','1',174),(173,'20141021010123123.png','20141021010123123-png',1413874892,1413874892,'a:5:{s:4:\"name\";s:21:\"20141021010123123.png\";s:4:\"path\";s:34:\"/usr/uploads/2014/10/822083363.png\";s:4:\"size\";i:30594;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',5,5,NULL,'attachment','publish',NULL,0,'1','0','1',174),(174,'Ubuntu安装搜狗输入法后无法切换的问题','174',1413874920,1413893579,'<!--markdown-->搜狗输入法有了Linux版,真好。个人比较偏好搜狗输入法,用不惯fitcx。\r\n安装搜狗输入法,可直接去[官网下载][1]。\r\n下载后直接双击下载的 deb 软件包,即可直接安装搜狗输入法。\r\n\r\n安装完成后重启。重启之后,发现右上角的输入法图标还是一个美式英语的图标。点击后发现没有搜狗输入法。\r\n![201410210213.png][2]\r\n这是因为没有将搜狗输入法添加到系统输入法当中。`点击配置当前输入法`,如图\r\n![201410210101231.png][3]\r\n然后点击左下角的 `+` ,再将 `Only Show Current Language`前的勾去掉\r\n![2014102101013421324.png][4]\r\n然后找到搜狗输入法,一般是在最下面,一直往下滚动到最低部就行了。选中 `Sougou Pinyin` 后 再点击 `OK` \r\n![2014102144.png][5]\r\n这时再点击右上角的输入法图标,就能找到搜狗输入法了。\r\n![20141021010123123.png][6]\r\n\r\n\r\n\r\n\r\n [1]: http://pinyin.sogou.com/linux/?r=pinyin\r\n [2]: http://log.fyscu.com/usr/uploads/2014/10/2045955589.png\r\n [3]: http://log.fyscu.com/usr/uploads/2014/10/2282326882.png\r\n [4]: http://log.fyscu.com/usr/uploads/2014/10/2523093893.png\r\n [5]: http://log.fyscu.com/usr/uploads/2014/10/2734436628.png\r\n [6]: http://log.fyscu.com/usr/uploads/2014/10/822083363.png',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(175,'Ubuntu下为Firefox安装adobe flash player','175',1413893160,1413966975,'<!--markdown-->网上搜索会有很多安装教程,大同小异.一般的文章只会说第一步第二步干嘛干嘛,但当离开某篇教程之后,就没办法自己再去安装.本文的目的就是为了避免这种情况.\r\n\r\n和平常一样,要安装,首先得去[官网下载一个adobe flash player][1].我下载的是 `install_flash_player_11_linux.x86_64.tar.gz` 安装包\r\n然后解压.解压后的目录结构如下\r\n\r\n + libflashplayer.so\r\n + /usr\r\n +readme.txt\r\n\r\n然后打开 `readme.txt` ,这里面有很多有用信息.其中一段是 `Installation instructions`,如下\r\n\r\n Installation instructions\r\n -------------------------\r\n \r\n Installing using the plugin tar.gz:\r\n o Unpack the plugin tar.gz and copy the files to the appropriate location. \r\n o Save the plugin tar.gz locally and note the location the file was saved to.\r\n o Launch terminal and change directories to the location the file was saved to.\r\n o Unpack the tar.gz file. Once unpacked you will see the following:\r\n + libflashplayer.so\r\n + /usr\r\n o Identify the location of the browser plugins directory, based on your Linux distribution and Firefox version\r\n o Copy libflashplayer.so to the appropriate browser plugins directory. At the prompt type:\r\n + cp libflashlayer.so <BrowserPluginsLocation>\r\n o Copy the Flash Player Local Settings configurations files to the /usr directory. At the prompt type:\r\n + sudo cp -r usr/* /usr\r\n \r\n Installing the plugin using RPM:\r\n o As root, enter in terminal:\r\n + # rpm -Uvh <rpm_package_file>\r\n + Click Enter key and follow prompts\r\n \r\n Installing the standalone player:\r\n o Unpack the tar.gz file\r\n o To execute the standalone player,\r\n + Double-click, or \r\n + Enter in terminal: ./flashplayer\r\n\r\n\r\n这一段就是说的怎么安装.因为之前下载的是 tar.gz 安装包,自然就找到对应的安装方法.即:\r\n\r\n Installing using the plugin tar.gz:\r\n o Unpack the plugin tar.gz and copy the files to the appropriate location. \r\n o Save the plugin tar.gz locally and note the location the file was saved to.\r\n o Launch terminal and change directories to the location the file was saved to.\r\n o Unpack the tar.gz file. Once unpacked you will see the following:\r\n + libflashplayer.so\r\n + /usr\r\n o Identify the location of the browser plugins directory, based on your Linux distribution and Firefox version\r\n o Copy libflashplayer.so to the appropriate browser plugins directory. At the prompt type:\r\n + cp libflashlayer.so <BrowserPluginsLocation>\r\n o Copy the Flash Player Local Settings configurations files to the /usr directory. At the prompt type:\r\n + sudo cp -r usr/* /usr\r\n\r\n翻译过来大概就是三步:\r\n1.解压下载的安装包 `install_flash_player_11_linux.x86_64.tar.gz` \r\n2.将 `libflashplayer.so` 文件复制到浏览器插件文件夹里面\r\n3.将 `/usr` 文件夹复制到系统的 `usr/` 文件夹内\r\n\r\n到此,adobe flash player 插件就算安装成功了.\r\n\r\n看到这个地方,至少你应该学会了**下载一个软件后,去看看 `readme.txt` 文件,软件的文档才是最好的教程**.很多人往往会忽略掉这个文档,而四处去搜索软件的安装或使用方法.而该文件往往包含很重要的信息,能解决你大部分的疑问.\r\n\r\n\r\n [1]: http://get.adobe.com/cn/flashplayer/',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(176,'HTML 5 Placeholder 特性的模拟实现','176',1413948780,1415345764,'<!--markdown-->网页表单**文字输入框内容提示** 这一特性在 **HTML 5** 中由 `placeholder` 属性来实现,但它依然没有标准化,IE 10 之前不支持,控制其样式的伪元素的命名、特性还不统一,让人用起来有些不爽……\r\n\r\n其实 HTML 4 原生的 `value` 属性配合 **JavaScript** 就能很好实现这个特性 ——\r\n\r\n // Version: 0.2\r\n\r\n $(document).ready(function () {\r\n function InputTips_Hide() {\r\n if (this.value != this.defaultValue) {\r\n this.select();\r\n return;\r\n }\r\n var $_This = $(this);\r\n this.value = \'\';\r\n this.focus();\r\n $_This.css(\'color\', $_This.data(\'color\'));\r\n\r\n if (Boolean( $_This.data(\'type\') )) {\r\n this.type = $_This.data(\'type\');\r\n $_This.data(\'type\', \'\');\r\n }\r\n }\r\n function InputTips_Show() {\r\n if (this.value != \'\') return;\r\n\r\n var $_This = $(this);\r\n this.value = this.defaultValue;\r\n this.blur();\r\n $_This.css(\'color\', \'gray\');\r\n\r\n if (jQuery.inArray(this.type, [\r\n \'password\', \'number\',\r\n \'email\', \'url\'\r\n ]) != -1) {\r\n $_This.data(\'type\', this.type);\r\n this.type = \'text\';\r\n }\r\n }\r\n $(\'input\').filter(function () {\r\n return jQuery.inArray(this.type, [\r\n \'text\', \'search\',\r\n \'password\', \'number\',\r\n \'email\', \'url\'\r\n ]) != -1;\r\n }).each(function () {\r\n if (this.defaultValue == \'\') return;\r\n\r\n var $_This = $(this);\r\n $_This.data(\'color\', $_This.css(\'color\'))\r\n .css(\'color\', \'gray\')\r\n .focus(InputTips_Hide)\r\n .hover(InputTips_Hide, InputTips_Show)\r\n .blur(InputTips_Show);\r\n\r\n if (jQuery.inArray(this.type, [\'text\', \'search\']) != -1)\r\n return;\r\n $_This.data(\'type\', this.type);\r\n this.type = \'text\';\r\n });\r\n });\r\n\r\n文本框的 `value`、`placeholder` 属性都可填写任何字符(一般字符 和 **HTML 实体**表示),也就是说我们可以用 **字体图标**的字符 来替代原来的**图片图标**,抛弃复杂的**堆叠式 DOM 结构**,实现文本框提示内容实现的简化与统一。(详见我的下篇博文)',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(177,'网页特殊字体的全局应用(图标字体、文字字体的混用,无需容器标签)','177',1413961860,1415178825,'<!--markdown-->**图标字体**的概念 其实从**计算机字符编码**诞生伊始就有了 ——\r\n\r\n> 世界上第一套字符编码 **ASCII 码**中,有一些用来**拼接表格边框**的字符,还有一些我们“谈码色变”的“**乱码**”字符。\r\n它们以前除了因为“乱码”而广为人知,一些洋人称之为 **ASCII 艺术**的“**字符画**”是**命令提示终端**画图的一种简便方式,千禧年之前算是 BBS 达人的必备技能,而今则是 QQ 聊天刷屏的必备了~\r\n\r\n图标字体 一般是利用 **Unicode 编码**预留的**高位编码**区域来表示一些自创的小图标,使用起来,在原理上和普通字符没有任何区别。但电脑的输入法没法打出它们,唯一的输出方式就是用它的字符编码引用它,在 HTML 中就是 **HTML 实体表示法** —— `&#编码的十进制数; `。\r\n\r\n如何确定上述的十进制编号呢?我们平时使用图标字体都是在 HTML 中引入了它的 CSS 文件之后,就用一个**容器标签**设置图标字体库定义好的 CSS Class,然后就显示出图标了~ 它们通常使用 DOM 元素的 **before/after 伪元素**的 `content` 属性来引用图标字符,这里的格式是**十六进制**的(如 \\xxxx),我们可以在 **JavaScript 控制台**中用如下代码来转换为十进制 —— `parseInt(\'十六进制字符串(无前缀)\', 16)` 或 `0x十六进制数.toString(10)`。\r\n\r\n但此时,网页中还是不能在一般容器中显示字体图标(或者是乱码)…… 这是因为图标字体通常只定义字体与图标,没有在全局应用这种字体。字体在网页中的全局使用要如下设置 ——\r\n\r\n body { font-family: 字体1, 字体2, ……, 字体n; }\r\n\r\n内含 **HTML 文档片段**的元素(`<input />`、`<textarea />`等)需要为其专门指定一下**字体设置**才能让所含内容的字体改变 ——\r\n\r\n input, textarea { font-family: 字体1, 字体2, ……, 字体n; }\r\n\r\n若需要默认应用所有已引入当前网页的字体,可以在网页中加载以下原创 jQuery 程序 ——\r\n\r\n $(document).ready(function () {\r\n\r\n var CSS_File = document.styleSheets, FontFamily = [],\r\n FF_RegEx = / /.compile(\r\n \"@font-face\\\\s*\\\\{\\\\s*font-family\\\\s*:\\\\s*([^;]+)\\\\s*;\", \'i\'\r\n ),\r\n is_IE = navigator.userAgent.match(/MSIE (\\d)|Trident[^\\)]+rv:(\\d+)/i),\r\n is_Webkit = navigator.userAgent.match(/Webkit/i);\r\n var IE_Ver = is_IE ? Number(is_IE[1] || is_IE[2]) : NaN;\r\n \r\n for (var i = 0, CSS_Text, FF_Rule, CSS_Rule; i < CSS_File.length; i++) {\r\n try {\r\n CSS_Text = CSS_File[i].cssText;\r\n } catch (Err) { continue; }\r\n try { // IE\r\n FF_Rule = CSS_Text.match(FF_RegEx);\r\n if (! FF_Rule) continue;\r\n for (var j = 1; j < FF_Rule.length; j++)\r\n FontFamily.push( FF_Rule[j] );\r\n } catch (Error) { // Firefox / Safari / Chrome\r\n CSS_Rule = CSS_File[i].cssRules || CSS_File[i].rules;\r\n for (var j = 0; j < CSS_Rule.length; j++)\r\n if (CSS_Rule[j].type == 5)\r\n FontFamily.push(\r\n is_Webkit ?\r\n CSS_Rule[j].style.fontFamily :\r\n CSS_Rule[j].cssText.match(FF_RegEx)[1]\r\n );\r\n }\r\n }\r\n var CSS_Text = $(\'body\').css(\'font-family\');\r\n if (CSS_Text != \'\')\r\n if (is_IE) {\r\n if (IE_Ver < 9) {\r\n var _FontFamily = [].concat(FontFamily);\r\n _FontFamily.push(\'sans-serif, monospace\');\r\n }\r\n FontFamily.unshift(\'sans-serif, monospace\');\r\n } else FontFamily.push(CSS_Text);\r\n var $_Target = $(\'body, input, textarea\').css(\'font-family\', FontFamily.join(\', \'));\r\n if (IE_Ver < 9)\r\n $_Target.not(\'body\').css(\'font-family\', _FontFamily.join(\', \'));\r\n });\r\n\r\n【特别注意】**font-family 属性**中**用非英文表示的字体名**过多,可能会导致浏览器完全无法应用你所设置的任何字体……(原因未知,但为了同时保证 CSS 文件在没有指定文件编码为 UTF-8 时也能正常解析,这个属性的值还是统统用英文名来写)',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(180,'jquery 新建的元素事件绑定问题 ','180',1414117740,1415951877,'<!--markdown--> js的事件监听跟css不一样,css只要设定好了样式,不论是原来就有的还是新添加的,都有一样的表现。而事件监听不是,你必须给每一个元素单独绑定事件。\r\n\r\n\r\n常见的例子是处理表格的时候。每行行末有个删除按钮,点了这个能够删除这一行。\r\n\r\n\r\n <table>\r\n <tbody>\r\n <tr>\r\n <td>这行原来就有</td>\r\n <td><buttonclass=\"del\">删除</button></td>\r\n </tr>\r\n <tr>\r\n <td>这行原来就有</td>\r\n <td><buttonclass=\"del\">删除</button></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n通常,我会这么绑定\r\n\r\n\r\n jQuery(function($){\r\n //已有删除按钮初始化绑定删除事件\r\n $(\".del\").click(function() {\r\n $(this).parents(\"tr\").remove();\r\n });\r\n });\r\n\r\n\r\n对于在domready之前就存在的删除按钮,一切都很完美。但如果在domready之后用js动态添加几行,那新增的几行中的这些按钮都将失去任何作用。\r\n\r\n如何解决这个问题?以下提供4种解决方案:\r\n\r\n\r\n0号解决方案——onclick法\r\n如果不顾结构与行为分离的准则的话,通常,我会这么做。\r\n注意,此时的deltr这个function必须是全局函数,得放jQuery(function($) {})外面,放里边就成局部函数了,html里的onclick就调用不到了!\r\n\r\n <td><buttononclick=\"deltr(this)\">删除</button></td>\r\n\r\n jQuery(function($){\r\n //添加行\r\n $(\"#add2\").click(function(){\r\n $(\"#table2>tbody\").append(\'<tr><td>新增行</td><td><button nclick=\"deltr(this)\">删除</button></td></tr>\')\r\n });\r\n });\r\n //删除行的函数,必须要放domready函数外面\r\n function deltr(delbtn){\r\n $(delbtn).parents(\"tr\").remove();\r\n };\r\n\r\n\r\n1号解决方案——重复绑定法\r\n即,在domready的时候就给已有的元素绑定事件处理函数,\r\n而后当新增加的元素的时候再次绑定。\r\n\r\n <td><buttonclass=\"del\">删除</button></td>\r\n jQuery(function($){\r\n //定义删除按钮事件绑定\r\n //写里边,防止污染全局命名空间\r\n function deltr(){\r\n $(this).parents(\"tr\").remove();\r\n };\r\n //已有删除按钮初始化绑定删除事件\r\n $(\"#table3 .del\").click(deltr);\r\n //添加行\r\n $(\"#add3\").click(function(){\r\n $(\'<tr><td>新增行</td><td><button class=\"del\">删除</button></td></tr>\')\r\n .find(\".del\").click(deltr).end()\r\n .appendTo($(\"#table3>tbody\"));\r\n });\r\n });\r\n\r\n\r\n2号解决方案——事件冒泡法\r\n利用事件冒泡的原理,我们给这个按钮的祖先元素绑定事件处理函数。\r\n然后通过event.target这个对象来判断,这个事件是不是我们要找的对象触发的。\r\n通常可以利用一些DOM属性,比如event.target.className、event.target.tagName等之类的来判断。\r\n\r\n <td><buttonclass=\"del\">删除</button></td>\r\n\r\n jQuery(function($){\r\n //第四个表格的删除按钮事件绑定\r\n $(\"#table4\").click(function(e) {\r\n if (e.target.className==\"del\"){\r\n $(e.target).parents(\"tr\").remove();\r\n };\r\n });\r\n //第四个表格的添加按钮事件绑定\r\n $(\"#add4\").click(function(){\r\n $(\"#table4>tbody\").append(\'<tr><td>新增行</td><td><button class=\"del\">删除</button></td></tr>\')\r\n });\r\n });\r\n\r\n\r\n\r\n\r\n3号解决方案——复制事件法\r\n上面几种方案可以说即便你没有用到jQuery库,你也能相对比较容易的实现。但这种方案相对依赖jQuery的程度更高。而且必须要求jQuery 1.2版以上。低版本jQuery需要插件。\r\n上面两个方案都是对删除函数动了很多脑筋,换了多种触发、绑定的方式。这个方案不同,可以与平时纯静态的元素一样在domready的时候绑定。但在我们添加新行的时候我们改动一下,不再想上面那样拼接字符串来添加新行了。这回我们尝试使用复制DOM元素的方式。并且复制的时候连同绑定的事件一起复制,复制完之后再用find之类的修改内部的元素。\r\n同时,就像这个例子,如果你会把所有元素都删除光,那template这个模板是必须的,如果不会删光,那就未必需要用template了。为了防止被误删,此处我把template设了隐藏。\r\n我使用了jQuery中特有的clone(true)\r\n\r\n\r\n 1..template{display:none;}\r\n\r\n 1.<trclass=\"template\">\r\n 2. <td>这里是模板</td>\r\n 3. <td><button class=\"del\">删除</button></td>\r\n 4. </tr>\r\n 5. <tr>\r\n 6. <td>这行原来就有</td>\r\n 7. <td><button class=\"del\">删除</button></td>\r\n 8. </tr>\r\n 9. <tr>\r\n 10. <td>这行原来就有</td>\r\n 11. <td><button class=\"del\">删除</button></td>\r\n 12. </tr>\r\n\r\n 1.jQuery(function($){\r\n 2. //第五个表格的删除按钮事件绑定\r\n 3. $(\"#table5 .del\").click(function() {\r\n 4. $(this).parents(\"tr\").remove();\r\n 5. });\r\n 6. //第五个表格的添加按钮事件绑定\r\n 7. $(\"#add5\").click(function(){\r\n 8. $(\"#table5>tbody>tr:eq(0)\")\r\n 9. //连同事件一起复制\r\n 10. .clone(true)\r\n 11. //去除模板标记\r\n 12. .removeClass(\"template\")\r\n 13. //修改内部元素\r\n 14. .find(\"td:eq(0)\")\r\n 15. .text(\"新增行\")\r\n 16. .end()\r\n 17. //插入表格\r\n 18. .appendTo($(\"#table5>tbody\"))\r\n 19. });\r\n 20.});\r\n\r\n复制代码\r\n\r\n总评:\r\n上面4种方案,各有优劣。\r\n0号方案,结构与行为完全没有分离,而且污染全局命名空间。最不推荐。所以我都不把它当作一个方案来看。但对于js初学者,可以用来项目救急。\r\n1号方案,中规中矩,没啥好也没啥不好\r\n2号方案,这种方法充分的发挥了js事件冒泡的优势。而且效率最高。但同时由于这种方案无视了jQuery强大的选择器,所以如果涉及的元素属性要求过多就会比较麻烦了。你会徘徊在众多if的条件的是非关系之中。后来我想起来,可以用jQuery中的$(event.target).is(selector)来作为条件。这样可以极大提升开发效率,但略微降低执行效率。\r\n3号方案,这是我认为最能体现结构与行为分离的思想的一种方案。但缺点也很明显,对于jQuery依赖性过于高了,要不就自己写一个复制连同事件一起复制的函数,但这也显然对于初学者来说异常困难。但从未来的趋势的角度来看,还是很推荐使用这种方案的。\r\n\r\n\r\n具体选用哪一个方案,没有定数。具体看你的项目以及你js还有结构与行为分离的思想的掌握程度。最适合的才是最好的。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(181,'Express全局跨域代码段','181',1414262558,1414262558,'<!--markdown-->```\r\napp.all(\'*\', function(req, res, next) {\r\n res.header(\"Access-Control-Allow-Origin\", \"*\");\r\n res.header(\"Access-Control-Allow-Headers\", \"Content-Type,Content-Length, Authorization, Accept,X-Requested-With\");\r\n res.header(\"Access-Control-Allow-Methods\",\"PUT,POST,GET,DELETE,OPTIONS\");\r\n res.header(\"X-Powered-By\",\' 3.2.1\');\r\n if(req.method==\"OPTIONS\") res.send(200);\r\n else next();\r\n});\r\n```\r\n 通过上面代码设置全部路由都允许跨域,每个参数的含义,自行搜索。\r\n马克专用',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(163,'2014102106.png','2014102106-png',1413871395,1413871395,'a:5:{s:4:\"name\";s:14:\"2014102106.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/1059496730.png\";s:4:\"size\";i:76465;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',6,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(160,'201410213.png','201410213-png',1413867721,1413867721,'a:5:{s:4:\"name\";s:13:\"201410213.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/1474176536.png\";s:4:\"size\";i:24370;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(161,'201410214.png','201410214-png',1413871060,1413871060,'a:5:{s:4:\"name\";s:13:\"201410214.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/1473891168.png\";s:4:\"size\";i:11241;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',4,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(162,'2014102105.png','2014102105-png',1413871227,1413871227,'a:5:{s:4:\"name\";s:14:\"2014102105.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2756964951.png\";s:4:\"size\";i:100140;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',5,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(158,'201410211.png','201410211-png',1413866600,1413866600,'a:5:{s:4:\"name\";s:13:\"201410211.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/1040566717.png\";s:4:\"size\";i:73464;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(159,'201410212.png','201410212-png',1413866607,1413866607,'a:5:{s:4:\"name\";s:13:\"201410212.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/3615092043.png\";s:4:\"size\";i:44649;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,5,NULL,'attachment','publish',NULL,0,'1','0','1',156),(156,'Ubuntu下搭建LAMP开发环境','156',1422902160,1422909381,'<!--markdown-->LAMP,即Linux,Apache,MySQL,PHP。\r\n本文介绍使用 apt-get 方法为Ubuntu安装 Linux+Apache+MySQL+PHP。编译安装请参考[<<linux 编译安装 PHP>>][1]\r\n\r\n**一.安装LAMP**\r\n首先确保软件包列表是最新的,执行\r\n`~$sudo apt-get update`\r\n\r\n1.安装MySQL\r\n`~$ sudo apt-get install mysql-server`\r\n`~$sudo apt-get install mysql-client`\r\n\r\n安装mysql-server的时候会提示设置密码。\r\n![201410211.png][2]\r\n![201410212.png][3]\r\n\r\nmysql-server是服务端,是mysql核心程序,生成管理数据库实例,数据库实例任务调度线程,并提供相关接口供不同客户端调用;\r\nmysql-client是客户端,是操作数据库实例的工具。\r\n\r\n操作mysql实例的客户端有很多,mysql-client只是其中一种,包括mysql,mysqldump,mysqlslap,这些访问,备份,压力测试的工具。\r\n\r\n举个例子,mysql-server 就相当于是西瓜,mysql-client是切西瓜的刀。切西瓜的刀有很多种,mysql-client只是其中一种。如果不安装mysql-server服务端,那么mysql-client客户端就没有实例去操作,也就好像有一把西瓜刀,但是没有西瓜可切。\r\n\r\n\r\n2.安装Apache\r\n`~$ sudo apt-get install apache2`\r\n\r\n3.安装PHP\r\n`~$ sudo apt-get install php5`\r\n`~$ sudo apt-get install libapache2-mod-php5`\r\n`~$ sudo apt-get install libapache2-mod-auth-mysql`\r\n`~$ sudo apt-get install php5-mysql`\r\n`~$ sudo apt-get install php5-gd`\r\n\r\n安装完之后重启Apache,让它加载PHP模块\r\n`~$ sudo /etc/init.d/apache2 restart`\r\n\r\nlibapache2-mod-php5 和 libapache2-mod-auth-mysql 是让apache支持php5,也就是说能够解析php5;\r\nphp5-mysql是php5的MySQL数据库扩展,提供php能够使用的访问MySQL的接口;\r\nphp5-gd是GD库。GD库是PHP处理图形的扩展库,GD库提供了一系列用来处理图片的API,使用GD库可以处理图片,或者生成图片。在网站上GD库通常用来生成缩略图或者用来对图片加水印或者对网站数据生成报表。\r\n\r\n4.安装phpmyadmin\r\nphpmyadmin是一个基于浏览器的图形化数据库管理工具,能方便我们使用数据库。\r\n通过如下命令安装:\r\n`~$ sudo apt-get install phpmyadmin`\r\n在安装过程中会要求选择Web server:apache2或lighttpd,因为之前是安装的Apache2,当然选择apache2。\r\n![2014102107.png][4]\r\n接下来是配置phpmyadmin数据库,选择 yes 之后,phpmyadmin的mysql配置文件就和mysql-server的配置文件一致 :\r\n![2014102108.png][5]\r\n然后是输入数据库密码。这里的密码就是之前安装mysql-server时设置的密码:\r\n![2014102109.png][6]\r\n\r\n将phpmyadmin与apache2建立连接\r\nApache2的默认项目目录是在`/var/www/html`,phpmyadmin在`/usr/share/phpmyadmin`目录,所以就用命令:`~$ sudo ln -s /usr/share/phpmyadmin/ /var/www/html/` 建立连接。\r\n\r\n**二.检测LAMP是否正常安装**\r\n1.检车MySQL是否正常\r\n在终端输入\r\n`~$ mysql -uusername -ppassword`\r\n(将username 和password 替换为安装的时候所设置的)\r\n如果能正常登陆,说明安装成功。\r\n\r\n2.检测Apache是否正常\r\n在浏览器中打开 http://localhost/\r\n如果出现如下界面,说明安装正常。\r\n![2014102105.png][7]\r\n\r\n3.检测PHP是否正常\r\nUbuntu下Apache的默认安装路径是 /var/www/html ,在其目录下新建 info.php 文件,如下:\r\n`sudo vim /var/www/html/info.php`\r\n按键盘上的 i 进入输入模式。然后编辑 info.php ,文件内容如下:\r\n\r\n <?php\r\n phpinfo();\r\n ?>\r\n\r\nphpinfo()是PHP的一个内置函数,显示PHP的基本信息。\r\n然后 按下 ESC 退出编辑模式,输入 :wq ,保存文件并退出Vim。\r\n然后在浏览器中打开 http://localhost/info.php\r\n如果出现如下界面,说明PHP安装正常。\r\n![2014102106.png][8]\r\n\r\n4.检测phpmyadmin是否正常\r\n在浏览器输入 http://localhost/phpmyadmin\r\n提示输入数据库的用户名和密码:\r\n![201410210101.png][9]\r\n正确输入后,出现如下界面,则说明安装成功:\r\n![2014102101011.png][10]\r\n\r\n\r\n\r\n**三.LAMP的一些配置**\r\n1.Apache2默认项目目录的权限\r\n一般情况下 /var/www/html 是没有权限的,可用如下命令为当前用户分配该目录的权限\r\n`~$ su root` (root用户)\r\n`~$ chown username /var/www/html` (username是当前用户名)\r\n`~$ exit` (退出root)\r\n\r\n如果系统的root用户不可用,是因为Ubuntu系统默认root密码为空。可以通过如下命令设置root用户的密码:\r\n`~$ sudo passwd -l root`\r\n\r\n2.更改Apache2的默认项目目录\r\nApache2的默认项目目录是 `/var/www/html` ,该路径配置在 `/etc/apache2/sites-enabled/00default` 文件,找到该文件的 DocumentRoot 项,将 `/var/www/html` 改为自己的开发目录就可以了。\r\n\r\n还有一种方法是不改变默认项目目录,只需在 `/var/www/html` 下建立一个到自己的开发目录的链接。比如开发目录为 `/home/username/php` ,那么只需\r\n`~$ sudo ln -s /home/username/html /var/www/html`\r\n这样就可以通过 http://localhost/html 来访问工作目录了。\r\n\r\n\r\n**四.安装过程中常见问题及解决办法**\r\n\r\n1.安装php5过程中,会自动重启Apache2,可能会有警告如下:\r\n\r\n * Restarting web server apache2 AH00558: apache2: Could not reliably determine the server\'s fully qualified domain name, using 127.0.1.1. Set the \'ServerName\' directive globally to suppress this message\r\n [ OK ]\r\n apache2_invoke: Enable module php5\r\n * Restarting web server apache2 AH00558: apache2: Could not reliably determine the server\'s fully qualified domain name, using 127.0.1.1. Set the \'ServerName\' directive globally to suppress this message\r\n\r\n待上述模块都安装了后,手动重启也依旧可能出现警告如下:\r\n\r\n AH00558: apache2: Could not reliably determine the server\'s fully qualified domain name, using 127.0.1.1. Set the \'ServerName\' directive globally to suppress this message\r\n [ OK ]\r\n\r\n![201410213.png][11]\r\n\r\n这个警告貌似不会影响服务(因为我暂时未发现,如有发现,请批评指出),但总是出现警告会很烦人,而且说不定哪天就出大问题了。**警告比错误更可怕!**\r\n\r\n在Ubuntu中,Apache2的配置文件分布和windows有较大的区别,限于篇幅,将在另一篇文章中细讲。这里只简单介绍。\r\n`~$ cd /etc/apache2` 进入Apache2的安装目录,有的系统可能有 httpd.conf文件,但该文件是空的;有的系统可能没用httpd.conf文件。接下来编辑该文件(在使用Vim的时候,如果没有所编辑的文件,则会自动创建该文件):\r\n`/etc/apache2$ sudo vi httpd.conf`\r\n如果不会使用 vim ,也可以用Ubuntu的另一个编辑器 gedit:\r\n`/etc/apache2$ sudo gedit httpd.conf`\r\n\r\n打开该文件后,输入内容如下:\r\n`ServerName localhost`\r\n然后保存。\r\n\r\n在Ubuntu中,Apache2的默认配置文件是 `/etc/apache2/apache2.conf`,刚才的 httpd.conf 是我们自定义的一个配置文件。再然后需要在Apache2中引入httpd.conf。如下:\r\n`~$ sudo vi apache2.conf`,然后在末尾添加 `Include httpd.conf`,添加后的文件如图:\r\n![201410214.png][12]\r\n最后保存。\r\n\r\n这时候再重启Apache2就不会有警告了。\r\n\r\n\r\n**五.一些常用命令**\r\n\r\n1.重启Apache\r\n`~$ sudo /etc/init.d/apache2 restart`\r\n2.建立系统链接\r\n`~$ sudo ln ls a b`\r\n\r\n\r\n [1]: http://log.fyscu.com/index.php/archives/228/\r\n [2]: http://log.fyscu.com/usr/uploads/2014/10/1040566717.png\r\n [3]: http://log.fyscu.com/usr/uploads/2014/10/3615092043.png\r\n [4]: http://log.fyscu.com/usr/uploads/2014/10/684354631.png\r\n [5]: http://log.fyscu.com/usr/uploads/2014/10/2984044950.png\r\n [6]: http://log.fyscu.com/usr/uploads/2014/10/253048103.png\r\n [7]: http://log.fyscu.com/usr/uploads/2014/10/2756964951.png\r\n [8]: http://log.fyscu.com/usr/uploads/2014/10/1059496730.png\r\n [9]: http://log.fyscu.com/usr/uploads/2014/10/112273718.png\r\n [10]: http://log.fyscu.com/usr/uploads/2014/10/2659802268.png\r\n [11]: http://log.fyscu.com/usr/uploads/2014/10/1474176536.png\r\n [12]: http://log.fyscu.com/usr/uploads/2014/10/1473891168.png',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(151,'Screenshot from 2014-10-20 13:49:25.png','Screenshot-from-2014-10-20-13-49-25-png',1413786679,1413786679,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-10-20 13:49:25.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/3340514297.png\";s:4:\"size\";i:22965;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',4,5,NULL,'attachment','publish',NULL,0,'1','0','1',155),(152,'Screenshot from 2014-10-20 13:51:00.png','Screenshot-from-2014-10-20-13-51-00-png',1413787289,1413787289,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-10-20 13:51:00.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/3284021277.png\";s:4:\"size\";i:35168;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',5,5,NULL,'attachment','publish',NULL,0,'1','0','1',155),(153,'Screenshot from 2014-10-20 13:51:12.png','Screenshot-from-2014-10-20-13-51-12-png',1413787298,1413787298,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-10-20 13:51:12.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/4002387652.png\";s:4:\"size\";i:48305;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',6,5,NULL,'attachment','publish',NULL,0,'1','0','1',155),(154,'Screenshot from 2014-10-20 14:47:29.png','Screenshot-from-2014-10-20-14-47-29-png',1413787734,1413787734,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-10-20 14:47:29.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2664833546.png\";s:4:\"size\";i:46495;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',7,5,NULL,'attachment','publish',NULL,0,'1','0','1',155),(155,'Ubuntu如何连接校园网','155',1413787898,1413787898,'<!--markdown-->Ubuntu连接校园网其实很简单。废话不多说,如图:\r\n\r\n\r\n**1.点击右上角的网络图标,选择 `Edit connections..`.**\r\n\r\n![Screenshot from 2014-10-16 05:17:42.png][1]\r\n![Screenshot from 2014-10-20 13:48:55.png][2]\r\n\r\n**2.点击 Add ,新建一个 `DSL` 连接,**\r\n![Screenshot from 2014-10-20 13:49:44.png][3]\r\n![Screenshot from 2014-10-20 13:49:25.png][4]\r\n选中 DSL 后,点击 `Create...`\r\n\r\n**3.设置 DSL 连接**\r\n`Connection name` 是连接名字,这个可以随便自定义,比如 `SCU`;\r\n`username` 是用户名,川大校园网的用户名是 `scu@edu`;\r\n`Service` 服务,我也搞不清楚是干什么的。不过这里不需要填写;\r\n`password` 是密码,校园网密码为空,可以用空格代替。一会再说这里不输入任何字符会出现什么情况。\r\n设置完成后,点击 `Save` 。\r\n\r\n**4.连接**\r\n设置完成后,再点击又上角的网络图标,就会发现多了一个名为 SCU 的连接,也就是刚刚创建的连接。\r\n这时单击它就可以连入校园网,出现 Conneted SCU 的提示,就说明连接成功了。如图:\r\n![Screenshot from 2014-10-20 13:48:55.png][5]\r\n![Screenshot from 2014-10-16 05:17:42.png][6]\r\n\r\n\r\n\r\n接下来说说第3步设置密码的时候,不输入空格会出现什么情况。\r\n不输入空格,依旧可以保存连接。但点击保存的连接,如SCU后,就会弹出如下的提示窗口:\r\n![Screenshot from 2014-10-20 14:47:29.png][7]\r\n如果不输入密码,`OK` 按钮就始终是 disable,无法点击。所以这里用一个空格代替。输入空格后,点击 `show password` 就会发现,其实输入的就是空字符串。这时 `OK` 按钮就可以点击,点击后再连接网络就不会弹出提示窗口了。\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/10/1770869974.png\r\n [2]: http://log.fyscu.com/usr/uploads/2014/10/1427340197.png\r\n [3]: http://log.fyscu.com/usr/uploads/2014/10/2353308581.png\r\n [4]: http://log.fyscu.com/usr/uploads/2014/10/3340514297.png\r\n [5]: http://log.fyscu.com/usr/uploads/2014/10/1427340197.png\r\n [6]: http://log.fyscu.com/usr/uploads/2014/10/1770869974.png\r\n [7]: http://log.fyscu.com/usr/uploads/2014/10/2664833546.png',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(148,'Screenshot from 2014-10-16 05:17:42.png','Screenshot-from-2014-10-16-05-17-42-png',1413786603,1413786603,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-10-16 05:17:42.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/1770869974.png\";s:4:\"size\";i:56736;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',155),(149,'Screenshot from 2014-10-20 13:48:55.png','Screenshot-from-2014-10-20-13-48-55-png',1413786616,1413786616,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-10-20 13:48:55.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/1427340197.png\";s:4:\"size\";i:23475;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,5,NULL,'attachment','publish',NULL,0,'1','0','1',155),(150,'Screenshot from 2014-10-20 13:49:44.png','Screenshot-from-2014-10-20-13-49-44-png',1413786670,1413786670,'a:5:{s:4:\"name\";s:39:\"Screenshot from 2014-10-20 13:49:44.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2353308581.png\";s:4:\"size\";i:26731;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,5,NULL,'attachment','publish',NULL,0,'1','0','1',155),(147,'各种软件资源,不定期更新','147',1413782640,1413782753,'<!--markdown-->以下是个人收藏的一些软件资源,附带激活方法,总有你需要的:\r\n\r\n1.Mac安装并破解PhotoShop CS6\r\n2.Mac 安装并破解 After Effect CC\r\n3.WampServer\r\n4.Sublime Text 3\r\n5.office 2013 附带激活工具\r\n\r\n分享了别忘了回来点个赞!\r\n\r\n链接: [http://pan.baidu.com/s/1qWv37UO][2] \r\n密码: mb5i\r\n\r\n\r\n [2]: http://pan.baidu.com/s/1qWv37UO',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(146,'写给还在困惑的新手程序员','146',1413717300,1413717349,'<!--markdown-->我想很多同学现在可能会有这个困惑:\r\n\r\n> 想加入项目去做但是有了项目又感觉拿不下来\r\n\r\n如果你有这个困惑的话,我的建议是:\r\n\r\n\r\n别去想大家一起要合伙的做的项目了,不要拿这些项目去练手,自己**单独**去做一个自己想做的项目,用自己想深入学习的语言写。\r\n\r\n有问题的时候及时百度/谷歌,或者问身边的人。\r\n\r\n\r\n不然,这个合伙的项目进度也慢,你自己的成长更慢。\r\n\r\n\r\n以上,我的一个感受。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(143,'首页2.png','首页2-png',1413462299,1413462299,'a:5:{s:4:\"name\";s:11:\"首页2.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/1066268473.png\";s:4:\"size\";i:64397;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,4,NULL,'attachment','publish',NULL,0,'1','0','1',141),(144,'挖一个坑,收藏一些看到的技术文章','144',1437835560,1437835620,'<!--markdown-->最后更新:11/7\r\n\r\n1.[理解与使用Javascript中的回调函数](http://www.html-js.com/article/1592) #js\r\n\r\n2.[彻底理解web中的session](http://beyond99.blog.51cto.com/1469451/543282)\r\n\r\n3.[git入门指南使用资料汇总及文章推荐](http://ixirong.com/2014/11/19/the-way-to-learn-git/)\r\n\r\n4.[前端开发面试知识点](http://segmentfault.com/a/1190000002562454) //有了这个知识 面试一般的前端应该都没问题了。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(145,'用setTimeout来做循环,实现串行效果','145',1413635460,1415951975,'<!--markdown-->## 背景\r\n\r\njavascript 里,我们一般用setInterval方法来实现一个定时循环业务,函数原型如下:\r\n\r\n setInterval(function(){\r\n //这里放你要执行的业务,后面的参数是时间,单位毫秒,1秒=1000毫秒,比如\r\n console.log(\'哈\');\r\n },5000);\r\n\r\n上面的代码,单独执行的时候,效果诚然是如我们所想的:\r\n\r\n 哈 哈 哈 哈 (循环 )\r\n\r\n\r\n# 但是,问题来了。\r\n`javascript 是单进程的,即时是在浏览器还是在服务端node,这时候问题来了。`\r\n而 `异步操作次序的不确定性` ,一个程序里不可能仅仅这几行代码,有可能出现一个情况,\r\n就是前一个callback(其他行为,比如写入一个大文件)执行的时间很长,回调队列处于阻塞状态,\r\n而你的`哈`正在以每5秒一个的频率进入队列。然后你可能看到的是这样的:\r\n\r\n 哈 哈 (某长时间操作) 哈哈哈哈哈哈 哈 哈 哈 ......\r\n\r\n中间某一段,因为回调堆积,引起的瞬间打印多个`哈`,这并不是我们想看到的。\r\n\r\n`===================================================================`\r\n# 怎么办呢?\r\n我们可以用 `setTimeout` 来实现,它的参数列表和上面的一样,区别是这个逻辑只执行一次。\r\n惯例先上代码:\r\n\r\n //先把逻辑定义成一个函数\r\n var do_sth = function(){\r\n console.log(\'哈\');\r\n //然后用神奇的setTimeout,还是5秒\r\n setTimeout(function(){\r\n //注意了,调用自己\r\n do_sth();\r\n },5000);\r\n };\r\n\r\n以上代码就是,输出了第一个`哈`以后,再申请下一个延时操作。\r\n这样,就能够让每个`哈`一个跟一个的输出,而不会出现回调堆积的情况。\r\n## 新技能GET!!\r\n\r\n后话:\r\n用这样的方法,可能会出现两次间隔超出5秒的情况,其实上面两种都会有这种情况。\r\n用setTimeout的意义在于解决堆积,避免一次性同时触发(尤其是一些IO操作)。\r\n\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(134,'QQ图片20141015191458.jpg','QQ图片20141015191458-jpg',1413371762,1413371762,'a:5:{s:4:\"name\";s:26:\"QQ图片20141015191458.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/10/818378579.jpg\";s:4:\"size\";i:26327;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',140),(135,'QQ图片20140912071307.jpg','QQ图片20140912071307-jpg',1413372052,1413372052,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912071307.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/3451252802.jpg\";s:4:\"size\";i:121690;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',2,5,NULL,'attachment','publish',NULL,0,'1','0','1',140),(136,'QQ图片20140912071529.jpg','QQ图片20140912071529-jpg',1413372070,1413372070,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912071529.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2649018332.jpg\";s:4:\"size\";i:38575;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',3,5,NULL,'attachment','publish',NULL,0,'1','0','1',140),(137,'QQ图片20140912071548.jpg','QQ图片20140912071548-jpg',1413372085,1413372085,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912071548.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/2135094155.jpg\";s:4:\"size\";i:84269;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',4,5,NULL,'attachment','publish',NULL,0,'1','0','1',140),(138,'QQ图片20140912071838.jpg','QQ图片20140912071838-jpg',1413372286,1413372286,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912071838.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/10/532638929.jpg\";s:4:\"size\";i:75187;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',5,5,NULL,'attachment','publish',NULL,0,'1','0','1',140),(139,'QQ图片20141015193231.jpg','QQ图片20141015193231-jpg',1413372887,1413372887,'a:5:{s:4:\"name\";s:26:\"QQ图片20141015193231.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/10/4200020521.jpg\";s:4:\"size\";i:115582;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',6,5,NULL,'attachment','publish',NULL,0,'1','0','1',140),(140,'安装win8.1+Ubuntu双系统','140',1413373982,1413373982,'<!--markdown-->本文使用EasyBCD安装win8.1+Ubuntu双系统。\r\n\r\n**一.准备工作**\r\n\r\n**1.分区**\r\n右键点击开始菜单->磁盘管理\r\n![QQ图片20141015191458.jpg][1]\r\n这时会出现磁盘管理界面,选取一个盘(我选的F盘),右键点击\"删除卷\",然后输入要给Ubuntu分配的硬盘空间大小。如图:\r\n![QQ图片20141015193231.jpg][2]\r\n![QQ图片20140912071529.jpg][3]\r\n![QQ图片20140912071548.jpg][4]\r\nFree Space就是给Ubuntu分配的硬盘空间。我分配的是130G。一般来说,50G就已经完全足够了。\r\n安装好的ubuntu的分区,在windows下是看不到的,但是进入ubuntu是可以访问windows的磁盘的。这才叫双系统的吧,和wubi安装的不一样。\r\n\r\n**2.下载Ubuntu**\r\n根据个人情况选择桌面版或服务器版。下面是桌面版的链接。\r\n[http://ubuntu.org.cn/download/desktop][5]\r\n*桌面版和服务器版的区别:\r\n (1).桌面版为个人电脑所配置,而服务器版适用于web服务器\r\n (2).桌面版预装了GUI,而服务器版没有\r\n (3).桌面版已经安装了许多服务器版没有的软件\r\n (4).桌面版缺少Apache、MySQL和PHP,而这些在服务器版中是标准配置*\r\n\r\n将下载的iso文件的放在C盘的根目录下。放在其他盘的根目录也行,不过需要记住路径和镜像的名字;为了方便,建议就放C盘根目录。第3步会用到。\r\n我是放在C盘的,镜像名字为`ubuntu-14.04.1-desktop-amd64.iso` 。\r\n然后用虚拟光驱或解压缩软件将iso打开, 将casper文件夹目录下的vmlinuz和 initrd.lz复制或解压到C盘根目录下。\r\n在64位里vmlinuz有后缀名,为vmlinuz.efi。vmlinuz是针对BIOS主板的启动内核文件。vmlinuz.efi是针对最新的EFI主板的启动内核文件。如果有后缀名,需要将后缀名去掉。\r\n\r\n**3.安装并运行EasyBCD**\r\nAdd New Entry -> NeoGrub -> Install\r\n![QQ图片20140912071838.jpg][6]\r\n然后点击旁边的 Configure,会打开一个记事本文件menu.lst,将如下代码粘贴到文件尾部并保存:\r\n\r\n title Install Ubuntu\r\n root (hd0,0)\r\n kernel (hd0,0)/vmlinuz boot=casper iso-scan/filename=/ubuntu-14.04.1-desktop-amd64.iso ro quiet splash locale=zh_CN.UTF-8\r\n initrd (hd0,0)/initrd.lz\r\n\r\n简单解释一个代码的含义:\r\n(1).title是为这个启动项指定一个名称。\r\n(2).root(hd0, 0)指的是windows系统的C盘,不过有时候可能不是这样子的。\r\n 查询方法:在磁盘管理工具中的下部可以看到,左侧一栏写着磁盘0,磁盘1,磁盘2等等,找到C盘所属的磁盘标号(一般是0)。然后看C盘时在此行第几个出现的,如果是第一个出现的,就是root(hd0,0);如果是第二个,则是root(hd0,1);以此类推。这样就可以确定C盘的位置了。\r\n(3).接下来是制定vmlinuz和initrid文件的位置。这两个文件已经拷贝至C盘的根目录,这里路径中的(hd0,0)也就指的是C盘。\r\nubuntu-14.04.1-desktop-amd64.iso 就是拷贝过来的镜像名称。\r\n\r\n如果在第一步的时候,将镜像文件或vmlinuz和initrd.lz文件拷贝到了其他盘,那么路径中的(hd0,0)也需要改变。\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/10/818378579.jpg\r\n [2]: http://log.fyscu.com/usr/uploads/2014/10/4200020521.jpg\r\n [3]: http://log.fyscu.com/usr/uploads/2014/10/2649018332.jpg\r\n [4]: http://log.fyscu.com/usr/uploads/2014/10/2135094155.jpg\r\n [5]: http://ubuntu.org.cn/download/desktop\r\n [6]: http://log.fyscu.com/usr/uploads/2014/10/532638929.jpg',0,5,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(141,'问道有先后的前期规划','141',1413440460,1413462313,'<!--markdown-->**背景介绍**\r\n\r\n作为程序员,我们常常会有这样的困惑:每次需要在项目中使用一些“常用”的代码(比如:php连接mysql,linux安装某环境口令,node.js安装模块)时,不免要去网上搜索相关代码,在国内如果用百度之流搜索的话,排在最前面的结果往往是诸如\"百度知道\",“脚本之家”,“博客园”之流的相关代码片段,虽说往往在test几次之后能解决问题,但终究在这种“重复劳动”的代码中浪费了本不该浪费的一些时间。而就算在谷歌搜索,往往排在最前面的一般是\"stackoverflow\",或者一些作者的博客,虽然 能解决问题,但还是颇费一番力气。\r\n\r\n**idea提出者**\r\n\r\n资深程序员:@小蓝 \r\n\r\n主页:[http://fyscu.lanhao.name][1]\r\n\r\n**需求分析**\r\n\r\n看起来这个问题已经存在多年了,我们需要这样一个产品来解决这个问题:\r\n\r\n1.在它上面能找到大多数我可能会用到的,别人已经写栏的代码。\r\n2.最重要的一点是:我需要这个代码是绝对正确,并且是最完美的写法。\r\n3.我能非常**快,准确**的找到我需要的代码。\r\n4.界面简洁,舒服,字大一点。手机,平板都需要很美观的找到,看到所需要的东西。\r\n5.代码在需要的地方要有注释。保证我能看懂。\r\n6.我可以收藏这个代码。\r\n\r\n**总结一下**\r\n\r\n我们在前期一起讨论了这个产品的形态,它大概是下面这个样子:\r\n\r\n用户可以在这个网站上非常迅速准确的搜索到需要的代码片段,所有的代码片段不能超过20行,超过的请继续拆分。代码片段是高亮显示,在需要的行有标注,每个代码片段有标签,有描述,可评论,可推荐(收藏),可分享,按照时间/热门度 列表排序,可按照语言/标签进行查看。\r\n\r\n**当然最重要的是:这些代码 是有资深编辑 提交的,在提交之前要经过严格测试,保证绝对正确。**\r\n\r\n**还有,界面要是 不美的话 就不发布出来了。**\r\n\r\n**大概界面**\r\n\r\n首页是这样的:\r\nv1\r\n![1152534.png][2]\r\n\r\nv2\r\n![首页2.png][3]\r\n\r\n\r\n [1]: http://fyscu.lanhao.name\r\n [2]: http://upload-images.jianshu.io/upload_images/54027-59726c0d6fd29395.png\r\n [3]: http://log.fyscu.com/usr/uploads/2014/10/1066268473.png',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(129,'Web 前端开发的 IE 调试与兼容','129',1412748024,1412748024,'<!--markdown-->WinXP 依然会像当年 Win98 退役时那样,再被广大群众用几年,它能装的 IE 最高版本也就是 v8。特别是各种中小企业、商户的办公电脑,很多连个新版的 360 安全浏览器 都不装,所以他们用的浏览器内核也必然是 IE 8…… 兼容它们还是大多数前端工程师的义务之一……\r\n\r\n但是,IE 11 之前版本的 F12 调试器 非常难用,IE 11 调试器对老版本的模拟又不算完全真实…… 所以只能曲线救国了 —— 开发者的真机装 IE 11,再用虚拟机中的 IE 8 来测试~\r\n\r\n还好微软为我们封装好了各种平台版本的 IE 虚拟机 —— [https://www.modern.ie/zh-cn/virtualization-tools][1]\r\n\r\n顺着开源到底的使用习惯,我下载了 VirtualBox 版的 IE8 for Windows 7 虚拟机镜像~\r\n\r\n但…… 万万没想到 —— VirtualBox [最近的几个版本][2]都不能正常运行……\r\n\r\n网上很多人都说最近 VirtualBox 在 Win7 上有 Bug,有人用 管理员权限 + 兼容模式 运行成功了,还不行的也用[重新注册组件的方法][3]搞定了(下附 我封装好的**一键修复脚本程序 vBox_Fix.cmd**)——\r\n\r\n @echo off\r\n cls\r\n title VirtualBox 4.3.x Win7 启动 Bug 补丁\r\n \r\n \r\n echo.\r\n set /P VB_ID=\" <<< VirtualBox 安装目录(支持文件夹拖放输入): \"\r\n echo.\r\n set VB_ID=%VB_ID:\"=%\r\n if NOT exist \"%VB_ID%\" (\r\n set VB_ID=%ProgramFiles%\\Oracle\\VirtualBox\\\r\n )\r\n pushd \"%VB_ID%\"\r\n \r\n VBoxSVC.exe /ReRegServer\r\n regsvr32 VBoxC.dll\r\n \r\n if ErrorLevel 0 (\r\n echo.\r\n echo ^>^>^> 修复结束。(按任意键退出)\r\n echo.\r\n pause > nul\r\n exit 0\r\n )\r\n\r\n但…… 我这边就是各种报错……\r\n\r\n再继续搜索,VirtualBox 官方网站上也有各种类似的针对 v4.x Bug 的讨论,有的人说修复代码已经被合并到了当时最新版安装包中云云……\r\n\r\n [1]: https://www.modern.ie/zh-cn/virtualization-tools\r\n [2]: https://www.virtualbox.org/wiki/Download_Old_Builds\r\n [3]: http://www.pczhishi.cn/jichu/yingyong/214.html\r\n',0,13,NULL,'post_draft','publish',NULL,0,'1','1','1',0),(131,'FYSCU 2.7.1发布,含重大更新','131',1412875080,1415952054,'<!--markdown-->零 . 虽然大版本号没变,但是里面包含重大更新,已经不兼容2.5版本,勉强升级,会带来麻烦。\r\n一 . 如果真要升级,可以使用新版创建一个项目,再将你的action和tpl覆盖进去,再修改一下配置文件即可。\r\n二 . 以下是本次更新内容:\r\n\r\n 1.controller和base,合成lib,强调这是框架核心模块\r\n 2.组件各自维护一套配置文件,从global里分离出去,更加强调组件的即插即用\r\n 3.CONFIG的调用模式改为静态方法CONFIG::get(),方便组件的配置注入\r\n 4.修正了fytpl的一处配置引用常量\r\n 5.去掉没什么用的url_base\r\n 6.action_base里render增加返回输出内容\r\n 7.action_base增加get_route方法返回路由信息\r\n 8.cache文件缓存组件0.1.1\r\n\r\n\r\n三 . 比较重要的是core的重新组合,以及彻底的组件化(每个组件独立维护配置文件,即插即用)。\r\n 另一个比较重要的是配置文件的调用方式,2.5版本也是因为这个变动而不能兼容。\r\n 增加了一个file_cache组件,详情参考项目主页。\r\n\r\n四 . 项目主页: http://fyscu.lanhao.name\r\n 目前PHP代码920行。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(199,'[翻译]教程序员学设计第一课:hello world','199',1416202140,1416209367,'<!--markdown-->原文:https://hackdesign.org/lessons/0 \r\n\r\n翻译员:4级飘过者。\r\n\r\n欢迎来到HackDesign!第0课,在这里你将开始你每周的课程,这将指导你走上精通设计的道路,躁起来吧!\r\n\r\n\r\n这个礼拜,就一个链接。它是我这辈子见过的最棒的设计的源头,很高兴把他分享给你。*Objectified*(电影中文名:*设计面面观*)不仅改变了我对产品设计的认识,更让我兴奋的是设计对人们生活产生积极的影响的潜力。\r\n\r\n你可以在推特上关注我[@wr](http://twitter.com/wr) ,让我知道你的想法。\r\n\r\n[Objectified:设计面面观](https://hackdesign.org/tasks/14)\r\n\r\n(译者注:腾讯视频中文字幕在线观看地址:[http://v.qq.com/boke/page/d/1/q/d0407t7c81q.html](http://v.qq.com/boke/page/d/1/q/d0407t7c81q.html)\r\n\r\n\r\n这个电影对你在这个课程中奠定基础是至关重要的,当你观看时,思考他们所说的以及如何把它应用在你自己的工作中。\r\n\r\n全部的电影:你可以从[Objectified 官网](http://www.hustwit.com/category/objectified/)在全世界各个地方观看这个电影。你也可以在[Netflix](http://www.netflix.com/WiMovie/70114976?trkid=439131),[Amazon Prime](http://www.amazon.com/Objectified/dp/B002SOUVKU/ref=sr_1_1?ie=UTF8&qid=1357966197&sr=8-1&keywords=objectified),或者[iTunes](https://itunes.apple.com/us/movie/objectified/id321244909)上观看。\r\n\r\n如果都失败了,看这个[youtube的列表](https://www.youtube.com/watch?v=S9E2D2PaIcI&list=PLG7_y8_uKhd71_RyV1m0nc5BtDzeecgiP&index=1)吧.\r\n\r\n\r\n译者注:第一次翻译文章,其实是抱着复习六级的心态翻译的。这个系列我没读完,不知道到底有没有干货,准备每次读的时候翻译成一篇文章,翻译完了,说不定六级就过了。第一课 很少,比较好翻译,但是还是查阅了不少资料才翻译出来的,如果想学好英语的人,不妨从翻译开始。\r\n\r\n\r\n\r\n\r\n\r\n\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(130,'【原创】JavaScript 文件响应式异步加载器(单页稳定版)','130',1412837340,1416806415,'<!--markdown-->我在做[《i飞扬》电子杂志 HTML5 在线版][1]的过程中,为了在不改变 **Web 前端程序猿的编程思维习惯**的前提下,保证整个 **WebApp 的好用、可靠**,自己开发了一个**【JavaScript 文件响应式异步加载器】**—— [EasyImport.js][2]。\r\n\r\n开始只是一段放在 HTML `<head />` 中的小脚本,没觉得是个多么复杂的东西。但随着应用的深入,要想做到上述自己定下的目标,**代码不断地迭代**,期间也因为严重的 Bug 而怀疑它的价值,所以有了后来的一次较大的局部重构。\r\n\r\n但辛劳总会有收获 —— 个人更深刻地理解了 **JavaScript**、**DOM** 的一些细节,它本身也到了足够成熟的地步,作为几个**线上实用项目的基础库**,运行在很多人的浏览器中~\r\n\r\n----------\r\n\r\nv0.6(单页稳定版)\r\n=============\r\n\r\n 这是 **EasyImport.js 首个功能完备的稳定版**,能给 **单页应用** 提供有力的**异步加载、响应式适配**支持,但不支持 **`<iframe />` 子页面的 JS、CSS 继承**(也就是说,它独立运行于每一个加载它的父/子页面中,不考虑关联页面的相互联系)。它将提供**长期 Bug 修复的官方维护**,后续版本与本版的公共代码也将同步更新,但不会再改变代码的整体结构。而子页面继承将在下个稳定版给予集成~\r\n\r\n //\r\n // >>> EasyImport.js <<<\r\n //\r\n //\r\n // [Version] v0.6 (2014-11-17) Stable\r\n //\r\n // [Usage] Only for loading JavaScript files in Single-Page Web,\r\n // no Inherit support for Frames.\r\n //\r\n //\r\n // (C)2013-2014 SCU FYclub-RDD\r\n //\r\n \r\n (function (BOM, DOM) {\r\n var UA = navigator.userAgent,\r\n RootPath, JS_List, CallBack,\r\n EIJS = {\r\n AsyncJS: [],\r\n DOM_Ready: []\r\n };\r\n // ----------- Inner Basic Member ----------- //\r\n var is_IE = UA.match(/MSIE (\\d)|Trident[^\\)]+rv:(\\d+)/i),\r\n is_Webkit = UA.match(/Webkit/i);\r\n var IE_Ver = is_IE ? Number(is_IE[1] || is_IE[2]) : NaN;\r\n var old_IE = IE_Ver && (IE_Ver < 9),\r\n is_Pad = UA.match(/Tablet|Pad|Book|Android 3/i),\r\n is_Phone = UA.match(/Phone|Touch|Android 2|Symbian/i);\r\n var is_Mobile = (\r\n is_Pad || is_Phone || UA.match(/Mobile/i)\r\n ) && (! UA.match(/ PC /));\r\n \r\n function DOM_Loaded_Event(DOM_E, CB_Func) {\r\n if (!old_IE) DOM_E.addEventListener(\'load\', CB_Func, false);\r\n else DOM_E.attachEvent(\'onreadystatechange\', function () {\r\n if (DOM_E.readyState.match(/loaded|complete/))\r\n CB_Func.call(DOM_E);\r\n });\r\n }\r\n function DOM_Ready_Event(_CB) {\r\n if (!old_IE) DOM.addEventListener(\'DOMContentLoaded\', _CB, false);\r\n else if (self !== top)\r\n DOM_Loaded_Event(DOM, _CB);\r\n else (function () {\r\n try {\r\n DOM.documentElement.doScroll(\'left\');\r\n _CB.call(DOM);\r\n } catch (Err) { setTimeout(arguments.callee, 1); }\r\n })();\r\n }\r\n function $_TN(HTML_Elements, TagName) {\r\n return HTML_Elements.getElementsByTagName(TagName);\r\n }\r\n function NewTag(TagName, AttrList) {\r\n var NE = DOM.createElement(TagName);\r\n if (AttrList) for (var AK in AttrList) {\r\n if (IE_Ver && (AK == \'class\'))\r\n NE.className = AttrList[AK];\r\n NE.setAttribute(AK, AttrList[AK]);\r\n }\r\n return NE;\r\n }\r\n \r\n var DOM_Head = $_TN(DOM, \'head\')[0];\r\n var DOM_Title = $_TN(DOM_Head, \'title\')[0];\r\n // ----------- Standard Mode Meta Patches ----------- //\r\n DOM_Head.appendChild(\r\n NewTag(\'meta\', {\r\n \'http-equiv\': \'Window-Target\',\r\n content: \'_top\'\r\n })\r\n );\r\n if (is_Mobile) {\r\n if (! old_IE) {\r\n var is_WeChat = UA.match(/MicroMessenger/i),\r\n is_UCWeb = UA.match(/UCBrowser|UCWeb/i);\r\n DOM_Head.insertBefore(\r\n NewTag(\'meta\', {\r\n name: \"viewport\",\r\n content: [\r\n [\r\n \'width\',\r\n (is_Phone && (is_WeChat || is_UCWeb)) ?\r\n 320 : \'device-width\'\r\n ].join(\'=\'),\r\n \'initial-scale=1.0\',\r\n \'minimum-scale=1.0\',\r\n \'target-densitydpi=medium-dpi\'\r\n ].join(\',\')\r\n }),\r\n DOM_Title\r\n );\r\n } else DOM_Head.insertBefore(\r\n NewTag(\'meta\', {\r\n name: \'MobileOptimized\',\r\n content: 320\r\n }),\r\n DOM_Title\r\n );\r\n DOM_Head.insertBefore(\r\n NewTag(\'meta\', {\r\n name: \'HandheldFriendly\',\r\n content: \'true\'\r\n }),\r\n DOM_Title\r\n );\r\n }\r\n if (IE_Ver) DOM_Head.appendChild(\r\n NewTag(\'meta\', {\r\n \'http-equiv\': \'X-UA-Compatible\',\r\n content: \'IE=Edge, Chrome=1\'\r\n })\r\n );\r\n \r\n // ----------- Inner Logic Module ----------- //\r\n function xImport(JS_URL, CB_Func) {\r\n var SE = NewTag(\'script\', {\r\n type: \'text/javascript\',\r\n charset: \'UTF-8\',\r\n src: JS_URL\r\n });\r\n if (CB_Func) DOM_Loaded_Event(SE, CB_Func);\r\n return $_TN(DOM, \'head\')[0].appendChild(SE);\r\n }\r\n function LI_Add(LQ, RP, FN) {\r\n if (! FN.match(/^http(s)?:\\/\\//)) FN = RP + FN;\r\n LQ.push( { URL: FN } );\r\n }\r\n function SL_Set(RP, List0) {\r\n for (var i = 0; i < List0.length; i++)\r\n if (!(List0[i] instanceof Array)) List0[i] = [List0[i]];\r\n var List1 = [];\r\n for (var i = 0, k = 0; i < List0.length; i++) {\r\n List1[k] = [];\r\n for (var j = 0, _URL; j < List0[i].length; j++) {\r\n if (typeof List0[i][j] == \'string\')\r\n LI_Add(List1[k], RP, List0[i][j]);\r\n else {\r\n var _Rule = {\r\n old_PC: old_IE,\r\n Mobile: is_Mobile,\r\n Phone: is_Phone,\r\n Pad: is_Pad\r\n }, no_Break = true;\r\n for (RI in _Rule) if (_Rule[RI]) {\r\n if (List0[i][j][RI] === false)\r\n no_Break = false;\r\n else if (List0[i][j][RI])\r\n LI_Add(List1[k], RP, List0[i][j][RI]);\r\n break;\r\n }\r\n }\r\n if (no_Break && !List1[k][j] && List0[i][j].new_PC)\r\n LI_Add(List1[k], RP, List0[i][j].new_PC);\r\n }\r\n if (List1[k].length) k++;\r\n }\r\n return List1;\r\n }\r\n function CB_Set(List, Index) {\r\n var Item = List[Index + 1];\r\n if (Item[0].CallBack) {\r\n var AJSQ = EIJS.AsyncJS;\r\n var AJS_NO = AJSQ.push(0) - 1;\r\n var AJS_CB = function () {\r\n if (++AJSQ[AJS_NO] == Item.length)\r\n Item[0].CallBack();\r\n };\r\n }\r\n return function TF_Import() {\r\n for (var n = 0; n < Item.length; n++)\r\n xImport(Item[n].URL, AJS_CB);\r\n };\r\n }\r\n function CB_Chain(JS_RC, Final_CB) {\r\n var DRQ = EIJS.DOM_Ready;\r\n var DRQ_NO = DRQ.push(0) - 1;\r\n for (var k = JS_RC.length - 2, l = 0; k > -2; k--, l++) {\r\n if (! l) {\r\n if (Final_CB) {\r\n JS_RC[k+1][0][\'CallBack\'] = function (iEvent) {\r\n if (++DRQ[DRQ_NO] == 2) Final_CB.apply(self);\r\n };\r\n DOM_Ready_Event(JS_RC[k+1][0].CallBack);\r\n } else if (k > -1) {\r\n var Last_Script = JS_RC[k+1][0].URL;\r\n JS_RC[k][0][\'CallBack\'] = function (iEvent) {\r\n if (++DRQ[DRQ_NO] == 2) xImport(Last_Script);\r\n };\r\n DOM_Ready_Event(JS_RC[k][0].CallBack);\r\n continue;\r\n }\r\n }\r\n if (k > -1) JS_RC[k][0][\'CallBack\'] = CB_Set(JS_RC, k);\r\n }\r\n }\r\n \r\n // ----------- Open API ----------- //\r\n BOM.ImportJS = function () {\r\n var Func_Args = Array.prototype.slice.call(arguments, 0);\r\n \r\n if (typeof Func_Args[0] == \'string\')\r\n RootPath = Func_Args.shift();\r\n else RootPath = $_TN(DOM, \'script\')[0].src.replace(\r\n /[^\\/]*EasyImport[^\\/]*\\.js[^\\/]*$/i, \'\'\r\n );\r\n if (Func_Args[0] instanceof Array)\r\n JS_List = Func_Args.shift();\r\n else throw \"Format of Importing List isn\'t currect !\";\r\n if (typeof Func_Args[0] == \'function\')\r\n CallBack = Func_Args.shift();\r\n else CallBack = null;\r\n \r\n var JS_Item = SL_Set(RootPath, JS_List);\r\n if (! JS_Item[0].length) return;\r\n CB_Chain(JS_Item, CallBack);\r\n xImport(JS_Item[0][0].URL, JS_Item[0][0].CallBack);\r\n };\r\n \r\n BOM.ImportJS.UA = {\r\n IE: !! old_IE,\r\n Modern: ! old_IE,\r\n Mobile: !! is_Mobile,\r\n Pad: !! is_Pad,\r\n Phone: !! is_Phone\r\n };\r\n })(window, document);\r\n\r\n【平台支持】\r\n------\r\n - 主流内核浏览器:IE 7~11、Firefox 3+、Chrome、Safari、Opera\r\n - 国产马甲浏览器:傲游 2+、枫树、搜狗高速 3+、360安全/极速、猎豹、QQ 等(还可能有个别奇葩 Bug,恕无力一一测试……)\r\n - Android、iOS、Windows Phone、Symbian 等智能设备平台上的自带浏览器及其内核控件\r\n\r\n【主要特性】\r\n------\r\n 1. 替代 `<script />` 加载 HTML 页面中**所有外置、内置 JavaScript 脚本**,但不改变原有“**顺序即依赖**”的前端编程习惯,且书写形式比原来更简洁\r\n 2. 所有外置脚本都可写在 `<head />` 中,但却能与整个页面的其它部分**并行加载**,**代码结构清晰**而又**高性能**\r\n 3. 最后一段脚本(无论内置回调、外置脚本)自动在 **DOM Ready** 后加载/执行,既靠谱又方便(`$(document).ready(function () {});` 之类的大包装可以完全不需要了)\r\n 4. 无依赖的部分外置脚本只需用 `[]`(数组字面量)括起来就可以**异步加载**\r\n 5. 外置脚本可以根据浏览器平台类型**选择性加载**,模块化管理 JavaScript\r\n 6. **移动设备浏览器布局模式自适配**:添加其适用的各种 `<meta />` 标签,让网页源码以标准而通用的简洁思维编写,自然地实施**响应式设计**\r\n 7. 浏览器级的 `<iframe />` 套用防御\r\n\r\n【典型案例】\r\n------\r\nhttp://mag.fyscu.com/iWB/iBookView.php?name=iFY&index=19\r\n\r\n以下**示例代码**摘抄自上述网页的 HTML 源码 ——\r\n\r\n <head>\r\n ......\r\n <script type=\"text/javascript\" src=\"./Libs/EasyImport.js\"></script>\r\n <script>\r\n ImportJS([\r\n {\r\n old_PC: \'jQuery.js\',\r\n new_PC: \'jQuery2.js\'\r\n },\r\n [{\r\n old_PC: \'Turn.HTML4.js\',\r\n new_PC: \'Turn.js\'\r\n },\r\n \'Smooth_Scroll.js\',\r\n \'jPlayer.js\',\r\n \'jQuery.Hammer.js\',\r\n {\r\n old_PC: false,\r\n new_PC: \'jQuery.PageZoomer.js\',\r\n Mobile: false\r\n },\r\n {\r\n new_PC: \'Hover_Scroll.js\',\r\n Mobile: false\r\n }\r\n ],\r\n \'FY_iWeBook.js\'\r\n ], function () {\r\n $(\'#iWB\').iWeBook(\'#jPlayer_Box\');\r\n });\r\n\r\n var duoshuoQuery= {short_name:\'fyscu\'};\r\n ImportJS([\'http://static.duoshuo.com/embed.js\']);\r\n </script>\r\n ......\r\n </head>\r\n\r\n【参考文章】\r\n------\r\n 1. http://sunnylost.com/article/js.load.scripts.sequence.html\r\n 2. http://bbs.fyscu.com/forum.php?mod=viewthread&tid=4808\r\n 3. http://www.cnblogs.com/pigtail/archive/2013/03/15/2961631.html\r\n 4. http://www.uiej.com/960.html\r\n\r\n [1]: http://mag.fyscu.com\r\n [2]: http://bbs.fyscu.com/forum.php?mod=viewthread&tid=4808',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(133,'飞扬俱乐部研发部20141012例会记录','133',1413258785,1413258785,'<!--markdown-->本文为代发,作者是:苏清洺\r\n\r\n在一个阳光灿烂万里无云的日子里(雾),在休假了很多天以后(大雾),窝萌研发终于又迎来了新的例会!没错这次记录还是窝。。。。。。(估计要持续一段时间了喵!~)\r\n\r\n其实记录员迟到了几分钟(吐槽一下XX章学院的开学典礼长度),一到地点就看见JH学长站在讲台上红光满面的发布新版本OA,JH学长表示感谢白会(精神上)的支持,他才能做出这个OA。顺便发布了蓝学长的UC登陆界面。然后开始对于飞扬官方的各种数据分析:\r\n\r\n总览:\r\n1.user统计图:(数据是狮虎统计的!虎统计的!统计的!计的!的!)此处着重强调部长的账号对于数据的强大干扰性,顺路强调了JS(highcharts)画图的优越性。\r\n\r\n2.飞扬官方的数据:此处详细观察了gpa的使用图像,提到了关于微信和账号绑定登陆的优越性,但是却被发现bug就是无法解绑,同时发现近几天(8-10)使用频率较高,经查可能是缓冲文件未删除,JH学长表示请期待2.0版本。\r\n\r\n3.OA曲线:9号起直线上升……(版本更新效应?)\r\n(此处插播由游览器之争引发的兼容性不同问题,进而影响到网页的开发)\r\n\r\n4.研发数据库的使用情况:此处部长再次刷屏,被JH果断从表上屏蔽,这个表的主要作用是关联需求与使用份额以及经费,狮虎建议以后需要使用可以提交需求报告。\r\n\r\n5.飞扬官方数据库的使用;\r\n(注释:svg:矢量图形格式后缀)\r\n\r\n(此处JH学长森森吐槽了charts教程全英文使用的艰难性,学长,英语选修欢迎您。。。)\r\n\r\n应用管理:\r\n此处着重说明了删除方面的功能,删除的部分不会清空数据,而是用update更新,不显示出来,但是原数据仍保留,具有了可恢复性,防止误删。\r\n\r\n用户:\r\n惊现部长账号被封,JH学长当机立断解封,白会账号已经被删除(默哀三分钟),为了演示,JH学长默默选择了两只账号点选了封禁,ID知名不具。。。\r\n\r\n服务器资产管理:演示了用户添加功能;\r\n域名:同样是基本演示;\r\n数据库:本地/远程可选;\r\n以上三部分大家纠结重点在于界面美观性,强迫症儿童欢乐多……\r\n\r\n然后……JH学长正式宣布:OA发布了!(场面壮观参见陶学姐视频)大家鼓掌!\r\n\r\nJH学长本打算继续秀秀个人主页,可惜失败。。。\r\n\r\n第二个是狮虎发布,主题是有关报修系统的重构问题\r\n\r\n主要提出了以下几个BUG\r\nQ1.代码问题:当年由3个人分工写报修系统代码,合并时接口问题很大,对数据库开关调用过于频繁,易于崩溃;\r\nQ2.维修员的接单状态确定新版只能由客户确定,造成订单显示和统计差错;\r\nQ3.技术员可以无限拒绝订单,且会减少可接单数目;\r\nQ4.界面设置问题,很多客户看不到确认订单完成,将已完成订单取消。\r\nQ5.官网报修出现链接进入微信报修,微信报修提示进入官网报修,死循环。\r\n\r\n然后大家休息了一下,就蓝学长和部长的缺席问题做出了声明,具体原因不赘述。\r\n\r\n第三只是白会,主要宣传了蓝学长十一做的PHP框架(万能的蓝学长。。。)\r\n\r\n简单讲解了几个比较方便的fyPHP函数使用以及蓝学长框架的优越性,重点关心了陶钰学姐的学习进度……\r\n\r\n最后的最后,大家商讨了关于“闻道有先后”代码库的制作问题,具体问题具体对待,窝萌期待这个想法的成熟与实践。\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(132,'Nginx:conflicting server name * 0.0.0.0:80, ignored','132',1413043740,1413043943,'<!--markdown-->在编写了nginx配置文件后,重启nginx时出现如下警告:\r\n\r\n [jh@VM_84_179_centos conf.d]$ sudo /etc/init.d/nginx restart\r\n nginx: [warn] conflicting server name \"blog.jianghang.name\" on 0.0.0.0:80, ignored\r\n Stopping nginx: [ OK ]\r\n Starting nginx: nginx: [warn] conflicting server name \"blog.jianghang.name\" on 0.0.0.0:80, ignored\r\n [ OK ]\r\n\r\n这一般是由于技术员的粗心造成的。原因是blog.jianghang.name这个域名出现了两次甚至多次,把同一个域名解析到了不同的目录。一般将配置文件单独分离出来容易出现这个错误。\r\n接下来就是解决办法:\r\n1.查询哪些文件里面包含了 `blog.jianghang.name`字段 。使用grep命令,该命令实例如下:\r\n\r\n sudo grep -r blog.jianghang.name /etc/nginx/conf.d/\r\n\r\n\r\n参数 -r 是指明确要求搜索子目录,此处的目录就是`/etc/nginx/conf.d/` ,因为我知道配置文件都是在这个目录下,所以用了 -r 参数。如果不知道具体目录,可以用 * 代替,其实就是正则表达式啦。这里不细讲。\r\n找到了出现 `blog.jianghang.name` 的文件之后,就将设置不正确的地方该正确吧。\r\n\r\n**记住一个域名只能有一个对应的目录,一个目录可以有多个对应的域名。**\r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(125,'【网页重构】CSS 规则清理(浏览器 BookMarkLet、FireBug 插件)','125',1412101800,1432882009,'<!--markdown-->很多程序猿认为 —— **最蛋疼的工作不在于重写或创新,而是“修改前任程序猿留下的代码”……**\r\n\r\n对**前端工程师**来说,若不进行彻底的**网页重构**,而只是修补现有网页的代码(多是之前由 **后端工程师** 乃至 **只会点儿 DreamWeaver 的运维网管** 写的),再加上浏览器兼容性的工作特性(特别是 **IE 8-**),简直是“英年早逝”的节奏……\r\n\r\n你能想象一个 HTML 文件中全是大量*乱七八糟、东拼西凑*的 标签结构 和 CSS 规则 吗?不仅如此,`<link rel=\"stylesheet\" />`、`<style />`、`<script />` 也是随时随地出现;很多 HTML 元素都由不止一个 CSS 文件中的多个毫无逻辑联系的规则 叠加影响;文件命名、目录结构也超乱…… **“大海捞针”、“牵一发而动全身”**便是再贴切不过的形容了……\r\n\r\n若能用工具清理一遍 CSS,那我们的工作就搞定一半了~\r\n\r\n----------\r\n\r\n原创小工具\r\n-----\r\n\r\n这里先分享一下我原创的一个 **BookMarkLet** 形式的 [**网页 CSS 规则使用率检测工具**][1] ——\r\n\r\n (function (BOM, DOM, $) {\r\n\r\n var CSS_File = DOM.styleSheets,\r\n CopyRight = \'(C)2014-2015 [email protected]\';\r\n\r\n if (! $) {\r\n BOM.alert(\r\n \'Please run This Tool in IE 8+ (Standard Mode) or a Modern Web Browser.\' + \"\\n\\n\" +\r\n CopyRight\r\n );\r\n return false;\r\n } else if (! console) {\r\n BOM.alert(\r\n \'Please run This Tool with JavaScript Console opened.\' + \"\\n\\n\" +\r\n CopyRight\r\n );\r\n return false;\r\n }\r\n\r\n function URL_Path(URL) {\r\n if ( URL.match(/^\\w+:\\/\\//) ) {\r\n URL = URL.split(\'/\').slice(3);\r\n URL.unshift(\'.\');\r\n URL = URL.join(\'/\');\r\n }\r\n return URL;\r\n }\r\n\r\n function SelectorCheck(Selector) {\r\n Selector = Selector.split(\',\');\r\n var _NU_ = [ ];\r\n\r\n for (var k = 0; k < Selector.length; k++)\r\n if (! $( Selector[k].trim().split(\':\')[0] ).length)\r\n _NU_.push(Selector[k]);\r\n\r\n return _NU_;\r\n }\r\n\r\n function CSS_Rule_Each(CSS_Rule_Group) {\r\n try {\r\n var CSS_Rule = CSS_Rule_Group.cssRules || CSS_Rule_Group.rules;\r\n } catch (Err) { }\r\n\r\n var Selector = \'\',\r\n NoUsage = [ ],\r\n Test_Result = {\r\n media: CSS_Rule_Group.media.mediaText,\r\n mediaRules: [ ],\r\n fontsRules: [ ]\r\n };\r\n if (CSS_Rule) {\r\n for (var j = 0, _Rule_; j < CSS_Rule.length; j++) {\r\n _Rule_ = CSS_Rule[j];\r\n switch (_Rule_.type) {\r\n case 1: { // CSSStyleRule\r\n _Rule_ = SelectorCheck(_Rule_.selectorText);\r\n if (_Rule_.length) NoUsage.push(_Rule_);\r\n } break;\r\n case 4: // CSSMediaRule\r\n Test_Result.mediaRules.push( arguments.callee(_Rule_)[0] ); break;\r\n case 5: // CSSFontFaceRule\r\n Test_Result.fontsRules.push({\r\n fontFamily: _Rule_.style.fontFamily,\r\n src: _Rule_.style.src\r\n });\r\n }\r\n }\r\n Test_Result.WasteRate = ((NoUsage.length / j) * 100).toFixed(2) + \'%\';\r\n }\r\n return [Test_Result, NoUsage];\r\n }\r\n\r\n for (var i = 0, _File_, _Result_ = [ ]; i < CSS_File.length; i++) {\r\n _Result_[i] = CSS_Rule_Each(CSS_File[i]);\r\n var _File_ = _Result_[i].shift();\r\n \r\n _File_.href = CSS_File[i].href;\r\n if (_File_.WasteRate && _File_.href)\r\n _File_.href = URL_Path(_File_.href);\r\n _File_.element = CSS_File[i].ownerNode;\r\n console.log(_File_);\r\n }\r\n console.log(_Result_);\r\n\r\n })(self, self.document, self.document.querySelectorAll);\r\n\r\n安装版代码 ——\r\n\r\n javascript: (function(a,b,c){function f(a){return a.match(/^\\w+:\\/\\//)&&(a=a.split(\"/\").slice(3),a.unshift(\".\"),a=a.join(\"/\")),a}function g(a){var b,d;for(a=a.split(\",\"),b=[],d=0;d<a.length;d++)c(a[d].trim().split(\":\")[0]).length||b.push(a[d]);return b}function h(a){var b,e,f,i,h;try{b=a.cssRules||a.rules}catch(c){}if(e=[],f={media:a.media.mediaText,mediaRules:[],fontsRules:[]},b){for(h=0;h<b.length;h++)switch(i=b[h],i.type){case 1:i=g(i.selectorText),i.length&&e.push(i);break;case 4:f.mediaRules.push(arguments.callee(i)[0]);break;case 5:f.fontsRules.push({fontFamily:i.style.fontFamily,src:i.style.src})}f.WasteRate=(100*(e.length/h)).toFixed(2)+\"%\"}return[f,e]}var j,i,k,d=b.styleSheets,e=\"(C)2014-2015 [email protected]\";if(!c)return a.alert(\"Please run This Tool in IE 8+ (Standard Mode) or a Modern Web Browser.\\n\\n\"+e),!1;if(!console)return a.alert(\"Please run This Tool with JavaScript Console opened.\\n\\n\"+e),!1;for(i=0,k=[];i<d.length;i++)k[i]=h(d[i]),j=k[i].shift(),j.href=d[i].href,j.WasteRate&&j.href&&(j.href=f(j.href)),j.element=d[i].ownerNode,console.log(j);console.log(k)})(self,self.document,self.document.querySelectorAll);\r\n\r\n工具特性 ——\r\n\r\n 1. **扫描当前网页中所有内置/外置的 CSS,在控制台显示各 CSS 标签/文件中哪些规则对本页无用、共占比多少**\r\n 2. 外置 CSS 会显示**文件相对路径**\r\n 3. 内置 CSS 会显示其对应的 HTML 元素,便于**在调试器显示的 DOM 树上定位**\r\n 4. **CSS 媒体查询、字体**的规则会在显示的对象中有独立分支\r\n 5. 暂不支持 CSS 选择符中间有 **伪类、伪元素**的情况,只支持它们出现在 选择符链的最后端(这是与下文提及的专业工具之**有效比计算**有误差的主要原因)\r\n 6. **跨域的 CSS 文件**无法扫描(它们一般都是 **CDN 通用库** 或 部署环境中的**静态文件服务器**托管的压缩版,本来就不是用于调试的)\r\n\r\n----------\r\n\r\nFireBug 插件 —— CSS Usage\r\n-----------------------\r\n\r\n现在比较成熟的 **CSS 有效性检查工具** 当属 `CSS Usage` 了,它不仅能用彩色的富文本显示每个 CSS 标签/文件中**每条规则在当前网页中的使用率**,还能**生成过滤后的 CSS 文本**,可以直接复制粘贴到代码编辑器中保存、使用~\r\n\r\n至于它的安装,和 FireBug 一样,在 **FireFox** 的**附加组件**管理界面中搜索、下载、安装、重启,在 FireBug 主界面上端的选项卡最后就能看到它了~\r\n\r\n\r\n [1]: http://git.oschina.net/Tech_Query/iBookmarkLet',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(121,'未命名文档','121',1411715880,1411717681,'<!--markdown-->`$data[\'name\'] = $_POST[\'name\'];`\r\n获取来自get/post的数据,最好先isset一下,虽然可以关闭警告输出,但是洁癖主义需要我们做得完美一些\r\n```\r\ncase \'post\':\r\n $value = isset($_POST[$key])?$_POST[$key]:\'\';\r\n break;\r\ncase \'get\':\r\n $value = isset($_GET[$key])?$_CET[$key]:\'\';\r\n break;\r\n```\r\n`变量命名`\r\n```\r\n$a=array(\r\n\'limit\'=>intval($num*($page-1)).\',\'.$num,\r\n\'order\'=>\'id desc\'\r\n);\r\n$c=array(\'id\',\'name\',\'username\',\'money\',\'pay_dateline\',\'server_lot\',\'language\',\'deadline\');\r\n$b=FYDB::find_all(\'server_assets\',$c,$a);\r\n//...\r\n(($count1)%$num!=0)?($count2 = ($count1)/$num+1):($count2 = ($count1)/$num);\r\n```\r\n\r\n`for($i=0;$i<(count($b));$i++) count放在外面`\r\n\r\n`$this->_data[\'prev_status\'] =($this->_data[\'prev\']<=0)?\'\':\'<a href=\"index.php/server/idc/?p=\'.$this->_data[\'prev\'].\'\">«上一页</a>\';`\r\n不建议在逻辑层里处理表现层\r\n\r\n`FYDB::delete(\'server_assets\',$data);`\r\n有些数据,尽量用更新状态来表达删除,不用真的删了的。万一手贱点错呢。\r\n另外,所有数据操作逻辑,最好加入来源检查, 提放被刷。$_SERVER[\'HTTP_REFERER\']\r\n\r\n`$count1 = count(FYDB::find_all(\'server_app\', array(\'id\')));`\r\n查询全部再计数,是个很老(dou)实(bi)是做法,应该用 FYDB::find_value(\'server_app\',\'count(id)\')\r\n\r\n\r\n\r\n\r\n',0,2,NULL,'post_draft','private',NULL,0,'1','1','1',0),(124,'飞扬俱乐部研发部会议记录(9.27)','124',1411833000,1411835531,'<!--markdown-->第一次写例会记录简直紧张,爪子默默攥着纸笔不停写写写。。。喵,不要问我为什么木有图。。。爪机木有电鸟。。。于是例会从3点开始。。。\r\n\r\n\r\n会前:\r\n 别问我为什么有会前,纯粹无聊记录一下大家的状态。白导在认真聆听蓝神的修改意见,投影仪上面播放着狮虎正在玩的实况足球。。。环视一圈以后发现蒋航学长迟到了,崔倩学姐神秘的木有粗线,于是,大家达成共识。。。下次例会迟到的。。。请客!~\r\n\r\n\r\n会中:\r\n\r\nBig News总是有的,具体如下:\r\n\r\n No.1 第一个是邹兵学长发言(PS.此处看见仙剑四的桌面,记录员表示很激动),主题是跨平台开发APP,一开场提出了两个很神秘的词语:Cordova 和Hybird app,并且简单列举了一些其他开发引擎(喵,是引擎吧?)。然后对Cordova 和Hybird app做了一定程度的简单介绍,得出结论:我们以后的应用里面可以参考淘宝京东的模式,将Web和Native结合。\r\n\r\n以下为提问小王子国宝部长的评价:你还是有点腼腆,But进步了,比大一的时候好。。。(什么奇怪的东西混进来了?)\r\n 答:进步的比较缓慢。\r\n 狮虎补充:以后每周可以有个大新闻。\r\n 答:不擅长PC端,移动端又怕新闻比较旧。\r\n 部长表示球以上内容的具体作用。\r\n 回答表示暂时没做,但是觉得会比较好用。\r\n 蓝学长继续追问方向和实现方法,最后变成了相对深入的讨论,但是,记录员貌似最后没有听到明确结论。\r\n\r\n\r\n\r\n No.2 蒋航(学长你神马时候来的?!)发言,在调试投影仪时隐约听见旁边讨论三国杀的声音。蒋航学长的主题是“给百会的公开信——关于OA官网的吐槽”具体列举了如下若干条Bug:\r\n 1.字体:宋体不如雅黑高大上(立刻被在场部分群众反驳,按下不表);\r\n 2.首页右边始终存在滚动标签(学长眼神真好。。。);\r\n 3.应用管理的布局有问题,可左右滚动;\r\n (此时鉴于PPT过渣的分辨率,以下开始打开官网直接验证,然后BUG就如同滔滔江水奔流不绝了。。。)\r\n 4.鼠标移开时“上(下)一页”会出现下划线,“封号”二字同理;(此处JH学长尝试封号未果,其实是根本没做这个功能喵)\r\n 5.服务器资产管理的布局很好,但是添加功能出了问题,而且即使是添加条目全部空白爷可以确定,蒋航提出加required(其实这里没人写对吧对吧对吧……?);\r\n 6.域名部分,JH增加了一个域名(无视了大家对于命名为juanjuan的呼声),并演示了修改和删除,就在确认删除成功之后……重点来了!localhost了!此处为大BUG!高亮之!\r\n 7.SSH用户管理无法添加;\r\n 8.数据库管理存在布局+创建时间可改+localhost的问题;(蓝神提出以后这个给JH跟进)\r\n 9.欢迎用户的括号全角与半角问题;(学长其实你是来找茬的对吧?)\r\n 10.窗口还原之后菜单无法下拉问题。(大家均表示,那个图标只是放上去给你看看的,没有任何特殊意义。。。)\r\n此段特@蒋航 学长\r\n\r\n\r\n\r\n No.3崔倩姐在刚才华丽丽的来了,所以第三个是崔倩姐的大新闻:Count down项目管理系统。简单说就是一个包含计时和推送功能的三端应用。以时间线为引导,横线为进度竖线为质量,提醒任务。同时可类似普通讨论组讨论,可公开项目。\r\n 听完后蓝神和部长均表示比较繁杂,后面有些乱,可以立项但最好先简化,后面再慢慢增加功能。\r\n\r\n\r\n\r\n No.4第四个是狮虎发新闻,被点名要好好听表示压力很大,吓得我都不敢做会议记录了。。。看到全英文的PPT整个人都不好了一下,总共只有三张的简洁PPT包含了简单的堆栈和动态静态库基础,记录员表示认真在听,具体木有记录。。。\r\n 讲述时全场寂静,之后部长有默默吐槽只有老师说专业课才会一张PPT说3节课。。。后话是这个高大上的内容被黑了一晚上。。。\r\n\r\n\r\n例会就此结束,同学们临走前JH补充了一个小新闻:10月11号OA正式发布!(那么多BUG真的呆胶布?) \r\nover\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n当人走完的时候,部长又说:水哥要来。。。于是后来水哥又过来和蓝神深入交换了意见并达成共识,以上为全部例会内容喵~如有雷人,纯属巧合~',0,22,NULL,'post','publish',NULL,0,'1','1','1',0),(120,'[Angular]数据和表现的分离,那种感觉太美妙','120',1411704540,1415586330,'<!--markdown-->之前用`Angular`的循环输出`ng-repeat`的时候,都是顺序输出集合内容的。\r\n今天有个需求要将数据`倒序输出`,一开始的想法是将集合内的数据反序一下,\r\n输出来就是倒序了。\r\n\r\n#但是\r\n\r\n一般“但是”后面都是大新闻。\r\n我仔细想过,这样改变数据层,以适应表现层的变化,违背了这个框架本事的精髓,带来了非常大的耦合。\r\n\r\n因为这样去操作数据,这个数据已经不是本身的`抽象定义`,而是变成了针对`视图`定制的模型。\r\n\r\n于是我打算,在不改变数据层本心的基础上,实现倒序输出。\r\n\r\n还好,Angular提供了这样的方法,在循环输出的时候加上 orderBy选项即可,如下:\r\n` ng-repeat=\"message in messages.live | orderBy:\'-time\'\" `\r\n\r\n总结下,像比如MVC这些体系下,一般表现层变化,万不得已(比如增加东西)不要改变数据模型。\r\n\r\n更多文章,请密切关注 `部长微博 @此刻你的梦想实现了吗 `',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(119,'【JavaScript 入门】类 jQuery 式的事件绑定(兼容主流浏览器内核)','119',1411700520,1411702358,'<!--markdown-->可能很多 **JavaScript 初学者**在熟悉了它的**基本语法**之后,往往会先用 **jQuery** 来**实践网页开发**。先做出点实用的东西来,有些直观的感受,再倒回来对 JavaScript **深入浅出**。\r\n\r\n这种方法的**学习曲线**比较平滑,利于大家愉快地发现、感悟 **JavaScript 的简洁与灵活、优雅与强大**~\r\n\r\n我今天的 Coding 正好遇到了必须用纯 JS 来做的地方,就和大家来分享一下手敲的 **JS 事件绑定的兼容性封装** ——\r\n\r\n function Event_Bind(_Element, _Type, _CallBack, _unBind) {\r\n var _CB_ = function (Event) {\r\n EO = self.event || Event;\r\n EO.target = EO.srcElement || EO.target;\r\n if (! _CallBack.call(_Element, EO))\r\n if (EO.returnValue) {\r\n EO.returnValue = false;\r\n EO.cancelBubble = true;\r\n } else {\r\n EO.preventDefault();\r\n EO.stopPropagation();\r\n };\r\n };\r\n if (_Element.attachEvent)\r\n _Element[ (_unBind ? \'de\' : \'at\') + \'tachEvent\'](\r\n \'on\' + ((_Type == \'input\') ? \'propertychange\' : _Type),\r\n _CB_\r\n );\r\n else\r\n _Element[\r\n (_unBind ? \'remove\' : \'add\') + \'EventListener\'\r\n ](_Type, _CB_, false);\r\n }\r\n\r\n示例代码 ——\r\n\r\n Var Event_Handle = function (EO) {\r\n var ET = EO.target;\r\n console.log(ET);\r\n \r\n if (ET.tagName.toLowerCase() == \'a\') {\r\n open(ET.href, \'_blank\');\r\n return false;\r\n }\r\n };\r\n // 事件绑定\r\n Event_Bind(document.body, \'click\', Event_Handle);\r\n\r\n // 事件解绑\r\n Event_Bind(document.body, \'click\', Event_Handle, true);\r\n\r\n【参考文章】http://vaotoo.com/r/15018',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(106,'QQ截图20140924103714.png','QQ截图20140924103714-png',1411526271,1411526271,'a:5:{s:4:\"name\";s:26:\"QQ截图20140924103714.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/1373443136.png\";s:4:\"size\";i:9289;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',108),(107,'QQ截图20140924103743.png','QQ截图20140924103743-png',1411526273,1411526273,'a:5:{s:4:\"name\";s:26:\"QQ截图20140924103743.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/1977159788.png\";s:4:\"size\";i:6299;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,2,NULL,'attachment','publish',NULL,0,'1','0','1',108),(108,'socket.io两次重复emit的问题','108',1411526340,1461828217,'<!--markdown-->背景:\r\n\r\n express+angular+socket.io实现的即时通信,在客户端emit一个事件信号的时候,\r\n 会重复发两次!任何信号都是!\r\n\r\n纠结这个问题很久,查了好多资料,再一次印证google强大的事实,在浏览一篇外文时找到了答案。\r\n` http://stackoverflow.com/questions/18815843/socket-io-event-being-triggered-twice `\r\n楼主自问自答也是蛮拼的,反正是解决了我的问题。\r\n\r\n> For future reference this was occurring because I was setting my angular controller in both my HTML and under my $routeProvider. This was then triggering everything twice. \r\n\r\n**原因就是:Angular惹的祸,在html页面里定义的控制器,和在路由表里定义的控制器,都会生效,这样就造成了定义了两个同样的控制器,那么触发两次emit就不难理解了。以下是两个定义路由的地方:**\r\n![QQ截图20140924103714.png][1]\r\n![QQ截图20140924103743.png][2]\r\n** 解决方案:我取消了路由表里定义的控制器,因为还是比较习惯在html里写控制器,scope范围比较好掌握。 **\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/09/1373443136.png\r\n [2]: http://log.fyscu.com/usr/uploads/2014/09/1977159788.png',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(109,'1.png','1-png-1',1411559673,1411559673,'a:5:{s:4:\"name\";s:5:\"1.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3658205544.png\";s:4:\"size\";i:6876;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',9,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(110,'2.jpg','2-jpg',1411560936,1411560936,'a:5:{s:4:\"name\";s:5:\"2.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2707660166.jpg\";s:4:\"size\";i:21215;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',8,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(111,'3.jpg','3-jpg',1411560940,1411560940,'a:5:{s:4:\"name\";s:5:\"3.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2274293924.jpg\";s:4:\"size\";i:4417;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',7,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(112,'1.jpg','1-jpg-1',1411562347,1411562347,'a:5:{s:4:\"name\";s:5:\"1.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/1993727533.jpg\";s:4:\"size\";i:19041;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',6,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(113,'2.jpg','2-jpg-1',1411562353,1411562353,'a:5:{s:4:\"name\";s:5:\"2.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/206781972.jpg\";s:4:\"size\";i:36823;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',5,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(114,'3.jpg','3-jpg-1',1411562595,1411562595,'a:5:{s:4:\"name\";s:5:\"3.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3997181510.jpg\";s:4:\"size\";i:21098;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',4,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(115,'4.png','4-png',1411562806,1411562806,'a:5:{s:4:\"name\";s:5:\"4.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/1719941127.png\";s:4:\"size\";i:12858;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(116,'5.jpg','5-jpg',1411562887,1411562887,'a:5:{s:4:\"name\";s:5:\"5.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/913217794.jpg\";s:4:\"size\";i:18899;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',2,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(117,'6.jpg','6-jpg',1411563231,1411563231,'a:5:{s:4:\"name\";s:5:\"6.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/4050117077.jpg\";s:4:\"size\";i:19702;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',1,9,NULL,'attachment','publish',NULL,0,'1','0','1',104),(118,'【浏览器小工具】网页浮层广告/锁屏一键清除(完善重发)','118',1411677600,1414128060,'<!--markdown--> 我之前写的【[网页浮动广告一键清除工具][1]】虽然不断完善至 v0.3,但对各种实现方式的**浮层广告** 适配得不全面,自己在使用过程中发现有些网站的浮层广告依然无法彻底清除(*某个很亮堂的党报的官网* 新闻阅读页的右下角广告 竟然比某些盗版资源站的还顽固)……\r\n 进一步调试、分析后发现,这些“地痞无赖”的广告有个特点 —— 在和 `<body />` 一样大的多个 `<div />` 层层包裹下(有的多达 13 层),浮层广告用任意的 CSS 设为 `display: block` 的 HTML 标签包裹(如 `<i />`),这个标签再用 `position: absolute` 定位。(此法也就是“IE 6 不支持 `position: fixed`”的兼容方法)\r\n 因为我和女友平时都经常使用它(我主要是大量地查技术资料、下经典电影,她主要是看娱乐八卦,反正都是广告满天飞的网站……)于是,继续更新之 ——\r\n\r\n## 最新稳定版 全部特性 ##\r\n\r\n 1. 可清除 **网页中任一位置的浮动广告**\r\n 2. 可清除 **遮蔽整个网页的登录框**\r\n 3. 可清除 **笼罩整个网页的透明弹窗广告超链接**\r\n 4. 可清除 **网页正文图片边缘的浮动广告**(一般在第二次点击本工具时成功,但此时会误杀一些网页本身的功能浮层,可能会影响某些功能的使用,**建议在纯阅读时二次点击本工具**)\r\n\r\n## 开发用源代码 ##\r\n\r\n //\r\n // 1Key Web Float Layer Cleaner v0.5\r\n //\r\n // 2014-10-10\r\n //\r\n // (C)2014 [email protected]\r\n //\r\n \r\n (function (WO, DO) {\r\n function $_TN(REO, TagName) {\r\n return [].slice.apply( REO.getElementsByTagName(TagName) );\r\n }\r\n function get_Style(_TE, _SN) {\r\n var _Style = _TE.currentStyle ?\r\n _TE.currentStyle.getAttribute(_SN) :\r\n DO.defaultView.getComputedStyle(_TE, null).getPropertyValue(_SN);\r\n var _Number = Number(\r\n (_Style == \'0px\') ? 0 : _Style\r\n );\r\n return isNaN(_Number) ? _Style : _Number;\r\n }\r\n function CSS_Match(EO, RG) {\r\n for (var i = 0; i < RG.length; i++)\r\n if (get_Style(EO, RG[i][0]) == RG[i][1])\r\n return 1;\r\n }\r\n function ParentMatch(EO, Parent, Level) {\r\n for (var i = 0; i < Level; i++)\r\n if (EO.parentNode === Parent)\r\n return 1;\r\n else if (EO.parentNode === DO)\r\n break;\r\n else EO = EO.parentNode;\r\n }\r\n function isFixedLayer(_TE) {\r\n var inVisible = CSS_Match(_TE, [\r\n [\'display\', \'none\'],\r\n [\'visibility\', \'hidden\'],\r\n [\'width\', 0]\r\n ]);\r\n var Fixed = (! inVisible) && CSS_Match(_TE, [\r\n [\'position\', \'absolute\'],\r\n [\'position\', \'fixed\']\r\n ]);\r\n if (Fixed && (\r\n WO.FLC ? true : (get_Style(_TE, \'z-index\') > 100)\r\n ))\r\n return ParentMatch(\r\n // 清除效果 基本只取决于“DOM 遍历深度”\r\n _TE, DO.body, (WO.FLC ? 13 : 3)\r\n );\r\n }\r\n var FL_Box = $_TN( $_TN(DO, \'body\')[0], \'*\');\r\n for (var iKey = FL_Count = 0, _FL; iKey < FL_Box.length; iKey++) {\r\n _FL = FL_Box[iKey];\r\n if ( isFixedLayer(_FL) ) {\r\n _FL.parentNode.removeChild(_FL);\r\n console.log(_FL);\r\n FL_Count++;\r\n }\r\n }\r\n if (! self.FLC) self.FLC = true;\r\n alert([\r\n FL_Count, \' of the fucking Float ADs/Layers have been cleaned !~\',\r\n \'\\n\', \'You can try Clicking my Button again to be cleaner.\',\r\n \'\\n\\n\', \'(C)2014 SCU FYclub-RDD\'\r\n ].join(\'\'));\r\n })(self, self.document);\r\n\r\n\r\n## 安装用代码 ##\r\n\r\n 用 **UglifyJS**([在线版][2])生成,压缩率 高于 50% ——\r\n\r\n javascript: (function(a,b){function c(a,b){return[].slice.apply(a.getElementsByTagName(b))}function d(a,c){var d=a.currentStyle?a.currentStyle.getAttribute(c):b.defaultView.getComputedStyle(a,null).getPropertyValue(c),e=Number(\"0px\"==d?0:d);return isNaN(e)?d:e}function e(a,b){for(var c=0;c<b.length;c++)if(d(a,b[c][0])==b[c][1])return 1}function f(a,c,d){for(var e=0;d>e;e++){if(a.parentNode===c)return 1;if(a.parentNode===b)break;a=a.parentNode}}function g(c){var g=e(c,[[\"display\",\"none\"],[\"visibility\",\"hidden\"],[\"width\",0]]),h=!g&&e(c,[[\"position\",\"absolute\"],[\"position\",\"fixed\"]]);return h&&(a.FLC?!0:d(c,\"z-index\")>100)?f(c,b.body,a.FLC?13:3):void 0}var j,i,h=c(c(b,\"body\")[0],\"*\");for(i=FL_Count=0;i<h.length;i++)j=h[i],g(j)&&(j.parentNode.removeChild(j),console.log(j),FL_Count++);self.FLC||(self.FLC=!0),alert([FL_Count,\" of the fucking Float ADs/Layers have been cleaned !~\",\"\\n\",\"You can try Clicking my Button again to be cleaner.\",\"\\n\\n\",\"(C)2014 SCU FYclub-RDD\"].join(\"\"))})(self,self.document);\r\n\r\n\r\n [1]: http://bbs.fyscu.com/forum.php?mod=viewthread&tid=4929\r\n [2]: http://www.css-js.cn/',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(103,'QQ图片20140923011209.jpg','QQ图片20140923011209-jpg',1411405948,1411405948,'a:5:{s:4:\"name\";s:26:\"QQ图片20140923011209.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/401503873.jpg\";s:4:\"size\";i:100167;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',102),(104,'对于小蓝9.22日提出的【论道】讨论结果的总结','104',1411484880,1411700575,'<!--markdown-->由于涉及众多讨论 \r\n本贴采用时间顺序来记录事情的起因发售经过结果\r\n\r\n起因\r\n==\r\n\r\n9月22日 10:48\r\n小蓝在术业有转攻发表了一篇名为“有没有可能一个条件结构的两个分支都被执行?”的文章 \r\n内容十分简单:\r\n“正方:不可能,不是true,就是false \r\n 反方:可能,不信我分分钟试一下 ”\r\n[原帖地址][1]\r\n\r\n\r\n------------------------------------手漂亮的工分割线------------------------------------\r\n\r\n经过\r\n==\r\n\r\n第一阶段\r\n----\r\n\r\n10:53 - 11:27\r\n小蓝在群里贴出了地址,吴会在马哲课上看到了并且发出了第一种解答\r\n\r\n int main(int argc,char *argv[])\r\n {\r\n int i=0;\r\n begin:\r\n if(i==0)\r\n {\r\n i=1;\r\n goto begin;\r\n }\r\n else\r\n {\r\n return 0;\r\n }\r\n }\r\n看到这种解答后,陈宁第一个表示了质疑“怎么还用goto”,随后又不知在何处截图,截图内容指出**“在结构化程序设计中一般不主张使用goto语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。”**\r\n吴会随即反驳称,此程序结构简单不需要考虑这个。并提出了第二种解法的雏形**“用循环也行”**,但陈宁还是表示了坚决的反对\r\n此时小花姐出现并发表了自己的意见,表示goto在这个地方感觉很好用啊,其余地方看情况慎用。同时小花姐还介绍了一种goto的用法给大家分享了一点人生的经验:**goto一般是用来做统一出口的,很多程序会将异常出口定义在函数末尾。如果有异常分支,就用goto出去。**\r\n举例\r\n\r\n void xx(xxx) {\r\n xxx;\r\n xxx;\r\n xxx;\r\n return;\r\n \r\n err_out:\r\n xxx; //虽然我没看goto 但是,小花姐原文是这样\r\n xxx; //小花姐的意思应该将错误处理和退出写在err_out标签后\r\n } //每次错误退出时都goto跳转err_out统一处理\r\n\r\n然后小蓝不知从哪冒出来了说**“用水哥的话就是,奇技淫巧”**\r\n这句话引发了小花与小蓝论战\r\n\r\n - 小花:“少年来给我不奇淫技巧一个?没有try catch 你准备怎么搞?”\r\n - 小花:“不用goto难道你准备在所有出错的分支都处理一遍?大部分程序异常退出都会释放资源等等一系列操作,你想怎么做?”\r\n - 小蓝:“没有try catch怪我咯?”\r\n - 小花:“……(你\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*)”\r\n\r\n好吧,回到正题\r\n吴会表示还见过一种**“把err_out定义成了宏”做为程序异常退出的的统一形式**\r\n小花姐以一个长者的身份说到**“宏是一样的。。都是代码重写了。。只不过程序员不用写那么多代码 实际上预处理完代码还是重复写了很多”**\r\n然后小蓝又来BB了 **“对于有逻辑洁癖强迫症的人,goto简直是!!”**(所以以后还是不要写goto了,至少别让小蓝看到,免得他又发动长者的愤怒)\r\n\r\n第二阶段\r\n----\r\n\r\n19:47\r\n\r\n小蓝再次贴上了网址,希望大家发表一下高见,一轮新的讨论开始了\r\n吴会再次第一个响应,**“switch case算?”**,小蓝甩给吴会两个字**“不算”**,并且表示,用switch case不用break更像**语法糖**\r\n(ps.百度百科:语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会)\r\n此时。。阿翔出现了,啊,不对是苏苏 她坚决的表示**“喵?两个分支都执行?If肯定不行喵”**(大概是目前唯一的正方观点?)\r\n然后,小花姐再次出现了贴出了一张图:\r\n![1.png][2]\r\n看到了小花姐实现了之后,陈宁这小子来了句“就是酱紫”...你丫不上午还说不能用goto么.....??苏苏也发出了好棒的赞许.....你丫刚才不还说If肯定不行喵么?\r\n回到正题,小蓝表示不服称“用goto全控已经超出范围了吧”,小花则声称**“这个都好说,用gets大法”**(我会告诉你我没懂?....好吧,懂的人下面回复下吧)然后小花又说“不对。。我先想想if的汇编指令是什么?”(没明白和上一句有什么联系)\r\n小蓝还是做出了一个评价“尽管如此小花的写法还是比吴会更完(wu)美(lai)一些”\r\n然后他又邀请了到了另一位大神——ten geek参与讨论 \r\n—— 骚年,不来一发么?\r\nten geek表示有点意思,参与进了讨论\r\n这时,吴会发来了两张图:\r\n![2.jpg][3]\r\n![3.jpg][4]\r\n我靠 实现了? 定睛一看,原来是switch case....完全没biger嘛 然后又被陈宁指出那个i++其实是多余的 小宁子 你成心和我作对? T T\r\n小蓝提出了一个艾斯比问题“说了奇怪,怎么都是反方观点?” 屁!你没看见苏苏说什么了么?\r\n当然后面又自己打自己脸了“正反方不都行么 阿翔多坚定的说绝对不行”\r\n好吧 这时ten geek出关了,甩出了一堆代码打在小蓝脸上:\r\n\r\n #include <stdio.h>\r\n int main()\r\n {\r\n if(1)\r\n {\r\n printf(\"1.\\n\");\r\n goto a;\r\n }else\r\n {\r\n a:\r\n printf(\"2.\\n\");\r\n }\r\n return 0;\r\n }\r\n看来简直是英雄所见略同嘛...\r\n接下来小花姐又提出了一个方案**“话说小蓝你能不能忍我在c里面嵌汇编,我强行jmp过去”**,并坚决的对小蓝表示这和goto是不同的 小蓝这个反复无常的家伙又冒出来一句**“我想了想,goto确实是可以,算是C语言强大的一个表现”** 我只能说 你个大数据库\r\n这时小花姐爆出了一系列新姿势\r\n\r\n> “我试了一下 if(1)和另外的条件语句编译结果不一样”\r\n> “if(1)根本不会做对比。。编译的汇编代码直接隐去了else的内容。。如果加上goto\r\n> 相当于把else的内容也编译在了源码里面。。我觉得也是优化 奇怪的是。。尼玛我没开优化选项。。gcc真特喵的智能”\r\n> **“不过goto还是等同于分支合并”**\r\n\r\n![1.jpg][5]\r\n![2.jpg][6]\r\n\r\n> “我之前以为是jmp过去的。。结果不是。。” \r\n> **“不过这种东西 应该是实现定义的吧。。。我这只有gcc 找个谁用vs调试看看”**\r\n\r\n然后一直潜水的蒋言斌发上了一张截图:\r\n![3.jpg][7]\r\n结果是vs是用jmp跳过去的\r\n正如小花姐之前所预测:**goto的汇编和编译器的定义相关**\r\n经过小花姐对文档的查询,得到了如下的结果:\r\n![4.png][8]\r\n自己看吧 英语不好的自行google\r\n并且还祭出了之前吴会提到过,但没写出来的循环实现模式\r\n![5.jpg][9]\r\n田值大神由于参与讨论较晚,再次提出了之前说过的switch case模式\r\n小蓝再次发表了自己的意见**“懒惰写法,又或者这个更倾向map逻辑,虽然都叫判断”**(完全没懂....请当事人来自行解释下吧)\r\n\r\n这时,小花姐又来了,发了C语言的一颗语法糖\r\n![6.jpg][10]\r\n\r\n> 解释如下:[]是语法糖,因为实际实现是\\*(i + a)满足加法交换律啊,\\*(a + i)也是一样的啊(小花姐语)\r\n> 用代码表示: i[a] = \\*(i+a) = \\*(a+i) = a[i]\r\n\r\n小蓝看到跑题,表示:\"I am angry\" 长者的愤怒啊\r\n然后甩出来一句:**“我忽然想到怎样反驳goto了,使用goto,准确说是执行了两个分支里面的逻辑,不等于说执行了两个分支。不然你甚至可以执行1.5个”**\r\n说到这\r\nten geek甩了一个程序——循环模式2.0\r\n\r\n #include <stdio.h>\r\n int main()\r\n {\r\n int c0=1,c1=0,c2=1;\r\n int b[]={c0,c1,c2};\r\n for(int i=0;i<sizeof(b)/sizeof(int);i++)\r\n {\r\n if(b[i])\r\n {\r\n printf(\"第%d个分支为true.\\n\",i);\r\n }\r\n }\r\n getchar();\r\n return 0;\r\n }\r\n但是小蓝和吴会对这种方式表示出了不认同 这已经不是一个结构了\r\nten geek又说**“我觉得如果遇到这种情况。完全可以一直if下去了。。”**\r\n\r\n接下来在一系列的讨论中又诞生一种新的模式——**函数指针法**\r\n\r\n> if(b[i]) {//这里放函数指针。} (ten geek语) \r\n> 告诉你们一个方法 在分支执行的那个里面调用一个函数 然后修改函数的返回地址 使之走到另外的分支 在分支里进 入函数调用的时候。。会把函数的返回地址压入栈中。。你只要 找到那块内存并修改 让这个值变成另一个分支的入口地址。。就可以实现(小花语)\r\n\r\n看到这些后:\r\n“流氓啊”——小蓝\r\n“还有更流氓的 自己实现个编译器 处理所有分支233333”——小花\r\n\r\n小蓝最后表示他也想到了一种方法,但是否定了....**fork()法**。 \r\n应该是\r\n\r\n if(pid==主进程pid)\r\n {\r\n printf(\"ture\");\r\n }\r\n else\r\n {\r\n printf(\"flase\");\r\n }\r\n终于轮到小花姐了“fork已经有不同的上下文了 怎么算同一分支”\r\n\r\n**原因**都是总之无论如何\r\n**也是两个都执行,但是只能算是执行了逻辑,而不是分支**\r\n\r\n\r\n\r\n\r\n------------------------------------漂亮的手工分割线------------------------------------\r\n\r\n结果\r\n==\r\n\r\n最后总结性对话\r\n\r\n - 小花:**“如果不用语言特性的话 正规讲 互斥的两个分支 本来就不应该能够全部执行 不然还互斥个ball 就是因为有些语言对内存有较高的控制权限 才能恶意修改正确流程 某种意义讲 是非法手段好吧 而且从应用场景上来说 没哪个逗比会把都想执行的语句放在互斥的语句里”**\r\n - 小蓝:“难道那些辩论的题目不都是逗比的么 我反正觉得是”\r\n - 吴会:“那些为了辩论而辩论的辩题本身就挺逗的”\r\n - 苏苏:“总觉得辩论队被黑了喵”\r\n\r\n\r\n然后:\r\n愉快的结束........\r\n\r\n\r\n\r\n [1]: http://log.fyscu.com/index.php/archives/99/\r\n [2]: http://log.fyscu.com/usr/uploads/2014/09/3658205544.png\r\n [3]: http://log.fyscu.com/usr/uploads/2014/09/2707660166.jpg\r\n [4]: http://log.fyscu.com/usr/uploads/2014/09/2274293924.jpg\r\n [5]: http://log.fyscu.com/usr/uploads/2014/09/1993727533.jpg\r\n [6]: http://log.fyscu.com/usr/uploads/2014/09/206781972.jpg\r\n [7]: http://log.fyscu.com/usr/uploads/2014/09/3997181510.jpg\r\n [8]: http://log.fyscu.com/usr/uploads/2014/09/1719941127.png\r\n [9]: http://log.fyscu.com/usr/uploads/2014/09/913217794.jpg\r\n [10]: http://log.fyscu.com/usr/uploads/2014/09/4050117077.jpg',0,9,NULL,'post','publish',NULL,0,'1','1','1',0),(99,'【论道】有没有可能一个条件结构的两个分支都被执行?','99',1411354080,1414137982,'<!--markdown-->正方:不可能,不是true,就是false\r\n\r\n反方:可能,不信我分分钟试一下',0,1,NULL,'post','publish',NULL,0,'1','1','1',0),(100,'QQ图片20140922124426.png','QQ图片20140922124426-png',1411405070,1411405070,'a:5:{s:4:\"name\";s:26:\"QQ图片20140922124426.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3416337755.png\";s:4:\"size\";i:14408;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,5,NULL,'attachment','publish',NULL,0,'1','0','1',102),(101,'QQ图片20140922145708.png','QQ图片20140922145708-png',1411405353,1411405353,'a:5:{s:4:\"name\";s:26:\"QQ图片20140922145708.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3602657190.png\";s:4:\"size\";i:14070;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,5,NULL,'attachment','publish',NULL,0,'1','0','1',102),(102,'wamp安装过程中httpd.exe-Application error ,错误代码0xc000007b','102',1411405740,1411405988,'<!--markdown-->问题:wamp安装完成之后,由红变黄,但不变绿。\r\n\r\n**在安装过程中出现过如下错误**\r\nwamp安装过程中,先是出现http.exe-System error的错误:The program can\'t start because MSVCR100.dll is missing from your computer.Try reinstalling the program to fix this problem.\r\n![QQ图片20140922124426.png][1]\r\n忽略此错误继续安装完成后,出现httpd.exe-Application error的错误:The appliction was unable to start correctlu(0xc000007b).Click OK to close the application.\r\n![QQ图片20140922145708.png][2]\r\n\r\n这个时候打开wamp,发现图标由红变黄,但不变绿。\r\n正如安装过程中出现的错误提示,可能是 MSVCR100.dll惹的祸,也可能是MSVCRTD.dll等文件缺失造成的。\r\n说到底还是系统的问题,不是软件的问题。建议用新毒霸或360等安全软件进行修复。这样就省得去网上找文件下载,有时候下载的文件还不一定有用。\r\n我是用新毒霸的电脑医生修复的。如下图\r\n![QQ图片20140923011209.jpg][3]\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/09/3416337755.png\r\n [2]: http://log.fyscu.com/usr/uploads/2014/09/3602657190.png\r\n [3]: http://log.fyscu.com/usr/uploads/2014/09/401503873.jpg',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(98,'2.png','2-png-1',1411231541,1411231541,'a:5:{s:4:\"name\";s:5:\"2.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3297010664.png\";s:4:\"size\";i:25451;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,4,NULL,'attachment','publish',NULL,0,'1','0','1',97),(96,'SIMS开发者文档','96',1411148940,1411220841,'<!--markdown-->Server information monitoring system(**SIMS**)开发者文档 1.0\r\nSIMS是一个基于C语言编写的小型的服务器信息监控系统,监控诸如用户存储空间大小,数据库文件大小等等有关于服务器信息,便于管理员对服务器进行管理。\r\n初步的架构是将每一个功能进行单独编写,然后编译成动态链接库。然后通过一个主程序每隔一段时间来调用相关的动态链接库,来执行某一功能。\r\n为了能让主程序正常调用到每一个动态链接库,请遵循下列要求:\r\n动态链接库必须有一个入口函数,同时编译出来的动态链接库名字应当同入口函数保持一致。这是因为主程序是采用显式方式调用动态链接库,会根据动态链接库来寻找函数的入口。\r\n例如:\r\n\r\n #include<stdio.h>\r\n #include<string.h>\r\n #include<stdlib.h>\r\n #include<errno.h>\r\n #include <time.h> \r\n #include <mysql/mysql.h>\r\n\r\n static int Getdata(){……}\r\n static void Process(){……}\r\n static int Update(){……}\r\n\r\n int HDStorage_check()\r\n {\r\n int flag;\r\n flag=Getdata();\r\n if (flag == -1)\r\n {\r\n return -1;\r\n }\r\n Process();\r\n flag=Update();\r\n if (flag == -1)\r\n {\r\n return -1;\r\n }\r\n int j;\r\n for (j = 0; j < count; j++)\r\n {\r\n free(storage[j]);\r\n free(name[j]);\r\n } \r\n memset(user, 0, sizeof(user));\r\n return 0;\r\n }\r\n这是SIMS监控用户存储空间大小的一段代码它的入口函数是HDStorage\\_check(),所以它编译出来的动态链接库应该是HDStorage_check.so\r\n\r\n在编译出动态链接库后的操作是相当简单的,首先先介绍一下主程序的配置文件\r\n\r\n /home/Iamw/SIMS/lib/ //动态链接库文件存放目录\r\n HDStorage_check 1440 //动态库名(入口函数名) 运行间隔时间\r\n MysqlStorage_check 1440 //动态库名(入口函数名) 运行间隔时间\r\n end //结束标志\r\n\r\n只需要将写好的动态链接库放入目录之下,并且将动态库吗和运行间隔时间安装格式添加至配置文件即可。\r\n',0,9,NULL,'post','publish',NULL,0,'1','1','1',0),(97,'飞扬俱乐部研发部会议纪要|9月21日','97',1411231260,1411233576,'<!--markdown-->标题写的还正式吧?\r\n\r\n写这个好烦啊。都谁出的主意要写这个!\r\n\r\n特此规定:\r\n\r\n> 以后历任部长不负责写会议记录,爱特么怎么办怎么办! \r\n\r\n\r\n\r\n9月21日。阴。\r\n\r\n这已经是研发这个学期第三次正式例会了。前面非正式的碰头进行了快20次吧。\r\n\r\n如果没有homo,很难想象这一个几乎没有女生的部门是如何做到这一点的。\r\n\r\n今天过来的除了各种大三老学姐hwj,cq,ly,和大三帅气学长dsgygb,jyb,以及lh,bq,jh,wlc,cn,zb,竟然还有想进宇宙最好部门的研发的12/13/14小学弟以及一个小学妹与一个大三学姐。这恐怕就是我们不想招新的原因了吧。\r\n\r\n唉。\r\n\r\n会议伊始,众人坐毕,jh做了主题为“情怀”的演讲。但是我听完都不知道讲的和情怀有j8关系。基本只是讲了绩点这个应用的一个重构的思想,且版本号直接由1.0->3.0,大概思想如下图:\r\n![2.png][1]\r\n\r\n期间稍微提到了angularjs。但是画了个大饼给我们。说是下回分解。嗯,那就下回再听你讲“情怀(下)”吧。\r\n\r\n少倾,bq上场,首先,再次谴责使用我的ppt模板之前未向我做任何授权说明,以及支付宝5元买ppt模板的协议。\r\n\r\n讲了个ACL的概念。\r\n\r\n> ACL就是Access Control List(访问控制列表)\r\n作用:\r\n> ACL可以限制网络流量、提高网络性能。 ACL提供对通信流量的控制手段。 ACL是提供网络安全访问的基本手段\r\n> ACL可以在路由器端口处决定哪种类型的通信流量被转发或被阻塞。\r\n\r\n大概整个演讲的意思都是围绕以上两点在展开。最后没有得出一个结论。差评。 \r\n\r\n这之后,江航分享了他对MVC的看法,dsgygb提出了了尖锐的意见,小蓝掷地有声的反驳了dsgygb。双方达成重要共识 。\r\n\r\n附:正确的MVC姿势:\r\nM:\r\n> 模型层表示你的应用程序,它实现了业务逻辑的一部分。它负责为你的应用获取数据并将其转换成有意义的概念。这包括处理,验证,关联等任务。\r\n> 乍一看,模型对象可以被看作是相互作用的一层与任何数据库。但总的来说,他们代表围绕并实现应用程序的主要概念。\r\n> 在社交网络中的情况下,模型层将被用来诸如保存用户数据,保存朋友的关联,存储和检索用户的照片,寻找新的朋友建议等的模型中的对象这种行为\r\n\r\nV:\r\n\r\n> 该视图呈现一个演示模型数据。从模型对象分开,负责使用它提供的信息产生的任何表象界面的应用程序可能需要。\r\n> \r\n> 例如,模型层返回一组数据,视图会使用它来渲染HTML页面\r\n> \r\n> 视图层不仅局限于数据的HTML或文本表示。它可以被用于运载各种根据你的需求,如视频,音乐,文档,你能想到的任何其他格式的格式。\r\n\r\nC:\r\n\r\n> 控制器层处理来自用户的请求。它负责渲染与双方的模型和视图层的响应。\r\n> \r\n> 控制器可以被看作是一个管理者,确保需要完成任务的所有资源都被委托给正确的人员。它等待来自客户端的请求,根据认证或授权规则检查其有效性,代表数据读取或处理的模型,选择表象数据的客户端接受,并最终代表的渲染过程,视图层的类型。\r\n\r\nok,小白部分结束。\r\n\r\n好烦啊你们,例会搞这么多主题。\r\n\r\n大会第三项:吴会发布一项重要阶段性研究成果“Server information monitoring system(SIMS )”,翻译过来就是:“服务器信息监控系统”。\r\n\r\n通俗的来讲就是:把服务器的一些情况 定时的 写在数据库里。\r\n\r\nbalabala讲了半天,说开发完成后会将开放文档发布在:open.fyscu.com 。还是 蛮期待的。虽然吴会不会写php。也开发不出来接口,但是我就是想看他笑话。嗯。他的开发文档最后一定只是个数据库表。哈哈哈哈哈哈好开心啊。\r\n\r\n接下来的这个是例会最激动人心的时刻:\r\n\r\n**蒋言斌带着他的小姨子跑了。**\r\n\r\n\r\n----------\r\n\r\n\r\n蒋言斌带来了一个big news。分享了big data的idea。\r\n\r\n可以在这说吗?\r\n\r\n说了还灵吗?\r\n\r\n总之这个项目做出来后要是不火遍全川大,我挖地三尺。\r\n\r\n项目是什么就不说了。想知道的 来参加例会啊。\r\n\r\n再这之后,大会的主要内容已经结束。\r\n\r\n吴会向新来的boys girls 做了精彩的QA,部长为新来的boys girls 传授了他丰富的人生经验。\r\n\r\n\r\n\r\n最后,推荐下杨胖子旁边的“天天饭店”,看起来很杀马特的饭店,但是饭好吃 又便宜。嗯,研发已经在那吃过5次了吧?\r\n\r\n妈蛋。这么多内容。我已经尽量没说废话了。\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/09/3297010664.png',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(94,'IE 运行框架页中的 JS,报错“SCRIPT5011: 不能执行已释放 Script 的代码”','94',1410925620,1411112807,'<!--markdown-->Bug 如题,搜索良久,参考如下 ——\r\n\r\n 1. http://www.oschina.net/question/724763_122803?sort=time\r\n 2. http://www.web-tinker.com/subject/495-1.html\r\n 3. http://bbs.csdn.net/topics/350088265\r\n 4. http://blog.csdn.net/ocean20/article/details/7294298\r\n 5. http://www.youzitool.com/index/detail/id/28.html\r\n 6. http://fengfan.blog.163.com/blog/static/134786220124472115285/\r\n 7. http://blog.sina.com.cn/s/blog_6ac4c6cb0101is29.html\r\n 8. http://winnie825.iteye.com/blog/1843926\r\n 9. http://chenys.pixnet.net/blog/post/29993042-%5Bjs%5D%5Bie%5D-%E7%84%A1%E6%B3%95%E5%9F%B7%E8%A1%8C%E5%B7%B2%E8%A2%AB%E9%87%8B%E6%94%BE%E7%9A%84-script-%E4%BB%A3%E7%A2%BC\r\n 10. http://blog.csdn.net/feng_sundy/article/details/2733172\r\n 11. http://www.cnblogs.com/zhouwenhong/p/3829710.html\r\n 12. http://msdn.microsoft.com/zh-cn/library/ie/gg622929(v=vs.85).aspx\r\n\r\n看完之后 总体思路 都清楚了,但**尝试各种写法,其它浏览器内核各种正常,IE 却 Bug 依旧……**\r\n\r\n鄙人愚钝…… @蓝神 能点拨我一下吗?\r\n\r\n----------\r\n\r\n我的使用情景是“**让父页面的 JavaScript 的主要命名空间(如 jQuery)能继承到框架中的子页面**”,也就是子页面无需再加载同样的 JS 文件(无需再新开辟同样大小的一块内存),可以参考[这个示例][1]。但现在只能对 IE 全系列用“笨办法”处理 ——\r\n\r\n var IE_Ver = UA.match(/MSIE (\\d)\\.\\d/i);\r\n IE_Ver = IE_Ver ? Number(IE_Ver[1]) : 0;\r\n \r\n function $TN(HTML_Elements, TagName) {\r\n return HTML_Elements.getElementsByTagName(TagName);\r\n }\r\n function PagePath_IE(_BOM) {\r\n var _PP = _BOM.document.URL;\r\n _PP = _PP.split(\'/\');\r\n if (_PP.length > 3) _PP.pop();\r\n _PP.push(\'\');\r\n return _PP.join(\'/\');\r\n }\r\n \r\n try {\r\n var _DOM = parent.document;\r\n var _SE = $TN($TN(_DOM, \'head\')[0], \'script\');\r\n \r\n for (var i = 2, JS_URL; i < _SE.length; i++) {\r\n JS_URL = _SE[i].src;\r\n if (IE_Ver < 8)\r\n JS_URL = PagePath_IE(parent) + JS_URL;\r\n ImportJS(JS_URL); // 自定义的 <script /> 元素创建函数\r\n }\r\n } catch (Err) {}\r\n\r\n\r\n [1]: http://log.fyscu.com/index.php/archives/81/',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(95,'PHP对于变量的“存在”判断小测',NULL,1411116360,1411116409,'<!--markdown--><div id=\"JIATHIS_CODE_HTML2\">\r\n<div class=\"t_fsz\">\r\n<table cellspacing=\"0\" cellpadding=\"0\"><tr><td class=\"t_f\" id=\"postmessage_62117\">\r\n参测项目:直接if判断,empty判断,isset判断<br>\r\n具体介绍不表,直接看实验记录<br><br>\r\n1.不设置变量的情形下:<br><ignore_js_op><img style=\"cursor:pointer\" id=\"aimg_6081\" aid=\"6081\" onclick=\"zoom(this, this.getAttribute(\'zoomfile\'), 0, 0, \'0\')\" src=\"http://bbs.fyscu.com/data/attachment/forum/201404/08/094922qicyy655rjjg2z0b.jpg\" file=\"data/attachment/forum/201404/08/094922qicyy655rjjg2z0b.jpg.thumb.jpg\" inpost=\"1\" alt=\"1.jpg\" title=\"1.jpg\" onmouseover=\"showMenu({\'ctrlid\':this.id,\'pos\':\'12\'})\"><div class=\"tip tip_4 aimg_tip\" id=\"aimg_6081_menu\" style=\"position: absolute; display: none\" disautofocus=\"true\">\r\n<div class=\"tip_c xs0\">\r\n<div class=\"y\">2014-4-8 09:49 上传</div>\r\n<a href=\"http://bbs.fyscu.com/forum.php?mod=attachment&aid=NjA4MXxlODRjN2Y0YnwxNDExMTE2Mzc4fDB8NTAyMg%3D%3D&nothumb=yes\" title=\"1.jpg 下载次数:0\" target=\"_blank\"><strong>下载附件</strong> <span class=\"xs0\">(37.44 KB)</span></a>\r\n\r\n</div>\r\n<div class=\"tip_horn\"></div>\r\n</div>\r\n\r\n</ignore_js_op><br>\r\n结论:三个都能确定变量不存在,但要注意,除了isset其他两个都可能引起 php notice。<br><br>\r\n2.变量为空<br><ignore_js_op><img style=\"cursor:pointer\" id=\"aimg_6082\" aid=\"6082\" onclick=\"zoom(this, this.getAttribute(\'zoomfile\'), 0, 0, \'0\')\" src=\"http://bbs.fyscu.com/data/attachment/forum/201404/08/095052f58deee5203m0ed5.jpg\" file=\"data/attachment/forum/201404/08/095052f58deee5203m0ed5.jpg.thumb.jpg\" inpost=\"1\" alt=\"2.jpg\" title=\"2.jpg\" onmouseover=\"showMenu({\'ctrlid\':this.id,\'pos\':\'12\'})\"><div class=\"tip tip_4 aimg_tip\" id=\"aimg_6082_menu\" style=\"position: absolute; display: none\" disautofocus=\"true\">\r\n<div class=\"tip_c xs0\">\r\n<div class=\"y\">2014-4-8 09:50 上传</div>\r\n<a href=\"http://bbs.fyscu.com/forum.php?mod=attachment&aid=NjA4MnwzYmUxZDNmOXwxNDExMTE2Mzc4fDB8NTAyMg%3D%3D&nothumb=yes\" title=\"2.jpg 下载次数:0\" target=\"_blank\"><strong>下载附件</strong> <span class=\"xs0\">(39.1 KB)</span></a>\r\n\r\n</div>\r\n<div class=\"tip_horn\"></div>\r\n</div>\r\n\r\n</ignore_js_op><br>\r\n结论:isset能接受空白,isset 的意思就是“是否设置”,而不考虑变量的值。<br><br>\r\n3.变量值为0<br><ignore_js_op><img style=\"cursor:pointer\" id=\"aimg_6083\" aid=\"6083\" onclick=\"zoom(this, this.getAttribute(\'zoomfile\'), 0, 0, \'0\')\" src=\"http://bbs.fyscu.com/data/attachment/forum/201404/08/095307ly3s273s7ss4s4um.jpg\" file=\"data/attachment/forum/201404/08/095307ly3s273s7ss4s4um.jpg.thumb.jpg\" inpost=\"1\" alt=\"3.jpg\" title=\"3.jpg\" onmouseover=\"showMenu({\'ctrlid\':this.id,\'pos\':\'12\'})\"><div class=\"tip tip_4 aimg_tip\" id=\"aimg_6083_menu\" style=\"position: absolute; display: none\" disautofocus=\"true\">\r\n<div class=\"tip_c xs0\">\r\n<div class=\"y\">2014-4-8 09:53 上传</div>\r\n<a href=\"http://bbs.fyscu.com/forum.php?mod=attachment&aid=NjA4M3xiN2I3MDUwZnwxNDExMTE2Mzc4fDB8NTAyMg%3D%3D&nothumb=yes\" title=\"3.jpg 下载次数:0\" target=\"_blank\"><strong>下载附件</strong> <span class=\"xs0\">(39.43 KB)</span></a>\r\n\r\n</div>\r\n<div class=\"tip_horn\"></div>\r\n</div>\r\n\r\n</ignore_js_op><br>\r\n和上面的情况差不多,起码说明直接 if 是看变量的值,而不是“是否存在”<br><br>\r\n4.变量为正常字符串<br><ignore_js_op><img style=\"cursor:pointer\" id=\"aimg_6084\" aid=\"6084\" onclick=\"zoom(this, this.getAttribute(\'zoomfile\'), 0, 0, \'0\')\" src=\"http://bbs.fyscu.com/data/attachment/forum/201404/08/095436o55sa1fjtq6a1tta.jpg\" file=\"data/attachment/forum/201404/08/095436o55sa1fjtq6a1tta.jpg.thumb.jpg\" inpost=\"1\" alt=\"4.jpg\" title=\"4.jpg\" onmouseover=\"showMenu({\'ctrlid\':this.id,\'pos\':\'12\'})\"><div class=\"tip tip_4 aimg_tip\" id=\"aimg_6084_menu\" style=\"position: absolute; display: none\" disautofocus=\"true\">\r\n<div class=\"tip_c xs0\">\r\n<div class=\"y\">2014-4-8 09:54 上传</div>\r\n<a href=\"http://bbs.fyscu.com/forum.php?mod=attachment&aid=NjA4NHwzZDRiYzI5OHwxNDExMTE2Mzc4fDB8NTAyMg%3D%3D&nothumb=yes\" title=\"4.jpg 下载次数:0\" target=\"_blank\"><strong>下载附件</strong> <span class=\"xs0\">(39.33 KB)</span></a>\r\n\r\n</div>\r\n<div class=\"tip_horn\"></div>\r\n</div>\r\n\r\n</ignore_js_op><br>\r\n都能返回true,isset就不说了,只要变量存在了都是true。直接 if 的话,对于字符串也是true 。<br>\r\n非空 !empty 就怪异了,!empty的表现全程跟随直接 if ,两者有什么区别?<br>\r\n主要就是用法上的却别,if能接受表达式,而empty只能接受变量,<br>\r\n就是说,empty(true) 这样的,是不行的,会触发一个错误。<br>\r\n</td></tr></table>\r\n</div>\r\n<div id=\"comment_62117\" class=\"cm\">\r\n</div>\r\n</div>',0,1,NULL,'post','publish',NULL,0,'1','1','1',0),(86,'QQ截图20140913010619.png','QQ截图20140913010619-png',1410541523,1410541523,'a:5:{s:4:\"name\";s:26:\"QQ截图20140913010619.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2920015810.png\";s:4:\"size\";i:314192;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',4,15,NULL,'attachment','publish',NULL,0,'1','0','1',82),(87,'QQ截图20140913010713.png','QQ截图20140913010713-png',1410541576,1410541576,'a:5:{s:4:\"name\";s:26:\"QQ截图20140913010713.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2201245878.png\";s:4:\"size\";i:320395;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',3,15,NULL,'attachment','publish',NULL,0,'1','0','1',82),(88,'QQ截图20140913010811.png','QQ截图20140913010811-png',1410541632,1410541632,'a:5:{s:4:\"name\";s:26:\"QQ截图20140913010811.png\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/721194596.png\";s:4:\"size\";i:259354;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',2,15,NULL,'attachment','publish',NULL,0,'1','0','1',82),(89,'QQ截图20140913011124.png','QQ截图20140913011124-png',1410541828,1410541828,'a:5:{s:4:\"name\";s:26:\"QQ截图20140913011124.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3624895145.png\";s:4:\"size\";i:299746;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,15,NULL,'attachment','publish',NULL,0,'1','0','1',82),(90,'【JS】为什么输出444','90',1410544560,1415952121,'<!--markdown-->##首先感谢大佳提出这个很典(dou)型(bi)的问题,对已理解异步是很有帮助的,首先看题。\r\n\r\n for(var a=1;a<=3;a++){\r\n setTimeout(function(){\r\n console.log(a);\r\n },0);\r\n }\r\n\r\n\r\n大佳一定迫不及待了,我们先看一下`setTimeout` 。\r\n\r\n setTimeout(code,millisec)\r\n\r\n`code` 要执行的代码,可以用高阶函数传入。\r\n`millisec` 毫秒数,就是多少时间以后 执行code\r\n\r\n###这个操作会发起一个异步,意在`millisec` 毫秒后执行`code`。\r\nOK,你听我说完,\r\n好像没什么问题,1,2,3, 输出很明确是不是?\r\n#大佳你错了!\r\n\r\n这个连DSG都懂了,答案是 333,哦不,444 。\r\n\r\n\r\n----------\r\n割割割割割割割割割割割割割割割割割割割割割割割割\r\n\r\n\r\n----------\r\n#接下来就是见证JJ的时刻了。\r\n先说一下JS执行任务的模式,JS是单线程的,每次只能有一个任务执行,\r\n就好比一个队列,如图:\r\n` ----【任务4】【任务3】【任务2】【任务1】---> `\r\n任何新的任务,都会进到队伍末尾,一个个等待执行,\r\n当然就包括`时机成熟的异步回调`。\r\n\r\n而在你发起循环的时候,每一个循环已经进到队列了,于是呼,实际情况是这样的:\r\n` ----【a++然后发起异步】【a++然后发起异步】【a++然后发起异步】---> `\r\n然后呢,异步会等到它的时间(`millisec`),进入队列,于是乎:\r\n` ----【log】【log】【log】【a++然后发起异步】【a++然后发起异步】【a++然后发起异步】---> `\r\n\r\n#答案已经很明显!\r\n\r\n至于你问,这个延时是0啊,我只能告诉你,那不是真正的`0`,下一个循环进入队列的间隔,也是很短,至于为什么 下一个循环能更快进入队列,我们下一节再讲。\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(92,'position.png','position-png',1410750361,1410750361,'a:5:{s:4:\"name\";s:12:\"position.png\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/862556436.png\";s:4:\"size\";i:3092;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',1,2,NULL,'attachment','publish',NULL,0,'1','0','1',93),(93,'大家最好安安静静地做一个程序员,不要胡搞毛搞','93',1410754140,1410754272,'<!--markdown-->####前言:DO NOT SAY JH/JUANJUAN\r\n研发2.0经过上一学期的一波大跃进之后,\r\n尽管取得了相当好的效果,\r\n但是到了新学期,展现出一种遇到瓶颈的迷失期。\r\n\r\n所以呢,有必要提个醒,借用水哥一句话:\r\n> 安安静静做人,踏踏实实做事。\r\n\r\n####1.FIND OUT YOUR POSITION\r\n清楚自己在哪个阶段。既然大家都很迷失,我用一张美图来说明一下:\r\n![001](http://log.fyscu.com/usr/uploads/2014/09/862556436.png)\r\n\r\n我随机抽出5个案例来说明:\r\n1. 像小白和JH这个阶段,感觉坡很陡很难,是因为没有走过门槛阶段,觉得处处受限发挥不佳。这个时期需要坚持下去,不耻求问水哥,争取早日走到下一阶段。这个阶段的程序员最需要我们的关心,大家不要觉得烦就不理他们,多一点爱,多一点包容。\r\n2.像大佳、吴会这个阶段的,跨过了一个坡,进入平台期,感觉上是什么都会做,有时又好像什么都做不了。这个阶段需要认准某个方向或产品,比如妹子UI、socket等,深入学习,从中加固基础知识,最终实现融会贯通的理想境界。\r\n3.像DSG大神这样的,已经进入了第二个瓶颈期,这个阶段的特点就是,想到的都能做到,但是作为程序员,要做好,才能成为工程师。这个阶段需要静下心来了解技术原理,知其然知其所以然,穷技术之极致,最后忽然天成,无招胜有招,一花一叶皆为代码。\r\n\r\n ## (正文已结束,后面都是题外话)\r\n\r\n####2.WHY NODE\r\n很多人问我,node有什么好,为什么要用node。主要是两方面:\r\n- 其一,node的事件驱动和异步IO,与其说这是node 的优势,还不如说是我看到的亮点,之所以用node,正正就是我弄php上这样的缺失,可以说是node弥补了我用php的空洞,这叫对症下药,而不在于网络上吹嘘得有多夸张。\r\n- 其二,就是缘分,能做到事件驱动和异步IO的平台很多,node只是其中一种。而在我需要弥补空洞的时候它的出现,就顺理成章成为我的选择。有时就是这样,能陪你走下去的,不一定是最好的那个,而是在你最需要的时候出现的对的那个。\r\n\r\n#### 3.加油同仁,闻道有先后,逼格有专攻\r\n在这个团队,给你最多的不是技术支持,而是精神支持,更多的是需要你自己学习,比如我根本无法给你指导C语言,你要跟百(goo)度(gle)学习。\r\n三人行,必有一个逼格高,最好的学习是相互学习,大家都是朋友嘛。\r\n\r\n#### 4.还是要SAY SAY JH\r\n好像大家都知道了,JH做GPA用了3个月,做bill用了两天。与其说是因为做GPA取得的进步,我更愿意相信是因为juanjuan给的动力,你愿意相信哪一个呢?\r\n所以,只要有足够的动(dong)力(ji),就能爆发很大的能量,实现自己的梦(ye)想(wang)。\r\n\r\n\r\n\r\n',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(82,'2014/9/12飞扬研发会议记录','82',1410540120,1410541955,'<!--markdown-->**会议记录**\r\n时间:2014年9月12日 地点:一教c某教室\r\n会议内容:\r\n1.田值学长为大家带来奶茶,大家一起喝奶茶、等小蓝。\r\n2.国宝君普及json的知识、等小蓝。\r\n3.部长接着普及msg的知识、等小蓝。\r\n4.小蓝终于来啦~\\(≧▽≦)/~啦啦啦\r\n**会议正式开始:**\r\nPart 1:\r\n江航为大家展示高大上的英文PPT(众人纷纷表示个别单词看不懂)\r\nPPT内容:say say jiang(juan) hang(juan)\r\nA.一个来自偶然的实习经验\r\nB.本来高大上的PPT突然出现很黄的页面,众人纷纷表示接受不了。\r\n![1.jpg][1]\r\nC.做了三十天的网页没有上线的悲惨经历。\r\nD.实习的收获(学会三国杀等)\r\nE.自己对这件事的看法:1)Front-End\r\n 2)Teamwork\r\n 3)Digest(就是这个词,记录人员不得不用有道词典)\r\n 4)Details\r\n 5)Interest\r\nF.最后再次表示,只想安安静静写代码。\r\n![QQ截图20140913010431.png][2]\r\nPart 2:\r\n吴会展示一堆用来检测服务器使用情况的代码(记录人员表示没看懂,代码内容在这不做赘述。)\r\n![QQ截图20140913010619.png][3]\r\n看着那么那么多行的代码,记录人员表示很混乱,国宝君表示两个公式可以搞定,小蓝直接上去补充讲解。\r\nPart 3:\r\n 国宝君带着大家温习json,内容吧啦吧啦,记录人员表示只明白了所有程序都可以用json愉快地调用data(国宝君强调了data的发音)\r\n![QQ截图20140913011124.png][4]\r\nPart 4:\r\n 小蓝介绍了Angular框架——关于前端的MVC(Model View Controller)框架,国宝君表示自己已经深入浅出了,江航表示已经混乱,众人表情复杂\r\nPart 5:\r\n 江航讲解绩点计算器的整个运行原理及过程\r\n![QQ截图20140913010713.png][5]\r\n小蓝上来补充并给其起名为绩点计算器2.0\r\n国宝君郑重宣布今后还会有3.0 4.0 ......100.0 众人表情复杂\r\nPart 6:\r\n 众人自由讨论,大家纷纷向田值学长请教,由于人太多,记录人员挤不过去,不造他们在请教什么,所以,请教内容不明。\r\n![QQ截图20140913010811.png][6]\r\n 倩姐不造在笑虾米。。。\r\n 突然插播大佳提的一个JS的问题,大家展开激烈讨论,最后田值学长对答案做出解释,记录人员表示没听懂。\r\nPart 7:\r\n 会议重点\r\n 吃烧烤。由于记录人员不在场,活动现场情况自行想象。\r\n\r\n\r\n会议就这么华丽丽地结束了,了,了......\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/09/3588868949.jpg\r\n [2]: http://log.fyscu.com/usr/uploads/2014/09/3210027497.png\r\n [3]: http://log.fyscu.com/usr/uploads/2014/09/2920015810.png\r\n [4]: http://log.fyscu.com/usr/uploads/2014/09/3624895145.png\r\n [5]: http://log.fyscu.com/usr/uploads/2014/09/2201245878.png\r\n [6]: http://log.fyscu.com/usr/uploads/2014/09/721194596.png',0,15,NULL,'post','publish',NULL,0,'1','1','1',0),(84,'1.jpg','1-jpg',1410541186,1410541186,'a:5:{s:4:\"name\";s:5:\"1.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3588868949.jpg\";s:4:\"size\";i:24194;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:9:\"image/png\";}',6,15,NULL,'attachment','publish',NULL,0,'1','0','1',82),(85,'QQ截图20140913010431.png','QQ截图20140913010431-png',1410541413,1410541413,'a:5:{s:4:\"name\";s:26:\"QQ截图20140913010431.png\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3210027497.png\";s:4:\"size\";i:36533;s:4:\"type\";s:3:\"png\";s:4:\"mime\";s:9:\"image/png\";}',5,15,NULL,'attachment','publish',NULL,0,'1','0','1',82),(81,'【奇技淫巧】jQuery 的选择器上下文','81',1410493980,1411723737,'<!--markdown-->用过 **jQuery** 的都知道 —— jQuery() 很强大,啥都能往里塞!\r\n\r\n 1. 塞 **HTML 代码** —— 创建 HTML 元素\r\n 2. 塞 **CSS 选择符** —— 检索 HTML 元素\r\n 3. 塞 **XPath 表达式** —— 检索 XML 元素\r\n 4. 塞 **DOM 对象** —— 包装 HTML 元素,使用 jQuery 的强大 API(对象方法)\r\n 5. 塞 **JS 函数** —— 相当于当在 DOM Ready 之后执行主业务逻辑代码\r\n\r\n但还有些细节需要注意,比如 **jQuery 选择器的上下文**问题。\r\n\r\n----------\r\n\r\njQuery 老手想必都知道,**jQuery() 的第二个参数**可以设置 选择器执行筛选的上下文,也就是**指定元素搜索只能在哪个(些)元素的子元素树形结构范围内**。比如 ——\r\n\r\n 1. `$(\'script\', document.body)` 相当于 `$(\'body\').find(\'script\')`\r\n 2. `$(\'table\',\r\n document.getElementsByTagName(\'iframe\')[0])` 相当于 `$(\'iframe\').eq(0).contents().find(\'table\')`\r\n\r\n改变了 jQuery 选择器的上下文之后,这个 jQuery 对象接下来的操作都以这个上下文为参考系,非常方便~\r\n\r\n但这里有个例外 —— **若一个 jQuery 对象由 DOM 对象包装而来,那它的上下文会被强制指向 DOM 元素本身,jQuery() 的第二个参数不能改变上下文……**\r\n\r\n大家可以用以下代码验证 ——\r\n\r\n console.log( $(\'body\') );\r\n // 显示的 jQuery 对象的 context 属性指向 document\r\n \r\n console.log( $(document.body, document) );\r\n // 显示的 jQuery 对象的 context 属性指向 document.body\r\n\r\n这有何影响?一个典型的实例就是 —— **HTML 子框架页(比如 `<iframe />`)直接使用父框架加载的 jQuery 及其插件**。\r\n\r\n----------\r\n\r\n因为不同框架页和其父页面一样,都是一个完整的网页,所以它们的 CSS、JS 之间默认是相互独立的(除了 BOM、DOM 树之间有相互引用)。程序猿一般都分别加载它们所引用的脚本,无论它们是否有相同的脚本。虽然浏览器都有缓存,不会重复从服务器下载相同的文件,但对本机性能而言,重复加载还是有影响。\r\n\r\n对 CSS 而言,它的属性最终要应用到具体的 DOM 元素上,不会单独占用内存,重复加载对本机无负面影响;但若**重复加载 JS,同样的对象(各种 JS 库所创建的自身实例)会在每个父/子页面的 Window 对象下创建,造成了内存的浪费**……\r\n\r\n综上,因为 **JS 等动态语言的赋值 默认是“引用”(传指针/地址)而非复制**,我们就可以借助框架之间的 BOM、DOM 之间的引用,使父页面加载的 JS 库工作在不同的子页面中。例如 ——\r\n\r\n self.jQuery = parent.jQuery;\r\n\r\n----------\r\n\r\n当我们使用类似 `$(self.document).find(\'selector\').doSomething()` 的代码时,程序运行正常,所以大家自然会想用更简洁的写法 `$(\'selector\').doSomething()`,但它不会在子页面里查找任何 DOM 元素,只会返回父页面的执行结果…… 因为**父页面的 jQuery 上下文默认是父页面中的 document 对象**~\r\n\r\n所以,我们必须**在子页面对父页面的 jQuery 做一层封装** ——\r\n\r\n self.$ = function () {\r\n return self.jQuery(\r\n arguments[0],\r\n (arguments.length > 1) ? arguments[1] : self.document\r\n );\r\n };\r\n\r\n\r\n----------\r\n\r\n但其实这样的封装有时无法改变 jQuery 对象 API 的上下文,比如在一个 `<iframe />` 中 ——\r\n\r\n $(\'<span class=\"Float_Button\"></span>\').appendTo(\'body\');\r\n\r\n你会发现,新建的元素被追加到了父页面的最后……\r\n\r\n不怕,解决方法也得益于 **jQuery 对象 API(公用方法)的优越性 —— CSS 选择符、DOM 对象、jQuery 对象 都能往里塞**,我们用自己封装的 jQuery 来强制指定目的地的上下文 ——\r\n\r\n $(\'<span class=\"Float_Button\"></span>\').appendTo( $(\'body\') );\r\n\r\n\r\n----------\r\n\r\n【参考文档】http://ucren.com/blog/archives/137/comment-page-1',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(74,'QQ图片20140912061447.jpg','QQ图片20140912061447-jpg',1410473695,1410473695,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912061447.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2638807152.jpg\";s:4:\"size\";i:907;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',6,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(75,'QQ图片20140912061414.jpg','QQ图片20140912061414-jpg',1410473699,1410473699,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912061414.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/4027527416.jpg\";s:4:\"size\";i:1084;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',5,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(76,'QQ图片20140912061426.jpg','QQ图片20140912061426-jpg',1410473701,1410473701,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912061426.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/604917552.jpg\";s:4:\"size\";i:911;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',4,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(77,'QQ图片20140912061741.jpg','QQ图片20140912061741-jpg',1410474010,1410474010,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912061741.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/1382469906.jpg\";s:4:\"size\";i:94848;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',3,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(78,'QQ图片20140912063835.jpg','QQ图片20140912063835-jpg',1410475129,1410475129,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912063835.jpg\";s:4:\"path\";s:34:\"/usr/uploads/2014/09/631714819.jpg\";s:4:\"size\";i:51778;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',2,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(79,'QQ图片20140912064225.jpg','QQ图片20140912064225-jpg',1410475375,1410475375,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912064225.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3397134743.jpg\";s:4:\"size\";i:39904;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',1,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(80,'windows下WAMP的安装','80',1410476200,1410476200,'<!--markdown-->**W:即Windows;A:即Apache;M:即MySql;P:即PHP.**\r\n\r\nWAMP是一组常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被放在一起使用,拥有了越来越高的兼容度,共同组成了一个强大的Web应用程序平台.\r\n对学习PHP的新手来说,WINDOWS下环境配置是一件很困难的事;对老手来说也是一件烦琐的事.因此无论你是新手还是老手,wamp该程序包都是一个不错的选择.\r\n\r\n**安装(WampServer):**\r\n1.[官网下载WampServer][1]\r\nWampServer是一个常用的WAMP集成环境.即在window下的apache,php和mysql的服务器软件.开启/关闭PHP扩展,Apache模块,鼠标点点就搞定,再也不用亲自去修改配置文件了,WAMP它会去做。再也不用到处询问php的安装问题了,WAMP一切都搞定了.\r\n\r\n2.如下,关键步骤截图说明\r\n[Next>] -> I accept thw agreement ->\r\n接下来是选择WampSerer的安装目录。比如我安装在D:\\wamp.选择好之后点击[Next>]\r\n![QQ图片20140912060129.jpg][2]\r\n再接下来是创建快速启动图标和桌面图标,看个人需要进行选择.\r\n![QQ图片20140912060153.jpg][3]\r\n然后[Next>]->[Install].等待几分钟出现如下画面,就说明初步成功了.\r\n![QQ图片20140912061015.jpg][4]\r\n3.上面才是初步成功,别高兴太早,赶紧启动该一下WampServer吧!\r\n如图,如果右下脚的图标由红变黄再变绿,就说明离成功很近很近啦!\r\n![QQ图片20140912061447.jpg][5]![QQ图片20140912061414.jpg][6]![QQ图片20140912061426.jpg][7]\r\n然后再浏览器地址栏分别输入 localhost 和 127.0.0.1,如果出现如下页面,说明只有一步之遥了!这个WampServer的默认页面,这里说明了WampServer的配置(Apache,PHP,MySql的版本号,以及安装的扩展),小工具(phpmyadmin:一种MySql的管理工具;phpinfo:php服务器的配置信息),和你的项目目录.项目文件的默认目录是 /wamp/www/ . \r\n![QQ图片20140912061741.jpg][8]\r\n接下来再在地址栏输入localhost/phpmyadmin,如果出现如下页面,就说明是真的安装成功了!\r\n上面说到phpmyadmin是一种MySql的管理工具,安装该工具后,可以通过web形式直接管理MySql数据,而不需要通过执行系统命令来管理.\r\nWampServer安装过程中,MySql root用户的密码默认为空.登录名root,密码空,登陆后即可自己修改密码.\r\n![QQ图片20140912063835.jpg][9]\r\n4.简单那说一下WanpServer的一些使用\r\n`单击WampServer图标 -> MySql -> MySql console` 启动MySql控制台.\r\n在MySql的子目录中,MySql log 是MySql的日志文件,如果MySql异常,可打开此文件查看异常信息;my.ini是MySql的配置文件.Apache,PHP类似.\r\nwww dirictory 即你的项目目录.点击可快速打开. \r\n5.编写你的第一个PHP程序\r\n打开项目目录,新建一个文件`hello.php`\r\n注意将后缀名改为 `.php`\r\n用记事本打开,输入\r\n\r\n <?php\r\n echo \"Hello World\";\r\n ?>\r\n\r\n然后保存.\r\n在浏览器地址栏输入 `localhost/hello.php` 看看会有什么效果!\r\n\r\n注:显示文件后缀名\r\nwin8: `View->file name extentions`\r\n![QQ图片20140912064225.jpg][10] \r\n\r\nwin7:双击\"计算机\",进入我->组织->文件夹及搜索选项->查看->高级设置->将滚动条拉到最底部,将\"隐藏已知文件类型的扩展名\"前面的勾去掉->确定\r\n\r\n [1]: http://www.wampserver.com/en/\r\n [2]: http://log.fyscu.com/usr/uploads/2014/09/1814952011.jpg\r\n [3]: http://log.fyscu.com/usr/uploads/2014/09/4157512698.jpg\r\n [4]: http://log.fyscu.com/usr/uploads/2014/09/2610072911.jpg\r\n [5]: http://log.fyscu.com/usr/uploads/2014/09/2638807152.jpg\r\n [6]: http://log.fyscu.com/usr/uploads/2014/09/4027527416.jpg\r\n [7]: http://log.fyscu.com/usr/uploads/2014/09/604917552.jpg\r\n [8]: http://log.fyscu.com/usr/uploads/2014/09/1382469906.jpg\r\n [9]: http://log.fyscu.com/usr/uploads/2014/09/631714819.jpg\r\n [10]: http://log.fyscu.com/usr/uploads/2014/09/3397134743.jpg',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(70,'给小蓝的一封信','70',1410432780,1411717737,'<!--markdown-->\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n新手问问题 好期望你的答案不是\"不想说\"。\r\n希望能稍微得到点建议。谢谢亲爱的小蓝。么么哒',0,4,NULL,'post','hidden',NULL,0,'1','1','1',0),(71,'QQ图片20140912060129.jpg','QQ图片20140912060129-jpg',1410473050,1410473050,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912060129.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/1814952011.jpg\";s:4:\"size\";i:35608;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',9,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(72,'QQ图片20140912060153.jpg','QQ图片20140912060153-jpg',1410473191,1410473191,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912060153.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/4157512698.jpg\";s:4:\"size\";i:32360;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',8,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(73,'QQ图片20140912061015.jpg','QQ图片20140912061015-jpg',1410473427,1410473427,'a:5:{s:4:\"name\";s:26:\"QQ图片20140912061015.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/2610072911.jpg\";s:4:\"size\";i:45161;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',7,5,NULL,'attachment','publish',NULL,0,'1','0','1',80),(69,'【笔记】字符编码转换方法大全(多语言)',NULL,1410422419,1410422419,'<!--markdown--><div id=\"JIATHIS_CODE_HTML2\">\n<div class=\"t_fsz\">\r\n<table cellspacing=\"0\" cellpadding=\"0\"><tr><td class=\"t_f\" id=\"postmessage_62882\">\r\n 对广大天朝程序猿来说,有时程序逻辑、算法都不是事儿,但<strong><font color=\"#ff0000\">字符编码</font></strong>却成了如我们一样的<strong>非拼音(象形)文字语言</strong>国家长久的隐痛…… 特别是 <strong><font color=\"#0000ff\">Web 开发</font></strong>,数据源文件、程序源码、数据库、浏览器等各个环节的字符编码必须相互兼容,乃至完全一致,整个网站系统才能正常使用……<br>\r\n 虽然国际上的技术前辈早已齐心协力开发出 <strong><font color=\"#008000\">Unicode 万国码</font></strong>,其中 <strong><font color=\"#0000ff\">UTF-8 格式</font></strong>标准又极为好用,但各国朝廷对自己的编码标准的固守,还有那些无数不能轻易抛弃的历史代码,还要让这种隐痛持续不知多久……<br><br>\r\n 因此,本人整理一些常用语言的字符编码常用方法,以期初学者入门不那么痛苦,也欢迎大家不断补充 ——<br><br><font size=\"3\"><strong>【HTML】</strong></font><br><br>\r\n<head /> 开头必备 ——\n<div id=\"code_BFP\"><ol><li><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></li></ol></div>\n<em onclick=\"copycode($(\'code_BFP\'));\"></em>\n</div>\n<font size=\"3\"><strong>【PHP】</strong></font><br><br>\r\n处理大段文字前,先转换编码 ——\n<div id=\"code_Fdn\"><ol><li>iconv(\'GBK\', \'UTF-8\', $string);</li></ol></div>\n<em onclick=\"copycode($(\'code_Fdn\'));\"></em>\n</div>向浏览器输出网页前,先通知所用编码 ——\n<div id=\"code_kQL\"><ol><li>header(\'Content-Type: text/html; charset=UTF-8\');</li></ol></div>\n<em onclick=\"copycode($(\'code_kQL\'));\"></em>\n</div>涉及中文文件名的应用,先统一运行时编码 ——\n<div id=\"code_fR3\"><ol><li>setlocale(LC_ALL, \'zh_CN.UTF-8\');</li></ol></div>\n<em onclick=\"copycode($(\'code_fR3\'));\"></em>\n</div>【参文】<br><ul>\n<li><a href=\"http://www.zeali.net/entry/539\" target=\"_blank\">http://www.zeali.net/entry/539</a></li>\n<li>\n<a href=\"http://ihacklog.com/post/solution-to-upload-chinese-filename-file-in-wordpress.html\" target=\"_blank\">http://ihacklog.com/post/solutio ... e-in-wordpress.html</a><br>\n</li>\n</ul>\n<br>\r\n【MySQL】<br><br>\r\n【Python】<br><br>\r\n【Node.JS】<br><br><font size=\"3\"><strong>【Windows 命令行】</strong></font><br><br>\r\n管道过滤器 —— <a href=\"http://fyscu.com/forum.php?mod=viewthread&tid=3667\" target=\"_blank\">http://fyscu.com/forum.php?mod=viewthread&tid=3667</a>\n</td></tr></table>\n</div>\r\n<div id=\"comment_62882\" class=\"cm\">\r\n</div>\r\n</div>',0,1,NULL,'post','publish',NULL,0,'1','1','1',0),(61,'软件设计七大原则(二):里氏代换原则','61',1410260640,1429899786,'<!--markdown--> 如果每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换称o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型.\r\n\r\n\r\n##解读:\r\n\r\n 公孙龙曰:白马非马。\r\n 就是违法这个原则的经典例子。正确的应该是 白马是马,马非白马。\r\n\r\n 用在软件设计中的含义就是,子类要全部实现基类的属性和方法,是全部。\r\n 换言之,基类能做到的东西,子类必须全部做到,\r\n 任何使用基类的地方,替换成其任意一个子类,都能正常运作。\r\n\r\n 就好比,“蒋航”这个实体,具备noob的技能;\r\n 那么“管理员蒋航”也必须实现noob技能,\r\n 在“蒋航”施展noob技能的地方,换了“管理员蒋航”,通用生效,\r\n 重要的事,我们根本擦觉不了这种替换。\r\n\r\n\r\n----------\r\n未完待续,感谢蒋航友情演出。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(62,'coder无聊的时候应该看到一些文章集合','62',1410267710,1410267710,'<!--markdown-->1.[优秀的程序员和一般的程序员差别在哪?](http://www.zhihu.com/question/19759297)\r\n\r\n2.[为什么有人说「远离企业应用开发」?](http://www.zhihu.com/question/24187432)\r\n\r\n\r\n\r\n长期待更新。欢迎共同编辑。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(63,'一些常用概念|记下来以后可以给新人讲一下','63',1410267916,1410267916,'<!--markdown-->1.前端的职位介绍。来自http://www.zhihu.com/question/19838787\r\n> 先来说说和前端有联系的几个职位:前端工程师、视觉设计师、用户研究工程师、交互设计师。我用一个简单的例子来分析:我们都经常在一些社区评论留言,留言的表面过程:打开留言页面——输入留言内容——点击提交按钮——留言显示在留言列表上。我这里不解释这个过程的实现原理。\r\n> \r\n> 前端工程师:留言框代码怎么写?留言框的显示、一些JS动态效果的显示(可能涉及异步请求)。 视觉设计师:什么样的留言框最漂亮?怎么布局?用什么色彩还是需要做一些纹理?\r\n> 用户研究工程师:用户怎么留言最舒服?很多人可能会和用户体验师混淆在一起,其实这两种人有着本质的区别,用户研究更侧重的是方法论,注重问卷调查访谈等等行为来了解用户的潜在行为习惯,而用户体验是一种行为,更侧重的是体验之后的实际感受。\r\n> 交互设计师:留言过程中的反馈?输入错误后的提示,留言成功后的反馈等等。交互设计可以理解为人机对话,交互设计侧重和用户交流之后,引导用户有效操作,比如鼠标放在超链接上字体变颜色,有title提示,用户点击超链接,我们就可以称这次交互是成功的,因此交互设计的重点在于目标向导。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(68,'window.showModalDialog() 的替代方案','68',1410416940,1416453910,'<!--markdown-->**window.showModalDialog()** 是 IE 很早就提出并最早实现的**“弹出窗口”方法**,它与 window.open() 的区别主要在 *有无原生返回值、子窗口能否锁定父窗口*,所以它的学名叫**【模态窗口】**。\r\n\r\n虽然后来的主流浏览器 都相继实现了这个非标准方法,但自从 **HTML5** 掀起了全球**网页浏览器标准化**浪潮,它们又在逐渐废弃这个方法。\r\n\r\n但有时,比 alert()、confirm()、prompt() 更能自由定制的 网页弹出窗口 还是蛮有用的(比如 知乎的第三方网站账号登录),我们就自己封装吧 ——\r\n\r\n //\r\n // iModalDialog.js v0.3\r\n //\r\n\r\n (function (BOM, DOM, $) {\r\n function iOpen(URL, Scale, CallBack) {\r\n Scale = (Scale > 0) ? Scale : 3;\r\n var Size = {\r\n height: BOM.screen.height / Scale,\r\n width: BOM.screen.width / Scale\r\n };\r\n var Top = (BOM.screen.height - Size.height) / 2,\r\n Left = (BOM.screen.width - Size.width) / 2;\r\n \r\n var new_Window = BOM.open(URL, \'_blank\', [\r\n \'top=\' + Top, \'left=\' + Left,\r\n \'height=\' + Size.height, \'width=\' + Size.width,\r\n \'resizable=no,menubar=no,toolbar=no,location=no,status=no,scrollbars=no\'\r\n ].join(\',\'));\r\n if (CallBack)\r\n var Timer = setInterval(function () {\r\n if (new_Window.closed) {\r\n CallBack.call(BOM, new_Window);\r\n clearInterval(Timer);\r\n }\r\n }, 200);\r\n return new_Window;\r\n }\r\n var $_Cover = $(\'<div id=\"iModalDialog_Cover\" />\').css({\r\n position: \'absolute\',\r\n \'z-index\': 2147483640,\r\n top: 0,\r\n left: 0,\r\n width: \'100%\',\r\n height: \'100%\',\r\n background: \'black\',\r\n opacity: 0.5,\r\n display: \'none\'\r\n }).appendTo(DOM.body);\r\n \r\n $.fn.iModalDialog = function () {\r\n var Args = Array.prototype.slice.call(arguments, 0);\r\n var URL = Args.shift();\r\n if (! isNaN( Number(Args[0]) )) \r\n var Scale = Args.shift();\r\n if (typeof Args[0] == \'string\')\r\n var Event = Args.shift();\r\n if (typeof Args[0] == \'function\')\r\n var CallBack = Args.shift();\r\n \r\n this.bind(Event || \'click\', function (EO) {\r\n $_Cover.show();\r\n var NW = iOpen.call(BOM, URL, Scale, function () {\r\n $_Cover.hide();\r\n });\r\n $_Cover.click(function () {\r\n NW.focus();\r\n });\r\n if (CallBack) CallBack.call(this, EO, NW);\r\n return false;\r\n });\r\n };\r\n })(self, self.document, self.jQuery);\r\n\r\n主要特性\r\n----\r\n\r\n 1. 直接绑定页面元素的用户事件(现代浏览器会拦截非用户操作而打开的新窗口),默认绑定 `click`,但可指定绑定其它类型,并设置事件回调\r\n 2. 弹出窗口自动在屏幕居中,其尺寸可由“一分之几”形式的参数设置\r\n 3. 弹窗后,父窗口启动全局半透明遮蔽层,用户点击父窗口将让弹窗活动焦点\r\n\r\n参考文章\r\n----\r\n 1. http://blog.csdn.net/itmyhome1990/article/details/27339269\r\n 2. http://www.iteye.com/topic/123995',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(122,'【懒人福利】子页面继承父页面的 CSS','122',1411719900,1415008912,'<!--markdown--> 当 **Web 开发** 逐渐复杂时,为了方便和**传统的后端系统**配合,一个页面可能需要划分成不同的 `<iframe />` 来实现。这样子页面就会比较多,但它们又要有**一致的用户体验**,让用户看不出来是多个页面的组合,这就要求这么多**父子页面共享一些 CSS**。\r\n 每新建一个页面就引入这些公共 CSS 吗?有 **JavaScript** 还怕不能“偷懒”?嘿嘿,**实践干货**来了 ——\r\n\r\n // 一些实用的封装\r\n var IE_Ver = UA.match(/MSIE (\\d)\\.\\d/i) ||\r\n UA.match(/Trident\\/.+; rv:(\\d+)\\.\\d/i);\r\n IE_Ver = IE_Ver ? Number(IE_Ver[1]) : NaN;\r\n var old_IE = IE_Ver && (IE_Ver < 9);\r\n\r\n function $_TN(HTML_Elements, TagName) {\r\n return HTML_Elements.getElementsByTagName(TagName);\r\n }\r\n function PagePath_IE(_BOM) {\r\n var _PP = _BOM.document.URL;\r\n _PP = _PP.split(\'/\');\r\n if (_PP.length > 3) _PP.pop();\r\n _PP.push(\'\');\r\n return _PP.join(\'/\');\r\n }\r\n // 遍历父页面的样式表,并拷贝 样式表元素\r\n var SS = parent.document.styleSheets;\r\n for (var i = 0, CSS_URL; i < SS.length; i++) {\r\n var LE = SS[i][old_IE ? \'owningElement\' : \'ownerNode\'];\r\n if (LE.rel.indexOf(\'nofollow\') > -1)\r\n continue;\r\n CSS_URL = SS[i].href;\r\n if (IE_Ver < 8)\r\n CSS_URL = PagePath_IE(parent) + CSS_URL;\r\n DOM_Head.appendChild( LE.cloneNode(true) ).href = CSS_URL;\r\n }\r\n\r\n把上述代码放在一个独立的脚本中(比如叫 `CSS_Inherit.js`),然后每一个子页面只需先引入这个脚本,再把自己专用的 CSS 文件在其后引入即可~\r\n\r\n----------\r\n\r\n【注】以上代码 摘编自本人开发的 **`EasyImport.js v0.8`**',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(58,'Sublime安装Package Control插件【翻译】','58',1410076860,1410077048,'<!--markdown-->**一.简易安装**\r\n\r\n打开Sublime text的console.打开console的快捷时`ctrl+,或者在菜单栏点击`View->Show Sonsole`.打开后将下面的代码复制到console中,注意选择对应的版本。\r\n**Sublime Text 3** \r\n\r\n import urllib.request,os,hashlib; h = \'7183a2d3e96f11eeadd761d777e62404\' + \'e330c659d4bb41d3bdf022e94cab3cd0\'; pf = \'Package Control.sublime-package\'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( \'http://sublime.wbond.net/\' + pf.replace(\' \', \'%20\')).read(); dh = hashlib.sha256(by).hexdigest(); print(\'Error validating download (got %s instead of %s), please try manual install\' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), \'wb\' ).write(by)\r\n\r\n**Sublime Text 2**\r\n\r\n import urllib2,os,hashlib; h = \'7183a2d3e96f11eeadd761d777e62404\' + \'e330c659d4bb41d3bdf022e94cab3cd0\'; pf = \'Package Control.sublime-package\'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( \'http://sublime.wbond.net/\' + pf.replace(\' \', \'%20\')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), \'wb\' ).write(by) if dh == h else None; print(\'Error validating download (got %s instead of %s), please try manual install\' % (dh, h) if dh != h else \'Please restart Sublime Text to finish installation\')\r\n\r\n\r\n这段代码将创建安装包文件到您的电脑(如果必要的话),然后下载`Package Control.sublime-package`到Package文件夹中 。由于python标准卡的限制,下载是通过HTTP而非HTTPS.该文件已使用SHA-256进行验证.\r\n\r\n\r\n\r\n**二.手动安装**\r\n\r\n如果因为某些原因,上面的安装方法失败(如使用了proxy等),则可根据以下步骤进行手动安装。\r\n1.点击`Preferences > Browse Packages…`菜单\r\n2.浏览文件夹,进入`Installed Packages/`文件夹\r\n3.下载[`Package Control.sublime-package`][1],并将其复制到`Installed Packages/`目录.\r\n4.重启Sublime Text.\r\n\r\n\r\n----------\r\n原文出处:https://sublime.wbond.net/installation#st2\r\n自动安装的时候每个版本的代码可能不同,可到原文查看最新代码。\r\n\r\n\r\n [1]: https://sublime.wbond.net/Package%20Control.sublime-package',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(59,'MySql导入导出数据库(表)命令','59',1410083160,1410083187,'<!--markdown-->**一.导出数据库(表)**\r\n\r\n\r\n mysqldump -u 用户名 -p 数据库名 > 导出的文件名\r\n\r\n然后会提示输入数据库密码,输入后回车即可导出。如果需要导出某个表,在数据库名后加表面即可。需注意的是,需要有导出的权限才能导出。\r\n例:`$ mysqldump -u jh -p jh_temp jh_user > jh_user.sql`\r\n表示导出用户jh中的数据库jh_temp中的jh_user表,并将导出的文件命名为jh_user.sql\r\n\r\n\r\n**二.导入数据库(表)**\r\n导入数据先要进入数据库.实例如下:\r\n\r\n $ls sql/\r\n jh_user.sql\r\n $ mysql -u jh -p\r\n Enter password:\r\n >create database jh;\r\n >use jh;\r\n >source sql/user.sql;\r\n\r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(60,'软件设计七大原则(一):开-闭 原则','60',1410260220,1415952393,'<!--markdown-->\r\n 一个软件实体应当对扩展开发,对修改关闭.说的是,再设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展.换言之,应当可以在不必修改源代码的情况下改变这个模块的行为,在保持系统一定稳定性的基础上,对系统进行扩展。这是面向对象设计(OOD)的基石,也是最重要的原则。\r\n\r\n##解读:\r\n所谓“开-闭”,就是对扩展开放,对修改关闭;\r\n换言之,你可以让我不伦不类,但不能改变我的初衷。\r\n举个实际点的例子,“人”这个实体,有年龄这个属性,有走路这个行为,\r\n你可以选择扩展出一个“杨国宝”,增加一个颜值属性,增加一个装哔行为,\r\n但是你不能把年龄改成颜值,这样杨国宝就没有年龄属性了,\r\n这样他就不是一个“人”了。\r\n这样就违反了“开-闭 原则”\r\n\r\n\r\n----------\r\n未完待续,感谢部长友情演出。',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(123,'【JavaScript 进阶】面向对象编程与 jQuery 式 API 的实现','123',1411763040,1416190396,'<!--markdown-->**JavaScript 简洁、灵活,jQuery 优雅、强大** —— 它们共同开拓了新的思维方式,影响了一代程序员和他们的 Web 前端开源项目,这是毋庸置疑的~\r\n\r\n要想让它们的简洁、灵活、优雅、强大为我所用,内化为编程上的精神法宝,亲手“临摹”一下既有趣又有力。一番死磕之后,jQuery 中蕴含的 **JavaScript 面向对象的思想方法** 自然就很容易理解了~\r\n\r\n## 山寨版 jQuery 半成品 ##\r\n目前仅简单地实现了**最常用的选择器**(标签、ID、类、first/last/only/nth-child 伪类)、**选择器上下文**、**最常用的 jQuery 对象方法**(each、find、on、off 等)、**连缀语法**等 ——\r\n\r\n // ----------- xDOM Core Object ----------- //\r\n function DOMxx(Selector, Context) {\r\n this.xDOM = \'0.5\';\r\n this.jquery = \'1.9.0\'; // Work with the version of jQuery API\r\n \r\n // ----------- Atom Functions (Private Method) ----------- //\r\n function Each(Object, CallBack) {\r\n for (var key in Object) if (key != \'length\') {\r\n var _RV_ = CallBack.call(\r\n Object[key],\r\n isNaN(Number(key)) ? key : Number(key)\r\n );\r\n if (_RV_ === false) break;\r\n }\r\n }\r\n function inArray(Value, iArray) {\r\n for (var i = 0; i < iArray.length; i++)\r\n if (iArray[i] === Value) return i;\r\n return false;\r\n }\r\n function Child_PC(EOS, PCS) {\r\n var PES = [], CES = [];\r\n Each(EOS, function () {\r\n if (inArray(this.parentNode, PES) === false)\r\n PES.push(this.parentNode);\r\n });\r\n var PCS_KW = PCS.match(/^(\\w+)-child/i)[1];\r\n if (PCS_KW == \'nth\')\r\n var PCS_EC = PCS.match(/^nth-child\\((.+)\\)/i)[1];\r\n Each(PES, function () {\r\n EOS = this.children;\r\n if (! EOS) return;\r\n switch (PCS_KW) {\r\n case \'first\': {\r\n CES.push(EOS[0]);\r\n return;\r\n }\r\n case \'last\': {\r\n CES.push(EOS[EOS.length - 1]);\r\n return;\r\n }\r\n case \'only\': {\r\n if (EOS.length == 1)\r\n CES.push(EOS[0]);\r\n return;\r\n }\r\n case \'nth\': {\r\n PCS_EC = PCS_EC.replace(/(\\d+)(\\w|\\()/g, \'$1 * $2\');\r\n for (var n = 1, N = 0; ; n++) {\r\n N = eval(PCS_EC);\r\n if (N >= EOS.length) return;\r\n CES.push(EOS[N]);\r\n }\r\n }\r\n }\r\n });\r\n return CES;\r\n }\r\n function $_Atom(REO, SE) {\r\n SE = SE.split(\':\');\r\n if (SE.length > 1) var PC = SE[1];\r\n SE = SE[0];\r\n switch (SE.slice(0, 1)) {\r\n case \'#\': {\r\n REO = self.document;\r\n MN = \'getElementById\';\r\n SE = SE.slice(1);\r\n break;\r\n }\r\n case \'.\': {\r\n MN = \'getElementsByClassName\';\r\n SE = SE.slice(1);\r\n break;\r\n }\r\n case \'*\': ;\r\n default: MN = \'getElementsByTagName\';\r\n }\r\n REO = REO[MN](SE);\r\n REO = PC ? Child_PC(REO, PC) : REO;\r\n return (! REO.length) ? [REO] : (\r\n (REO instanceof Array) ? REO : [].slice.apply(REO)\r\n );\r\n }\r\n function Select(Selector, Context) {\r\n var Selector_Group = Selector.split(\' \'), Level = 0,\r\n Select_Result = [];\r\n Each(\r\n $_Atom( Context, Selector_Group[Level] ),\r\n function (Index) {\r\n if (! Index) Level++;\r\n while (Selector_Group[Level] == \'\')\r\n Level++;\r\n if (! Selector_Group[Level]) {\r\n Select_Result.push(this);\r\n return;\r\n }\r\n if (! this.childNodes.length) return;\r\n Each(\r\n $_Atom(this, Selector_Group[Level]),\r\n arguments.callee\r\n );\r\n \r\n }\r\n );\r\n return Select_Result;\r\n }\r\n function Event_Bind(_Element, _Type, _CallBack, _unBind) {\r\n var _CB_ = function (Event) {\r\n EO = self.event || Event;\r\n EO.target = EO.srcElement || EO.target;\r\n if (! _CallBack.call(_Element, EO))\r\n if (EO.returnValue) {\r\n EO.returnValue = false;\r\n EO.cancelBubble = true;\r\n } else {\r\n EO.preventDefault();\r\n EO.stopPropagation();\r\n };\r\n };\r\n if (_Element.attachEvent)\r\n _Element[ (_unBind ? \'de\' : \'at\') + \'tachEvent\'](\r\n \'on\' + ((_Type == \'input\') ? \'propertychange\' : _Type),\r\n _CB_\r\n );\r\n else\r\n _Element[\r\n (_unBind ? \'remove\' : \'add\') + \'EventListener\'\r\n ](_Type, _CB_, false);\r\n }\r\n \r\n // ----------- Powerful API (Public Method / Data) ----------- //\r\n this.selector = Selector;\r\n this.context = (Context || self.document);\r\n this.DOM = Select(Selector, this.context);\r\n if (this.DOM.length == 1)\r\n this.context = this.DOM[0];\r\n \r\n this.get = function (Index) {\r\n return this.DOM[Index];\r\n };\r\n this.each = function (CallBack) {\r\n Each(this.DOM, CallBack);\r\n return this;\r\n };\r\n this.find = function (Selector) {\r\n return new this.constructor(\r\n [this.selector, Selector].join(\' \'), this.context\r\n );\r\n }\r\n this.on = function (Event_Type, CallBack) {\r\n return this.each(function () {\r\n Event_Bind(this, Event_Type, CallBack);\r\n });\r\n };\r\n this.off = function (Event_Type, CallBack) {\r\n return this.each(function () {\r\n Event_Bind(this, Event_Type, CallBack, true);\r\n });\r\n }\r\n }\r\n // ----------- xDOM Shortcut Function ----------- //\r\n function xDOM(CSS_Selector, DOM_Context) {\r\n return new DOMxx(CSS_Selector, DOM_Context);\r\n }\r\n\r\n有木有一种步 **Zepto.js** 后尘的感觉……?\r\n\r\n【参考文献】\r\n------\r\n 1. http://www.cnblogs.com/newyorker/archive/2013/02/14/2891298.html',0,13,NULL,'post','publish',NULL,0,'1','1','1',0),(55,'解决Ubuntu下Sublime text3无法输入中文的问题','55',1410028320,1410028943,'<!--markdown-->最开始在ubuntu14.04上装了Aptana,但无奈启动有点慢,稍显笨重,于是又继续用Sublime了。Sublime text 功能强大而又不失简约,个人非常喜欢。\r\n然而在Ubuntu中sublime无法输入中文,这确实是个有点狗血的问题,在windows上完全不会有这种问题。\r\n既然有问题,那就去解决。\r\n\r\n我一开始安装有搜狗输入法,我的sublime时安装在`/opt/sublime_text`文件中的。\r\n\r\n1.新建文件sub-fcitx.c,建议放在Sublime Text的所在目录下,将下面的代码复制进去\r\n\r\n /*\r\n sublime-imfix.c\r\n Use LD_PRELOAD to interpose some function to fix sublime input method support for linux.\r\n By Cjacker Huang\r\n \r\n gcc -shared -o libsublime-imfix.so sublime-imfix.c `pkg-config --libs --cflags gtk+-2.0` -fPIC\r\n LD_PRELOAD=./libsublime-imfix.so subl\r\n */\r\n #include <gtk/gtk.h>\r\n #include <gdk/gdkx.h>\r\n typedef GdkSegment GdkRegionBox;\r\n \r\n struct _GdkRegion\r\n {\r\n long size;\r\n long numRects;\r\n GdkRegionBox *rects;\r\n GdkRegionBox extents;\r\n };\r\n \r\n GtkIMContext *local_context;\r\n \r\n void\r\n gdk_region_get_clipbox (const GdkRegion *region,\r\n GdkRectangle *rectangle)\r\n {\r\n g_return_if_fail (region != NULL);\r\n g_return_if_fail (rectangle != NULL);\r\n \r\n rectangle->x = region->extents.x1;\r\n rectangle->y = region->extents.y1;\r\n rectangle->width = region->extents.x2 - region->extents.x1;\r\n rectangle->height = region->extents.y2 - region->extents.y1;\r\n GdkRectangle rect;\r\n rect.x = rectangle->x;\r\n rect.y = rectangle->y;\r\n rect.width = 0;\r\n rect.height = rectangle->height;\r\n //The caret width is 2;\r\n //Maybe sometimes we will make a mistake, but for most of the time, it should be the caret.\r\n if(rectangle->width == 2 && GTK_IS_IM_CONTEXT(local_context)) {\r\n gtk_im_context_set_cursor_location(local_context, rectangle);\r\n }\r\n }\r\n \r\n //this is needed, for example, if you input something in file dialog and return back the edit area\r\n //context will lost, so here we set it again.\r\n \r\n static GdkFilterReturn event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer im_context)\r\n {\r\n XEvent *xev = (XEvent *)xevent;\r\n if(xev->type == KeyRelease && GTK_IS_IM_CONTEXT(im_context)) {\r\n GdkWindow * win = g_object_get_data(G_OBJECT(im_context),\"window\");\r\n if(GDK_IS_WINDOW(win))\r\n gtk_im_context_set_client_window(im_context, win);\r\n }\r\n return GDK_FILTER_CONTINUE;\r\n }\r\n \r\n void gtk_im_context_set_client_window (GtkIMContext *context,\r\n GdkWindow *window)\r\n {\r\n GtkIMContextClass *klass;\r\n g_return_if_fail (GTK_IS_IM_CONTEXT (context));\r\n klass = GTK_IM_CONTEXT_GET_CLASS (context);\r\n if (klass->set_client_window)\r\n klass->set_client_window (context, window);\r\n \r\n if(!GDK_IS_WINDOW (window))\r\n return;\r\n g_object_set_data(G_OBJECT(context),\"window\",window);\r\n int width = gdk_window_get_width(window);\r\n int height = gdk_window_get_height(window);\r\n if(width != 0 && height !=0) {\r\n gtk_im_context_focus_in(context);\r\n local_context = context;\r\n }\r\n gdk_window_add_filter (window, event_filter, context);\r\n }\r\n\r\n2.安装编译环境\r\n\r\n sudo apt-get install build-essential\r\n sudo apt-get install libgtk2.0-dev\r\n\r\n3.切换到sub-fcitx.c,所在目录,编译生成so文件\r\n\r\n cd /opt/sublime_text/\r\n gcc -shared -o libsublime-imfix.so sub-fcitx.c `pkg-config --libs --cflags gtk+-2.0` -fPIC\r\n\r\n正常的话,目录下会多一个libsublime-imfix.so文件\r\n切换到Sublime Text目录下,通过`LD_PRELOAD=./libsublime-imfix.so ./sublime_text`命令启动Sublime Text之后,就会发现可以输入中文了,但是这样太麻烦了,通过添加自己的启动脚本可以简化这一过程\r\n\r\n4.在终端通过 subl 直接启动sublime\r\n\r\n sudo vim /usr/bin/subl\r\n\r\n在第一行添加\r\n\r\n export LD_PRELOAD=/opt/sublime_text/libsublime-imfix.so\r\n\r\n5.在启动器快捷启动\r\n找到sublime启动图标的放置位置\r\n\r\n sudo find -iname sublime*\r\n我find的结果如下\r\n\r\n ./.local/share/icons/sublime_text.png\r\n ./.local/share/applications/sublime_text.desktop\r\n ./.config/sublime-text-3\r\n\r\n说明sublime启动图标位置为`./.local/share/applications/sublime_text.desktop`\r\n然后修改启动设置\r\n\r\n sudo vim ./.local/share/applications/sublime_text.desktop\r\n\r\n将`Exec=/opt/sublime_text/sublime_text`修改为\r\n\r\n Exec=/usr/bin/subl\r\n\r\n可见原sublime_text.desktop中的/opt/sublime_text/sublime_text就是sublime的安装位置。\r\n\r\n\r\n这时,不管时在终端优雅的输入 subl 还是在启动器中优雅的点击 sublime 进入后都可以输入中文啦!\r\n\r\n总结:设置终端启动和启动器启动图标启动的时候,最重要的是路径必须写对!我google了很多教程,不同教程路径有所不同,自己的sublime安装位置和教程的也有所不同,如果路径不对,配置后就可能依旧无法输入中文甚至无法启动。\r\n**两个重要的路径(以我的为例):**\r\n安装路径:`/opt/sublime_text`\r\n启动器图标路径:`./.local/share/applications/sublime_text.desktop`\r\n\r\n\r\n----------\r\n参考资料:http://my.oschina.net/wugaoxing/blog/121281',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(56,'Ubuntu高速apt-get源(转)','56',1410028920,1410247045,'<!--markdown-->使用方法:\r\n\r\n1、修改源地址:\r\n\r\n cp /etc/apt/sources.list /etc/apt/sources.list.bak\r\n vim /etc/apt/sources.list\r\n\r\n加入如下内容(中科大的U源):\r\n\r\n deb http://mirrors.ustc.edu.cn/ubuntu/ precise-updates main restricted\r\n deb-src http://mirrors.ustc.edu.cn/ubuntu/ precise-updates main restricted\r\n deb http://mirrors.ustc.edu.cn/ubuntu/ precise universe\r\n deb-src http://mirrors.ustc.edu.cn/ubuntu/ precise universe\r\n deb http://mirrors.ustc.edu.cn/ubuntu/ precise-updates universe\r\n deb-src http://mirrors.ustc.edu.cn/ubuntu/ precise-updates universe\r\n deb http://mirrors.ustc.edu.cn/ubuntu/ precise multiverse\r\n deb-src http://mirrors.ustc.edu.cn/ubuntu/ precise multiverse\r\n deb http://mirrors.ustc.edu.cn/ubuntu/ precise-updates multiverse\r\n deb-src http://mirrors.ustc.edu.cn/ubuntu/ precise-updates multiverse\r\n deb http://mirrors.ustc.edu.cn/ubuntu/ precise-backports main restricted universe multiverse\r\n deb-src http://mirrors.ustc.edu.cn/ubuntu/ precise-backports main restricted universe multiverse\r\n \r\n deb http://security.ubuntu.com/ubuntu precise-security main restricted\r\n deb-src http://security.ubuntu.com/ubuntu precise-security main restricted\r\n deb http://security.ubuntu.com/ubuntu precise-security universe\r\n deb-src http://security.ubuntu.com/ubuntu precise-security universe\r\n deb http://security.ubuntu.com/ubuntu precise-security multiverse\r\n deb-src http://security.ubuntu.com/ubuntu precise-security multiverse\r\n\r\n备选比较快的源:\r\n\r\n搜狐源:\r\n\r\n deb http://mirrors.sohu.com/ubuntu/ precise-updates main restricted\r\n deb-src http://mirrors.sohu.com/ubuntu/ precise-updates main restricted\r\n deb http://mirrors.sohu.com/ubuntu/ precise universe\r\n deb-src http://mirrors.sohu.com/ubuntu/ precise universe\r\n deb http://mirrors.sohu.com/ubuntu/ precise-updates universe\r\n deb-src http://mirrors.sohu.com/ubuntu/ precise-updates universe\r\n deb http://mirrors.sohu.com/ubuntu/ precise multiverse\r\n deb-src http://mirrors.sohu.com/ubuntu/ precise multiverse\r\n deb http://mirrors.sohu.com/ubuntu/ precise-updates multiverse\r\n deb-src http://mirrors.sohu.com/ubuntu/ precise-updates multiverse\r\n deb http://mirrors.sohu.com/ubuntu/ precise-backports main restricted universe multiverse\r\n deb-src http://mirrors.sohu.com/ubuntu/ precise-backports main restricted universe multiverse\r\n\r\n网易源:\r\n\r\n deb http://mirrors.163.com/ubuntu/ precise-updates main restricted\r\n deb-src http://mirrors.163.com/ubuntu/ precise-updates main restricted\r\n deb http://mirrors.163.com/ubuntu/ precise universe\r\n deb-src http://mirrors.163.com/ubuntu/ precise universe\r\n deb http://mirrors.163.com/ubuntu/ precise-updates universe\r\n deb-src http://mirrors.163.com/ubuntu/ precise-updates universe\r\n deb http://mirrors.163.com/ubuntu/ precise multiverse\r\n deb-src http://mirrors.163.com/ubuntu/ precise multiverse\r\n deb http://mirrors.163.com/ubuntu/ precise-updates multiverse\r\n deb-src http://mirrors.163.com/ubuntu/ precise-updates multiverse\r\n deb http://mirrors.163.com/ubuntu/ precise-backports main restricted universe multiverse\r\n deb-src http://mirrors.163.com/ubuntu/ precise-backports main restricted universe multiverse\r\n\r\n2、更新一下看看速度:\r\n\r\n sudo apt-get update\r\n sudo apt-get upgrade\r\n\r\n\r\n----------\r\n文章来源:http://www.ha97.com/4950.html',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(45,'Markdown——入门指南','45',1410007419,1410007419,'<!--markdown-->非常简单易懂的markdown语法入门指南。我相信你使用markdown语法写完3篇文章之后 你会爱上他的。\r\n\r\n白会你说是吗?\r\n\r\n[请点这里](http://www.jianshu.com/p/1e402922ee32)\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(50,'蒋航总结.pptx','蒋航总结-pptx',1410012803,1410012803,'a:5:{s:4:\"name\";s:17:\"蒋航总结.pptx\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/549525290.pptx\";s:4:\"size\";i:94677;s:4:\"type\";s:4:\"pptx\";s:4:\"mime\";s:15:\"application/zip\";}',1,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(52,'研发部这学期的规划','52',1410013800,1410111507,'<!--markdown-->今天收到新任务。\r\n\r\n说社团联需要各个部门做个新学期规划。要每个步骤写个word文档给行政。\r\n\r\n刚好下午买鸭腿的时候遇见社团联的一个主席,问说你们还有时间看各个部门的规划啊。主席说形式而已啦啦啦。反正不管你看不看,我们自己是有规划的。\r\n\r\n索性放在这里吧。稍微写得正式一点,以下要提交给行政。\r\n\r\n飞扬俱乐部·研发部2014-2015秋季学期规划:\r\n\r\n总体目的:让研发部现在的所有成员都能从研发学到真本事。能独当一面,从各方面在同龄的同学中脱颖而出。能独立完成整个项目的设计/划分/code,能掌握编程通用技巧以及熟练使用至少一门编程语言。本学期开始注重关注每一个coder的代码质量。每个人至少有一份自己作为PM已上线运行的项目。如果这学期完了还没有的话,最好就不要再呆在研发部了,带来太多负能量了。\r\n\r\n具体规划:\r\n\r\n### 招新\r\n\r\n春季学期不再招新,把现有成员内功练好,秋季学期进行换届以及新成员接纳。\r\n\r\n### 工作计划\r\n\r\n1.四川大学绩点在线计算在测试阶段尚未推广已在朋友圈火的一塌糊涂,但是作为程序设计人员,仍觉得有非常大的不足,体现在方方面面,比如该应用的交互性,美观性,后台获取成绩等数据的混乱性,虽实现了功能,但代码写的不够规范,本学期完成绩点2.0的设计以及正式上线。\r\n\r\n语言:PHP+html+js+css 框架:thinkphp 3.22 PM:蒋航\r\n\r\n2.服务器资源管理\r\n\r\n对服务器资源进行定时统计,写入数据库。\r\n\r\n语言:C PM:吴磊城\r\n\r\n3.飞扬内部OA(办公自动化系统)搭建\r\n\r\n目前已完成邮件群发系统,之后会有管理服务器资源,管理微信后台的OA系统上线。\r\n\r\n语言:PHP PM:陈宁 蓝浩 杨国宝\r\n\r\n4.接口的开发\r\n\r\n完成一些永久使用的飞扬提供给大家使用的接口。包括发送邮件等接口\r\n\r\n语言:PHP node PM:蓝浩\r\n\r\n5.积淀\r\n\r\n每个人都在log.fyscu.com 写下自己在成长中的积淀。记录下自己爬过的坑。力求能产出原创的好文章。\r\n\r\n\r\n### 其他\r\n\r\n想租江安花园的房子作为研发实验室。\r\n\r\n以上。\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(53,'马克一下,QQ头像接口','53',1410017640,1410097303,'<!--markdown-->![请输入图片描述][1]\r\n\r\n\r\n [1]: http://q1.qlogo.cn/g?b=qq&s=100&nk=540590988\r\n\r\n` http://q1.qlogo.cn/g?b=qq&s=100&nk={号码}`',0,2,NULL,'post','publish',NULL,0,'1','1','1',0),(54,'Linux修改文件目录权限','54',1410022800,1410022966,'<!--markdown-->**一.chmod**\r\nchmod命令用于改变文件或目录的访问权限。该命令有两种使用方式:符号模式和绝对模式。\r\n\r\n1.符号模式:\r\nchmod命令符号模式的一般语法格式为\r\n\r\n chmod [role] [+|-|=] [mode] filename\r\n\r\n`[role]` 由字母 u,g,o,a 组合而成,他们各自的含义为:u (user) 代表用户,g (group) 代表用户组,o (orther) 代表其他用户,a (all) 代表所有用户。\r\n`[+|-|=]` 操作符 +,-,= 分别表示为某个用户添加某个权限,取消某个权限,赋予给定权限并取消其他所有权限。\r\n[mode] 所表示的权限可用字母 r (read,可读), w (write,可写),x (excute,可执行) 任意组合。只有目标文件对某些用户是可执行的或该目标文件是目录时才追加 x 属性。\r\n\r\n\r\n在一下命令中,test.txt 文件的最初文件属性字段位 \"-rw-r--r--\",其中第1位 - 表示该文件是一个普通文件,第2~4位表示文件所有者权限,第5~7位表示组内用户权限,8~10位表示其他用户权限。\"-rw-r--r--\"即该普通文件的文件所有者具有可读可写的权限,组内用户和其他用户拥有可读权限。\r\n关于ll命令字段所代表的意思请参考《ll命令参数及字段详解》。\r\n使用 chomd 命令位组内用户设置可写和可执行权限,为其他用户添加可写权限。最后 test.txt 文件权限设置位\"-rwx-wxrw-\"。\r\n\r\n noob@ubuntu:~$ls -l test.txt\r\n --rw-r--r-- 1 root root 12962 9月 6 23:46 libsublime-imfix.so\r\n noob@ubuntu:~$chmod u+x test.txt\r\n noob@ubuntu:~$chmod g=wx test.txt\r\n noob@ubuntu:~$chmod o+w test.txt\r\n noob@ubuntu:~$ls -l test.txt\r\n -rwx-wxrw- 1 root root 12962 9月 6 23:56 libsublime-imfix.so\r\n\r\n\r\n2.绝对模式\r\n绝对模式的一般语法风格为\r\n\r\n chmod [model] filename\r\n\r\n`[model]` 表示设置权限模式,用数字表示。\r\n 4:可读权限;\r\n 2:可写权限;\r\n 1:可执行权限;\r\n 0:没有权限;\r\n绝对模式下八进制权限表示\r\n\r\n 数字 八进制权限表示 权限引用\r\n 7 所有:4+2+1=7 rwx\r\n 6 读取和写入:4+2=6 rw-\r\n 5 读取和执行:4+1=5 r-x\r\n 4 读取 r--\r\n 3 写入和执行:2+1=3 -wx\r\n 2 写入 -w-\r\n 1 执行 --x\r\n 0 无 --- \r\n\r\n延续上面的例子,将test.txt的权限\"-rwx-wxrw-\"设置为最初的\"-rw-r--r--\"。\r\n\r\n noob@ubuntu:~$ls -l test.txt\r\n -rwx-wxrw- 1 root root 12962 9月 6 23:56 test.txt\r\n noob@ubuntu:~$chmod 611 test.txt\r\n -rw-r--r-- 1 root root 12962 9月 7 23:56 test.txt\r\n\r\n**二.chgrp**\r\nchgrp命令用于改变文件或目录所属的组。chgrp命令的一般语法格式为\r\n\r\n chgrp [-R] group filename\r\n\r\n需要说明的是,更改文件/目录的所属组,需要有超级用户或所改组用户权限才可执行有关操作。\r\n`[-R]` 表示递归的改变制定目录及其子目录所属组;\r\n`filename` 表示改变所属组的文件名。\r\n如将 test.txt 由原来所属的 root 组改为 noob 组:\r\n\r\n noob@ubuntu:test.txt$ ls -l test.txt \r\n -rwxr-xr-x 1 root root 12962 9月 6 23:56 test.txt\r\n noob@ubuntu:~$ sudo chgrp noob test.txt \r\n [sudo] password for noob: \r\n noob@ubuntu:~$ ls -l test.txt \r\n -rwxr-xr-x 1 root noob 12962 9月 6 23:56 test.txt\r\n注: 在`-rwxr-xr-x 1 root root 12962 9月 6 23:56 test.txt`中,第一个 root 表示文件拥有者,第2个 root 表示文件拥有者所在的组。\r\n\r\n三.chown命令\r\nchown命令用于将指定文件的所有者改变为指定用户或组。其语法格式一般位\r\n\r\n chown [-R] [user:group] filename\r\n\r\n`-[R],filename` 同chgrp;\r\n`[user:group]` 表示文件所有者和所属组。\r\n\r\n noob@ubuntu:~$ ls -l libsublime-imfix.so \r\n -rwxr-xr-x 1 root root 12962 9月 6 23:56 test.txt\r\n noob@ubuntu:~$ chown noob:noob test.txt \r\n noob@ubuntu:~$ ls -l test.txt\r\n -rwxr-xr-x 1 noob noob 12962 9月 6 23:56 test.txt\r\n\r\n \r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(43,'ubuntu重启apache警告','43',1409987580,1410015854,'<!--markdown-->当安装LAMP后,执行\r\nsudo /etc/init.d/apache2 restart\r\n提示如下\r\n\r\n * Restarting web server apache2\r\n AH00558: apache2: Could not reliably determine the server\'s fully qualified domain name, using 127.0.1.1. Set the \'ServerName\' directive globally to suppress this message\r\n [ OK ]\r\n\r\napache是重启成功了,但始终会提示“Could not reliably determine the server\'s fully qualified domain name......”\r\n\r\n**方法一:解决方式如下**\r\n\r\n sudo vim /etc/init.d/httpd.conf\r\n\r\n在其中加上\r\n\r\n ServerName localhost\r\n\r\n在ubuntu里面,时没有 httpd 的,也没有默认的 httpd.conf这个配置文件,只有apache2.conf 。所以在 `sudo/etc/init.d/httpd start` 的时候,会提示 `command not found`\r\n\r\n手动添加了 httpd.conf 后,还需要将 httpd.conf 引入到apache2.conf中。\r\n\r\n sudo vim /etc/init.d/apache2.conf \r\n\r\n在文件末尾添加\r\n\r\n Include httpd.conf \r\n\r\n然后再重启即可。\r\n\r\n\r\n**方法二:**\r\n既然方法一中说了,ubuntu中没有 httpd 也没有 httpd.conf ,那么为何不直接在 apache2.conf 中配置服务器的域名呢?\r\n这是完全可行的。\r\n\r\n sudo vim /etc/init.d/apache2.conf\r\n\r\n直接在末尾添加\r\n\r\n ServerName localhost\r\n\r\n然后再 `sudo /etc/init.d/apache2 restart` 的时候就会发现可爱的\r\n\r\n Restarting web server apache2 [ OK ] \r\n\r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(44,'既然博客的后台编辑器被部分作者吐槽.我来给你们普及下我们高端大气的markdown[上]','44',1409999520,1409999616,'<!--markdown-->本文原载 [Apple4us](http://apple4us.com/2012/02/why-writers-should-use-markdown.html)。为了在研发普及markdown,特转载过来。本文作者为 Lawrence Li。\r\n\r\nMarkdown 是一种「标记语言」,通常为程序员群体所用。我想用这篇文章解释一下作家用 Markdown 保存自己写的东西有什么好处。\r\n\r\n大部分作家用 Word 或 Pages 写作,过去的文档也大都以 .doc, .docx 格式或是 Pages 格式储存。还有人为了保证文稿发给谁都能正常打开,会用 .txt 格式。\r\n\r\n.doc 或 Pages 格式有如下问题:\r\n\r\n1. 不一定谁都能打开。用 Windows 的人打不开 .pages 文件,用旧版 Word 的人不一定能打开你用新版 Word 写的稿子。\r\n\r\n2. 对方看到的稿子的样子和你自己看到的可能差别很大。\r\n\r\n3. Office 已经是你电脑上唯一的盗版软件,导致心情不佳。\r\n\r\n4. .txt 格式的问题在于没有样式:收到稿子的编辑和设计师可能不知道哪个是小标题,哪里需要斜体,哪里需要加粗。\r\n\r\n这就是 Markdown 登场的时候了。\r\n\r\n不要被「标记语言」这个说法吓到,这一点也不难。事实上我见过一位记者已经在用标记语言写稿了。\r\n\r\n以下便是一则标记语言的应用实例:\r\n\r\n> 「你们现在看到的,仅仅是冰山一角」(小标题)\r\n\r\n所有编辑都能认出,「(小标题)」不是这个小标题的一部分,它只是在告诉你,「『你们现在看到的,仅仅是冰山一角』」是一个小标题。这就是标记语言。\r\n\r\nMarkdown 比这更简单。上述标题用 Markdown 改写后是这样的:\r\n\r\n> ## 「你们现在看到的,仅仅是冰山一角」\r\n\r\n在 Markdown 的语法里,两个井号(##)代表二级标题。若你要告诉编辑或设计师某句话是小标题,只要在标题前加入两个井号即可。若该小标题下还有其它小标题(三级标题),只要在三级标题前加上三个井号即可。从打字量上讲,两个井号只需要按两次键,「(小标题)」的按键次数多了一倍不止。从易读性上讲,「(小标题)」是自然语言,容易跟稿件正文混淆,## 则清晰得多。\r\n\r\n这里是一份用手写成的 Markdown 文稿:\r\n\r\n![](http://apple4.us/wordpress/wp-content/uploads/2012/02/markdown_demo.png)\r\n\r\n\r\n用 Markdown 有如下好处:\r\n\r\n兼顾了「什么人都能打开」和「样式」。Markdown 就是纯文本,就是 txt,所以什么人都能打开。而如上所述,你可以用它来标记文本的样式,而且语法非常简单。\r\n\r\n由于是纯文本,Markdown 文稿也不会因为未来软件升级而产生不同版本之间的兼容问题,即,不会出现「我这篇稿子是用旧版 Word 写的,你用新版 Word 看可能格式会有点问题」的情况。\r\n\r\nMarkdown 转 HTML 非常方便。HTML 是整个万维网(web)的标记语言,但更重要的是,它也是目前主流电子书格式所用的标记语言。无论是 EPUB, mobi,还是 Kindle 用的专有格式 .azw,都只是把一堆 HTML 文件打包而已。如果你写的是书,用 Markdown 标注格式之后,可以很方便地转为以上格式(当然这个转换工作不需要由你来做);如果你写的是单篇的文章(例如新闻报道或专栏),未来也不排除结集出书的可能。若采用 Markdown,对于日后的文件转换工作也大有裨益。\r\n\r\n如何开始用 Markdown?继续用你习惯的写作软件即可。记事本、Word、Pages 都没问题,但请记得存成纯文本格式。就这么简单。\r\n\r\n纯文本万岁。',0,4,NULL,'post','publish',NULL,0,'1','1','1',0),(42,'(转帖+总结)变量名的命名规则','42',1409979900,1409980078,'<!--markdown-->昨晚例会的时候\r\n 小蓝竟然写起了C语言 简直是醉了 O.O\r\n然后他问了一个问题 C语言的变量函数命名规则是什么.... 想了半天也没想出来是什么\r\n回来之后百度了一下 找到了各种回答,自己总结一下贴上来了\r\n\r\n**1、常见命名规则**\r\n比较著名的命名规则首推**匈牙利命名法**,基本原则是:**变量名=属性+类型+对象描述**。\r\n这种命名方法是由Microsoft程序员查尔斯•西蒙尼(Charles Simonyi) 提出的。\r\n其主要思想是“在变量和函数名中加入前缀以增进人们对程序的理解”。\r\n匈牙利命名法关键是:标识符的名字以一个或者多个小写字母开头作为前缀;\r\n前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途。\r\n例如:\r\nbool(BOOL) 用b开头 bIsParent \r\nbyte(BYTE) 用by开头 byFlag \r\nshort(int) 用n开头 nStepCount \r\nlong(LONG) 用l开头 lSum \r\nchar(CHAR) 用c开头 cCount \r\nfloat(FLOAT) 用f开头 fAvg \r\ndouble(DOUBLE) 用d开头 dDeta \r\nvoid(VOID) 用v开头 vVariant \r\nDWORD 用dw开头 dwWord \r\nLPCSTR(LPCTSTR) 用str开头 strString \r\n\r\n**骆驼(又称驼峰)命名法**近年来越来越流行,在许多新的函数库和Java这样的平台下使用\r\n得当相多。\r\n骆驼式命名法就是当变量名或函式名是由一个或多个单字连结在一起,而构成的唯一识\r\n别字时,第一个单词以小写字母开始;第二个单词的首字母大写或每一个单词的首字母\r\n都采用大写字母。\r\n例如:printEmployeePaychecks(),函数名中每一个逻辑断点都有一个大写字母来标记。\r\n**帕斯卡(Pascal)命名法**与骆驼命名法类似。\r\n只不过骆驼命名法是第一个单词首字母小写,而帕斯卡命名法则是第一个单词首字母大写。\r\n例如:DisplayInfo()和UserName都是采用了帕斯卡命名法。\r\n事实上,很多程序设计者在实际命名时会将骆驼命名法和帕斯卡结合使用,\r\n例如变量名采用骆驼命名法,而函数采用帕斯卡命名法。\r\n\r\n最后,另一种流行的命名规则,也是要这次详细说的,称为**下划线命名法**。\r\n下划线法是随着C语言的出现流行起来的,在UNIX/LIUNX这样的环境,以及GNU代码中使用非常普遍。\r\n在下划线命名法中\r\n**1、函数命名法**\r\n函数名使用下划线分割小写字母的方式命名:\r\n\r\n 设备名_操作名()\r\n 操作名一般采用:谓语(此时设备名作为宾语或者标明操作所属的模块)或者\r\n 谓语+宾语/表语(此时设备名作为主语或者标明操作所属的模块)等形式\r\n tic_init()\r\n adc_is_busy()\r\n uart_tx_char()\r\n\r\n中断函数的命名直接使用设备名_isr() 的形式命名,如:\r\n\r\n timer2_isr()\r\n\r\n**2、变量的命名**\r\n变量的命名也采用下划线分割小写字母的方式命名。\r\n命名应当准确,不引起歧义,且长度适中。如:\r\n\r\n Int length;\r\n uint32 test_offset;\r\n 单字符的名字也是常用的,如i, j, k等,它们通常可用作函数内的局部变量。\r\n tmp常用做临时变量名。\r\n\r\n局部静态变量,应加s_词冠(表示static),如:\r\n\r\n static int s_lastw;\r\n\r\n全局变量(尤其是供外部访问的全局变量),应加g_词冠(表示global),如:\r\n\r\n void (* g_capture_hook)(void);\r\n\r\n**3、常量及宏的命名**\r\n采用下划线分割大写字母的方式命名,一般应以设备名作为前缀,\r\n防止模块间命名的重复。如:\r\n\r\n #define TIMER0_MODE_RELOAD 2\r\n #define TIMER2_COUNT_RETRIEVE(val) ((uint16)(65536 - (val)))\r\n\r\n当然,看作接口的宏可以按照函数的命名方法命名,例如:\r\n\r\n #define timer2_clear() (TF2 = 0)\r\n #define timer0_is_expired() (TF0)\r\n\r\n**常用缩写词**\r\n原词 缩写\r\naddition add\r\nanswer ans\r\narray arr\r\naverage avg\r\nbuffer buf或buff\r\ncapture cap或capt\r\ncheck chk\r\ncount cnt\r\ncolumn col\r\ncontrol ctrl\r\ndecode dec\r\ndefine def\r\ndelete del\r\ndestination dst或dest\r\ndisplay disp\r\ndivision div\r\nencode enc\r\nenvironment env\r\nerror err\r\nfloat flt\r\nfrequency freq\r\nheader hdr\r\nindex idx\r\nimage img\r\nincrement inc\r\ninitalize init\r\niteration itr\r\nlength len\r\nmemory mem\r\nmiddle mid\r\nmake mk\r\nmessage msg\r\nmultiplication mul\r\nnumber num\r\noperand opnd\r\noptimization opt\r\noperator optr\r\npacket pkt\r\npositon pos\r\nprevious pre或prev\r\npayload type pt\r\npointer ptr\r\nreturn code rc\r\nrecord rcd\r\nreceive recv\r\nresult res\r\nreturn ret\r\nsource src\r\nstack stk\r\nstring str\r\nsubtraction sub\r\ntable tab\r\ntemporary tmp或temp\r\ntotal tot\r\ntime stamp ts\r\nvalue val\r\n\r\n**写在最后\r\n没有一种命名规则可以让所有的程序员赞同。而这多种命名规则也确实各有利弊。\r\n没有必要花太多的精力试图发明最好的命名规则,\r\n而是应当制定一种令大多数项目成员满意的命名规则并切实执行。\r\n标识符命名的一致性自然会体现出代码的优雅。\r\n当然,如果你的程序使用了第三方的代码,而这些模块经验证确实是正确无误的。\r\n那么也没有必要一味追求命名的一致性,而去修改这些已经定型的模块中的函数和变量名。**',0,9,NULL,'post','publish',NULL,0,'1','1','1',0),(41,'创建数据库用户&&赋予用户数据库(表)权限','41',1409946720,1410536112,'<!--markdown-->一.创建数据库用户\r\n\r\n首先用root账号进入MySQL:\r\n\r\n $ mysql -u root -p\r\n\r\n然后输入密码即可。\r\n\r\n\r\n新建用户有两种方式\r\n\r\n 1.> create user username@hostname identified by \'yourpassword\';\r\n\r\n 2.> insert into mysql.user(host,user,password) value(\'hostname\',\'username\',password(\'yourpassword\'));\r\n > flush privileges;\r\n\r\n说明:\r\nusername:即将创建的用户名;\r\nhostname:主机名。主机名为localhost表示用户可以本地登录;主机名为 % 表示远程访问,该用户可以从任意远程主机登陆。\r\nyourpassword:该用户密码。如果密码为空,则该用户可不通过密码直接登录服务器。密码为空也可以直接写为:\r\n\r\n > create user \'username\'@\'hostname\';\r\n\r\nflsu privileges:刷新权限。\r\n方法1设置后不需刷新权限即可生效;方法2需要刷新权限才能生效。\r\n\r\n例:\r\n\r\n > create user test@localhost identified by \'testpasswd\';\r\n > create user test@\'%\' identified by \'testpasswd\';\r\n创建一个用户名为test的用户,并设置其本地访问和远程访问。注意通配符 % 需要加引号。\r\n\r\n \r\n\r\n\r\n二.查看已有用户\r\n查看用户名,主机名,密码:\r\n\r\n > select user,host,password from mysql.user;\r\n\r\n\r\n三.删除已有用户\r\n删除也有两种方式。\r\n\r\n 1.> drop user username@hostname;\r\n 2.> delete from mysql.user where user=\'usrname\' and host=\'hostname\';\r\n\r\n说明:如果未指定主机名,则 drop user username 默认删除username@\'%\';如果没有 username@\'%\',则会提示 ERROR 1396 (HY000) 的错误。\r\n\r\n四.设置修改用户密码\r\n同样有两种方式。\r\n\r\n 1.> set password for username@\'hostname\' = password(\'newpassword\');\r\n 2.> update mysql.user password=password(\'newpassword\') where user=\'username\' and host=\'hostname\';\r\n同样,方法一不需要刷新即可生效;方法2需要刷新才能生效。\r\n\r\n\r\n五.为用户分配数据库及数据库表的权限\r\n\r\nMySQL给用户分配数据库(表)权限的命令可概括为\r\n\r\n grant 权限 on 数据库对象 to 用户\r\n\r\n1.分配某个数据库的所有权限\r\n\r\n > grant all privileges on db.* to username@\'%\';\r\n表示将数据库db中所有表的所有权限赋予用户username,通配符 % 表示可远程访问。 \r\n\r\n2.分配数据库中一个表的所有权限\r\n\r\n > grant all privileges on db.table to username@\'%\';\r\n表示将数据库db中的table表的所有权限赋予用户username。\r\n\r\n3.分配创建、修改、删除 MySQL 数据表结构权限。\r\n\r\n > grant create on db.* to username@\'%\';\r\n > grant alter on db.* to username@\'%\';\r\n > grant drop on db.* to username@\'%\';\r\n\r\n 操作 MySQL 外键权限\r\n\r\n > grant references on db.* to username@\'%\';\r\n\r\n 操作 MySQL 临时表权限\r\n\r\n > grant create temporary tables on db.* to username@\'%\';\r\n\r\n 操作 MySQL 索引权限\r\n\r\n > grant index on db.* to username@\'%\';\r\n \r\n 操作 MySQL 视图、查看视图源代码 权限\r\n\r\n > grant create view on db.* to username@\'%\';\r\n > grant show view on db.* to username@\'%\';\r\n\r\n 操作 MySQL 存储过程、函数 权限\r\n\r\n > grant create routine on db.* to username@\'%\'; -- now, can show procedure status\r\n > grant alter routine on db.* to username@\'%\'; -- now, you can drop a procedure\r\n > grant execute on db.* to username@\'%\';\r\n\r\n六.查看用户权限\r\n查看当前用户权限\r\n\r\n > show grants;\r\n查看其它用户权限\r\n\r\n > show grants for username@\'%\';\r\n\r\n\r\n七.撤销已经赋予给 MySQL 用户权限的权限。\r\n revoke 与 grant 的语法类似,只需要把关键字 “to” 换成 “from” 即可:\r\n\r\n > grant all on *.* to username@\'%\';\r\n > revoke all on *.* from username@\'%\';\r\n\r\n\r\n八.MySQL grant,revoke 用户权限注意事项\r\n\r\n1. grant, revoke 用户权限后,该用户只有重新连接 MySQL 数据库,权限才能生效。\r\n\r\n2. 如果想让授权的用户,也可以将这些权限 grant 给其他用户,需要选项 “grant option“\r\n\r\n > grant select on db.* to username@localhost with grant option;\r\n\r\n\r\n这个特性一般用不到。实际中,数据库权限最好由 管理员 来统一管理。\r\n\r\n\r\n',0,5,NULL,'post','publish',NULL,0,'1','1','1',0),(51,'网页退出事件的浏览器兼容',NULL,1410013416,1410013416,'<div id=\"JIATHIS_CODE_HTML2\">\n<div class=\"t_fsz\">\r\n<table cellspacing=\"0\" cellpadding=\"0\"><tr><td class=\"t_f\" id=\"postmessage_62962\">\r\n在开发 <strong>WebApp</strong>(通常是 <strong>单页面应用</strong>)时,我们通常不希望<strong>用户不小心离开</strong>我们的网页。但目前,各种浏览器对 网页退出、键盘按键事件的处理 差异不小,用一种看似符合标准的方法不足以确保拦截网页退出,我们只能“使出浑身解数”……<br><br>\r\n通常,<strong>用户退出一个网页的方式</strong> 包括 ——<br><ul>\n<li>关闭浏览器 或 其标签页<br><ul>\n<li>键盘关闭快捷键</li>\n<li>鼠标点击关闭按钮</li>\n<li>鼠标关闭手势<br>\n</li>\n</ul>\n</li>\n<li>地址栏网址改变</li>\n<li>浏览历史导航到不同的网址(# 之前的部分改变)<br><ul>\n<li>键盘后退/前进快捷键(通用 或 品牌机专用)</li>\n<li>鼠标点击后退/前进按钮</li>\n<li>鼠标后退/前进手势<br>\n</li>\n</ul>\n</li>\n</ul>\n<br>\r\n据此,我们可以用 jQuery 实现一个 <strong><font color=\"Blue\">$(window).exit() 方法</font></strong> ——<div class=\"blockcode\">\n<div id=\"code_Dvi\"><ol>\n<li>(function ($) {<br>\n</li>\n<li>    var NoticeText = \"误操作?您没想关闭本页面,是吧?\";<br>\n</li>\n<li>    var Blocked = 0;<br>\n</li>\n<li><br></li>\n<li>    function iConfirm(Text_Only) {<br>\n</li>\n<li>        if (! Blocked)  Blocked = 1;<br>\n</li>\n<li>        else return;<br>\n</li>\n<li><br></li>\n<li>        if  (Text_Only) {<br>\n</li>\n<li>            Blocked = 0;<br>\n</li>\n<li>            return NoticeText;<br>\n</li>\n<li>        } else if (confirm(NoticeText))  return false;<br>\n</li>\n<li>            else  return true;<br>\n</li>\n<li>    }<br>\n</li>\n<li><br></li>\n<li>    $.fn.exit = function (NT, NE_Bind) {<br>\n</li>\n<li>        if (!(this[0] instanceof Window))  return false;<br>\n</li>\n<li>        if ((typeof NT == \'string\') && (NT.length > 0))<br>\n</li>\n<li>            NoticeText = NT;<br>\n</li>\n<li>        NE_Bind = (NE_Bind === undefined) ? 1 : NE_Bind;<br>\n</li>\n<li><br></li>\n<li>        $DO.keydown(function (Event) {<br>\n</li>\n<li>            Blocked = 0;<br>\n</li>\n<li>            var KC = Event.keyCode;<br>\n</li>\n<li>            var CloseEvent = (<br>\n</li>\n<li>                (Event.altKey && (KC == 115)) ||                   //  Alt + F4<br>\n</li>\n<li>                (Event.ctrlKey && (KC == 87)) ||                   //  Ctrl + W<br>\n</li>\n<li>                (Event.ctrlKey && Event.shiftKey && (KC == 81))    //  Ctrl + Shift + Q<br>\n</li>\n<li>            ),  NavEvent = (<br>\n</li>\n<li>                (KC == 8) ||                                       //  BackSpace<br>\n</li>\n<li>                (Event.altKey && (KC == 37)) ||                    //  Alt + ←<br>\n</li>\n<li>                (Event.altKey && (KC == 39)) ||                    //  Alt + →<br>\n</li>\n<li>                (KC == 166)  ||  (KC == 167)                       //  OEM Specical NavButton<br>\n</li>\n<li>            );<br>\n</li>\n<li>            if (CloseEvent)  return iConfirm();<br>\n</li>\n<li>            else if (NE_Bind && NavEvent)<br>\n</li>\n<li>                if ((KC == 8) && Event.target.form)  return true;<br>\n</li>\n<li>                else  return iConfirm();<br>\n</li>\n<li>        });<br>\n</li>\n<li>        this.unload(function () {<br>\n</li>\n<li>            return iConfirm();<br>\n</li>\n<li>        }).bind(\'beforeunload\', function () {<br>\n</li>\n<li>            return iConfirm(1);<br>\n</li>\n<li>        });<br>\n</li>\n<li>    };<br>\n</li>\n<li>})(jQuery);</li>\n</ol></div>\n<em onclick=\"copycode($(\'code_Dvi\'));\"> </em>\n</div>示例 ——<div class=\"blockcode\">\n<div id=\"code_ve9\"><ol>\n<li>//  对某一级 Window 对象 启用“退出提示”(提示文字可留空为缺省,第二参数可禁用导航改变的拦截)<br>\n</li>\n<li>$(top).exit(\'\', false);</li>\n</ol></div>\n<em onclick=\"copycode($(\'code_ve9\'));\"> </em>\n</div>【参考文章】<br><ul type=\"1\" class=\"litype_1\">\n<li><a href=\"http://www.cnblogs.com/unique/archive/2009/04/17/1438065.html\" target=\"_blank\">http://www.cnblogs.com/unique/archive/2009/04/17/1438065.html</a></li>\n<li><a href=\"http://javascriptkeycodes.com/\" target=\"_blank\">http://javascriptkeycodes.com/</a></li>\n<li>\n<a href=\"http://www.asheep.cn/skill/onunload.html\" target=\"_blank\">http://www.asheep.cn/skill/onunload.html</a><br>\n</li>\n</ul>\n</td></tr></table>\n</div>\r\n<div id=\"comment_62962\" class=\"cm\">\r\n</div>\r\n</div>',0,1,NULL,'post','publish',NULL,0,'1','1','1',0),(39,'QQ图片20140906000828.jpg','QQ图片20140906000828-jpg',1409933562,1409933562,'a:5:{s:4:\"name\";s:26:\"QQ图片20140906000828.jpg\";s:4:\"path\";s:35:\"/usr/uploads/2014/09/3062111195.jpg\";s:4:\"size\";i:67402;s:4:\"type\";s:3:\"jpg\";s:4:\"mime\";s:10:\"image/jpeg\";}',2,9,NULL,'attachment','publish',NULL,0,'1','0','1',40),(40,'2014/9/5飞扬研发例会记录','40',1409929440,1410013670,'<!--markdown-->例会行程安排一览表\r\n1、一餐二楼小型聚餐\r\n2、综B111正式会议\r\n3、白家烧烤摊夜宵\r\n\r\n会议内容:\r\n1、部长展示了他新的又黄又暴力的PPT模板\r\n![QQ图片20140906000629.jpg][2]\r\n2、第一个议题 谁来记录会议内容 无辜躺枪人士泣不成声 T T\r\n3、第二个议题 SaySayJuan(3)Juan(3) 哦... 不对是JH\r\n JH作为GPA online的PM,项目进度延期达3个月 \r\n 这一切究竟是XXXX(自行脑补)还是XXXX(自行脑补)\r\n 请关注今晚的大型主题演讲——论如何成为一个失败的PM&&学渣\r\n4、JH主题演讲\r\n ①回顾了项目的102天,感谢了两位组员的贡献(CXY YGB)\r\n ②反思总结了上学期,点出了自己犯过的错误...巴拉巴拉的\r\n ③我只想安安静静写代码。![QQ图片20140906000550.jpg][3]\r\n5、部长总结,指出了一些我们的不足——项目经验和知识储备,以\r\n 及我们努力的方向和方法。JH的原因在部里每个人\r\n 的身上都或多或少有体现——拖沓、浮夸、不专心、懒……,![QQ图片20140906000529.jpg][4]\r\n **今天不是我们而是JH上去总结自己的错误,很大的原因是我们还没\r\n 有接手这样大的项目,我们每个人都或多或少存在着问题每个\r\n 人都还需要不断的前进,一直以来我真心觉得JH是个很努力的\r\n 人,他的努力使每一位研发人能看见的,我很佩服他,我也相\r\n 信他的努力会有收获的。最后研发2.0加油!**\r\n (PS.以上言论总结自多人再加上了我的自我感受)\r\n6、部长巴拉巴拉一堆话包括一些“code之前”“奖与罚”“正负能量”![QQ图片20140906000716.jpg][5]![QQ图片20140906000838.jpg][6]![QQ图片20140906000842.jpg][7]\r\n7、部长继续巴拉巴拉一些问题“无爱负能量”“确定面基时间”“基友会\r\n 组织者”“基友房(请关注群邮)”……\r\n9、小蓝答疑环节\r\n 关于InnoDB,MyISAM的选择——选MyISAM\r\n 关于堆栈的两种理解(firebug的不算)\r\n 关于MVC(Model View Controller)的理解\r\n 关于断点的理解\r\n 关于callback关于异步\r\n 巴拉巴拉\r\n10、好像没了....\r\n \r\n\r\nps.PPT附件已上传附件(有价值5元的PPT模板)![QQ图片20140906000828.jpg][8]\r\n\r\n[JHPPT](http://log.fyscu.com/usr/uploads/2014/09/549525290.pptx)\r\n[例会PPT]——死活传不上 也是醉了\r\npps.第一次写,有问题大家请指教,请轻喷\r\n\r\n\r\n [1]: http://log.fyscu.com/usr/uploads/2014/09/549525290.pptx\r\n [2]: http://log.fyscu.com/usr/uploads/2014/09/166474125.jpg\r\n [3]: http://log.fyscu.com/usr/uploads/2014/09/3585076068.jpg\r\n [4]: http://log.fyscu.com/usr/uploads/2014/09/452968601.jpg\r\n [5]: http://log.fyscu.com/usr/uploads/2014/09/2915171706.jpg\r\n [6]: http://log.fyscu.com/usr/uploads/2014/09/410271054.jpg\r\n [7]: http://log.fyscu.com/usr/uploads/2014/09/2482170320.jpg\r\n [8]: http://log.fyscu.com/usr/uploads/2014/09/3062111195.jpg',0,9,NULL,'post','publish',NULL,0,'1','1','1',0);
/*!40000 ALTER TABLE `typecho_contents` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `typecho_fields`
--
DROP TABLE IF EXISTS `typecho_fields`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `typecho_fields` (
`cid` int(10) unsigned NOT NULL,
`name` varchar(200) NOT NULL,
`type` varchar(8) DEFAULT 'str',
`str_value` text,
`int_value` int(10) DEFAULT '0',
`float_value` float DEFAULT '0',
PRIMARY KEY (`cid`,`name`),
KEY `int_value` (`int_value`),
KEY `float_value` (`float_value`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `typecho_fields`
--
LOCK TABLES `typecho_fields` WRITE;
/*!40000 ALTER TABLE `typecho_fields` DISABLE KEYS */;
INSERT INTO `typecho_fields` VALUES (293,'keywords','str','promise,javascript,JS',0,0),(292,'keywords','str','ES6,JS,javascript',0,0),(291,'keywords','str','http',0,0),(290,'keywords','str','redis,lbs,geo',0,0),(289,'keywords','str','redis',0,0),(288,'keywords','str','mysql,update',0,0),(286,'keywords','str','php,foreach,unset',0,0),(283,'keywords','str','oop',0,0),(282,'keywords','str','git,git-flow-flow',0,0),(281,'keywords','str','get,post,http',0,0),(280,'keywords','str','mysql,replace',0,0),(277,'keywords','str','javascript,object,defineProperty,Object.defineProperty',0,0),(276,'keywords','str','函数',0,0),(275,'keywords','str','php,autoload,oop',0,0),(274,'keywords','str','面向对象,oop',0,0),(261,'keywords','str','redis,LBS,地理信息',0,0),(260,'keywords','str','v8,js,优化',0,0),(249,'keywords','str','javascript,delete',0,0),(240,'keywords','str','http',0,0),(236,'keywords','str','sse,EventSource,推送',0,0),(198,'keywords','str','javascript,referer',0,0),(197,'keywords','str','跨域,http,CORS',0,0),(181,'keywords','str','express,跨域',0,0),(180,'keywords','str','jquery,绑定,javascript',0,0),(145,'keywords','str','setTimeout,setInterval,javascript',0,0),(131,'keywords','str','php,框架,fyscu',0,0),(120,'descriptions','str','angular倒序输出',0,0),(120,'keywords','str','angular,mvc,ng-repeat',0,0),(108,'descriptions','str','socket.io重复发送emit的问题',0,0),(108,'keywords','str','socket.io,node,express,angular',0,0),(90,'keywords','str','异步,javascript,setTimeout',0,0),(67,'keywords','str','javascript,闭包,作用域',0,0),(7,'keywords','str','Express,用户ip,反向代理',0,0),(61,'descriptions','str','软件设计,里氏替换,设计模式',0,0),(61,'keywords','str','软件设计,里氏替换,设计模式',0,0),(60,'descriptions','str','软件设计,开闭原则,设计模式',0,0),(60,'keywords','str','软件设计,开闭原则,设计模式',0,0),(43,'keywords','str','ubuntu,apache,服务器,linux',0,0),(28,'keywords','str','M3U,M3U8',0,0),(294,'keywords','str','promise,javascript',0,0),(295,'keywords','str','generator,yield,promise',0,0),(296,'keywords','str','php,array,json',0,0),(297,'keywords','str','elasticsearch,es',0,0),(298,'keywords','str','php,pdo,事务',0,0),(299,'keywords','str','php,die,exit',0,0),(301,'keywords','str','php,psr2,phpcs',0,0),(302,'keywords','str','javascript,js,node',0,0),(304,'keywords','str','node,命令行',0,0),(305,'keywords','str','结构化,schema',0,0),(306,'keywords','str','js,javascript',0,0),(307,'keywords','str','ci,cd,gitlab',0,0),(308,'keywords','str','js,javascript,有限状态机',0,0),(310,'keywords','str','前后分离',0,0),(311,'keywords','str','node,npm,package',0,0),(315,'keywords','str','javascript,node',0,0),(316,'keywords','str','javascript,优化',0,0),(317,'keywords','str','three.js,webgl',0,0);
/*!40000 ALTER TABLE `typecho_fields` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `typecho_metas`
--
DROP TABLE IF EXISTS `typecho_metas`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `typecho_metas` (
`mid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL,
`slug` varchar(200) DEFAULT NULL,
`type` varchar(32) NOT NULL,
`description` varchar(200) DEFAULT NULL,
`count` int(10) unsigned DEFAULT '0',
`order` int(10) unsigned DEFAULT '0',
`parent` int(10) unsigned DEFAULT '0',
PRIMARY KEY (`mid`),
KEY `slug` (`slug`)
) ENGINE=MyISAM AUTO_INCREMENT=77 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `typecho_metas`
--
LOCK TABLES `typecho_metas` WRITE;
/*!40000 ALTER TABLE `typecho_metas` DISABLE KEYS */;
INSERT INTO `typecho_metas` VALUES (1,'乱七八糟','default','category','根本无法归类',51,1,0),(2,'性感的程序员','programmer','category','研发部的一群性感的程序猿/程序媛的碎碎念?',58,2,0),(3,'linux','linux','tag',NULL,5,0,0),(4,'ubuntu','ubuntu','tag',NULL,5,0,0),(46,'apache','apache','tag',NULL,1,0,0),(44,'mysql','mysql','tag',NULL,1,0,0),(45,'php','php','tag',NULL,2,0,0),(43,'lamp','lamp','tag',NULL,2,0,0),(42,'搜狗输入法','搜狗输入法','tag',NULL,1,0,0),(41,'flash player','flash-player','tag',NULL,1,0,0),(40,'nginx','nginx','tag',NULL,1,0,0),(39,'异步编程','异步编程','tag',NULL,1,0,0),(38,'响应式设计','响应式设计','tag',NULL,1,0,0),(37,'原创作品','原创作品','tag',NULL,4,0,0),(36,'firefox','firefox','tag',NULL,1,0,0),(35,'收藏','收藏','tag',NULL,1,0,0),(34,'css','css','tag',NULL,2,0,0),(33,'面向对象','面向对象','tag',NULL,1,0,0),(32,'网页设计','网页设计','tag',NULL,10,0,0),(31,'福利','福利','tag',NULL,1,0,0),(30,'兼容性','兼容性','tag',NULL,1,0,0),(29,'事件','事件','tag',NULL,1,0,0),(28,'入门教程','入门教程','tag',NULL,2,0,0),(27,'开源代码','开源代码','tag',NULL,8,0,0),(26,'网页浏览器','网页浏览器','tag',NULL,7,0,0),(25,'实用工具','实用工具','tag',NULL,3,0,0),(24,'bug','bug','tag',NULL,1,0,0),(23,'框架','框架','tag',NULL,1,0,0),(22,'ie','ie','tag',NULL,1,0,0),(21,'应用开发','应用开发','tag',NULL,7,0,0),(20,'jquery','jquery','tag',NULL,3,0,0),(19,'技巧','技巧','tag',NULL,1,0,0),(18,'编程','编程','tag',NULL,1,0,0),(17,'实用代码','实用代码','tag',NULL,4,0,0),(16,'前端开发','前端开发','tag',NULL,1,0,0),(15,'javascript','javascript','tag',NULL,10,0,0),(14,'浏览器','浏览器','tag',NULL,1,0,0),(13,'web','web','tag',NULL,3,0,0),(12,'原创','原创','tag',NULL,2,0,0),(11,'小蓝','lan','category',NULL,50,4,0),(10,'markdown','markdown','tag',NULL,1,0,0),(9,'水哥专栏','waterbrother','category','用于存放原《电脑答疑》板块的干货',23,3,0),(8,'js','js','tag',NULL,1,0,0),(7,'安装','安装','tag',NULL,3,0,0),(6,'node','node','tag',NULL,1,0,0),(5,'mongodb','mongodb','tag',NULL,1,0,0),(76,'#搞机','yingjian','category','硬件知识,机器推荐,拆机清灰经验总结,同好交流~',0,3,0),(75,'#more bigger','zhuangbility','category','更多逼格!\r\n有什么好玩的厉害的(装哔----的)都分享给大家吧!',0,2,0),(47,'html5','html5','tag',NULL,1,0,0),(48,'用户体验','用户体验','tag',NULL,1,0,0),(49,'学习笔记','学习笔记','tag',NULL,4,0,0),(50,'中文处理','中文处理','tag',NULL,1,0,0),(51,'移动互联网','移动互联网','tag',NULL,1,0,0),(52,'设计','设计','tag',NULL,1,0,0),(53,'产品设计','产品设计','tag',NULL,1,0,0),(54,'项目','项目','category','研发2.0的各种项目汇总',2,1,2),(55,'活动','活动','tag',NULL,1,0,0),(56,'翻墙','翻墙','tag',NULL,2,0,0),(57,'搜索引擎','搜索引擎','tag',NULL,1,0,0),(58,'服务器配置','服务器配置','tag',NULL,1,0,0),(59,'ssh','ssh','tag',NULL,1,0,0),(60,'网页动画','网页动画','tag',NULL,1,0,0),(61,'二维码','二维码','tag',NULL,1,0,0),(62,'开放api','开放api','tag',NULL,1,0,0),(63,'开源项目','开源项目','tag',NULL,1,0,0),(64,'用户组','用户组','tag',NULL,1,0,0),(65,'[email protected]','dsgygb-126-com','tag',NULL,2,0,0),(66,'nodejs','nodejs','tag',NULL,1,0,0),(67,'docker','docker','tag',NULL,1,0,0),(68,'会议','会议','tag',NULL,1,0,0),(69,'记录','记录','tag',NULL,1,0,0),(70,'莫回首','莫回首','category',NULL,1,6,0),(71,'设计模式','设计模式','tag',NULL,1,0,0),(72,'nodejh','nodejh','category',NULL,1,5,0),(73,'delete','delete','tag',NULL,1,0,0),(74,'内部属性','内部属性','tag',NULL,1,0,0);
/*!40000 ALTER TABLE `typecho_metas` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `typecho_options`
--
DROP TABLE IF EXISTS `typecho_options`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `typecho_options` (
`name` varchar(32) NOT NULL,
`user` int(10) unsigned NOT NULL DEFAULT '0',
`value` text,
PRIMARY KEY (`name`,`user`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `typecho_options`
--
LOCK TABLES `typecho_options` WRITE;
/*!40000 ALTER TABLE `typecho_options` DISABLE KEYS */;
INSERT INTO `typecho_options` VALUES ('theme',0,'betterme'),('timezone',0,'28800'),('charset',0,'UTF-8'),('contentType',0,'text/html'),('gzip',0,'0'),('generator',0,'Typecho 1.0/14.10.10'),('title',0,'术业有专攻'),('description',0,'飞扬俱乐部用来记录一些有用的东西'),('autoSave',1,'1'),('keywords',0,'四川大学飞扬俱乐部,飞扬研发'),('rewrite',0,'0'),('frontPage',0,'recent'),('frontArchive',0,'0'),('commentsRequireMail',0,'1'),('commentsWhitelist',0,'0'),('commentsRequireURL',0,'0'),('commentsRequireModeration',0,'0'),('plugins',0,'a:2:{s:9:\"activated\";a:0:{}s:7:\"handles\";a:0:{}}'),('commentDateFormat',0,'F jS, Y \\a\\t h:i a'),('siteUrl',0,'http://log.fyscu.com'),('defaultCategory',0,'1'),('allowRegister',0,'1'),('defaultAllowComment',0,'1'),('defaultAllowPing',0,'1'),('defaultAllowFeed',0,'1'),('pageSize',0,'5'),('postsListSize',0,'10'),('commentsListSize',0,'10'),('commentsHTMLTagAllowed',0,NULL),('postDateFormat',0,'Y-m-d'),('feedFullText',0,'1'),('editorSize',0,'350'),('autoSave',0,'0'),('markdown',0,'1'),('commentsMaxNestingLevels',0,'5'),('commentsPostTimeout',0,'2592000'),('commentsUrlNofollow',0,'1'),('commentsShowUrl',0,'1'),('commentsMarkdown',0,'0'),('commentsPageBreak',0,'0'),('commentsThreaded',0,'1'),('commentsPageSize',0,'20'),('commentsPageDisplay',0,'last'),('commentsOrder',0,'ASC'),('commentsCheckReferer',0,'1'),('commentsAutoClose',0,'0'),('commentsPostIntervalEnable',0,'1'),('commentsPostInterval',0,'60'),('commentsShowCommentOnly',0,'0'),('commentsAvatar',0,'1'),('commentsAvatarRating',0,'G'),('routingTable',0,'a:26:{i:0;a:25:{s:5:\"index\";a:6:{s:3:\"url\";s:1:\"/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:8:\"|^[/]?$|\";s:6:\"format\";s:1:\"/\";s:6:\"params\";a:0:{}}s:7:\"archive\";a:6:{s:3:\"url\";s:6:\"/blog/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:13:\"|^/blog[/]?$|\";s:6:\"format\";s:6:\"/blog/\";s:6:\"params\";a:0:{}}s:2:\"do\";a:6:{s:3:\"url\";s:22:\"/action/[action:alpha]\";s:6:\"widget\";s:9:\"Widget_Do\";s:6:\"action\";s:6:\"action\";s:4:\"regx\";s:32:\"|^/action/([_0-9a-zA-Z-]+)[/]?$|\";s:6:\"format\";s:10:\"/action/%s\";s:6:\"params\";a:1:{i:0;s:6:\"action\";}}s:4:\"post\";a:6:{s:3:\"url\";s:24:\"/archives/[cid:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:26:\"|^/archives/([0-9]+)[/]?$|\";s:6:\"format\";s:13:\"/archives/%s/\";s:6:\"params\";a:1:{i:0;s:3:\"cid\";}}s:10:\"attachment\";a:6:{s:3:\"url\";s:26:\"/attachment/[cid:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:28:\"|^/attachment/([0-9]+)[/]?$|\";s:6:\"format\";s:15:\"/attachment/%s/\";s:6:\"params\";a:1:{i:0;s:3:\"cid\";}}s:8:\"category\";a:6:{s:3:\"url\";s:17:\"/category/[slug]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:25:\"|^/category/([^/]+)[/]?$|\";s:6:\"format\";s:13:\"/category/%s/\";s:6:\"params\";a:1:{i:0;s:4:\"slug\";}}s:3:\"tag\";a:6:{s:3:\"url\";s:12:\"/tag/[slug]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:20:\"|^/tag/([^/]+)[/]?$|\";s:6:\"format\";s:8:\"/tag/%s/\";s:6:\"params\";a:1:{i:0;s:4:\"slug\";}}s:6:\"author\";a:6:{s:3:\"url\";s:22:\"/author/[uid:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:24:\"|^/author/([0-9]+)[/]?$|\";s:6:\"format\";s:11:\"/author/%s/\";s:6:\"params\";a:1:{i:0;s:3:\"uid\";}}s:6:\"search\";a:6:{s:3:\"url\";s:19:\"/search/[keywords]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:23:\"|^/search/([^/]+)[/]?$|\";s:6:\"format\";s:11:\"/search/%s/\";s:6:\"params\";a:1:{i:0;s:8:\"keywords\";}}s:10:\"index_page\";a:6:{s:3:\"url\";s:21:\"/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:22:\"|^/page/([0-9]+)[/]?$|\";s:6:\"format\";s:9:\"/page/%s/\";s:6:\"params\";a:1:{i:0;s:4:\"page\";}}s:12:\"archive_page\";a:6:{s:3:\"url\";s:26:\"/blog/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:27:\"|^/blog/page/([0-9]+)[/]?$|\";s:6:\"format\";s:14:\"/blog/page/%s/\";s:6:\"params\";a:1:{i:0;s:4:\"page\";}}s:13:\"category_page\";a:6:{s:3:\"url\";s:32:\"/category/[slug]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:34:\"|^/category/([^/]+)/([0-9]+)[/]?$|\";s:6:\"format\";s:16:\"/category/%s/%s/\";s:6:\"params\";a:2:{i:0;s:4:\"slug\";i:1;s:4:\"page\";}}s:8:\"tag_page\";a:6:{s:3:\"url\";s:27:\"/tag/[slug]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:29:\"|^/tag/([^/]+)/([0-9]+)[/]?$|\";s:6:\"format\";s:11:\"/tag/%s/%s/\";s:6:\"params\";a:2:{i:0;s:4:\"slug\";i:1;s:4:\"page\";}}s:11:\"author_page\";a:6:{s:3:\"url\";s:37:\"/author/[uid:digital]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:33:\"|^/author/([0-9]+)/([0-9]+)[/]?$|\";s:6:\"format\";s:14:\"/author/%s/%s/\";s:6:\"params\";a:2:{i:0;s:3:\"uid\";i:1;s:4:\"page\";}}s:11:\"search_page\";a:6:{s:3:\"url\";s:34:\"/search/[keywords]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:32:\"|^/search/([^/]+)/([0-9]+)[/]?$|\";s:6:\"format\";s:14:\"/search/%s/%s/\";s:6:\"params\";a:2:{i:0;s:8:\"keywords\";i:1;s:4:\"page\";}}s:12:\"archive_year\";a:6:{s:3:\"url\";s:18:\"/[year:digital:4]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:19:\"|^/([0-9]{4})[/]?$|\";s:6:\"format\";s:4:\"/%s/\";s:6:\"params\";a:1:{i:0;s:4:\"year\";}}s:13:\"archive_month\";a:6:{s:3:\"url\";s:36:\"/[year:digital:4]/[month:digital:2]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:30:\"|^/([0-9]{4})/([0-9]{2})[/]?$|\";s:6:\"format\";s:7:\"/%s/%s/\";s:6:\"params\";a:2:{i:0;s:4:\"year\";i:1;s:5:\"month\";}}s:11:\"archive_day\";a:6:{s:3:\"url\";s:52:\"/[year:digital:4]/[month:digital:2]/[day:digital:2]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:41:\"|^/([0-9]{4})/([0-9]{2})/([0-9]{2})[/]?$|\";s:6:\"format\";s:10:\"/%s/%s/%s/\";s:6:\"params\";a:3:{i:0;s:4:\"year\";i:1;s:5:\"month\";i:2;s:3:\"day\";}}s:17:\"archive_year_page\";a:6:{s:3:\"url\";s:38:\"/[year:digital:4]/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:33:\"|^/([0-9]{4})/page/([0-9]+)[/]?$|\";s:6:\"format\";s:12:\"/%s/page/%s/\";s:6:\"params\";a:2:{i:0;s:4:\"year\";i:1;s:4:\"page\";}}s:18:\"archive_month_page\";a:6:{s:3:\"url\";s:56:\"/[year:digital:4]/[month:digital:2]/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:44:\"|^/([0-9]{4})/([0-9]{2})/page/([0-9]+)[/]?$|\";s:6:\"format\";s:15:\"/%s/%s/page/%s/\";s:6:\"params\";a:3:{i:0;s:4:\"year\";i:1;s:5:\"month\";i:2;s:4:\"page\";}}s:16:\"archive_day_page\";a:6:{s:3:\"url\";s:72:\"/[year:digital:4]/[month:digital:2]/[day:digital:2]/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:55:\"|^/([0-9]{4})/([0-9]{2})/([0-9]{2})/page/([0-9]+)[/]?$|\";s:6:\"format\";s:18:\"/%s/%s/%s/page/%s/\";s:6:\"params\";a:4:{i:0;s:4:\"year\";i:1;s:5:\"month\";i:2;s:3:\"day\";i:3;s:4:\"page\";}}s:12:\"comment_page\";a:6:{s:3:\"url\";s:53:\"[permalink:string]/comment-page-[commentPage:digital]\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:36:\"|^(.+)/comment\\-page\\-([0-9]+)[/]?$|\";s:6:\"format\";s:18:\"%s/comment-page-%s\";s:6:\"params\";a:2:{i:0;s:9:\"permalink\";i:1;s:11:\"commentPage\";}}s:4:\"feed\";a:6:{s:3:\"url\";s:20:\"/feed[feed:string:0]\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:4:\"feed\";s:4:\"regx\";s:17:\"|^/feed(.*)[/]?$|\";s:6:\"format\";s:7:\"/feed%s\";s:6:\"params\";a:1:{i:0;s:4:\"feed\";}}s:8:\"feedback\";a:6:{s:3:\"url\";s:31:\"[permalink:string]/[type:alpha]\";s:6:\"widget\";s:15:\"Widget_Feedback\";s:6:\"action\";s:6:\"action\";s:4:\"regx\";s:29:\"|^(.+)/([_0-9a-zA-Z-]+)[/]?$|\";s:6:\"format\";s:5:\"%s/%s\";s:6:\"params\";a:2:{i:0;s:9:\"permalink\";i:1;s:4:\"type\";}}s:4:\"page\";a:6:{s:3:\"url\";s:12:\"/[slug].html\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";s:4:\"regx\";s:22:\"|^/([^/]+)\\.html[/]?$|\";s:6:\"format\";s:8:\"/%s.html\";s:6:\"params\";a:1:{i:0;s:4:\"slug\";}}}s:5:\"index\";a:3:{s:3:\"url\";s:1:\"/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:7:\"archive\";a:3:{s:3:\"url\";s:6:\"/blog/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:2:\"do\";a:3:{s:3:\"url\";s:22:\"/action/[action:alpha]\";s:6:\"widget\";s:9:\"Widget_Do\";s:6:\"action\";s:6:\"action\";}s:4:\"post\";a:3:{s:3:\"url\";s:24:\"/archives/[cid:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:10:\"attachment\";a:3:{s:3:\"url\";s:26:\"/attachment/[cid:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:8:\"category\";a:3:{s:3:\"url\";s:17:\"/category/[slug]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:3:\"tag\";a:3:{s:3:\"url\";s:12:\"/tag/[slug]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:6:\"author\";a:3:{s:3:\"url\";s:22:\"/author/[uid:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:6:\"search\";a:3:{s:3:\"url\";s:19:\"/search/[keywords]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:10:\"index_page\";a:3:{s:3:\"url\";s:21:\"/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:12:\"archive_page\";a:3:{s:3:\"url\";s:26:\"/blog/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:13:\"category_page\";a:3:{s:3:\"url\";s:32:\"/category/[slug]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:8:\"tag_page\";a:3:{s:3:\"url\";s:27:\"/tag/[slug]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:11:\"author_page\";a:3:{s:3:\"url\";s:37:\"/author/[uid:digital]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:11:\"search_page\";a:3:{s:3:\"url\";s:34:\"/search/[keywords]/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:12:\"archive_year\";a:3:{s:3:\"url\";s:18:\"/[year:digital:4]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:13:\"archive_month\";a:3:{s:3:\"url\";s:36:\"/[year:digital:4]/[month:digital:2]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:11:\"archive_day\";a:3:{s:3:\"url\";s:52:\"/[year:digital:4]/[month:digital:2]/[day:digital:2]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:17:\"archive_year_page\";a:3:{s:3:\"url\";s:38:\"/[year:digital:4]/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:18:\"archive_month_page\";a:3:{s:3:\"url\";s:56:\"/[year:digital:4]/[month:digital:2]/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:16:\"archive_day_page\";a:3:{s:3:\"url\";s:72:\"/[year:digital:4]/[month:digital:2]/[day:digital:2]/page/[page:digital]/\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:12:\"comment_page\";a:3:{s:3:\"url\";s:53:\"[permalink:string]/comment-page-[commentPage:digital]\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}s:4:\"feed\";a:3:{s:3:\"url\";s:20:\"/feed[feed:string:0]\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:4:\"feed\";}s:8:\"feedback\";a:3:{s:3:\"url\";s:31:\"[permalink:string]/[type:alpha]\";s:6:\"widget\";s:15:\"Widget_Feedback\";s:6:\"action\";s:6:\"action\";}s:4:\"page\";a:3:{s:3:\"url\";s:12:\"/[slug].html\";s:6:\"widget\";s:14:\"Widget_Archive\";s:6:\"action\";s:6:\"render\";}}'),('actionTable',0,'a:0:{}'),('panelTable',0,'a:0:{}'),('attachmentTypes',0,'@image@,@media@,@doc@'),('theme:betterme',0,'a:2:{s:7:\"logoUrl\";N;s:12:\"sidebarBlock\";a:5:{i:0;s:15:\"ShowRecentPosts\";i:1;s:18:\"ShowRecentComments\";i:2;s:12:\"ShowCategory\";i:3;s:11:\"ShowArchive\";i:4;s:9:\"ShowOther\";}}'),('editorSize',5,'393'),('editorSize',4,'621'),('editorSize',2,'382'),('editorSize',9,'319'),('editorSize',13,'448'),('secret',0,'@pmxlU@3Zjd^)z5)6N9G$daQ3sn5nyrf'),('lang',0,NULL),('commentsAntiSpam',0,'1'),('autoSave',30,'1'),('markdown',30,'1'),('defaultAllowComment',30,'1'),('defaultAllowPing',30,'1'),('defaultAllowFeed',30,'1'),('xmlrpcMarkdown',0,'0'),('installed',0,'1'),('allowXmlRpc',0,'0'),('markdown',1,'1'),('xmlrpcMarkdown',1,'0'),('defaultAllowComment',1,'1'),('defaultAllowPing',1,'1'),('defaultAllowFeed',1,'1');
/*!40000 ALTER TABLE `typecho_options` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `typecho_relationships`
--
DROP TABLE IF EXISTS `typecho_relationships`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `typecho_relationships` (
`cid` int(10) unsigned NOT NULL,
`mid` int(10) unsigned NOT NULL,
PRIMARY KEY (`cid`,`mid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `typecho_relationships`
--
LOCK TABLES `typecho_relationships` WRITE;
/*!40000 ALTER TABLE `typecho_relationships` DISABLE KEYS */;
INSERT INTO `typecho_relationships` VALUES (7,11),(9,2),(10,2),(13,2),(14,2),(14,3),(14,4),(14,5),(14,6),(14,7),(15,2),(15,8),(16,2),(18,1),(19,2),(21,2),(23,2),(27,1),(28,11),(32,1),(40,1),(41,2),(42,1),(43,2),(44,1),(44,10),(45,1),(51,9),(52,1),(53,1),(54,2),(55,2),(56,2),(58,2),(59,2),(60,11),(61,11),(62,1),(63,1),(64,2),(67,11),(68,9),(68,12),(68,13),(68,14),(68,15),(68,16),(68,17),(69,9),(70,1),(80,1),(81,9),(81,13),(81,15),(81,18),(81,19),(81,20),(81,21),(82,1),(90,11),(93,11),(94,9),(94,13),(94,15),(94,21),(94,22),(94,23),(94,24),(95,11),(96,1),(97,1),(99,2),(102,1),(104,1),(108,11),(118,2),(118,9),(118,12),(118,21),(118,25),(118,26),(118,27),(119,2),(119,9),(119,15),(119,20),(119,28),(119,29),(119,30),(120,11),(121,1),(122,2),(122,9),(122,15),(122,21),(122,27),(122,31),(122,32),(123,2),(123,9),(123,15),(123,27),(123,32),(123,33),(124,1),(125,2),(125,9),(125,17),(125,21),(125,26),(125,32),(125,34),(125,35),(125,36),(126,1),(129,1),(130,2),(130,9),(130,15),(130,21),(130,27),(130,37),(130,38),(130,39),(131,11),(132,2),(132,3),(132,40),(133,1),(140,1),(141,2),(144,2),(145,11),(146,2),(147,1),(155,1),(156,1),(156,3),(156,4),(156,43),(156,44),(156,45),(156,46),(174,1),(174,4),(174,7),(174,42),(175,2),(175,4),(175,7),(175,41),(176,2),(176,9),(176,27),(176,32),(176,47),(176,48),(177,2),(177,9),(177,15),(177,27),(177,32),(180,1),(180,11),(181,11),(182,2),(183,2),(183,9),(183,32),(183,34),(183,49),(183,50),(184,1),(185,1),(187,9),(187,21),(187,32),(187,49),(188,9),(188,26),(188,49),(188,51),(189,1),(191,2),(191,9),(193,1),(195,2),(195,9),(196,1),(197,1),(198,1),(199,2),(199,52),(199,53),(200,1),(201,1),(202,9),(202,27),(202,32),(202,37),(204,54),(206,1),(207,2),(207,54),(207,55),(209,1),(210,2),(210,9),(210,25),(210,26),(210,56),(211,2),(211,9),(211,25),(211,26),(211,27),(211,37),(211,56),(211,57),(212,2),(212,9),(212,25),(212,26),(212,56),(214,2),(214,3),(214,58),(214,59),(215,1),(216,1),(216,2),(217,1),(218,2),(218,3),(218,64),(219,2),(220,1),(221,9),(221,17),(221,20),(221,32),(221,60),(222,54),(223,2),(224,9),(224,17),(224,26),(224,32),(224,37),(225,9),(225,15),(225,26),(225,61),(225,62),(225,63),(226,9),(227,1),(228,2),(229,2),(229,72),(231,2),(231,65),(234,11),(236,11),(237,1),(237,11),(239,9),(239,26),(239,30),(239,37),(239,54),(239,63),(240,11),(241,2),(242,2),(242,65),(243,2),(244,2),(245,2),(246,2),(247,1),(248,1),(249,11),(250,1),(251,1),(251,11),(256,1),(257,2),(259,1),(260,11),(261,11),(262,2),(262,66),(264,1),(265,1),(266,2),(267,2),(268,2),(269,2),(270,11),(271,2),(272,4),(272,9),(272,28),(272,43),(272,49),(272,67),(274,11),(275,11),(276,11),(277,11),(278,1),(280,11),(281,11),(282,11),(283,1),(286,11),(287,1),(287,68),(287,69),(288,11),(289,11),(290,11),(291,11),(292,1),(293,1),(294,11),(295,11),(296,11),(297,11),(298,11),(299,11),(300,45),(300,70),(300,71),(301,1),(302,11),(303,2),(303,15),(303,72),(303,73),(303,74),(304,11),(305,11),(306,11),(307,11),(308,11),(310,1),(311,11),(315,11),(316,1),(317,11);
/*!40000 ALTER TABLE `typecho_relationships` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `typecho_users`
--
DROP TABLE IF EXISTS `typecho_users`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `typecho_users` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL,
`mail` varchar(200) DEFAULT NULL,
`url` varchar(200) DEFAULT NULL,
`screenName` varchar(32) DEFAULT NULL,
`created` int(10) unsigned DEFAULT '0',
`activated` int(10) unsigned DEFAULT '0',
`logged` int(10) unsigned DEFAULT '0',
`group` varchar(16) DEFAULT 'visitor',
`authCode` varchar(64) DEFAULT NULL,
PRIMARY KEY (`uid`),
UNIQUE KEY `name` (`name`),
UNIQUE KEY `mail` (`mail`)
) ENGINE=MyISAM AUTO_INCREMENT=89 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `typecho_users`
--
LOCK TABLES `typecho_users` WRITE;
/*!40000 ALTER TABLE `typecho_users` DISABLE KEYS */;
INSERT INTO `typecho_users` VALUES (1,'admin','$T$kX6So9NrTfc73bd2658b7d07c993309772301e4d3','[email protected]','http://fyscu.com','飞扬俱乐部',1404240429,1415110244,1410502309,'administrator','4e078886803148170dc3fb5d0cd971b1'),(2,'lanhao','$T$EkzvuviPubf4a8dcfb4727f2de3ffc5b23f2c8681','[email protected]','http://www.lanhao.name','小蓝',1404241654,1550499432,1524375982,'administrator','dda1d800fb6c3b13ab9de26e6eb6184a'),(26,'小威_Ian','$P$B18pJS5Yz09.ticQIvKpYaFjK6TXJ8.','[email protected]',NULL,'小威_Ian',1415712149,1422274667,1415712414,'subscriber','279aab26389d34bc6ba66328b01e3083'),(35,'UC用户_18653369105','b578ce2b9437ca25fb13132b06328357',NULL,NULL,'UC用户_18653369105',1429065516,1429065674,0,'subscriber',NULL),(4,'dsgygb','$T$diXhFbJ4u6236636c895e1ba6a13cd9a903ddd2d0','[email protected]',NULL,'杨国宝',1404258412,1446571454,1427793301,'administrator','fc317ac72302fc39118708a5a5edaf6c'),(5,'nodejh','$P$BTC2ws4LKDMWs0I9H5YrLHVaErgQ5Z1','[email protected]','http://nodejh.com','蒋航',1405660197,1482911448,1481883712,'editor','8145de67286512e6b92ca6c3044db26b'),(7,'小白','$T$YsGOVluXg2875a6f0458c1df713d69016d0e2730b','[email protected]',NULL,'小白',1407998101,1474970110,1463287401,'administrator','efc576f984729901d0410cd910df0e8f'),(9,'吴磊城啦啦啦','$T$41L9JzKU79814d9e906e9d6a114efdb33a142c0fb','[email protected]','http://c.fyscu.com','吴磊城啦啦啦',1409750503,1422874792,1412098438,'editor','70231e25cd3cd2c070ff8cad3e83bc74'),(11,'孙建平','$T$9iMcwO8r4c863c97272411abda971e7f7f8ffc35d','[email protected]',NULL,'孙建平',1410004487,1410004488,0,'subscriber','91b95b20d77702db1822395efe6e95ec8f65802e'),(10,'吴杰超','$T$DIs2qKWAXf9cb02429f606b221fd21bf4f3c99824','[email protected]',NULL,'吴杰超',1409751241,1455524640,1454922588,'editor','27d82421d0fc9dcb1adceaae4e3135ea'),(12,'马丹','$T$Y2wPcCt64e1341f1425ca2b0a87fb381044303c05','[email protected]',NULL,'马丹',1410007220,1410281033,0,'subscriber','318e57a69409edfcabcee463d2a58cb3c9daf817'),(13,'test_32','$T$EWCm7g2Cvd4f39a6b4d6400ec5e4c9b1512d07b1b','[email protected]','http://fyscu.com/wiki/User:test_32','test_32',1410397306,1463110094,1463024702,'editor','15f9e64ac85e70113db5d2df83916a1c'),(15,'小鱼.php','$T$niIYMA6gJ76cb35abbef863d0eda2fc03a76ecc43','[email protected]',NULL,'小鱼.php',1410535182,1491887499,1410541979,'editor','c1ee48aeab158202c277b32e36aabf26'),(34,'UC用户_18084814782','1a69cf72cb53831d1ad2e2b4acaf7df3',NULL,NULL,'UC用户_18084814782',1428989020,1429030133,0,'subscriber',NULL),(33,'UC用户_13980643012','f6b2ec41fd5df4d3d0ee6832964a4ea6',NULL,NULL,'UC用户_13980643012',1428982076,1437447973,0,'subscriber',NULL),(17,'Rsvns','$T$Yz5t4KK8oa7186dda0754478a7032e4fa6b09819d','[email protected]',NULL,'Rsvns',1410772984,1410773067,0,'subscriber','3c528db66c6072fb57ad9fe9772d291ff7c00a62'),(18,'Khuntoria 薰','$T$l16OmcJQka5bcc4642912bd7721aebd5ef6110690','[email protected]',NULL,'Khuntoria 薰',1410874889,1410874979,0,'subscriber','8dcd64d58ba7ac0acdc795d71861e5a999490de9'),(19,'test','$T$pItEGfyqxf60f6003c8a36d499a01a5b38a978dca','[email protected]',NULL,'test',1410969170,1410969267,0,'subscriber','9cc79124782d4e75032635ebeb7ff23d53de8d68'),(20,'_玖','$T$qLgNM5kVaec8fbf89436292be45295223351cbfd9','[email protected]',NULL,'_玖',1411060129,1419067846,1417878816,'editor','c792559762521039a8121618f121e162'),(28,NULL,'$P$BKiVw/WPI72lrs6a0wDN.0/f/1e2lb.',NULL,NULL,NULL,1417879408,0,0,'subscriber',NULL),(22,'Rapunzel','$T$AuRMYvtNu4ec4a25a23465f520da7af7e60e06f56','[email protected]',NULL,'Rapunzel',1411573053,1411835532,1411573385,'editor','b336b7b0f0dcbf527ae2566b63c056084048c667'),(23,'饭饭','$P$BJ4dsMvmqInWGwTFD1T6e2IRHrGJWx0','[email protected]',NULL,'饭饭',1413210124,1413210162,0,'subscriber','4e53057ab043159db77263100c532cab'),(24,'slina009720','$P$BArrOCoyaS9q5jrWwtXHgqDp5ekXoF0','[email protected]',NULL,'slina009720',1413791968,1413792085,0,'subscriber','b5703a349721128235d9dcea20fb9197'),(25,'LC','$P$BJxnlpYfdXWIDEgXkYY5RF.jZrchcD0','[email protected]',NULL,'LC',1414253444,1414253696,0,'subscriber','ce16218cb8e3a5ce9d0b7a6b9347214a'),(27,'Belladonna','$P$BaaWiV90C6qxKtvyMBR2O.qTWY2Kic0','[email protected]',NULL,'Belladonna',1417877883,0,0,'subscriber',NULL),(29,NULL,'$P$B2VJ7uPmonrVwyoJH9gCCodZYKQgL1.',NULL,NULL,NULL,1424230997,0,0,'subscriber',NULL),(30,'莫回首','$P$B9mH6p0MquOOK8Pqk9cE9Dt9XL.mmG1','[email protected]','http://lxl520.com','莫回首',1427513242,1470813162,1427513334,'editor','9c2c77a0aff875c5aea25d62216df071'),(31,NULL,'$P$BmOaZoz8ujyIV0xtYzx05g6KZaJCVJ0',NULL,NULL,NULL,1428731919,0,0,'subscriber',NULL),(36,'UC用户_15928531260','ec4a57bb5bb97c3d81cb8a751685185e',NULL,NULL,'UC用户_15928531260',1430718935,1430718978,0,'subscriber',NULL),(37,'UC用户_18380140713','688cd6a9839e51731ed35a915bba33fc',NULL,NULL,'Bohesody',1431174264,1447507386,0,'subscriber',NULL),(38,'UC用户_15680698256','e182f4c6fe43e365b6a78672d870dff1','[email protected]','http://www.lailin.xyz','莫回首',1431486439,1434340720,0,'subscriber',NULL),(39,'UC用户_15608076865','afd2c1ef6d9a0016018a21ffb67844fc',NULL,NULL,'UC用户_15608076865',1437738521,1437738548,0,'subscriber',NULL),(40,'UC用户_13547843011','d59722abe18070b63c14a90996eefd9b',NULL,NULL,'UC用户_13547843011',1442927726,1442927738,0,'subscriber',NULL),(41,NULL,'$P$BT9iDDSplF.Gqh8aOeaSrAK5gIgisp.',NULL,NULL,NULL,1443217739,0,0,'subscriber',NULL),(42,'UC用户_18380140506','af40b08f7da9e531464299494565636d',NULL,NULL,'UC用户_18380140506',1445342444,1445342455,0,'subscriber',NULL),(43,'UC用户_15073236797','fe6679cc238c2fddb28580b50c5f2630',NULL,NULL,'吴磊城',1447921363,1447921420,0,'subscriber',NULL),(81,'dangyichao','$P$BmMhFGIJiCi5Xl6JMgyxhee07nFm3w/','[email protected]',NULL,'党一超',1538919333,1549889873,1549810502,'administrator','d912b87ee2960809445293ac6439d170'),(82,'wanguolin','$P$BYlSvoTrH7n2iE.uXNc5y6ednHrcfg.','[email protected]',NULL,'万国麟',1549797055,0,0,'administrator',NULL),(83,'cailiangping','$P$B9EmbKXql4x8Gh7ncyBCw8pxdnUKeP.','[email protected]',NULL,'蔡良平',1549797202,0,0,'administrator',NULL),(84,'guiyefei','$P$BH.9lwTeS4Eh.BJemATEgcSNujAEvD0','[email protected]',NULL,'桂烨菲',1549797286,0,0,'administrator',NULL),(44,'UC用户_18328588094','48bc766509149dd168f231ef7d279904',NULL,NULL,'UC用户_18328588094',1448013723,1448013725,0,'subscriber',NULL),(45,'UC用户_18224451240','bbb741b7d60363c58f4ecc5582646ee1',NULL,NULL,'UC用户_18224451240',1448379860,1448379868,0,'subscriber',NULL),(46,'UC用户_18093000300','$P$B6Vf2pQouYKfmQeFYxmWwaU5SIVMsT1',NULL,NULL,'UC用户_18093000300',1448579994,1448580060,0,'subscriber',NULL),(47,NULL,'$P$BPfOlabQKd9TBwsbSCZKRPM6jfOI2k1',NULL,NULL,NULL,1452181308,0,0,'subscriber',NULL),(48,NULL,'$P$Bg2yK2gBiUdyONUOemeN7Hvi3hMzD8.',NULL,NULL,NULL,1455185503,0,0,'subscriber',NULL),(49,'ervinewell','$P$B/Yv.7cyQISnLRGzGp27WW.bW7/mdL1','[email protected]',NULL,'ervinewell',1461072562,1495072767,1461216971,'editor','a361ba4dda9f0c38a94352e94dc90872'),(50,'颜冰','$P$BwjJiVa6B9w0kNivQVSBlZfCb5FZb20','[email protected]',NULL,'颜冰',1464000470,1464000578,0,'subscriber','40ca1b7f782e39c87834d0826a98dc35'),(51,NULL,'$P$BWivCn8uDNiEMruEfXsc0qm.d4OtFl1',NULL,NULL,NULL,1464000470,0,0,'subscriber',NULL),(52,'feiyun','$P$BLyRB5cu8.Mf9tbxbndgkVW0mPdaQW/','[email protected]',NULL,'feiyun',1464668447,1464668906,0,'subscriber','05b6e886656ac88b15c15c388c0054f6'),(53,'三鹿伴我长大','$P$BZ68/G8ojciiv73facGem/Sotdy5wp1','[email protected]',NULL,'三鹿伴我长大',1464697284,1464697334,0,'subscriber','ff8279125e75abc7197a9d77c77ae231'),(54,NULL,'$P$BIqnLYKbEkZP5TyNqcWb0z56vP3Ljf/',NULL,NULL,NULL,1470344543,0,0,'subscriber',NULL),(55,'xuange','$P$BHyd.Giy24/UhT0Lk6F0FL2GtG8Nqi/','[email protected]',NULL,'xuange',1472808681,1472808692,0,'subscriber','199366362942ace50cca3357b753296a'),(56,NULL,'$P$Bcja0iQDe3tnwgKMzw0N2uUDogkuyh0',NULL,NULL,NULL,1472808869,0,0,'subscriber',NULL),(57,NULL,'$P$BxxCr9RkJBVYp.GHhYQWp2USbM.bHx/',NULL,NULL,NULL,1477297333,0,0,'subscriber',NULL),(58,NULL,'$P$B0gvrWd22zDXzAUqA5q8M4uNAeTgPp.',NULL,NULL,NULL,1478062548,0,0,'subscriber',NULL),(59,NULL,'$P$BAM6ew/DCd4OfBmEk3G6ESVFXHdD3a.',NULL,NULL,NULL,1478062548,0,0,'subscriber',NULL),(60,NULL,'$P$BKSp/Kz.WCSLQ0N4fzcQJrKxTV.32n0',NULL,NULL,NULL,1478062548,0,0,'subscriber',NULL),(61,NULL,'$P$BjQuGGMXWFFCXeXT5mlBFNR4EXCFJb1',NULL,NULL,NULL,1478062548,0,0,'subscriber',NULL),(62,NULL,'$P$BYOdfgols23GZb6/5qaOl/th1MyNph0',NULL,NULL,NULL,1478062549,0,0,'subscriber',NULL),(63,NULL,'$P$BAAQdQHgHmxXfMMXiryHn50KfCbdfn1',NULL,NULL,NULL,1478062549,0,0,'subscriber',NULL),(64,NULL,'$P$BR9yF/cSQCQNZ8SpkPSooEyTfkePYH1',NULL,NULL,NULL,1478062549,0,0,'subscriber',NULL),(65,NULL,'$P$B8Ol5ZaCxRzhurewYUzuT8PlHE10iU0',NULL,NULL,NULL,1478062549,0,0,'subscriber',NULL),(66,NULL,'$P$B15cnBzyLmh.VkjCdlvcbBVF9jXF0l0',NULL,NULL,NULL,1478062550,0,0,'subscriber',NULL),(67,NULL,'$P$BBGROn38uSERwjOOy7JW25ZTkgBL4x1',NULL,NULL,NULL,1478062550,0,0,'subscriber',NULL),(68,NULL,'$P$BgOkjSn0PJ7b5QSNB1bzW4Zn4mxHQ81',NULL,NULL,NULL,1478062550,0,0,'subscriber',NULL),(71,'testuser','$P$B8bF9/Iv74VjZrZ1EhZJ8ZCyLSaUl1/','[email protected]',NULL,'testuser',1491987504,1491987558,0,'subscriber','03c9848cc937e6c60c64d89052879ccb'),(72,'赵豪杰','$P$BJtTUkmGVCd9c6YNPHCCh0TIjBsSiE/','[email protected]',NULL,'赵豪杰',1505996146,1505996189,0,'subscriber','e506736fcb593e6ec8efdd548fcb4d6a'),(73,'阿川','$P$BW2Lpm2opOVKiq8gD2e19lbM.dNLxI1','[email protected]',NULL,'阿川',1509336770,1509336796,0,'subscriber','57da88fc153dd6ef1ce5db2fdb59a7bb'),(74,'scudrt','$P$BYL69bYHbhkt.dgHx7Yjpg9sey3fSt1','[email protected]',NULL,'scudrt',1512903999,1514738370,0,'subscriber','6affbd0a8ea79f30015add01738a4e4d'),(75,'执念','$P$BqjR607M/Y73CdyOQQYYLuPgf0IIFq0','[email protected]',NULL,'执念',1521546310,1522060178,1521546380,'subscriber','22e233edb2c28afe84d6361108bdaf05'),(76,'aguyue','$P$BApyZpSLX.haHM76mMLctJssiryvN1.','[email protected]',NULL,'aguyue',1523278684,1523278737,0,'subscriber','64c0b2c3000f17a0bbe8b35cfb57a2b8'),(85,'小黑','$P$BNcylkl4cDfNAvGgMMWv22n.v8o8bQ.','[email protected]',NULL,'小黑',1558699360,1558699782,1558699641,'subscriber','29844bfdbe2136859ea6f3651fc590c1'),(86,'Dihambo','$P$Bm48r84kb/jAUHFaG/Wx.y83b6orIg0','[email protected]',NULL,'Dihambo',1567741794,1567742073,0,'subscriber','c5907ebb58d01624a8596af090733553'),(87,'we','$P$BkdAJ.EtBkb9CXkVQnBUg9fgrR9uCi0','[email protected]',NULL,'we',1569635939,1569636033,0,'subscriber','ca3752ca62e55bce1a7179732151938e'),(88,'赵民权','$P$BEQ9ct.NfEpKgEn8uDKrpwA6FvJLGH0','[email protected]',NULL,'赵民权',1590910200,1590910586,0,'subscriber','ad906daa929e09bcebe59bff7414056e');
/*!40000 ALTER TABLE `typecho_users` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2020-10-13 16:33:35