Golang Channel用法简编

Standard

一、Golang并发基础理论

Golang在并发设计方面参考了C.A.R Hoare的CSP,即Communicating Sequential Processes并发模型理论。但就像John Graham-Cumming所说的那样,多数Golang程序员或爱好者仅仅停留在“知道”这一层次,理解CSP理论的并不多,毕竟多数程序员是搞工程 的。不过要想系统学习CSP的人可以从这里下载到CSP论文的最新版本。

维基百科中概要罗列了CSP模型与另外一种并发模型Actor模型的区别:

Actor模型广义上讲与CSP模型很相似。但两种模型就提供的原语而言,又有一些根本上的不同之处:
– CSP模型处理过程是匿名的,而Actor模型中的Actor则具有身份标识。
– CSP模型的消息传递在收发消息进程间包含了一个交会点,即发送方只能在接收方准备好接收消息时才能发送消息。相反,actor模型中的消息传递是异步 的,即消息的发送和接收无需在同一时间进行,发送方可以在接收方准备好接收消息前将消息发送出去。这两种方案可以认为是彼此对偶的。在某种意义下,基于交 会点的系统可以通过构造带缓冲的通信的方式来模拟异步消息系统。而异步系统可以通过构造带消息/应答协议的方式来同步发送方和接收方来模拟交会点似的通信 方式。
– CSP使用显式的Channel用于消息传递,而Actor模型则将消息发送给命名的目的Actor。这两种方法可以被认为是对偶的。某种意义下,进程可 以从一个实际上拥有身份标识的channel接收消息,而通过将actors构造成类Channel的行为模式也可以打破actors之间的名字耦合。

二、Go Channel基本操作语法

Go Channel的基本操作语法如下:

c := make(chan bool) //创建一个无缓冲的bool型Channel
c <- x        //向一个Channel发送一个值
<- c          //从一个Channel中接收一个值
x = <- c      //从Channel c接收一个值并将其存储到x中
x, ok = <- c  //从Channel接收一个值,如果channel关闭了或没有数据,那么ok将被置为false

不带缓冲的Channel兼具通信和同步两种特性,颇受青睐。

三、Channel用作信号(Signal)的场景

1、等待一个事件(Event)

等待一个事件,有时候通过close一个Channel就足够了。例如:

//testwaitevent1.go
package main

import “fmt”

func main() {
fmt.Println(“Begin doing something!”)
c := make(chan bool)
go func() {
fmt.Println(“Doing something…”)
close(c)
}()
<-c
fmt.Println(“Done!”)
}

这里main goroutine通过”<-c“来等待sub goroutine中的“完成事件”,sub goroutine通过close channel促发这一事件。当然也可以通过向Channel写入一个bool值的方式来作为事件通知。main goroutine在channel c上没有任何数据可读的情况下会阻塞等待。

关于输出结果:

根据《Go memory model》中关于close channel与recv from channel的order的定义:The closing of a channel happens before a receive that returns a zero value because the channel is closed.

我们可以很容易判断出上面程序的输出结果:

Begin doing something!
Doing something…
Done!

如果将close(c)换成c<-true,则根据《Go memory model》中的定义:A receive from an unbuffered channel happens before the send on that channel completes.
<-c“要先于”c<-true“完成,但也不影响日志的输出顺序,输出结果仍为上面三行。

2、协同多个Goroutines

同上,close channel还可以用于协同多个Goroutines,比如下面这个例子,我们创建了100个Worker Goroutine,这些Goroutine在被创建出来后都阻塞在”<-start”上,直到我们在main goroutine中给出开工的信号:”close(start)”,这些goroutines才开始真正的并发运行起来。

//testwaitevent2.go
package main

import “fmt”

func worker(start chan bool, index int) {
<-start
fmt.Println(“This is Worker:”, index)
}

func main() {
start := make(chan bool)
for i := 1; i <= 100; i++ {
go worker(start, i)
}
close(start)
select {} //deadlock we expected
}

3、Select

【select的基本操作】
select是Go语言特有的操作,使用select我们可以同时在多个channel上进行发送/接收操作。下面是select的基本操作。

select {
case x := <- somechan:
// … 使用x进行一些操作

case y, ok := <- someOtherchan:
// … 使用y进行一些操作,
// 
检查ok值判断someOtherchan是否已经关闭

case outputChan <- z:
// … z值被成功发送到Channel上时

default:
// … 上面case均无法通信时,执行此分支
}

【惯用法:for/select】

我们在使用select时很少只是对其进行一次evaluation,我们常常将其与for {}结合在一起使用,并选择适当时机从for{}中退出。

for {
select {
case x := <- somechan:
// … 使用x进行一些操作

        case y, ok := <- someOtherchan:
// … 使用y进行一些操作,
// 检查ok值判断someOtherchan是否已经关闭

        case outputChan <- z:
// … z值被成功发送到Channel上时

        default:
// … 上面case均无法通信时,执行此分支
}

【终结workers】

下面是一个常见的终结sub worker goroutines的方法,每个worker goroutine通过select监视一个die channel来及时获取main goroutine的退出通知。

//testterminateworker1.go
package main

import (
“fmt”
“time”
)

func worker(die chan bool, index int) {
fmt.Println(“Begin: This is Worker:”, index)
for {
select {
//case xx:
//做事的分支
case <-die:
fmt.Println(“Done: This is Worker:”, index)
return
}
}
}

func main() {
die := make(chan bool)

    for i := 1; i <= 100; i++ {
go worker(die, i)
}

    time.Sleep(time.Second * 5)
close(die)
select {} 
//deadlock we expected
}

【终结验证】

有时候终结一个worker后,main goroutine想确认worker routine是否真正退出了,可采用下面这种方法:

//testterminateworker2.go
package main

import (
“fmt”
//”time”
)

func worker(die chan bool) {
fmt.Println(“Begin: This is Worker”)
for {
select {
//case xx:
//做事的分支
case <-die:
fmt.Println(“Done: This is Worker”)
die <- true
return
}
}
}

func main() {
die := make(chan bool)

    go worker(die)

    die <- true
<-die
fmt.Println(“Worker goroutine has been terminated”)
}

【关闭的Channel永远不会阻塞】

下面演示在一个已经关闭了的channel上读写的结果:

//testoperateonclosedchannel.go
package main

import “fmt”

func main() {
cb := make(chan bool)
close(cb)
x := <-cb
fmt.Printf(“%#v\n”, x)

        x, ok := <-cb
fmt.Printf(“%#v %#v\n”, x, ok)

        ci := make(chan int)
close(ci)
y := <-ci
fmt.Printf(“%#v\n”, y)

        cb <- true
}

$go run testoperateonclosedchannel.go
false
false false
0
panic: runtime error: send on closed channel

可以看到在一个已经close的unbuffered channel上执行读操作,回返回channel对应类型的零值,比如bool型channel返回false,int型channel返回0。但向close的channel写则会触发panic。不过无论读写都不会导致阻塞。

【关闭带缓存的channel】

将unbuffered channel换成buffered channel会怎样?我们看下面例子:

//testclosedbufferedchannel.go
package main

import “fmt”

func main() {
c := make(chan int, 3)
c <- 15
c <- 34
c <- 65
close(c)
fmt.Printf(“%d\n”, <-c)
fmt.Printf(“%d\n”, <-c)
fmt.Printf(“%d\n”, <-c)
fmt.Printf(“%d\n”, <-c)

        c <- 1
}

$go run testclosedbufferedchannel.go
15
34
65
0
panic: runtime error: send on closed channel

可以看出带缓冲的channel略有不同。尽管已经close了,但我们依旧可以从中读出关闭前写入的3个值。第四次读取时,则会返回该channel类型的零值。向这类channel写入操作也会触发panic。

【range】

Golang中的range常常和channel并肩作战,它被用来从channel中读取所有值。下面是一个简单的实例:

//testrange.go
package main

import “fmt”

func generator(strings chan string) {
strings <- “Five hour’s New York jet lag”
strings <- “and Cayce Pollard wakes in Camden Town”
strings <- “to the dire and ever-decreasing circles”
strings <- “of disrupted circadian rhythm.”
close(strings)
}

func main() {
strings := make(chan string)
go generator(strings)
for s := range strings {
fmt.Printf(“%s\n”, s)
}
fmt.Printf(“\n”)
}

四、隐藏状态

下面通过一个例子来演示一下channel如何用来隐藏状态:

1、例子:唯一的ID服务

//testuniqueid.go
package main

import “fmt”

func newUniqueIDService() <-chan string {
id := make(chan string)
go func() {
var counter int64 = 0
for {
id <- fmt.Sprintf(“%x”, counter)
counter += 1
}
}()
return id
}
func main() {
id := newUniqueIDService()
for i := 0; i < 10; i++ {
fmt.Println(<-id)
}
}

$ go run testuniqueid.go
0
1
2
3
4
5
6
7
8
9

newUniqueIDService通过一个channel与main goroutine关联,main goroutine无需知道uniqueid实现的细节以及当前状态,只需通过channel获得最新id即可。

五、默认情况

我想这里John Graham-Cumming主要是想告诉我们select的default分支的实践用法。

1、select  for non-blocking receive

idle:= make(chan []byte, 5) //用一个带缓冲的channel构造一个简单的队列

select {
case b = <-idle:
 //尝试从idle队列中读取

default:  //队列空,分配一个新的buffer
makes += 1
b = make([]byte, size)
}

2、select for non-blocking send

idle:= make(chan []byte, 5) //用一个带缓冲的channel构造一个简单的队列

select {
case idle <- b: //尝试向队列中插入一个buffer
//…
default: //队列满?

}

六、Nil Channels

1、nil channels阻塞

对一个没有初始化的channel进行读写操作都将发生阻塞,例子如下:

package main

func main() {
var c chan int
<-c
}

$go run testnilchannel.go
fatal error: all goroutines are asleep – deadlock!

package main

func main() {
var c chan int
c <- 1
}

$go run testnilchannel.go
fatal error: all goroutines are asleep – deadlock!

2、nil channel在select中很有用

看下面这个例子:

//testnilchannel_bad.go
package main

import “fmt”
import “time”

func main() {
var c1, c2 chan int = make(chan int), make(chan int)
go func() {
time.Sleep(time.Second * 5)
c1 <- 5
close(c1)
}()

        go func() {
time.Sleep(time.Second * 7)
c2 <- 7
close(c2)
}()

        for {
select {
case x := <-c1:
fmt.Println(x)
case x := <-c2:
fmt.Println(x)
}
}
fmt.Println(“over”)
}

我们原本期望程序交替输出5和7两个数字,但实际的输出结果却是:

5
0
0
0
… … 0死循环

再仔细分析代码,原来select每次按case顺序evaluate:
– 前5s,select一直阻塞;
– 第5s,c1返回一个5后被close了,“case x := <-c1”这个分支返回,select输出5,并重新select
– 下一轮select又从“case x := <-c1”这个分支开始evaluate,由于c1被close,按照前面的知识,close的channel不会阻塞,我们会读出这个 channel对应类型的零值,这里就是0;select再次输出0;这时即便c2有值返回,程序也不会走到c2这个分支
– 依次类推,程序无限循环的输出0

我们利用nil channel来改进这个程序,以实现我们的意图,代码如下:

//testnilchannel.go
package main

import “fmt”
import “time”

func main() {
var c1, c2 chan int = make(chan int), make(chan int)
go func() {
time.Sleep(time.Second * 5)
c1 <- 5
close(c1)
}()

        go func() {
time.Sleep(time.Second * 7)
c2 <- 7
close(c2)
}()

        for {
select {
case x, ok := <-c1:
if !ok {
c1 = nil
} else {
fmt.Println(x)
}
case x, ok := <-c2:
if !ok {
c2 = nil
} else {
fmt.Println(x)
}
}
if c1 == nil && c2 == nil {
break
}
}
fmt.Println(“over”)
}

$go run testnilchannel.go
5
7
over

可以看出:通过将已经关闭的channel置为nil,下次select将会阻塞在该channel上,使得select继续下面的分支evaluation。

七、Timers

1、超时机制Timeout

带超时机制的select是常规的tip,下面是示例代码,实现30s的超时select:

func worker(start chan bool) {
timeout := time.After(30 * time.Second)
for {
select {
// … do some stuff
case <- timeout:
return
}
}

2、心跳HeartBeart

与timeout实现类似,下面是一个简单的心跳select实现:

func worker(start chan bool) {
heartbeat := time.Tick(30 * time.Second)
for {
select {
// … do some stuff
case <- heartbeat:
//… do heartbeat stuff
}
}
}

来源:http://tonybai.com/2014/09/29/a-channel-compendium-for-golang/

 

使用公用表表达式(CTE)简化嵌套SQL

Standard

先看下面一个嵌套的查询语句:

select * from person.StateProvince where CountryRegionCode in
(select CountryRegionCode from person.CountryRegion where Name like ‘C%’)

上面的查询语句使用了一个子查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句非常难以阅读和维护。因此,也可以使用表变量的方式来解决这个问题,SQL语句如下:

declare @t table(CountryRegionCode nvarchar(3))
insert into @t(CountryRegionCode)  (select CountryRegionCode from person.CountryRegion where Name like ‘C%’)select * from person.StateProvince where CountryRegionCode
in (select * from @t)

 

虽然上面的SQL语句要比第一种方式更复杂,但却将子查询放在了表变量@t中,这样做将使SQL语句更容易维护,但又会带来另一个问题,就是性能的损失。由于表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况。为此,在SQL Server 2005中提供了另外一种解决方案,这就是公用表表达式(CTE),使用CTE,可以使SQL语句的可维护性,同时,CTE要比表变量的效率高得多。

下面是CTE的语法:

[ WITH <common_table_expression> [ ,n ] ]
<common_table_expression>::=
expression_name [ ( column_name [ ,n ] ) ]
AS
( CTE_query_definition )

 

现在使用CTE来解决上面的问题,SQL语句如下:

with
cr as
(
select CountryRegionCode from person.CountryRegion where Name like ‘C%’
)select * from person.StateProvince where CountryRegionCode in (select * from cr)

其中cr是一个公用表表达式,该表达式在使用上与表变量类似,只是SQL Server 2005在处理公用表表达式的方式上有所不同。

在使用CTE时应注意如下几点:
1. CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。如下面的SQL语句将无法正常使用CTE:

 

with
cr as
(
select CountryRegionCode from person.CountryRegion where Name like ‘C%’
)
select * from person.CountryRegion  — 应将这条SQL语句去掉
— 使用CTE的SQL语句应紧跟在相关的CTE后面 —
select * from person.StateProvince where CountryRegionCode in (select * from cr)

 

2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示:

with
cte1 as
(
select * from table1 where name like ‘abc%’
),
cte2 as
(
select * from table2 where id > 20
),
cte3 as
(
select * from table3 where price < 100
)
select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id

3. 如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了,如下面的SQL语句所示:

—  table1是一个实际存在的表

with
table1 as
(
select * from persons where age < 30
)
select * from table1  —  使用了名为table1的公共表表达式
select * from table1  —  使用了名为table1的数据表

4. CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。

5. 不能在 CTE_query_definition 中使用以下子句:

(1)COMPUTE 或 COMPUTE BY

(2)ORDER BY(除非指定了 TOP 子句)

(3)INTO

(4)带有查询提示的 OPTION 子句

(5)FOR XML

(6)FOR BROWSE

6. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:

declare @s nvarchar(3)
set @s = ‘C%’
;  — 必须加分号
with
t_tree as
(
select CountryRegionCode from person.CountryRegion where Name like @s
)
select * from person.StateProvince where CountryRegionCode in (select * from t_tree)

CTE除了可以简化嵌套SQL语句外,还可以进行递归调用,关于这一部分的内容将在下一篇文章中介绍。

转自:http://www.cnblogs.com/nokiaguy/archive/2009/01/31/1381562.html

每个程序员都应该知道的 15 个最佳 PHP 库

Standard

原文:http://www.codeceo.com/article/15-php-lib-every-programmer-know.html

PHP是一种功能强大的web站点脚本语言,通过PHP,web网站开发者可以更容易地创建动态的引人入胜的web页面。开发人员可以使用PHP代码与一些网站模板和框架来提升功能和特性。然而,编写PHP代码是一个繁琐又耗时的过程。为了缩短开发时间,开发人员可以用PHP库替代编写代码来为站点添加功能。

使用PHP库来取代编写代码,可以显着地降低网站的开发时间,从而开发人员可以将时间投入到网站设计等重要环节。

今天我们要介绍的就是15个最佳的PHP库,它们将帮助网站开发人员轻松提高网站的功能,优化PHP的开发时间。

 

1. PChart

PChart是一个令人印象深刻的PHP库,可以以一种可视化图表的形式生成文本数据。数据可以展示为柱状图,饼状图,以及其他格式。使用SQL查询可以帮助PHP脚本创建令人惊叹的图表和图形。

2. PHP CAPTCHA

PHP CAPTCHA是另一个伟大的用于创建自动化音频和可视化CAPTCHA的PHP库。CAPTCHA系统是完全自动的使用图灵测试来完成区分人和机器人的挑战。 PHP库需要PHP 4以及编译的FreeType文本和GD 1或2图像生成的支持。

3.Dispatch

Dispatch是一个简单的PHP库,可以定义URL规则以更好地组织网站。使用这个PHP库你可以匹配HTTP路径和要求,显示器等的特定类型。结合Dispatch和本文中列出的其他库,开发人员就能有一个强大而简单的工作设置。

3. Services_JSON

Services_JSON允许人脑可读数据的传输。 PHP库的最新版本为服务器传输数据提供了极大的便捷。

4. phpAES

phpAES是支持128,192和256位AES加密密码的一类实现PHP代码。当涉及到汇编成PHP的时候,你不需要其他的扩展。phpAES是全功能的,并且符合FIPS 197。

5. ImageWorkshop

ImageWorkshop是一个伟大的开源PHP库,允许你层次化地控制操作图像。使用PHP库,你可以裁剪、调整大小、添加水印、制作缩略图等以不同的方式处理图像。 PHP库还可以更容易地进一步加强在web网站上所使用的图像。

6.Mink

Mink是另一个有用的PHP库,可以帮助你用互联网浏览器测试web页面的交互。该库删除了不同浏览器之间的API的差异,从而给开发人员提供更好的测试环境。

7. PHP Thumbnailer

PHP Thumbnailer是一个简单的图像处理PHP库,能够帮助生成缩略图。此库不需要再安装外部库。PHP Thumbnailer提供了对缩略图的多种控制,如根据高度、宽度、百分比调整缩略图大小,旋转图像,以及创建自定义的小图形,如正方形。

8.Hoa

Hoa是结构化,模块化,可扩展的PHP库,可创建研究和工业领域之间的链接。 此PHP库建议必不可少的范式、机制、算法,以确保web站点的可靠性。

9. PHP Text to Image

PHP Text to Image是一个可以将文本转换成图像的PHP库。在某些简单的情况下,如显示email地址作为不能以编程方式发现的图像的时候,这是很有用的。使用这个PHP库可以通过网络爬虫以及将它当作垃圾邮件来减少电子邮件地址泛滥。

10.Faker

Faker是一个非常有用的PHP库,可以在需要时创建假数据。使用这个PHP库,你可以执行各种诸如匿名数据,引导数据库,创建XML文档,进行压力测试的任务。

11.PHP Image Upload Class

PHP Image Upload Class是一个功能强大的PHP库,可以简化上传图像到窗体表格的过程。通过这个库,开发人员可以使用文件输入命令上传图片。开发人员也可以在类之外定义用户消息,通过gettext或类似的命令,在本地提供帮助。

12.Ratchet

使用Ratchet PHP库,web开发人员可以创建实时性以及在客户端和服务器之间双向性的应用程序。 这个PHP库能够帮助促进和创造事件驱动应用程序,而不是使用传统的HTTP请求。

13. PHP Export XLS Class

PHP Export XLS Class是一个轻量级的,快速又简单的PHP库,可以导出不同类型的数据到Excel中。它可以转换各种数据格式到.xls格式。此库还可工作于多个工作表,元数据(标题,作者,描述,等),不同的字体类型和风格,填充,单元格边框和渐变。开发人员也可以使用PHP扩展来添加图像到工作表中。

14. phpDocumentor

phpDocumentor是一个很不错的自动文档工具,可以帮助我们创建一个使用PHP代码的专业文档。 该PHP库支持添加多种不同的功能到网站。一些由PHP库支持的增值功能,包括支持合并自定义文档——例如教程,链接文档,创建高亮源代码,功能交叉引用到PHP常规文档。 此PHP库可以帮助自动化文档。

15. PHP DB Class

PHP DB Class是一个伟大的PHP库,可以帮助开发PHP和MySQL。该工具可轻松方便地访问一个数据库,并减少执行任务所需的代码数量。此外,此PHP库提供各种调试功能。例如,开发人员可以使用调试功能来显示请求和结果表,还可以通过添加参数到它的类的方法来执行此任务。

http://www.programmableweb.com/news/15-best-php-libraries-every-developer-should-know/analysis/2015/11/18

How to create a quick ASCII banner in the OS X Terminal

Standard

From:http://www.macissues.com/2015/11/05/how-to-create-a-quick-ascii-banner-in-the-os-x-terminal/

Even if you are not a Terminal wizard, there are some fun tools and features of it that can be amusing. For instance, some online services are available for you to log into with Telnet and watch a text-based version of Star Wars, or you can play odd games that folks have coded into the “emacs” editor, among others. If you are ever sitting at your Mac and suddenly have the urge to print out a massive banner of a text phrase, then you can do that to.

First, open the Terminal, then type the following:

banner "MacIssues"

This will create a vertical banner in hash characters of the word “MacIssues” and you can change the text to whatever you would like, to have a banner of that printed. By default this will output to the Terminal window, but you can quickly route the output to a TextEdit document by piping the output with the following approach:

banner "MacIssues" | open -fe

In the text document that opens, if the banner appears garbles, then resize the window until the message is accommodated, and then print to whatever printer you have.

Granted there are plenty of free tools or those in common word processing and design programs that can do this, and often with greater style (drop shadows, colors, fonts, etc.); however, this is a quick way to punch out a banner on pretty much any Mac, at any time. Note that being a Terminal-based option, this approach is doable on many other Unix and Linux distributions as well, so if you’re ever indulging in your geek side and suddenly have the urge to make a banner, this is likely how you would do it.

TextEdit printing banner from the Terminal

Create Hidden Administrative Accounts In OS X From The Terminal

Standard

If you have a system that is used by other people, you may want to give them managed user accounts and then reserve a separate administrative account for installing apps and changing system settings. This is especially true for situations where many people may be using one computer, such as in classrooms. While you can always create an administrative account, by default such accounts will show up along with others at the login window, in the Fast User Switch menu, and other locations; however, you can set this up to be hidden from most of these locations.

The root account

One approach for a hidden user account is to enable the root account. However this being fully unrestricted comes with inherent risks. Even though admin accounts may authenticate for root access, this ability is time- or session-limited, meaning that authentication is regularly required to ensure administrative actions are truly desired. However, with the root account no such checks are done, and faulty administrative actions can be harmful. Since practically every root action can be done from an administrative account, its best to avoid enabling root unless some action cannot be done otherwise.

Dedicated administrative accounts

To create a special hidden user account that has administrative rights, you can go one of two routes based on the version of OS X that you have, but first you must create the account. This can either be done in the Users & Groups system preferences, or by using the command line (useful for scripting or remote-access approaches). For the second approach, open the Terminal and then run the following set of commands (replace USERNAME with the corresponding name of your account):

  1. Get a list of current User ID numbers:
    dscl . list /Users UniqueID
  2. Create the user’s account in the local directory:
    sudo dscl . create /Users/USERNAME
  3. Set the user’s password:
    sudo dscl . passwd /Users/USERNAME
  4. Set the user’s full name:
    sudo dscl . create /Users/USERNAME RealName "USER NAME"
  5. Set the user’s default shell:
    sudo dscl . create /Users/USERNAME UserShell /bin/bash
  6. Add the user to the “admin” group:
    sudo dscl . append /Groups/admin GroupMembership USERNAME

Now the following commands will create and assign the user’s home folder, which by default is in the /Users directory, but since this is a hidden account we are putting it in the hidden /var directory:

  1. Create the folder:
    sudo mkdir /var/USERNAME;
    sudo chown USERNAME /var/USERNAME
  2. Set the home directory:
    sudo dscl . create /Users/USERNAME NFSHomeDirectory /var/USERNAME
  3. Set the user’s ID to a value unique from the list of User IDs you found in the first step above (change NUM to reflect the value of your selected ID):
    sudo dscl . create /Users/USERNAME UniqueID NUM

If your version of OS X is prior to Yosemite, then you can set this unique value to something less than 500, and OS X should hide it. Otherwise, run the following command to have the login window hide users under 500:

sudo defaults write /Library/Preferences/com.apple.loginwindow Hide500Users -bool TRUE

Note that if you have created the user account in the Users & Groups system preferences, then you can change the User ID and home folder location in the system preferences by right-clicking the user and choosing the advanced options, then adjusting the values accordingly.

If your version of OS X is Yosemite or later, then you have additional approaches available to you for hiding the user account. Instead of being forced to use a User ID value under 500, you can use any ID you want and then set a special attribute for the user account that will hide it:

sudo dscl . create /Users/USERNAME IsHidden 1

To undo this change, re-run the command with “0” instead of “1,” or run the following command to remove the attribute altogether:

sudo dscl . delete /Users/USERNAME IsHidden

Finding hidden user accounts

While these approaches will hide a user account from the login window, the Users & Groups system preferences, and the Fast User Switching menu, you can still view the account. The following command will list the users on the system and then filter out system-based accounts, so you will see the short usernames of all the current users:

dscl . list /Users | grep -v "_\|nobody\|root\|daemon"

From:http://www.macissues.com/2015/11/17/how-to-create-hidden-administrative-accounts-in-os-x/

Go语言学习资料整理

Standard

原文:http://www.the5fire.com/golang-reference-data.html

最近在学习和实践Go语言,整理一些学习资料

系列文档&教程:

官网:http://golang.org/doc/ 【官方的一定要看,内容相当的多其他的书呀什么的都是从这来的】

官方博客:http://blog.golang.org

tour:http://tour.golang.org/#1 【必看】

《the Way to Go》中文版:https://github.com/Unknwon/the-way-to-go_ZH_CN

《Go Web编程》: https://github.com/astaxie/build-web-application-with-golang

官方文档翻译: https://code.google.com/p/golang-china/

Let’s learn Go:  http://go-book.appsp0t.com/

Go by Example: https://gobyexample.com/

视频:

许世伟——go,基于连接和组合的语言:http://open.qiniudn.com/thinking-in-go.mp4

Go编程基础视频,面向新手:https://github.com/Unknwon/go-fundamental-programming

相关的blog:

风云blog go学习笔记:http://blog.codingnow.com/eo/go_oieno/

blog: http://www.lubia.me/?tag=golang

beego(beego框架的作者): http://blog.beego.me/

当然还有我的博客:http://the5fire.com

SublimeText3常用快捷键和优秀插件

Standard

来源:http://www.cnblogs.com/manfredHu/p/4941307.html

SublimeText是前端的一个神器,以其精简和可DIY而让广大fans疯狂。好吧不吹了直入正题 -_-!!

首先是安装,如果你有什么软件管家的话搜一下就好,一键安装。然后,有钱的土豪就自己买个吧,穷逼就搜下注册码看下有没有土豪共享咯。

既然是神器,肯定有你不知道的东西不是,下面这部分来讲操作。PS:大部分图片和文字来自网络,这里只是略微排版方便查阅。

测试操作系统:Win10
测试软件版本:SublimeText3 3059


SublimeText3 操作部分

1. 就近选择相同项: ctrl+d

把光标放在一个单词上,按下ctrl+d,将选择这个单词。一直按住ctrl且按D多次,将选择当前选中项的下一个匹配项。通过按住ctrl,再按D三次,将选择三个相同的文本。

2. 选择当前文件所有匹配项: alt+f3

选择文件中的所有匹配项。小心使用这个,因为它能选择一个文件中的所有匹配项. .

3. 选择文本的包裹标签: ctrl+shift+` (ESC键下面的那个)

这是一个法宝。也许你希望所有属性保持不变,但只是想选择标签。这个快捷键为你这样做,会注意到你可以在一次操作多个标签。ps:需要Emmet插件(可以直接到后面看插件的安装)

4. 向上扩展一层: ctrl+shift+a

如果你把光标放在文本间再按下上面的键将选择文本,就像ctrl+d。但是再次按下它,将选择父容器,再按,将选择父容器的父容器。ps:需要Emmet插件(可以直接到后面看插件的安装)

5. 选择括号内的内容: ctrl+shift+m

这有助于选择括号之间的一切。同样适用于CSS。

6. 整行的上下移动: ctrl+shift+↑或 ctrl+shift+↓

7. 复制行或选中项: ctrl+shift+d

如果你已经选中了文本,它会复制你的选中项。否则,把光标放在行上,会复制整行。

8. 增加和减少缩进: ctrl+[ 或 ]

9. 单行剪辑或选中项: ctrl+x

10. 粘贴并复制格式: ctrl+shift+v

11. 用标签包裹行或选中项: alt+shift+w

12. 移除未闭合的容器元素: ctrl+shift+;

这会移除与你的光标相关的父标签。对清除标记很有帮助。

13. 大写和小写: 大写ctrl+k+u、小写ctrl+k+l

14. 注释选中项/行: ctrl+/

这个在所有语言下都可用, 对行和选中项都可用

15. 删除一行: ctrl+shift+k

这个就不用图了吧


SublimeText3 插件部分

首先是安装包管理器Package Control,SublimeText3的指令已经更新了,SublimeText2更新上来的童鞋注意下
Ctrl+`打开控制台或者View->Show Console菜单打开命令行

import urllib.request,os; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read())

就是上面这串东西了,然后就可以接下来的安装插件了

Tips: 插件名字链接到github,网络不好的童鞋自行下载包扔到Preferences->Browse Packages打开的文件夹下面,然后解压,重启Sublime就行

1. emmet

这个没有什么好说的,类似jQuery的语法,编码蹭蹭往上提。不过要求PyV8环境(安装完后你会看到有一个文件夹),最好还是选择在线装吧。
ctrl+shift+P 输入 install Package 等待读取服务器列表,输入emmet第一个就是了
ps:最好看一下 github里面的简单教程

2. 侧边栏增强插件SideBarEnhancements

这个也没有什么好说的,谁用谁知道,大大增强右键列表的功能,装上就能用。

3. 控制台呼出插件Terminal

用node,Grunt等等要调出控制台的娃知道的,简直神奇有木有,装上就能用。

Tips:快捷键 ctrl+shift+T呼出当前文件路径的控制台

4. 代码提示插件SublimeCodeIntel

这个也没什么废话吧,支持多语言的高速编码的代码提示工具。
装上后还不能直接使用,查了一下原因要配置
你可以点击 Preferences->Browse Packages->SublimeCodeIntel然后添加一个.codeintel文件夹再再在文件夹里面添加一个config文件(Windows创建.codeintel文件夹需要输入.codeintel.

config文件配置:

{
    "PHP": {
        "php": '/usr/bin/php',
        "phpExtraPaths": [],
        "phpConfigFile": 'php.ini'
    },
    "JavaScript": {
        "javascriptExtraPaths": []
    },
    "Perl": {
        "perl": "/usr/bin/perl",
        "perlExtraPaths": []
    },
    "Ruby": {
        "ruby": "/usr/bin/ruby",
        "rubyExtraPaths": []
    },
    "Python": {
        "python": '/usr/bin/python',
        "pythonExtraPaths": []
    },
    "Python3": {
        "python": '/usr/bin/python3',
        "pythonExtraPaths": []
    }
}

其实只要有JS就够了,不过或许某天你要写PHP了呢是吧,留着吧。

然后打开Sublime创建个文件试一下,如果还不行就按下 ctrl+shift+space 开启提示功能

5. 代码排版插件Sublime-HTMLPrettify

以前用的是什么TAG,CssComb和JSFormat,但是某一天发现这款集成prettify的插件后就一直没换过了,不要被插件的HTML迷惑,这是一款可以用于HTML,CSS,Javascript的集成排版插件

Tips:安装完快捷键ctrl+shift+h 一键格式化代码

6. CSS3前缀补充插件Autoprefixer

ctrl+shift+P输入install Package等待读取服务器列表,输入autoprefixer第一个就是了
要装Node.js,没有的话去下载安装吧
插件使用CanIUse资料库,能精准判断哪些属性需要什么前缀

Tips:使用方法:在输入CSS3属性后(冒号前)按Tab键


SublimeText3 添加右键菜单和快捷开启浏览器

添加右键菜单

有时候要开个文件要开个SublimeText3,又要拉文件,麻烦。这里介绍将Sublime添加到右键菜单。

  1. 打开注册表,开始→运行→regedit
  2. 在 HKEY_CLASSSES_ROOT→ * → Shell 下面新建项命名为SublimeText
  3. 右键SublimeText项,新建字符串值,命名为Icon,值为 “sublime_text.exe所在路径,0”,例如:C:\Program Files\Sublime Text 3\sublime_text.exe,0
  4. 右键SublimeText项,新建项,命名为command,默认值为 “sublime_text.exe所在路径 %1”,例如:C:\Program Files\Sublime Text 3\sublime_text.exe %1

搞定后随便右击个文本文件试试,是不是看到了Sublime打开的选项了捏?Perfect

一键浏览文件

Preferences->Key Bindings - User打开用户快捷键设置,copy下面的设置

[
    //firefox
    {
        "keys": ["f1"],
        "command": "side_bar_files_open_with",
        "args": {
            "paths": [],
            "application": "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
            "extensions": ".*"
        }
    },
    //chorme
    {
        "keys": ["f2"],
        "command": "side_bar_files_open_with",
        "args": {
            "paths": [],
            "application": "C:\\Users\\manfr\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
            "extensions": ".*"
        }
    },
    //IE
    {
        "keys": ["f3"],
        "command": "side_bar_files_open_with",
        "args": {
            "paths": [],
            "application": "C:\\Program Files\\Internet Explorer\\iexplore.exe",
            "extensions": ".*"
        }
    },
    //safari
    {
        "keys": ["f4"],
        "command": "side_bar_files_open_with",
        "args": {
            "paths": [],
            "application": "C:\\Program Files (x86)\\Safari\\Safari.exe",
            "extensions": ".*"
        }
    }
]

稍微解释下,keys是按键,application是浏览器应用程序路径,注意反斜杠的要转义。extensions是匹配所有的文件后缀格式。

Tips:查了下默认的快捷键,SublimeText3中f1-f12中只有f11被默认为全屏命令,其他的没设置。也就是说,你可以装十个八个浏览器一字排开按过去测试。


SublimeText3 问题部分(自己遇到过的)

1.自动更新

有时候会弹出自动更新的框,解决方法:

  1. 找到Preferences -> Settings-User(设置用户)
  2. 在最后一个花括号结尾(“}”)前添加一句:"update_check":false
  3. 然后请关闭Submine Text并重启,即不会再弹出更新提醒了

2.不能获取插件列表 Package Control:There are no packages available for installation

  1. cmd下输入ping sublime.wbond.net链接一下看下sublime.wbond.net这个域名的ip
  2. 打开C:\Windows\system32\drivers\etc\hosts文件。
    在最后面加上例如 50.116.34.243 sublime.wbond.net这样的对应关系,IP是上面测试的
  3. 然后请关闭Submine Text并重启,即不会再弹出更新提醒了

The 10 Best Online Tools for Testing Code Snippets

Standard
http://designsparkle.com/testing-code-snippets/
code testing snippets

Online tools for testing code snippets make it an indispensable assistant to the developers to check the quality of their code in reducing errors and keep coding practices easier. Here are 10 of the best online tools for testing code snippets in order to help find security flaws and reduce developments costs. 

You May Also Like:

Online Tools for Testing Code Snippets

CodePen

Build, Explore, and Teach the Web, Instantly. CodePen is a web-based HTML, CSS, and JavaScript code editor that lets you experiment with code right in the browser.

code editor

JSBin

JS Bin is a webapp specifically designed to help JavaScript and CSS folk test snippets of code, within some context, and debug the code collaboratively.

code editor

SQLFiddle

SQLFiddle is an online SQL query processing tool. You can run your SQL statements online without having a locally installed database. It can overcome the feature where you can have a database inside a portable disk and plug it for use anywhere. It is also designed to support multiple databases.

code snippet

jsFiddle

jsFiddle is a free code-sharing tool that allows you to edit, share, execute and debug Web code within a browser.

Advertisements


code editors

Liveweave

Liveweave is a HTML5, CSS3 & JavaScript playground for web designers and developers.

liveweave

RegExr

RegExr is a HTML/JS based tool for creating, testing, and learning about Regular Expressions.

testing code

Dabblet

Dabblet is an interactive playground for quickly testing code snippets of CSS and HTML. It uses -prefix-free, so that you won’t have to add any prefixes in your CSS code. You can save your work in Github gists, embed it in other websites and share it with others.

code testing snippets

iDeone

Ideone is an online compiler and debugging tool which allows you to compile source code and execute it online in more than 60 programming languages. Choose a programming language, enter the source code with optional input data and you are ready to go!

code testing snippets

TinkerBin 

Tinkerbin lets you play around with HTML, JavaScript, and CSS without creating files or uploading to servers. It also supports CoffeeScript, Sass(with Compass), Less, HAML, and more.

code testing tools

CSSDesk

CSSDesk is a online HTML/CSS sandbox. Experiment with CSS, see the results live, and share your code with others.

sandbox tools

30 Pro jQuery Tips, Tricks and Strategies

Standard

原文:http://www.problogdesign.com/coding/30-pro-jquery-tips-tricks-and-strategies/

Whether you’re a developer or a designer, a strong jQuery skillset is something you can’t afford to be without. Today, I’m going to show you 30 handy jQuery coding tricks that will help you make your scripts more robust, elegant and professional.

Getting Started

These tips and tricks all have one thing in common- they are all smashingly useful. With this stuff in your back pocket, you’ll be ready to go change the world, and even better, write jQuery like you know what you’re doing. It’s gonna be fun.

We’ll start with some basic tricks, and move to some more advanced stuff like actually extending jQuery’s methods and filters. Of course, you should be familiar with the basics of jQuery first. If you haven’t used jQuery before, I highly recommend browsing the documentation and watching jQuery for Absolute Beginners Video Series. Otherwise, you’re ready to dig in!

#1 – Delay with Animate()

This is a very quick, easy way to cause delayed actions in jQuery without using setTimeout. The way we make it work is to add an animate function into your chain and animate the element to 100% opacity (which it’s already at), so it looks like nothing is happening.

For instance, let’s say that you wanted to open a dialog and then fade it away after 5 seconds. Using animate, you can do it like this:

1
2
3
$(function(){
	$("body").append("<div class='dialog'></div>").<em>animate({ opacity : 1.0 }, 5000)</em>.fadeOut();
});

Don’t you just love jQuery chaining? You’re welcome to read more about this technique from Karl Swedberg.

UPDATE: jQuery 1.4 has eliminated the need for this hack with a method called delay(). It is just what is sounds like – a function specifically made to delay an animation effect. Way to go, jQuery!

#2 – Loop through Elements Backwards

One of my personal favorites is being able to loop backwards through a set of elements. We all know each() lets us easily loop through elements, but what if we need to go backwards? Here’s the trick:

1
2
3
4
5
6
7
8
$(function(){
	var reversedSet = $("li").get().reverse();
	//Use get() to return an array of elements, and then reverse it
 
	$(reversedSet).each(function(){
		//Now we can plug our reversed set right into the each function. Could it be easier?
	});
});

#3 – Is There Anything in the jQuery Object?

Another very elementary but regularly useful trick is checking if there are any elements in the jQuery object. For example, let’s say we need to find out if there are any elements with a class of ‘active’ in the DOM. You can do that with a quick check of the jQuery object’s length property like this:

1
2
3
4
5
$(function(){
	if( $(".active").length ){
		//Now the code here will only be executed if there is at least one active element
	}
});

This works because 0 evaluates false, so the expression only evaluates true if there is at least one element in the jQuery object. You can also use size() to do the same thing.

#4 – Access iFrame Elements

Iframes aren’t the best solution to most problems, but when you do need to use one it’s very handy to know how to access the elements inside it with Javascript. jQuery’s contents() method makes this a breeze, enabling us to load the iframe’s DOM in one line like this:

1
2
3
4
5
6
7
$(function(){
	var iFrameDOM = $("iframe#someID").contents();
	//Now you can use <strong>find()</strong> to access any element in the iframe:
 
	iFrameDOM.find(".message").slideUp();
	//Slides up all elements classed 'message' in the iframe
});

#5 – Equal Height Columns

This was one of CSS Newbie’s most popular posts of 2009, and it is a good, solid trick to have in your toolbox. The function works by accepting a group of columns, measuring each one to see which is largest, and then resizing them all to match the biggest one. Here’s the code (slighly modified):

1
2
3
4
5
6
7
8
9
10
11
12
$(function(){
	jQuery.fn.equalHeight = function () {
		var tallest = 0;
		this.each(function() {
			tallest = ($(this).height() > tallest)? $(this).height() : tallest;
		});
		return this.height(tallest);	
	}
 
	//Now you can call equalHeight
	$(".content-column").equalHeight();
});

An interesting and similar concept is the awesome jQuery masonry plugin, if you’re interested in checking it out.

#6 – Find a Selected Phrase and Manipulate It

Whether you’re looking to perform find and replace, highlight search terms, or something else, jQuery again makes it easy with html():

1
2
3
4
5
6
7
8
9
10
11
12
$(function(){
	//First define your search string, replacement and context:
	var phrase = "your search string";
	var replacement = "new string";
	var context = $(body);
 
	//
	context.html(
		context.html().replace('/'+phrase+'/gi', replacement);
	);
 
});

#7 – Hack Your Titles to Prevent Widows

Nobody likes to see widows – but thankfully with some jQuery and a little help from &nbsp; we can stop that from happening:

1
2
3
4
5
6
7
8
$(function(){
	//Loop through each title
	$("h3").each(function(){
		var content = $(this).text().split(" ");
		var widow = "&amp;nbsp;"+content.pop();
		$(this).html(content.join(" ")+widow);
	});
});

This technique was suggested in a comment by Bill Brown on Css-Tricks.

#8 – Add Pseudo-Selector Support in IE

Whether or not to support IE (especially 6) is a hotly debated issue, but if you are of the “let’s-make-the-best-of-this” camp, it’s nice to know that you can add pseudo-selector support with jQuery. And we aren’t just limited to :hover, although that’s the most common:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$(function(){
	<strong>//ADD HOVER SUPPORT:</strong>
	function hoverOn(){
		var currentClass = $(this).attr('class').split(' ')[0]; //Get first class name
		$(this).addClass(currentClass + '-hover');
	}
	function hoverOff(){
		var currentClass = $(this).attr('class').split(' ')[0]; //Get first class name
		$(this).removeClass(currentClass + '-hover');
	}
	$(".nav-item").hover(hoverOn,hoverOff);
 
	<strong>//ADD FIRST-CHILD SUPPORT:</strong>
	jQuery.fn.firstChild = function(){
		return this.each(function(){
			var currentClass = $(this).attr('class').split(' ')[0]; //Get first class name
			$(this).children(":first").addClass(currentClass + '-first-child');
		});
	}
	$(".searchform").firstChild();
});

The great thing about setting it up that way firstChild(), hoverOn() and hoverOff() are very reusable. Now, in the CSS we can simply add the ‘nav-item-hover’ or ‘searchform-first-child’ classes as additional selectors:

1
2
3
4
5
6
7
8
.nav-item:hover, <strong>.nav-item-hover</strong>{
	background:#FFFFFF;
	border: solid 3px #888;
}
.searchform:first-child, <strong>.searchform-first-child</strong>{
	background:#FFFFFF;
	border: solid 3px #888;
}

It’s not pretty, but it is valid and it works. I’ve got to say, though, that I sure am looking forward to the day we won’t have to bother with this stuff!

#9 – Manage Search Box Values

A popular effect is to fill a site’s search box with a value (like ‘search…’) and then use jQuery to clear the default value when the field receives focus, reverting if the field is empty when blurred. That is easily accomplished with a couple lines of jQuery:

1
2
3
4
5
6
7
8
9
$(function(){
	//set default value:
	$("#searchbox")
	  .val('search?');
	  .focus(function(){this.val('')})
	  .blur(function(){
		(this.val() === '')? this.val('search?') : null;
	  });
});

#10 – Create a Disappearing ‘Back-to-Top’ Link

The disappearing back-to-top link was inspired by Brian Cray. All you have to do is add a back-to-top link at the bottom of your content like normal, and then jQuery performs the magic:

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
$(function(){
/* set variables locally for increased performance */
	var scroll_timer, 
		displayed = false,
		$message = $('#message a'),
		$window = $(window),
		top = $(document.body).children(0).position().top;
 
	/* react to scroll event on window */
	$window.scroll(function () {
		window.clearTimeout(scroll_timer);
		scroll_timer = window.setTimeout(function () { // use a timer for performance
			if($window.scrollTop() <= top) // hide if at the top of the page
			{
				displayed = false;
				$message.fadeOut(500);
			}
			else if(displayed == false) // show if scrolling down
			{
				displayed = true;
				$message.stop(true, true).show().click(function () { $message.fadeOut(500); });
			}
		}, 100);
	});
});

Brian also added some nice-looking CSS, which you could add as a css file or define in an object literal and apply it using jQuery.css(). Feel free to go check out his in-depth explanation if you want to learn more.

#11 – Easily Respond to Event Data

One of my favorite things about jQuery is its convenient remapping of event data, virtually eliminating cross-browser inconsitencies and making events much easier to respond to. jQuery passes an event parameter into all bound/triggered functions, which is commonly called e:

1
2
3
4
5
6
7
8
9
10
11
12
$(function() {
	//We can get X/Y coordinates on click events:
	$("a").click(function(<em>e</em>){
		var clickX = e.pageX;
		var clickY = e.pageX;
	});
 
	//Or detect which key was pressed:
	$("window").keypress(function(<em>e</em>){
		var keyPressed = e.which;
	});
});

You can check out the jQuery docs on this one to see all the possibilites, or view this keycode reference if you’d like to look up a certain key’s character code.

#12 – Encode HTML Entities

The first place I saw this mentioned was over at Debuggable, and I have to say they really came up with something good here. The idea is to produce a jQuery result similar to PHP’s htmlentities(). Check this out:

1
2
3
4
5
6
7
8
9
$(function(){
	var text = $("#someElement").text();
	var text2 = "Some <code> & such to encode";
	//you can define a string or get the text of an element or field
 
	var html = $(text).html();
	var html2 = $(text2).html();
	//Done - html and html2 now hold the encoded values!
});

#13 – Friendly Text Resizing

Originally mentioned at ShopDev, this is an excellent way to include some user-centricity in your code (allowing them to control the font-size):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$(function(){
  // Reset Font Size
  var originalFontSize = $('html').css('font-size');
    $(".resetFont").click(function(){
    $('html').css('font-size', originalFontSize);
  });
  // Increase Font Size
  $(".increaseFont").click(function(){
    var currentFontSize = $('html').css('font-size');
    var currentFontSizeNum = parseFloat(currentFontSize, 10);
    var newFontSize = currentFontSizeNum*1.2;
    $('html').css('font-size', newFontSize);
    return false;
  });
  // Decrease Font Size
  $(".decreaseFont").click(function(){
    var currentFontSize = $('html').css('font-size');
    var currentFontSizeNum = parseFloat(currentFontSize, 10);
    var newFontSize = currentFontSizeNum*0.8;
    $('html').css('font-size', newFontSize);
    return false;
  });
});

As I said, this is nice trick to know and adds some of that dynamic friendliness that people enjoy so much.

#14 – Open External Links in a New Window

This external links hack has been mentioned before at Cats Who Code, and although imperfect it’s a good way to open external links in new windows without causing validation errors in XHTML 1.0 Strict.

1
2
3
4
5
$(function(){
	$('a[rel$='external']').click(function(){
		this.target = "_blank";
	});
});

This works by grabbing all links with an external rel and adding a blank target. Same result, it’s just not hardcoded into the site.

#15 – Gracefully Degrading AJAX Navigation

AJAX navigation is great – but not for users and bots who can’t use it. The good news is, it’s possible to offer direct links to your content while still presenting AJAX functionality (to users who have that capability) by catching links before they go anywhere, returning false on them and loading the AJAX content instead. It could look like this:

1
2
3
4
5
6
$(function(){
	$("a").bind("click",function(){
		//Put your AJAX request code here
		return false;
	});
});

Of course, this is very basic, but it’s an essential facet to any AJAX navigation. You can also check out SpeckyBoy’s post on Easy-to-Use Free Ajax Navigation Solutions.

#16 – Create an Array of GET variables

Although this is not specifically a jQuery trick, it’s useful enough to be included here. Using GET variables in Javascript code doesn’t happen everyday, but when it does you’ll want to know a quick and efficient way to read them. All we have to do is get document.location.search and do some parsing on it:

1
2
3
4
5
6
7
8
9
10
 
var searchArray = document.location.search.substring(1).split("&");
//Take off the '?' and split into separate queries
 
//Now we'll loop through searchArray and create an associative array (object literal) called GET
var GET = []; 
for (searchTerm in searchArray){
	searchTerm.split("="); //Divide the searchTerm into property and value
	GET[searchTerm[0]] = searchTerm[1]; //Add property and value to the GET array
}

#17 – Partial Page Refresh Using load()

This excellent technique found at the Mediasoft Blog is way cool and very handy for creating a regularly updating dashboard/widget/etc. It works by using jQuery.load() to perform a AJAX request:

1
2
3
4
5
$(document).ready(function() {
	setInterval(function() {
		$("#content").load(location.href+" #content>*","");
	}, 5000);
});

Voila! It works – no iframes, meta refreshes or other such nonsense.

#18 – Skin with jQuery UI

If you’re going to write any jQuery plugins (I hope you have already!), you should know that a great way to add flexibility and elegance is to incorporate jQueryUI theming classes into any widgets/visible elements your plugin produces. The great thing about doing this is that it cuts or eliminates the css you have to provide with the plugin, and it adds a lot of customizability, too (which is one of the key factors in a successful plugin).

And the actual implementation is as simple as learning how the classes work and attaching them to plugin elements. I can see this would be especially great with plugins like form beautifiers and photo sliders, making it easy to keep a consistent look throughout a website or app. You can check out the Theming Reference here.

#19 – Include Other Scripts

Stylesheet switchers are nothing new, but adding other scripts with jQuery is something that is often overlooked. The advantage is twofold:

  1. It makes it easy to have lazy script loading.
  2. It also allows us to add scripts at runtime, which could be useful in a whole host of situations.

It’s as easy as using append() to add a new script to the head of the document:

1
2
3
4
5
6
7
8
$(function(){
	$("head").append("<script type='text/javascript' src='somescript.js'></script>");
 
	//Or, loading only when the slow stuff is ready:
	$("img,form").load(function(){
		$("head").append("<script type='text/javascript' src='somescript.js'></script>");
	});
});

#20 – Use Body Classes for Easy Styling

Do you want to save on code and keep your styling in the css file where it should be? Body classes (another great ideas suggested by Karl Swedberg) allow you to do that. In short, you can use jQuery to add a ‘JS’ class to the body element, which will enable you to set styles in your css that will only be applied if Javascript is enabled. For example:

1
2
3
$(document).ready(function() {
	$("body").addClass("JS");
});

For Javascript users the body now has a JS class, so in our CSS we can add styles like this:

ul.navigation{
	display:block;
}
.JS ul.navigation{
	display:none;
}

This gives us a great way to change styles based on whether or not Javascript is supported/enabled, and we can still keep the styling in the CSS file. Another interesting related use of this technique is to add browser classes to the body, enabling easy browser-specific styling. You can read more about that here.

#21 – Optimize Your Performance

Experienced coders don’t make clients wait – they write code that runs fast! There are several ways you can make your code run faster like:

  • Reference id’s rather than classes (id selection is native and therefore quicker)
  • Use for instead of each()
  • Limit DOM manipulation by adding elements in one big chunk rather than one at a time
  • Take advantage of event delegation
  • Link to Google’s jQuery copy rather than hosting your own – it’s faster and always up to date

Basically, it all boils down to not making jQuery do any more work than it has to (and using native abilites whenever possible). Giulio Bai wrote an excellent post on jQuery perfomance, if you’d like to dig in deeper.

#22 – Adapt Your Scripts to Work Cross-Browser – The Right Way

Thankfully, jQuery’s cross-browser compatibility really cuts down the need for browser hacks. Sometimes, though, it is good to be able to get information about the client, and we can do that cleanly and unobtrusively with jQuery.support:

1
2
3
4
5
//Does this client follow the W3C box model?
var boxModel = $.support.boxModel;
 
//Does this client support 'opacity'?
var opacity = $.support.opacity;

It’s definitely better practice to use feature-detection rather than browser sniffing, and this is a very efficient way to do it. Read more about jQuery.support’s properties here.

#23 – Configure jQuery to be Compatible with Other Libraries

We all find ourselves in situations where multiple libraries are needed, and because jQuery isn’t the only library that uses the $ alias, compatiblity issues sometimes pop up. Thankfully, this is easy to fix using jQuery’s noConflict(). You can even define a custom alias to replace the $:

1
2
3
4
var $j = jQuery.noConflict();
 
//Now you can use '$j' just like '$'
$j("div").hide();

An alternate technique is to wrap jQuery calls in an anonymous function and pass jQuery in as a parameter. Then you can use whatever alias you want, including the ‘$’. This is especially useful for plugin authoring:

1
2
3
4
5
(function($){
	$(document).ready(function(){
		//You can use normal jQuery syntax here
	});
})(jQuery);

#24 – Efficiently Store Element-Specific Information with data()

data() is probably one of the lesser used jQuery methods, although it certainly shouldn’t be. It allows us to attach/retrieve as much data as we want to DOM elements without misusing attributes, and is especially useful for more complex scripts. For example, Stefan Petre’s Colorpicker plugin uses data a lot because it’s tracking lots of fields and colors, converting rgb to hex, etc. Here’s are some examples of how data() works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$(document).ready(function() {
	//Set status to 'unsaved'
    $("button:first").data("status", "unsaved");
 
	//Retrieve status
	var buttonStatus = $("button:first").data("status");
 
	//Change status, this time defining an object literal
	$("button:first").data("status", {saved : true, index : 1});
 
	//Retrieve status of index property
	var buttonStatusIndex = $("button:first").data("status").index;
 
	//Remove status data
	$("button:first").removeData("status");
});

I’m sure you can imagine the huge extent of possibilities this presents. Again, it’s worth reading the documentation if you haven’t used data() before.

#25 – Extend/Modify Existing jQuery Functions

Nobody says you can’t use the existing jQuery platform as a springboard for new ideas – and many have done just that using extend(), another wonderful jQuery method. The popular Easing plugin, for example, adds some animation variety by extending the easing object, an already existing object that is passed to animate() and others:

1
2
3
4
5
6
7
8
9
10
11
12
13
jQuery.extend({
	easing: {
		easein: function(x, t, b, c, d) {
			return c*(t/=d)*t + b; // in
		},
		easeinout: function(x, t, b, c, d) {
			if (t < d/2) return 2*c*t*t/(d*d) + b;
			var ts = t - d/2;
			return -2*c*ts*ts/(d*d) + 2*c*ts/d + c/2 + b;		
		},
		easeout: function(x, t, b, c, d) {
			return -c*t*t/(d*d) + 2*c*t/d + b;
		}...

By extending and improving jQuery’s default functionality, you can open up a whole new world of cool possibilities.

#26 – Reverse Engineer before() and after()

I always appreciated how jQuery provided append()/prepend() and appendTo()/prependTo(), enabling us to easily perform an append in either direction. I’ve wished, though, that a similar ability was provided with before() and after(). To change that, we can easily add two functions called putBefore() and putAfter() that will fulfill that purpose. Here’s how:

1
2
3
4
5
6
7
8
9
10
11
12
$(function(){
	jQuery.fn.putBefore = function(dest){
		return this.each(function(){
			$(dest).before($(this));
		});
	}
	jQuery.fn.putAfter = function(dest){
		return this.each(function(){
			$(dest).after($(this));
		});
	}
});

#27 – Add an isChildOf() Test

I’m sure we all have found ourselves in this situation – needing to know if an element is a descendant of another element. The good news is, with one line of code we can extend jQuery to allow this:

1
2
3
4
5
6
7
8
$(function(){
	jQuery.fn.isChildOf = function(b){return (this.parents(b).length > 0);};
 
	//Now we can evaluate like this:
	if ( $("li").isChildOf("ul") ){
		//Obviously, the li is a child of the ul so this code is executed
	}
});

Thanks to Dan Switzer II for this contribution!

#28 – Add Custom Selectors

This is another one that has been talked about a lot in the development community, so you may have this already figured out. If not, get ready because this will open some whole new windows for jQuery efficiency. The short story is, jQuery allows us to extend its expression object, which means we can add whatever custom selectors we want. For example, say we wanted to add a selector version of the isChildOf() method we wrote earlier:

1
2
3
4
5
6
7
8
9
10
$(function(){
	jQuery.extend(jQuery.expr[':'], {   
		'child-of' : function(a,b,c) {
			return (jQuery(a).parents(c[3]).length > 0);
		}   
	});
 
	//'child-of' is now a valid selector:
	$("li:child-of(ul.test)").css("background","#000");  
});

Debuggable has a great post on this one as well, if you’d like to read more about how the parameters work, etc.

#29 – Smooth Scrolling Without Plugin

Karl Swedberg posted this one a while back on the Learning jQuery site, and it is definitely worth a look. Of course, there are a couple of plugins to accomplish this (and they have more features), but I think the real value in this is the excercise of doing it yourself. Plus, look at how tiny it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
$(document).ready(function() {
  $('a[href*=#]').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') 
      && location.hostname == this.hostname) {
       var $target = $(this.hash);
       $target = $target.length && $target || $('[name=' + this.hash.slice(1) +']');
       if ($target.length) {
           $target.ScrollTo(400);
           return false;
       }
    };
  });
});

#30 – Add Tabs without a Plugin

jQuery tabs are often covered but also often used, and like the scrolling trick above it’s important to know how to do these without a plugin. The first thing to do is write our markup, which should be perfectly presentable in the absence of Javascript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="widget">
	<h3>Popular</h3>
	<ul>
		<li>Item #1</li>
		<li>Item #2</li>
		<li>Item #3</li>
	</ul>
</div>
<div class="widget">
	<h3>Recent</h3>
	<ul>
		<li>Item #1</li>
		<li>Item #2</li>
		<li>Item #3</li>
	</ul>
</div>

With a bit of styling, this would look just fine, so we know our jQuery is going to degrade gracefully. Now we can write the code:

1
2
3
4
5
6
7
8
9
10
11
$(document).ready(function() {
	$("div.widget").hide().filter(":first").before("<ul class='tabs'></ul><div class='tab-content'></div>").add("div.widget").each(function(){
		$(this).find("ul").appendTo(".tab-content");
		$("ul.tabs").append("<li>" +$(this).find(":header:first").text()+ "</li>");
	});
	$("ul.tabs li").click(function(){
		$(this).addClass("active");
		$(".tab-content ul").slideUp().eq($("ul.tabs li").index(this)).slideDown();
	});
	$("ul.tabs li:first").click();
});

Of course, that’s just one way to do it. If you’d like to see some other approaches, see Extra Tuts’ jQuery Tabs Tutorials collection.

Wrapping Up

Thanks for reading, I hope you’ve enjoyed it! In case you’re all fired up on jQuery now, here are some links to more great tips n’ tricks collections:

As you can see, there are infinite opportunities for amazing innovation with jQuery. So keep experimenting, keep trying things, keep thinking, “What if?” You could be the next jQuery supergeek!

CTE公用表表达式和With用法总结

Standard

CTE(Common Table Expression) 公用表表达式,它是在单个语句的执行范围内定义的临时结果集,只在查询期间有效。它可以自引用,也可在同一查询中多次引用,实现了代码段的重复利用。

CTE最大的好处是提升T-Sql代码的可读性,可以更加优雅简洁的方式实现递归等复杂的查询。

CTE可用于:
⒈ 创建递归查询,这个应该是CTE最好用的地方
⒉ 在同一语句中多次引用生成的表
3. 减少子查询和表变量,提高执行效率

CTE优点:
1. 使用 CTE 可以获得提高可读性和轻松维护复杂查询的优点。同时,CTE要比表变量的效率高得多。
2. 可以用来定义一个SQL片断,该SQL片断会被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数据的部分。
3. 查询可以分为单独块、简单块、逻辑生成块。之后,这些简单块可用于生成更复杂的临时 CTE,直到生成最终结果集。

下面是CTE的语法:

WITH cte_name ( column_name [,...n] )
AS
(
    CTE_query_definition –- Anchor member is defined.
)

 

使用示例
1. 查询临时结果集

复制代码
WITH cte(CategoryID,CategoryName,ParentID,CategoryLevel)
AS (
  SELECT CategoryID
      ,CategoryName
      ,ParentID
      ,CategoryLevel
  FROM Category(NOLOCK)
  WHERE Status = 1 and parentid = 23
)
select * from cte;
复制代码

注意: 1.使用CTE的SQL语句应紧跟在相关的CTE后面。
2.多重CTE中间用逗号,分隔。
3.可以被紧跟着的一条SQL语句所使用多次,但不能被紧跟着的多条SQL语句使用。

2. 创建递归查询

复制代码
WITH cte(CategoryID ,CategoryName,ParentID,CategoryLevel)
AS (
  SELECT CategoryID
      ,CategoryName
      ,ParentID
      ,CategoryLevel
      FROM Category(NOLOCK)
  WHERE Status= 1 and parentid in (21,22,23,25,26)
  UNION ALL
  SELECT t.CategoryID
      ,t.CategoryName
      ,t.ParentID
      ,t.CategoryLevel
  FROM Category(NOLOCK) AS t
  INNER JOIN cte AS c ON t.parentid = c.CategoryID where Status= 1
)
select * from cte;
复制代码

 

3. cte结果集和数据表关联

复制代码
WITH cte(CategoryID,CategoryName,ParentID,CategoryLevel)
AS (
  SELECT CategoryID
      ,CategoryName
      ,ParentID
      ,CategoryLevel
  FROM Category(NOLOCK)
  WHERE Status = 1 and parentid = 23
)
select p.ProductId,p.ProductName,c.CategoryID,c.CategoryName,c.CategoryLevel 
from product p(NOLOCK)
inner join cte c(NOLOCK) on p.CategoryId=c.CategoryID
复制代码