Giter Site home page Giter Site logo

blog's People

Contributors

confidence68 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blog's Issues

webapp手机网站顶部固定fixed不为0的情况出现,滑动出现闪动!

问题描述

头部是一个普通的div,高度是48,头部下面有个固定的banner,手下滑的时候,banner会固定在浏览器最顶部不动。出现的问题是,PC端是好的,手机浏览器向上滑动的时候出现闪动!影响用户体验。

之前的做法

 if ($(window).scrollTop() < 48) {
                $(".nav ").css("top", 48 - parseInt($(window).scrollTop()));
            }else{
              $(".nav ").css("top", "0");  
            }
        $(window).scroll(function () {
            $(".nav ").css("top", "0");
            var toplength = parseInt($(window).scrollTop());
            if ($(window).scrollTop() < 48) {
                $(".nav ").css("top", 48 - toplength);
            }
 });

这样做手机网站中会出现明显的闪动效果!

改进之后的做法

if ($(window).scrollTop() < 48) {
            $(".nav ").stop().animate({"top":48 - parseInt($(window).scrollTop())},"fast");
        } else {
            $(".nav ").stop().animate({"top": "0"},"fast");
        }
$(window).scroll(function () {
            var toplength = parseInt($(window).scrollTop());
            if ($(window).scrollTop() < 48) {
                $(".nav ").stop().animate({"top": 48 - toplength},"fast");
            }else{
            $(".nav ").stop().animate({"top": "0"},"fast"); 
            }
});

这样做滑动的时候,有个向上的动画效果,不会出现闪动!

方法二

思路:顶部固定的地方,一开始和上面不固定的地方是一体的,不写position:fixed,当要固定的div的offset比scrolltop小的时候,让其固定。(我之前之所以没有用这个方法,是因为整个页面在ios中要引用,当在ios中的时候,头部不出现。)

代码如下:

menuPosition: function() {
            var m = $(window).scrollTop(), 
            n = $("#idmenuinfo的父亲").offset().top,
            l = $("#menuinfo");
            if (m >= n) {
                if (!l.hasClass("menuinfo")) {
                    l.addClass("menuinfo")
                }
            } else {
                l.removeClass("menuinfo")
            }
        }

menuinfo的样式如下:

.menuinfo {
  position: fixed!important;
  width: 100%;
  left: 0;
  top: 0;
}

期待更好的解决方案!

百度地图或者高德地图开发

前段时间写个html5的一个关于定位的文章,getCurrentPosition,在web端,只要你允许,就可以通过手机网页获取到你的当前坐标(经纬度)。那么获取这些坐标有什么用呢?

我现在就来说下作用,获取你当前的坐标,就可以定位你当前的位置,就可以通过百度地图或者高德地图,获取你周边的公交、餐饮、娱乐设施等等。这些设施可以在地图上展现,并可以获取到这个位置的距离,路线等等。

看了我上面的介绍,你是不是觉得这些在web端实现很困难?

错!这些在web端实现起来也很简单,只要你允许定位,我拿到你的经纬度,就可以通过百度或者高德地图的API获取到周边信息!那么下面让我们来看下地图周边的API吧!

我们先来看下高德地图周边的案例吧! http://lbs.amap.com/api/javascript-api/example/l/1202-2/

用高德地图周边搜索插件“AMap.PlaceSearch”来完成的。PlaceSearch差价中有用searchNearBy等等,可以通过关键词来搜索到周边的信息。

代码可以参考如下写法:

function placeSearch() {
            var MSearch;
            //加载服务插件,实例化地点查询类 
            AMap.service(["AMap.PlaceSearch"], function() {
                MSearch = new AMap.PlaceSearch({
                    city: "北京"
                });

                MSearch.searchNearBy("酒店", cpoint, 500, function(status, result){
                    if(status === 'complete' && result.info === 'OK'){
                        placeSearch_CallBack(result);
                    }
                });
            });
        }

关于高德地图的周边,我做过一个案例,大家可以参考一下。具体代码我就不公开了,因为这是我们项目中用到的一小部分!

告诉大家一下地址吧,看代码你懂得,我写的代码也比较通俗!

地图周边的案例,案例先拿掉了!

关于地图,还有很多功能!今天就先说到这里!(PS 地图还可以获取整条轨交线路、区域等等、还可以根据缩放、拖拽事件进行变化等等!)

还有点得聚合显示:http://lbs.amap.com/api/javascript-api/example/e/0515-4/ 等等!

百度地图其实也是类似的,大家有兴趣可以去看下,demo地址:http://developer.baidu.com/map/jsdemo.htm#a1_2

百度地图应用案例大家可以看:http://www.iwjw.com/chuzu/map/

今天就说到这里,详细的后面在细说!

CSS3引发大学maya的美好回忆!

今天在网上看css3的有关东西,突然看到了我们大学时候,maya建模第一课的机器狗,这个机器狗还会动。不一样的是,这个机器狗不是用maya做的了,他是用纯css3写的,很惊讶,勾起了我大学时期学习maya的美好回忆!
下面看看这个机器狗吧!

<iframe width="100%" height="300" src="http://jsfiddle.net/confidence68/pg77urh9/1/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

具体代码和演示都在上面,演示结果点击Result查看!(我把代码写在jsfiddle中了,代码引用jsfiddle的,可能有点慢,请耐心等待!)

我当时为了用maya建这个机器狗,耗费了不少时间,当时看到朱伟老师建模,是那么轻松,但是我们建起来犹如登天!班级当中maya比较好的事陈思钦,王振荣,和梁国强。王振荣,又名老四,虽然平时上课不认真,但是,这个家伙有美术方面的天赋,maya建模一学就会,很快成为高手!

当时maya建模那会,乐趣还是蛮多的!想想我也有不少maya建模青涩的作品!时光荏苒,如今,maya软件已经离我远去。。。。

RequireJs的使用和快速理解

前面我已经有两篇文章介绍requirejs 了,今天再详细介绍一下!

RequireJs已经流行很久了,它提供了以下功能:

声明不同js文件之间的依赖

可以按需、并行、延时载入js库

可以让我们的代码以模块化的方式组织

初看起来并不复杂。

在html中引入requirejs

在HTML中,添加这样的 < script> 标签:

<script src="/path/to/require.js" data-main="/path/to/app/config.js"></script>

通常使用requirejs的话,我们只需要导入requirejs即可,不需要显式导入其它的js库,因为这个工作会交给requirejs来做。

属性 data-main 是告诉requirejs:你下载完以后,马上去载入真正的入口文件。它一般用来对requirejs进行配置,并且载入真正的程序模块。

在config.js中配置requirejs

config.js 中通常用来做两件事:

1、配置requirejs 比如项目中用到哪些模块,文件路径是什么

2、载入程序主模块

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    app: 'app'
  }
});

requirejs(['app'], function(app) {
  app.hello();
});

在 paths 中,我们声明了一个名为 app 的模块,以及它对应的js文件地址。在最理想的情况下, app.js 的内容,应该使用requirejs的方式来定义模块:

define([], function() {
  return {
    hello: function() {
      alert("hello, app~");
    }
  }
});

这里的 define 是requirejs提供的函数。requirejs一共提供了两个全局变量:

1、requirejs/require: 用来配置requirejs及载入入口模块。如果其中一个命名被其它库使用了,我们可以用另一个
define: 定义一个模块

2、另外还可以把 require 当作依赖的模块,然后调用它的方法:

define(["require"], function(require) {
    var cssUrl = require.toUrl("./style.css");
});

依赖一个不使用requirejs方式的库

前面的代码是理想的情况,即依赖的js文件,里面用了 define(...) 这样的方式来组织代码的。如果没用这种方式,会出现什么情况?

比如这个 hello.js :

function hello() {
  alert("hello, world~");
}

它就按最普通的方式定义了一个函数,我们能在requirejs里使用它吗?

先看下面不能正确工作的代码:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    hello: 'hello'
  }
});

requirejs(['hello'], function(hello) {
  hello();
});

这段代码会报错,提示:

Uncaught TypeError: undefined is not a function 

原因是最后调用 hello() 的时候,这个 hello 是个 undefined . 这说明,虽然我们依赖了一个js库(它会被载入),但requirejs无法从中拿到代表它的对象注入进来供我们使用。

在这种情况下,我们要使用 shim ,将某个依赖中的某个全局变量暴露给requirejs,当作这个模块本身的引用。

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    hello: 'hello'
  },
  shim: {
    hello: { exports: 'hello' }
  }
});

requirejs(['hello'], function(hello) {
  hello();
});

再运行就正常了。

上面代码 exports: 'hello' 中的 hello ,是我们在 hello.js 中定义的 hello 函数。当我们使用 function hello() {} 的方式定义一个函数的时候,它就是全局可用的。如果我们选择了把它 export 给requirejs,那当我们的代码依赖于 hello 模块的时候,就可以拿到这个 hello 函数的引用了。

所以: exports 可以把某个非requirejs方式的代码中的某一个全局变量暴露出去,当作该模块以引用。

暴露多个变量:init

但如果我要同时暴露多个全局变量呢?比如, hello.js 的定义其实是这样的:

function hello() {
  alert("hello, world~");
}
function hello2() {
  alert("hello, world, again~");
}

它定义了两个函数,而我两个都想要。

这时就不能再用 exports 了,必须换成 init 函数:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    hello: 'hello'
  },
  shim: {
    hello: {
      init: function() {
        return {
          hello: hello,
          hello2: hello2
        }
      }
    }
  }
});

requirejs(['hello'], function(hello) {
  hello.hello1();
  hello.hello2();
});

当 exports 与 init 同时存在的时候, exports 将被忽略。

无主的与有主的模块

我遇到了一个折腾我不少时间的问题:为什么我只能使用 jquery 来依赖jquery, 而不能用其它的名字?

比如下面这段代码:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    myjquery: 'lib/jquery/jquery'
  }
});

requirejs(['myjquery'], function(jq) {
  alert(jq);
});

它会提示我:

jq is undefined

但我仅仅改个名字:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    jquery: 'lib/jquery/jquery'
  }
});

requirejs(['jquery'], function(jq) {
  alert(jq);
});

就一切正常了,能打印出 jq 相应的对象了。

为什么?我始终没搞清楚问题在哪儿。

有主的模块

经常研究,发现原来在jquery中已经定义了:

define('jquery', [], function() { ... });

它这里的 define 跟我们前面看到的 app.js 不同,在于它多了第一个参数 'jquery' ,表示给当前这个模块起了名字 jquery ,它已经是有主的了,只能属于 jquery .

所以当我们使用另一个名字:

myjquery: 'lib/jquery/jquery'

去引用这个库的时候,它会发现,在 jquery.js 里声明的模块名 jquery 与我自己使用的模块名 myjquery 不能,便不会把它赋给 myjquery ,所以 myjquery 的值是 undefined 。

所以我们在使用一个第三方的时候,一定要注意它是否声明了一个确定的模块名。

无主的模块

如果我们不指明模块名,就像这样:

define([...], function() {
  ...
});

那么它就是无主的模块。我们可以在 requirejs.config 里,使用任意一个模块名来引用它。这样的话,就让我们的命名非常自由,大部分的模块就是无主的。

为什么有的有主,有的无主

可以看到,无主的模块使用起来非常自由,为什么某些库(jquery, underscore)要把自己声明为有主的呢?

按某些说法,这么做是出于性能的考虑。因为像 jquery , underscore 这样的基础库,经常被其它的库依赖。如果声明为无主的,那么其它的库很可能起不同的模块名,这样当我们使用它们时,就可能会多次载入jquery/underscore。

而把它们声明为有主的,那么所有的模块只能使用同一个名字引用它们,这样系统就只会载入它们一次。

挖墙角

对于有主的模块,我们还有一种方式可以挖墙角:不把它们当作满足requirejs规范的模块,而当作普通js库,然后在 shim 中导出它们定义的全局变量。

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    myjquery: 'lib/jquery/jquery'
  },
  shim: {
    myjquery: { exports: 'jQuery' }
  }
});

requirejs(['myjquery'], function(jq) {
  alert(jq);
});

这样通过暴露 jQuery 这个全局变量给 myjquery ,我们就能正常的使用它了。

不过我们完全没有必要这么挖墙角,因为对于我们来说,似乎没有任何好处。

如何完全不让jquery污染全局的$

在前面引用jquery的这几种方式中,我们虽然可以以模块的方式拿到jquery模块的引用,但是还是可以在任何地方使用全局变量 jQuery 和 $ 。有没有办法让jquery完全不污染这两个变量?

在init中调用noConflict (无效)

首先尝试一种最简单但是不工作的方式:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    jquery: 'lib/jquery/jquery'
  },
  shim: {
    jquery: {
      init: function() {
        return jQuery.noConflict(true);
      }
    }
  }
});

requirejs(['jquery'], function(jq) {
  alert($);
});

这样是不工作的,还是会弹出来一个非 undefined 的值。其原因是,一旦requirejs为模块名 jquery 找到了属于它的模块,它就会忽略 shim 中相应的内容。也就是说,下面这段代码完全没有执行:

jquery: {
  init: function() {
    return jQuery.noConflict(true);
  }
}

使用另一个名字

如果我们使用挖墙角的方式来使用jquery,如下:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    myjquery: 'lib/jquery/jquery'
  },
  shim: {
    myjquery: {
      init: function() {
        return jQuery.noConflict(true);
      }
    }
  }
});

requirejs(['myjquery'], function(jq) {
  alert($);
});

这样的确有效,这时弹出来的就是一个 undefined 。但是这样做的问题是,如果我们引用的某个第三方库还是使用 jquery 来引用jquery,那么就会报“找不到模块”的错了。

我们要么得手动修改第三方模块的代码,要么再为它们提供一个 jquery 模块。但是使用后者的话,全局变量 $ 可能又重新被污染了。

使用map

如果我们有办法能让在继续使用 jquery 这个模块名的同时,有机会调用 jQuery.noConflict(true) 就好了。

我们可以再定义一个模块,仅仅为了执行这句代码:

jquery-private.js

define(['jquery'], function(jq) {
  return jQuery.noConflict(true);
});

然后在入口处先调用它:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    jquery: 'lib/jquery/jquery',
    'jquery-private': 'jquery-private'
  }
});

requirejs(['jquery-private', 'jquery'], function() {
  alert($);
});

这样的确可行,但是还是会有问题: 我们必须小心的确保 jquery-private 永远是第一个被依赖,这样它才有机会尽早调用 jQuery.noConflict(true) 清除全局变量 $ 和 jQuery 。这种保证只能靠人,非常不可靠。

我们这时可以引入 map 配置,一劳永逸地解决这样问题:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    jquery: 'lib/jquery/jquery',
    'jquery-private': 'jquery-private'
  },
  map: {
    '*': { 'jquery': 'jquery-private'},
    'jquery-private': { 'jquery': 'jquery'}
  }
});

requirejs(['jquery'], function(jq) {
  alert($);
});

这样做,就解决了前面的问题:在除了jquery-private之外的任何依赖中,还可以直接使用 jqurey 这个模块名,并且总是被替换为对 jquery-private 的依赖,使得它最先被执行。

小结

与requirejs类似的还有seajs等等。javascript模块化编程很重要,requirejs属于AMD规范,关于AMD 规范,请看:https://github.com/amdjs/amdjs-api/wiki/AMD

假如您也是前端,可以在项目中用一下!

CentOS安装NodeJS及Express开发框架

本文演示在Linux上安装NodeJS及Express开发框架
nodejs和mongodb的更新速度太快。参考以前的老文章进行安装,但是用最新版本的nodejs的话,通常会出现很多问题。最新版本的nodejs解压就可以使用和运行,但是,为了更好的配置nodejs,我使用了nodejs 的v0.10.24版本进行安装。

具体安装过程如下:

Step 1、确认服务器有nodejs编译及依赖相关软件,如果没有可通过运行以下命令安装。

[root@BobServerStation local]# yum -y install gcc gcc-c++ openssl-devel 

Step 2、下载NodeJS源码包并解压

[root@BobServerStation local]# wget http://nodejs.org/dist/v0.10.24/node-v0.10.24.tar.gz  
[root@BobServerStation local]# tar zxvf node-v0.10.24.tar.gz  
[root@BobServerStation local]# cd node-v0.10.24  

Step 3、配置、编译、安装。

[root@BobServerStation node-v0.10.24]# ./configure --prefix=/usr/local/node  
[root@BobServerStation node-v0.10.24]# make && make install  

Step 4、接下来配置Node环境

[root@BobServerStation node-v0.10.24]# vim /etc/profile  

#set nodejs env  
export NODE_HOME=/usr/local/node  
export PATH=$NODE_HOME/bin:$PATH  
export NODE_PATH=$NODE_HOME/lib/node_modules:$PATH    
[root@BobServerStation node-v0.10.24]# source /etc/profile

--重启生效

Step 5、测试是否安装成功

[root@BobServerStation node-v0.10.24]# node -v  
v0.10.24  

出现NodeJS版本号则表示OK。

Step 6、输出NodeJS之Hello World

[root@BobServerStation node-v0.10.24]# node  
> console.log(”Hello NodeJS, I'm Bob.Z“);  
Hello NodeJS, I'm Bob.Z  
undefined  
>   

输出:Hello NodeJS, I'm Bob.Z

Step 7、安装Express开发框架

[root@BobServerStation local]# npm install express -g  

Step 8、创建Demo项目

[root@BobServerStation local]# express DemoApp  
[root@BobServerStation local]# cd DemoApp  
[root@BobServerStation DemoApp]#   

Step 9、进入项目目录并安装项目依赖组件

[root@BobServerStation local]# cd DemoApp  
[root@BobServerStation DemoApp]# npm install

Step 10、安装依赖组件npm的时候,出错的话,请运行如下命令(npm国内镜像)

方法一:通过config命令
     npm config set registry http://registry.cnpmjs.org
     npm info underscore (如果上面配置正确这个命令会有字符串response)
方法一:命令行指定
    npm --registry http://registry.cnpmjs.org info underscore
方法三:编辑 ~/.npmrc 加入下面内容
    registry = http://registry.cnpmjs.org

Step 11、依赖组件安装完成后启动app

[root@BobServerStation DemoApp]# node app  
Express server listening on port 3000  

最后通过浏览器访问服务器3000端口,页面显示,
Express
Welcome to Express

电脑上调试手机网站的几种方法

手机网站开发,最让人头疼的是网站的兼容问题,不同的手机可能会出现一些莫名的问题。手机网站常见问题及解决方案,我会在后面的文章陆续发表,大家可以看一下。

本文主要讲解电脑上如何调试手机网站:

一、安卓手机的调试:

1、最常见的安卓手机的调试方法是用chrome浏览器调节,既方便有简单。(chrome的版本要在v20.0以上)

按F12,调出代码调试器,如下图

![enter image description here](http://www.haorooms.com/uploads/images/chrome.jpg)

可以让代码调试器左右结构显示

按照下面画红色圈圈的地方进行操作,如下图:

![enter image description here](http://www.haorooms.com/uploads/images/chrome2.jpg)

您可以看到有很多设备可以选择

![enter image description here](http://www.haorooms.com/uploads/images/chrome3.jpg)

选择Emulate就可以对您的网站进行模拟调试了!

2、安装安卓虚拟机,这种方式可以模拟真机,效果更好一些!

方法如下:
地址http://www.genymotion.cn/
打开上面的地址,注册下载。

安装方法参见:http://www.genymotion.cn/#theme=guide

安装好了以后,有时候不能安装软件,需要破解,下面写写破解步骤!

第一部: 装个ARM转换器 Genymotion-ARM-Translation

地址: http://goo.gl/tfjjMt

第二部: 装个Google Apps ,http://goo.im/gapps

把这两个文件拖进虚拟机就可以了!【注意:对应版本要下载好,不然不好用的】

安装好了,运行之后如下图:

![enter image description here](http://www.haorooms.com/uploads/images/virtual_device_home.jpg)

二、苹果手机的调试方法:

对于苹果手机的调试,要想在电脑上进行,那必须要用苹果电脑(Mac)了!Mac 版的 Safari 浏览器早就可以连接 iPhone 进行测试了,可以看这里:通过Mac远程调试iPhone/iPad上的网页。

也就是说,你将 iPhone 连接 Mac 之后在 iPhone 的 Safari 打开网页,然后再打开 Mac 上的 Safari 浏览器,选择“开发”就可以看到你的 iPhone 上面的网页了,然后会打开 Console 这样的工具。就可以进行各种调试和检查,操作会实时改变在 iPhone 上。
这里如果没有 iPhone 或者觉得 iPhone 连接麻烦,其实也可以使用 Xcode 开发套装中的 iPhone 模拟器。

打开 Xcode 之后,在 “Xcode”->“Open Developer Tool”->“iOS Simulator” 即可打开一个 iPhone 模拟器。

![enter image description here](http://www.haorooms.com/uploads/images/mobile2.png)

这个模拟器几乎跟真实环境一致,还可以设置 iOS 的设备型号等。在模拟器中 Safari 打开的网页,也可以被 Safari 检测到并进行调试,这样就方便多了,不需要来回插拔数据线,同时还可以方便对照设计稿进行细节调整等。

总结:

安卓手机的调试,大部分可以用安卓虚拟机或者chrome进行。苹果手机的调试就要用MAC机进行。要是大家还有什么好的调试方法,可以留言交流!当然,真机调试也是一种不错的选择!

Centos6.5安装配置nginx

我也是第一次安装nginx,现在将我的安装方法记录下来:

方法一:安装最新版的nginx

1、下载nginx1.7.4

注:下载地址:http://nginx.org/download/nginx-1.7.4.tar.gz

wget -c http://nginx.org/download/nginx-1.7.4.tar.gz  

2、安装

注:默认安装到/usr/local/nginx

tar -zxvf nginx-1.7.4.tar.gz   
cd nginx-1.7.4   
./configure    
make && make install #注:会出来一堆东西  

3、运行

/usr/local/nginx/sbin/nginx

查看nginx是否正常

[root@aaa nginx-1.2.4]# /usr/local/nginx/sbin/nginx -t  

出现如下代码:
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
安装成功!

方法二:

编译安装nginx,(参考我同事的安装方法)
安装 OpenSSL(方法自行搜索,或者yum install openssl)
准备 pcre 库
pere 是为了让 nginx 支持正则表达式。只是准备,并不安装,是为了避免在64位系统中出现错误。

wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.30.tar.gz
//在/usr/local目录下解压
tar -zxf pcre-8.30

准备 zlib 库,同样只是准备,并不安装,是为了避免在64位系统中出现错误。

wget http://sourceforge.net/projects/libpng/files/zlib/1.2.6/zlib-1.2.6.tar.gz/download
//在/usr/local目录下解压
tar -zxf zlib-1.2.6.tar.gz

编译安装

1、下载、创建临时目录

wget http://nginx.org/download/nginx-1.1.9.tar.gz
tar -zxf nginx-1.1.9.tar.gz
cd nginx-1.1.9
mkdir -p /var/tmp/nginx

2、编译与安装

./configure --prefix=/usr/local/nginx \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--with-http_ssl_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-mail --with-mail_ssl_module \
--with-pcre=../pcre-8.30 \
--with-zlib=../zlib-1.2.6 \
--with-debug \
--http-client-body-temp-path=/var/tmp/nginx/client \
--http-proxy-temp-path=/var/tmp/nginx/proxy \
--http-fastcgi-temp-path=/var/tmp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
--http-scgi-temp-path=/var/tmp/nginx/scgi 

make && make install
ln -s /usr/local/nginx/sbin/nginx /usr/sbin/

可参考:Nginx编译参数解析

–prefix #nginx安装目录,默认在/usr/local/nginx
–pid-path #pid问件位置,默认在logs目录
–lock-path #lock问件位置,默认在logs目录
–with-http_ssl_module #开启HTTP SSL模块,以支持HTTPS请求。
–with-http_dav_module #开启WebDAV扩展动作模块,可为文件和目录指定权限
–with-http_flv_module #支持对FLV文件的拖动播放
–with-http_realip_module #支持显示真实来源IP地址
–with-http_gzip_static_module #预压缩文件传前检查,防止文件被重复压缩
–with-http_stub_status_module #取得一些nginx的运行状态
–with-mail #允许POP3/IMAP4/SMTP代理模块
–with-mail_ssl_module #允许POP3/IMAP/SMTP可以使用SSL/TLS
–with-pcre=../pcre-8.11 #注意是未安装的pcre路径
–with-zlib=../zlib-1.2.5 #注意是未安装的zlib路径
–with-debug #允许调试日志
–http-client-body-temp-path #客户端请求临时文件路径
–http-proxy-temp-path #设置http proxy临时文件路径
–http-fastcgi-temp-path #设置http fastcgi临时文件路径
–http-uwsgi-temp-path=/var/tmp/nginx/uwsgi #设置uwsgi 临时文件路径
–http-scgi-temp-path=/var/tmp/nginx/scgi #设置scgi 临时文件路径

3、开机自启动 nginx 脚本

vim /etc/init.d/nginx

进入编辑模式,键入以下脚本内容:

#!/bin/bash  
#  
#chkconfig: - 85 15  
#description: Nginx is a World Wide Web server.  
#processname: nginx  

nginx=/usr/local/nginx/sbin/nginx  
conf=/usr/local/nginx/conf/nginx.conf  

case $1 in  
       start)  
              echo -n "Starting Nginx"  
              $nginx -c $conf  
              echo " done"  
       ;;  

       stop)  
              echo -n "Stopping Nginx"  
              killall -9 nginx  
              echo " done"  
       ;;  

       test)  
              $nginx -t -c $conf  
       ;;  

        reload)  
              echo -n "Reloading Nginx"  
              ps auxww | grep nginx | grep master | awk '{print $2}' | xargs kill -HUP  
              echo " done"  
       ;;  

        restart)  
                $0 stop  
                $0 start  
       ;;  

       show)  
              ps -aux|grep nginx  
       ;;  

       *)  
              echo -n "Usage: $0 {start|restart|reload|stop|test|show}"  
       ;;  

esac

保存以上脚本后,执行以下操作

chmod +x /etc/init.d/nginx
chkconfig --add nginx  
chkconfig nginx on 

可以使用nginx -t来检验语法是否有问题。

input文本框输入时正则判断

1、只能输入数字

文本框只能输入数字代码(小数点也不能输入)

方式一:

<input type="text"name="number" id="number" value="1" maxlength="8" title="nb" onkeyup="value=value.replace(/[^\d]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g, ''))">

方式二:

<input onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')"> 

2.只能输入数字,能输小数点.

方法一:

<input onkeyup="if(isNaN(value))execCommand('undo')" onafterpaste="if(isNaN(value))execCommand('undo')"> 
<input name=txt1 onchange="if(/\D/.test(this.value)){alert('只能输入数字');this.value='';}"> 

方法二 :

<input type=text t_value="" o_value="" onkeypress="if(!this.value.match(/^[\+\-]?\d*?\.?\d*?$/))this.value=this.t_value;else this.t_value=this.value;if(this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?)?$/))this.o_value=this.value" onkeyup="if(!this.value.match(/^[\+\-]?\d*?\.?\d*?$/))this.value=this.t_value;else this.t_value=this.value;if(this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?)?$/))this.o_value=this.value" onblur="if(!this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?|\.\d*?)?$/))this.value=this.o_value;else{if(this.value.match(/^\.\d+$/))this.value=0+this.value;if(this.value.match(/^\.$/))this.value=0;this.o_value=this.value}"> 

3.只能输入字母和汉字

<input onkeyup="value=value.replace(/[\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[\d]/g,''))" maxlength=10 name="Numbers"> 

4.只能输入英文字母和数字,不能输入中文

<input onkeyup="value=value.replace(/[^\w\.\/]/ig,'')"> 

5.只能输入数字和英文

方法一:

<input onKeyUp="value=value.replace(/[^\d|chun]/g,'')"> 

方法二:

<input onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))">

6.小数点后只能有最多两位(数字,中文都可输入),不能输入字母和运算符号:

<input onKeyPress="if((event.keyCode<48 || event.keyCode>57) && event.keyCode!=46 || /\.\d\d$/.test(value))event.returnValue=false"> 

7.小数点后只能有最多两位(数字,字母,中文都可输入),可以输入运算符号:

<input onkeyup="this.value=this.value.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3')">

8、禁止特殊字符:

onKeyPress="if(event.keyCode < 45 || event.keyCode > 57 ) event.returnValue = false;"

9、只能输入汉字:

<input onkeyup="value=value.replace(/[^/u4E00-/u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^/u4E00-/u9FA5]/g,''))">

10、只禁止空格输入

onkeyup="value=value.replace(/\s/g,'')"

11、只能输入中文和英文:

onkeyup="value=value.replace(/[^\a-zA-Z\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\a-zA-Z\u4E00-\u9FA5]/g,''))"

12、身份证的正则判断:

  var aCity={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"**",71:"**",81:"香港",82:"澳门",91:"国外"} 

function isCardID(sId){ 
var iSum=0 ;
var info="" ;
if(!/^\d{17}(\d|x)$/i.test(sId)){ alert("你输入的身份证长度或格式错误"); flagsid=true;return;}
sId=sId.replace(/x$/i,"a"); 
if(aCity[parseInt(sId.substr(0,2))]==null){ alert("你的身份证地区非法"); flagsid=true;return;}
sBirthday=sId.substr(6,4)+"-"+Number(sId.substr(10,2))+"-"+Number(sId.substr(12,2)); 
var d=new Date(sBirthday.replace(/-/g,"/")) ;
if(sBirthday!=(d.getFullYear()+"-"+ (d.getMonth()+1) + "-" + d.getDate())){alert("身份证上的出生日期非法") ; flagsid=true;return;}
for(var i = 17;i>=0;i --) iSum += (Math.pow(2,i) % 11) * parseInt(sId.charAt(17 - i),11) ;
if(iSum%11!=1) {alert("你输入的身份证号非法"); flagsid=true;return;}
                    flagsid=false;
return true;//aCity[parseInt(sId.substr(0,2))]+","+sBirthday+","+(sId.substr(16,1)%2?"男":"女") 
}

DEDECMS导航栏制作,(一二三)级导航

DEDECMS源码相信很多朋友都用过,DEDECMS 和phpmywind,对于建设企业网站,是很不错的两款源码,dedecms可以建设相对大型的企业网站,phpmywind可以建设中小型的,方便操作。还有就是ECSHOP源码,对于建设电商网站,是不错的选择。后期会对ECSHOP做简单介绍,请关注我的博客。

切入正题,来谈谈织梦的导航栏制作:

一、对于只有主栏目,没有子栏目的网站,该类栏目的dedecms调用方法比较简单,如下:

{dede:channel type='top' currentstyle="<li class='thisclass'><a href='~typelink~'>~typename~</a> </li>"} 
<li>
     <a href='[field:typeurl/]'>[field:typename/]</a>
</li>
{/dede:channel}

注释(参数): typeid='0' 栏目ID; reid = '0' 上级栏目ID; row = '100' 调用栏目数;col = '1' 分多少列显示(默认为单列);type = 'son | sun' son表示下级栏目,self表示同级栏目,top顶级栏目; currentstyle = '' 应用样式"。

这种方法会把后台的顶级栏目都调用出来,如果想有些栏目不被调用出来,可以加上参数typeid=‘所要调用栏目的id’。对于调用指定的栏目可以用下面的标签:

{dede:type typeid=‘指定栏目的id’}<a href="[field:typelink /]">[field:typename /]</a>{/dede:type}

二、 带有二级子栏目的栏目的调用

代码如下:

    <li class="nav">
            {dede:type typeid='指定ID'}<a href='[field:typelink/]' class="depth_1" >[field:typename/]</a>{/dede:type}
          <ul  style="display: none; ">        
                                   {dede:channelartlist typeid='top'  typeid='指定ID'}          
                                      <li><a href='{dede:field name='typeurl'/}' class="depth_2">{dede:field name='typename'/}</a> </li>                
                                     {/dede:channelartlist}      
        </ul>
    </li>

三、 带有三级子栏目的栏目的调用

代码如下:

<li class="nav">
        {dede:type typeid='指定ID'}
                <a href='[field:typelink/]' class="depth_1" style="width:110px; text-align:center;">[field:typename/]</a>{/dede:type}
           <ul  style="display: none; ">        
                            {dede:channelartlist typeid='top'  typeid='指定ID'}          
                              <li><a href='{dede:field name='typeurl'/}' class="depth_2">{dede:field name='typename'/}</a>   
                                <ul>        
                                 {dede:sql sql='Select * from t_arctype where reid=~id~  ORDER BY id limit 0,20'}  //最多20条
                                   <li><a href="/plus/list.php?tid=[field:id/]"  class="depth_3">[field:typename/]</a></li>      
                                  {/dede:sql}                               
                                  </ul>                 
                             </li>                
                              {/dede:channelartlist}   

     </ul>
      </li>

其中最里面的SQl也可以这么写:

{dede:sql sql='Select * from dede_arctype where reid=~id~  ORDER BY id limit 0,20'}  //limit 起始三级栏目id  显示栏目的条数                                  <li><a href="[field:typedir function='str_replace("{cmspath}","",@me)'/]"  class="depth_3">[field:typename/]</a></li>                                  {/dede:sql}  

JavaScript RegExp 常用的手机和邮箱正则

在做前端form表单验证的时候,经常,也是必须对input做一下判断,例如邮箱了,手机了,input非空了,input只能输入数字了等等。关于input文本框输入限制,请看文章:input文本框输入时正则判断

本篇文章主要讲解“JavaScript RegExp 常用的手机和邮箱正则”,我在做表单的时候,一般是应用Validform,这个插件是比较好用的,能很好的解决绝大部分的表单验证。具体的demo地址是:http://validform.rjboy.cn/demo.html

但是,这个表单验证不是万能的,有需要特殊处理的时候,例如,如何正确判断一个input文本框既能输入手机,又能输入邮箱呢?

这种情况的应用场景很多,有时候用户名必须是手机或者邮箱,其他不对,就用到了这个判断。

其实这种正则表达式也是比较简单的,下面我就讲解一下:

邮箱的正则:

^[\w.\-]+@(?:[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z]{2,3}$

手机的正则

^1[3|4|5|8]\d{9}$

两个正则的结合,只需要“I”就可以了,如下:

(^[\w.\-]+@(?:[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z]{2,3}$)|(^1[3|4|5|8]\d{9}$) //邮箱和手机

同样的道理,有时候在填写物流信息的时候,需要留联系方式,联系方式可以是手机或者电话,那么正则同理也很简单,可以如下写:

(^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|18[0-9]{9}$)|(^0(10|2[0-5789]|\\d{3})\\d{7,8}$) //手机和电话

若你运用Validform,找到Validform_v5.3.2.js这个文件,找到如下代码:

dataType:{
    "*":/[\w\W]+/,
    "*6-16":/^[\w\W]{6,16}$/,
    "n":/^\d+$/,
    "n6-16":/^\d{6,16}$/,
    "s":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s]+$/,
    "s6-18":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s]{6,18}$/,
    "p":/^[0-9]{6}$/,
    "m":/^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|18[0-9]{9}$/,
    "e":/^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
    "url":/^(\w+:\/\/)?\w+(\.\w+)+.*$/
},

将上面的正则添加在后面就可以了!

或者你也可以自己判断,方法如下:

 var reg = new RegExp("(^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|18[0-9]{9}$)|(^0(10|2[0-5789]|\\d{3})\\d{7,8}$)");
 if(!reg.test(phone_mob)){
        hiAlert('请输入正确的手机号码', '请注意',function(){
        $("#phone_mob").focus();
        });
             return false;
             }

上面代码我运用的是hiAlert插件,您也可以自己直接用alert,提示!

CSS选中状态修改,谷歌滚动轴修改

1、滚动轴美化,一下代码是针对谷歌中滚动轴的设置美化,把它加到你的css中就可以了,代码如下:

::-webkit-scrollbar{
    padding-left:1px;
    background-color:#fafafa;
    overflow:visible;
    width:9px;
}
::-webkit-scrollbar-thumb{
    background-color:rgba(0, 0, 0, .1);
    background-clip:padding-box;
    border-left-width:2px;
    min-height:10px;
    box-shadow:inset 1px 1px 0 rgba(0, 0, 0, .1),inset 0 -1px 0 rgba(0, 0, 0, .07);
}
::-webkit-scrollbar-thumb:vertical:hover{
    background-color:rgba(0, 0, 0, .2);
}
::-webkit-scrollbar-thumb:vertical:active{
    background-color:rgba(0, 0, 0, .2);
}
::-webkit-scrollbar-button{
    height:0;
    width:0;
}
::-webkit-scrollbar-track{
    background-clip:padding-box;
    border:solid transparent;
    border-width:0 0 0 2px;
}
::-webkit-scrollbar-corner{
    background:transparent;
}
::-webkit-scrollbar-track-piece{
margin: 10px 0;
-webkit-border-radius: 0;
-webkit-border-bottom-right-radius: 4px;
-webkit-border-bottom-left-radius: 4px;
}

2、选中状态的修改,如下图:

enter image description here

很多网站洪,选中文字,不是默认的蓝色了,改成了别的颜色,修改方法如下:

::selection {
background: #ff0;
}

将上面代码放到你的css中就可以了。

前端开发中的复文本框

在做前端开发的时候,特别是后台提交文章,包括后台博客编辑等等,经常会用到复文本框。例如,csdn博客用的是xheditor,这个复文本框我之前也经常使用,很好用,可以自定义,如果你有csdn博客,在发布文章的时候你就知道了,还是比较好用的。

xheditor在线演示:http://xheditor.com/demo

今天主要介绍的是另一款复文本编辑器,ueditor

这款编辑器虽然我在项目中没有使用过,但是对他是一见钟情。

知道这款编辑器,还是从我领导的博客后台看到的,他的博客是用Z-blog源码建成的,后台编辑器用的是ueditor,ueditor功能强大之处在于可以直接将QQ截图等复制到文本框中,同时也可以将word文件导入到复文本框中,还有就是它有不少插件,其中一个插件就是WEB表单设计器,就是在博客中直接编辑表单,强大吧!

先看看它的模样:

enter image description here

UEdiror创建demo也很简单,

解压下载的包,在解压后的目录创建 demo.html 文件,填入下面的html代码

<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <meta charset="UTF-8">
    <title>ueditor demo</title>
</head>

<body>
    <!-- 加载编辑器的容器 -->
    <script id="container" name="content" type="text/plain">
        这里写你的初始化内容
    </script>
    <!-- 配置文件 -->
    <script type="text/javascript" src="ueditor.config.js"></script>
    <!-- 编辑器源码文件 -->
    <script type="text/javascript" src="ueditor.all.js"></script>
    <!-- 实例化编辑器 -->
    <script type="text/javascript">
        var ue = UE.getEditor('container');
    </script>
</body>

</html>

在浏览器打开demo.html

如果看到了下面这样的编辑器,恭喜你,初次部署成功!
enter image description here

是不是很简单。在这里我就不废话了,直接把它的API献上:http://ueditor.baidu.com/doc/

css对话框的写法

最近比较忙,好久没有维护博客了,在这里表示歉意。

最近主要在做touchweb的项目,那么我就记录一下我在做这个项目中的问题吧,当然,今天主要是从css开始。后面博客会陆续记录其他的问题,例如图片延迟加载、图片的canvas渲染、jquery模拟下拉选择以及highchart图表、高德地图、swipe滑动、jquery的hover图片闪烁等问题。好吧,言归正传,今天主要先介绍一下css吧。

之前我在css常用效果总结这篇文章中写了一下常用的容易忘掉的css ,今天写的这个css模拟对话框,假如你理解了,那么是很好记的,你不理解没有关系,可以把我的这篇文章收藏起来,用到的时候,可以翻出来看一下!

如下图:左侧三角形

<iframe style="width: 100%; height: 100px" src="http://sandbox.runjs.cn/show/qe7lk7pm" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

css代码如下:

#talkbubble {
    margin-left:30px;
   width: 120px; 
   height: 80px; 
   background: red;
   position: relative;
   -moz-border-radius:    10px; 
   -webkit-border-radius: 10px; 
   border-radius:         10px;
}
#talkbubble:before {
   content:"";
   position: absolute;
   right: 100%;
   top: 26px;
   width: 0;
   height: 0;
   border-top: 13px solid transparent;
   border-right: 26px solid red;
   border-bottom: 13px solid transparent;
}

其实,本案例的精华就是三角形的绘制,那么如何绘制三角形呢?我在这里总结一下!

1、上三角形,上三角形,顶部是尖的,所以用border-left,border-right,和border-bottom可以实现,给bottom一个颜色,其他设置为transparent

#triangle-up {
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 100px solid red;
}

同理,大家可以判断一下如下代码分别是什么样的三角形!

#triangle-down {
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-top: 100px solid red;
} 

#triangle-left {
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-right: 100px solid red;
    border-bottom: 50px solid transparent;
}

 #triangle-right {
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-left: 100px solid red;
    border-bottom: 50px solid transparent;
} 

#triangle-topleft {
    width: 0;
    height: 0;
    border-top: 100px solid red; 
    border-right: 100px solid transparent;          
}
#triangle-topright {
    width: 0;
    height: 0;
    border-top: 100px solid red; 
    border-left: 100px solid transparent;
}
#triangle-bottomleft {
    width: 0;
    height: 0;
    border-bottom: 100px solid red; 
    border-right: 100px solid transparent;  
}  

#triangle-bottomright {
    width: 0;
    height: 0;
    border-bottom: 100px solid red; 
    border-left: 100px solid transparent;
}

判断出上面代码分别代表什么三角形吗?没错,我的命名是根据三角形的方向来的。大家可以试一下。三角形会写了,那么对话框就迎刃而解了!
不管是左侧的,还是上面的,只要改变一下before伪类的定位,就可以实现了。

当然,三角形的写法是很基础的。你也可以用css绘制出五角星、六角星、多边形、爱心等等。当然有些符号是不常用的,用的最多的还是三角形。

touchweb手机网站图片加载方法(canvas加载和延迟加载)

关于手机网站的图片加载,canvas方法加载图片,占用内存最小,效果最佳,关于canvas图片加载,我之前的一篇文章中提几个。具体请看手机网站几点注意的问题。当然,这些都是很久之前整理的,有些地方写的可能有点问题,例如zeptiojs了等等。

一、canvas图片加载

关于canvas加载,我的方法是,将文章中所有用到图片的地方,都用canvas代替,给canvas一个data-src,里面存放img的路径,通过canvas方法渲染图片。因为图片渲染需要时间,一般会给canvas一个背景,背景可以用gif图片。图片渲染好了之后把背景去掉。

我的canvas代码如下:

canvasload: function () {
            //canvas加载图片
            var imglength = $("#您的id").find("canvas").length;
            if (imglength > 0) {
                $("#您的id").find("canvas").each(function () {
                    var imgSrc = $(this).data("src");
                    var imageObj = new Image();
                    imageObj.canvs = $(this)[0];
                    var cvs = imageObj.canvs.getContext('2d');
                    if (cvs) {
                        imageObj.onload = function () {
                            imageObj.canvs.width = this.width;
                            imageObj.canvs.height = this.height;
                            cvs.drawImage(this, 0, 0);
                            $(imageObj.canvs).css("background-image", "none");
                        }
                        imageObj.src = imgSrc;
                    }
                })
            }
},

用法很简单,直接在页面中引用这个函数就可以了,注意,所有canvas外层要包裹一个ID

二、图片延迟加载

图片延迟加载方法有很多,下面简单介绍一个,可以引入一个jquery插件。这个插件是一个网友写的,试了一下能用,代码如下:

;(function ($) {  
    $.fn.lazyloading = function (options) {  
        var defaults = {  
            preyimg: "/load.gif",  
            picpath: "data-original",  
            container: $(window),  
            loadfirst: false, //进入页面后是否加载当前页面的图片  
            defaultHeightID: "lazyloadingHeight"//页面上默认高度的input标签id  
            //imgPaddingID: "lazyloadingPadding"//img的padding值  
        };  
        var params = $.extend({}, defaults, options || {});  
        params.cache = [];  
        $(this).each(function () {  
            var node = this.nodeName.toLowerCase(), url = $(this).attr(params["picpath"]), preyimg = params["preyimg"];  
            var defaultheight = $("#" + params["defaultHeightID"]).val(); //, padding = $("#" + params["imgPaddingID"]).val(); //  
            //重组  
            var data = {  
                obj: $(this),  
                tag: node,  
                url: url,  
                preyimg: preyimg,  
                defaultheight: defaultheight  
            };  
            params.cache.push(data);  
        });  

        var init = function () {  
            $.each(params.cache, function (i, data) {  
                var thisImg = data.obj, tag = data.tag, url = data.url, preyimg = data.preyimg;  
                if (typeof (url) != "undefined")// 判断是否需要延迟加载  
                {  
                    var parent1 = thisImg.parent(); //a  
                    var Inner = null; //  
                    if (parent1.is("a") == true) {//img wrap by a  
                        Inner = parent1;  
                    }  
                    else {  
                        Inner = thisImg;  
                    }  
                    var width = thisImg.attr("width") || thisImg.css("width");  
                    var height = data.defaultheight || thisImg.css("height");  
                    //if (i == 0) alert(data.defaultheight);  
                    var attrheight = thisImg.attr("height");  
                    if (attrheight != null) height = attrheight;  
                    if (width != null && width.indexOf("px") > -1) width.replace("px", "");  
                    if (height != null && height.indexOf("px") > -1) height.replace("px", "");  
                    var divstr = "<div class='.loading' style='text-align: left;position:relative;float:left;width:" + width + "px;";  
                    var HasHeight = true; //图片是否指定了高度  
                    divstr = divstr + "height:" + height + "px;";  
                    if (attrheight == null || attrheight == "") {  
                        HasHeight = false;  
                    }  

                    thisImg.css("position", "relative");  

                    divstr = divstr + "' ></div>"  
                    //修正外层div:text-align的影响  
                    Inner.wrap(divstr);  
                    //修正img外面不是a标签时parent()已经改变的问题  
                    parent1 = thisImg.parent();  
                    if (HasHeight == true) { parent1.attr("lazyloading_hasheight", "1"); } //是否指定了高度  
                    else { { parent1.attr("lazyloading_hasheight", "0"); } }  
                    parent1.append("<img class='loadhiddenimg' width='0' height='0' style='display:none;' src='' />");  
                    thisImg.attr("src", preyimg);  
                    thisImg.removeAttr("width").removeAttr("height");  
                    thisImg.attr("width1", width).attr("height1", attrheight);  

                    ////thisImg.attr("width", "50px").attr("height", "50px"); //loading图大小  
                    //thisImg.css("margin", "0 auto");  
                    thisImg.css("margin", ((height / 2) - 25) + "px auto auto " + ((width / 2) - 25) + "px");  
                    $(".lazyloading").css("display", "table"); //.css("position", "relative");  
                }  
            });  
        }  
        //动态显示数据  
        var loading1 = function () { };  
        var loading = function () {  
            //窗口的高度+看不见的顶部的高度=屏幕低部距离最顶部的高度  
            var thisButtomTop = parseInt($(window).height()) + parseInt($(window).scrollTop());  
            var thisTop = parseInt($(window).scrollTop()); //屏幕顶部距离最顶部的高度  

            $.each(params.cache, function (i, data) {  
                var thisImg = data.obj, tag = data.tag, url = data.url, post, posb;  

                if (thisImg) {//对象不为空  
                    if (typeof (url) != "undefined") {// 判断是否需要延迟加载  
                        var PictureTop = parseInt(thisImg.offset().top);  
                        //如果处理可见范围内,并且原图地址data-original不等于src,则加载图片  
                        if (PictureTop >= thisTop && PictureTop <= thisButtomTop && thisImg.attr("data-original") != thisImg.attr("src")) {  
                            var hiddenImg = thisImg.siblings("img.loadhiddenimg");  

                            hiddenImg.load(function () { //隐藏图片加载完之后的回调函数  
                                var width = thisImg.attr("width1");  
                                var height = thisImg.attr("height1");  
                                thisImg.attr("width", width).attr("height", height).removeAttr("width1").removeAttr("height1");  
                                thisImg.css("margin", "0 auto");  
                                if (thisImg.parent().attr("lazyloading_hasheight") == "0") {//没有指定高度时,加载图片后去掉div高度自适应  
                                    if (thisImg.parent().is("a") == true) {  
                                        thisImg.parent().parent().css("height", "");  
                                    }  
                                    else {  
                                        thisImg.parent().css("height", "");  
                                    }  
                                }  
                                thisImg.load(function () {  
                                    if (thisImg.parent().is("a") == true) {  
                                        thisImg.parent().parent().css("height", thisImg.height());  
                                    }  
                                    else {  
                                        thisImg.parent().css("height", thisImg.height());  
                                    }  
                                });  
                                thisImg.css('opacity', '0.2');  
                                thisImg.attr("src", hiddenImg.attr("src"));  
                                thisImg.animate({ opacity: 1.0 });  
                                if (thisImg.attr("alt") != "") {  
                                    thisImg.attr("title", thisImg.attr("alt"));  
                                    thisImg.attr("alt", "");  
                                }  
                            }).error(function () {  
                                thisImg.error(function () {  
                                    thisImg.css("margin", "0 auto auto 0");  
                                    if (thisImg.parent().attr("lazyloading_hasheight") == "0") {//没有指定高度时,加载图片后去掉div高度自适应  
                                        if (thisImg.parent().is("a") == true) {  
                                            thisImg.parent().parent().css("height", "");  
                                        }  
                                        else {  
                                            thisImg.parent().css("height", "");  
                                        }  
                                    }  
                                });  
                                thisImg.attr("src", hiddenImg.attr("src")); //alert("error");  
                                if (thisImg.attr("alt") != "") {  
                                    thisImg.attr("title", thisImg.attr("alt"));  
                                    thisImg.attr("alt", "");  
                                }  
                            });  
                            hiddenImg.attr("src", url);  
                        }  
                    }  
                }  
            });  
        };  
        //初始化  
        init();  
        //事件触发  
        //加载完毕即执行  
        if (params["loadfirst"] == true) loading();  
        //滚动执行  
        params.container.bind("scroll", loading).bind("resize", loading);  
    };  
})(jQuery);  

用法很简单:

<a href="#"><img  alt="haorooms博客" src="" data-original="http://www.haorooms.com/uploads/images/table.gif" class="lazyloading" /></a>
<script type="text/javascript">
$(function () {
    $("img.lazyloading").lazyloading({ loadfirst: true });
})

</script>

上面就可以完成图片的延迟加载了!

jquery判断页面滚动条(scroll)是上滚还是下滚,且是否滚动到头部或者底部

项目背景

webtouch(webapp)页面,防苹果手机safari浏览器,网上滑动,底部导航消失,滑动到底部又出现。向下滑动,底部导航出现。

遇到问题

1、我一开始用swipeup和swipedown来做,发现因为有滚动条,不会触发。因此只能判断滚动条是上滚下滚等。关于手机手势,后面的文章会介绍,欢迎关注!

2、通过上滚下滚来让底部导航显示或者因此,安卓上面的浏览器都可以,但是苹果safari会一闪一闪,原因是苹果safari自动有个弹跳效果,导致事件重复执行,解决办法是给上滚下滚一个距离,滚动到一定距离后返回是上滚还是下滚。

单纯判断滚动条方向

function scroll( fn ) {
    var beforeScrollTop = document.body.scrollTop,
        fn = fn || function() {};
    window.addEventListener("scroll", function() {
        var afterScrollTop = document.body.scrollTop,
            delta = afterScrollTop - beforeScrollTop;
        if( delta === 0 ) return false;
        fn( delta > 0 ? "down" : "up" );
        beforeScrollTop = afterScrollTop;
    }, false);
}

调用方法:

scroll(function(direction) { console.log(direction) });   

以上方法手机苹果浏览器事件会跳动,解决方法及代码改进

scrollDirect: function (fn) {
    var beforeScrollTop = document.body.scrollTop;
    fn = fn || function () {
    };
    window.addEventListener("scroll", function (event) {
        event = event || window.event;

        var afterScrollTop = document.body.scrollTop;
        delta = afterScrollTop - beforeScrollTop;
        beforeScrollTop = afterScrollTop;

        var scrollTop = $(this).scrollTop();
        var scrollHeight = $(document).height();
        var windowHeight = $(this).height();
        if (scrollTop + windowHeight > scrollHeight - 10) {  //滚动到底部执行事件
            fn('up');
            return;
        }
        if (afterScrollTop < 10 || afterScrollTop > $(document.body).height - 10) {
            fn('up');
        } else {
            if (Math.abs(delta) < 10) {
                return false;
            }
            fn(delta > 0 ? "down" : "up");
        }
    }, false);
}

调用方法:

   var upflag=1;
   var  downflag= 1;
    //scroll滑动,上滑和下滑只执行一次!
scrollDirect(function (direction) {
        if (direction == "down") {
            if (downflag) {
                $(".footer_wrap").slideUp(200);
                downflag = 0;
               upflag = 1;
            }
        }
        if (direction == "up") {
            if (upflag) {
                $(".footer_wrap").slideDown(200);
               downflag = 1;
                upflag = 0;
            }
        }
 });

滚动条滚动到底部和头部判断

其实我上面的函数中已经有判断,下面再列一下!看如下函数!

BottomJumpPage: function () {
            var scrollTop = $(this).scrollTop();
            var scrollHeight = $(document).height();
            var windowHeight = $(this).height();
            if (scrollTop + windowHeight == scrollHeight) {  //滚动到底部执行事件
                    console.dir("我到底部了");

            }
            if (scrollTop == 0) {  //滚动到头部部执行事件
            console.dir("我到头部了");

            }
 }

调用方法:

$(window).scroll(BottomJumpPage);

关于是否滚动到页面底部和头部,相关的文章还有http://www.haorooms.com/post/js_jquery_height

理解了这篇文章,是否滚动轴滚到底部和头部就迎刃而解了!

百度ueditor的二次开发

最近在做一个后台的项目,项目中用到了复文本框,公司用的是UEditor,但是需求为了更方便编辑图片,特意提了如下功能:

1、上传图片时图片宽度固定为500,长度等比例进行缩放,但不限制单张图片长度;图片进行等比缩放后保持100%原画质;

2、长传图片是选中图片后点击确定自动上传,无需再选择一次“开始上传”。

3、图片上传完成后,在图片下方添加一个选填的文本输入框用以填写图注,如填写,图注使用默认字体居中显示。

针对上面的需求,我对 UEditor源码进行了研究和修改。看到网上有关UEditor上传图片默认居中和控制默认大小,也有不少帖子,但是都没有给出具体的解决办法,有些甚至用css控制。下面我把我的解决方法共享一下,希望对大家有所帮助。关于ueditor的使用,我之前的一篇文章ueditor使用过程的注意事项,有兴趣的可以看下!

ueditor 上传图片默认居中对齐 和控制上传图片的默认大小

如下图:

上传图片默认选择的是居中对齐!
enter image description here

网上有的介绍是修改config.json里面的 "imageInsertAlign": "center", 把none改成center。还有就是把

<div class="alignBar">
            <label class="algnLabel"><var id="lang_input_align"></var></label>
                    <span id="alignIcon">
                        <span id="noneAlign" class="none-align" data-align="none"></span>
                        <span id="leftAlign" class="left-align" data-align="left"></span>
                        <span id="rightAlign" class="right-align" data-align="right"></span>
                        <span id="centerAlign" class="center-align focus" data-align="center"></span>
                    </span>
            <input id="align" name="align" type="hidden" value="center"/>
        </div>
<div id="tabbody" class="tabbody">

class中的focus,默认给center-align 。

我这么修改了,但是没有反应!默认选择的还是none,还是第一个。实在没有办法,我就开始修改ueditor.all.js了。

看了它的源代码,我修改了image.js,修改了如下代码:

/* 初始化对其方式的点击事件 */
 function initAlign() {
        setAlign("center");//修改默认居中对齐
        /* 点击align图标 */
        domUtils.on($G("alignIcon"), 'click', function (e) {
            var target = e.target || e.srcElement;
            if (target.className && target.className.indexOf('-align') != -1) {
                setAlign(target.getAttribute('data-align'));
            }
        });
    }

/* 设置对齐方式 */
function setAlign(align) {
        align =  align || 'center';
        var aligns = $G("alignIcon").children;
        for (i = 0; i < aligns.length; i++) {
            if (aligns[i].getAttribute('data-align') == align) {
                domUtils.addClass(aligns[i], 'focus');
                $G("align").value = aligns[i].getAttribute('data-align');
            } else {
                domUtils.removeClasses(aligns[i], 'focus');
            }
        }
}

然后就默认用center方式对齐了!

上传图片默认给个宽度

主要是修改ueditor.all.js,找到UE.commands['insertimage'] ,然后找到

 (ci.width ? 'width="' + ci.width + '" ' : 'width="500"')

在单张上传和多张上传中都设置个宽度,然后上传图片就会默认有了一个宽度,如下图:

enter image description here

长传图片是选中图片后点击确定自动上传,无需再选择一次“开始上传”

针对这个,我给“开始上传”做了一个点击事件。上传图片之后,自动对“开始上传”做一次点击。

在image.js中,找到addFile(file) 函数,function addFile(file) {}

在这个函数最后增加一个点击函数。延迟点击就可以了!

$li.insertBefore($filePickerBlock);
clickUpload = function () {
     $upload.click();
 }
 setTimeout("clickUpload()", 200);

图片上传完成后,在图片下方添加一个文本输入框

前面的两个问题很容易就解决了!这个问题就稍微有点费事!下面说一下吧!

(注:image.js有缓存,修改完js,记得清理缓存!)

效果如下图:

enter image description here

这里还是修改addfile()函数,里面增加如下方法:

 // 获取图片下面input的描述
getInputvalue = function(files){
                if(_this.imageList.length==1){
                _this.imageList[0].imgDes=$(files).find("input[name='imgDes']").val();
                   }else{
                       if(_this.imageList.length>1){
                           for(var i=0;i<_this.imageList.length;i++){
                               if(files.id.indexOf(i)!=-1){
                                  _this.imageList[i].imgDes=$(files).find("input[name='imgDes']").val();  
                               }
                           }  
                       }
                   }

 };
 $li.append('<input type="text" class="inputDes" name="imgDes" onkeyup="getInputvalue(' + file.id + ')" placeholder="(图注)" value="">');

这样在imageList这个数组中增加了一个imgDes字段,在鼠标onkeyup的时候写入!

这样,可以直接在ueditor.all.js中调用了。

UE.commands['insertimage'] = {
    execCommand:function (cmd, opt) {

上面函数中的opt中就有了imgDes这个字段了!然后插入的时候增加如下代码就可以了!(记得在单张上传和多张中都添加)

把一段代码都贴出来吧!

var html = [], str = '', ci;
 ci = opt[0];
            if (opt.length == 1) {
                str = '<img src="' + ci.src + '" ' + (ci._src ? ' _src="' + ci._src + '" ' : '') +
                    (ci.width ? 'width="' + ci.width + '" ' : 'width="500"') +
                    (ci.height ? ' height="' + ci.height + '" ' : '') +
                    (ci['floatStyle'] == 'left' || ci['floatStyle'] == 'right' ? ' style="float:' + ci['floatStyle'] + ';"' : '') +
                    (ci.title && ci.title != "" ? ' title="' + ci.title + '"' : '') +
                    (ci.border && ci.border != "0" ? ' border="' + ci.border + '"' : '') +
                    (ci.alt && ci.alt != "" ? ' alt="' + ci.alt + '"' : '') +
                    (ci.hspace && ci.hspace != "0" ? ' hspace = "' + ci.hspace + '"' : '') +
                    (ci.vspace && ci.vspace != "0" ? ' vspace = "' + ci.vspace + '"' : '') + '/>'+  (ci.imgDes && ci.imgDes != "" ? '<br/><span style="display:block;width:100%;text-align:center">'+ci.imgDes+'</span>' : '');
                if (ci['floatStyle'] == 'center') {
                    str = '<p style="text-align: center">' + str + '</p>';
                }
 html.push(str);

这样就搞定了!

上传确定之后,文本框中代码如下:

enter image description here

本文原创!转载请标明出处和地址!

希望对您在进行百度ueditor的二次开发过程中有所帮助!

javascript导出EXCEl方法总结

javascript导出excel,一般用于后台开发,主要是公司内部人员使用是用js直接导出excel,原因是,javascript必须在IE内核的浏览器下面才能成功导出,chrome浏览器不支持。

应用场景:1、公司内部后台 2、IE浏览器 3、导出比较复杂,通常是带合并单元格等 4、后端数据导出比较难处理的情况。

PS:导出EXCEL还是强烈建议打击用PHPEXCEl,因为PHP导出excel兼容性更好!格式也可以调整,也很强到,具体PHP导出excel请见后面文章!

方法一:js导出EXCEl带单元格合并

首先,要改IE浏览器安全设置,如下图:

enter image description here

enter image description here

然后请看如下函数:

函数参数说明:

// JavaScript Document
//调用方法
//   var test=new PageToExcel("data",0,255,"测试.xls");//table id , 第几行开始,最后一行颜色 ,保存的文件名
//   test.CreateExcel(false);
//   test.Exec();
//   test.SaveAs();
//   test.CloseExcel();
//LastRowColor 0黑色 255红色
//

函数:

function PageToExcel(TableID,FirstRow,LastRowColor,SaveAsName){
this.lastRowColor=LastRowColor==""?0:LastRowColor;
var today=new Date();
this.saveAsName=(SaveAsName==""?today.getYear()+"年"+(today.getMonth()+1)+"月"+today.getDate()+"日.xls":SaveAsName);
this.tableId=TableID;
this.table=document.getElementById(this.tableId);//导出的table 对象
this.rows=this.table.rows.length;//导出的table总行数
this.colSumCols=this.table.rows[0].cells.length;//第一行总列数
this.fromrow=FirstRow;
this.beginCol=0; //起始列数
this.cols=this.colSumCols;
this.oXL=null;
this.oWB=null;
this.oSheet=null;
this.rowSpans=1; //行合并
    this.colSpans=1; //列合并
    this.colsName={0:"A",1:"B", 2:"C", 3:"D", 4:"E", 5:"F", 6:"G", 7:"H", 8:"I",9:"J", 10:"K", 11:"L", 12:"M", 13:"N", 14:"O", 15:"P", 16:"Q", 16:"R" ,18:"S", 19:"T", 20:"U", 21:"V", 22:"W", 23:"X", 24:"Y", 25:"Z"};
}
PageToExcel.prototype.DeleteExcelCols=function(NotShowColList){//数组NotShowColList
    //this.notShowColList=NotShowColList;//不显示列集合,1,2,3,1
    //删除excel中的列
   var m=0;
   for(var i=0;i<NotShowColList.length;i++){
         if(i>0){
            m++;
         }
        var temp=NotShowColList[i]- m;
        var index=this.colsName[temp];
   this.oSheet.Columns(index).Delete;//删除
   }
   m=0;
}


PageToExcel.prototype.CreateExcel=function(ExcelVisible)
{
   try{
   this.oXL = new ActiveXObject("Excel.Application"); //创建应该对象
   this.oXL.Visible = ExcelVisible;
   this.oWB = this.oXL .Workbooks.Add();//新建一个Excel工作簿
    this.oSheet = this.oWB.ActiveSheet;//指定要写入内容的工作表为活动工作表
   //不显示网格线
   this.oXL.ActiveWindow.DisplayGridlines=false;
   }catch(e){
    alert("请确认安装了非绿色版本的excel!"+e.description);
    CloseExcel();
   }
}

PageToExcel.prototype.CloseExcel=function()
{
    this.oXL.DisplayAlerts = false;   
            this.oXL.Quit();   
            this.oXL = null;   
            this.oWB=null;   
            this.oSheet=null; 
}

PageToExcel.prototype.ChangeElementToLabel=function (ElementObj){
   var GetText="";
   try{
   var childres=ElementObj.childNodes;

   }catch(e){ return GetText}
   if(childres.length<=0) return GetText;
   for(var i=0;i<childres.length;i++){
   try{if(childres[i].style.display=="none"||childres[i].type.toLowerCase()=="hidden"){continue;}}
   catch(e){}

     try{
      switch (childres[i].nodeName.toLowerCase()){
        case "#text" :
         GetText +=childres[i].nodeValue ;
         break;
        case "br" :
         GetText +="\n";
         break;
        case "img" :
         GetText +="";
         break;
        case "select" :
         GetText +=childres[i].options[childres[i].selectedIndex].innerText ;
         break;
        case "input" :
         if(childres[i].type.toLowerCase()=="submit"||childres[i].type.toLowerCase()=="button"){
          GetText +="";
         }else if(childres[i].type.toLowerCase()=="textarea"){
          GetText +=childres[i].innerText;
         }else{
          GetText +=childres[i].value;
         }
         break;
        default :
         GetText += this.ChangeElementToLabel(childres[i]);
         break;
      }

     }catch(e){}
   }
   return GetText;
}
PageToExcel.prototype.SaveAs=function (){
   //保存
   try{
    this.oXL.Visible =true;
    var fname = this.oXL.Application.GetSaveAsFilename(this.saveAsName, "Excel Spreadsheets (*.xls), *.xls"); 
    if(fname){ 
    this.oWB.SaveAs(fname);
     this.oXL.Visible =false;
    }
   }catch(e){}; 
}
PageToExcel.prototype.Exec=function()
{

   //寻找列数,考虑到第一行可能存在
   for (var i=0; i<this.colSumCols;i++) {
    var tmpcolspan = this.table.rows(0).cells(i).colSpan;
    if ( tmpcolspan>1 ) {
     this.cols += tmpcolspan-1;
    }
   }

   //定义2维容器数据,1:行;2:列;值(0 可以填充,1 已被填充)
   var container=new Array(this.rows);
   for (var i=0;i<this.rows;i++) {
    container[i]=new Array(this.cols);
    for (j=0;j<this.cols;j++) {
     container[i][j]=0;
    }
   }

   //将所有单元置为文本,避免非数字列被自动变成科学计数法和丢失前缀的0
   this.oSheet.Range(this.oSheet.Cells(this.fromrow+1,1), this.oSheet.Cells(this.fromrow+this.rows,this.cols)).NumberFormat = "@";
   // 循环行
   for (i=0;i<this.rows;i++){
    //循环列
    for (j=0;j<this.cols;j++){
     //寻找开始列
     for (k=j;k<this.cols;k++){
      if (container[i][k]==0) {
       this.beginCol=k;
       k=this.cols; //退出循环
      }
     }
//try{
      //赋值
      //此处相应跟改 根据 标签的类型,替换相关参数
      this.oSheet.Cells(i+1+this.fromrow,this.beginCol+1).value = this.ChangeElementToLabel(this.table.rows(i).cells(j));


      //计算合并列
      try{
     this.colSpans = this.table.rows(i).cells(j).colSpan;
      }catch(e){
     this.colSpans=0   
     }
     if (this.colSpans>1) {
      //合并
      this.oSheet.Range(this.oSheet.Cells(i+1+this.fromrow,this.beginCol+1),this.oSheet.Cells(i+1+this.fromrow,
         this.beginCol+this.colSpans)).Merge();
     }
     //将当前table位置填写到对应的容器中
     for (k=0; k<this.colSpans;k++) {
      container[i][this.beginCol+k]= 1;
     }
     // 计算合并行

     try{
      this.rowSpans = this.table.rows(i).cells(j).rowSpan;
       }catch(e){
       this.rowSpans = 0;
     }

     if (this.rowSpans>1) { //行合并
      this.oSheet.Range(this.oSheet.Cells(i+1+this.fromrow,this.beginCol+1),this.oSheet.Cells(i+this.rowSpans+this.fromrow,
        this.beginCol+this.colSpans)).Merge();
      //将当前table位置填写到对应的容器中
      for (k=1; k<this.rowSpans;k++) { //由于第0行已经被colSpans对应的代码填充了,故这里从第1行开始
       for (l=0;l<this.colSpans;l++) {
        container[i+k][this.beginCol+l]=1;
       }
      }
     }
     //如果开始列+合并列已经等于列数了,故不需要再循环html table
     if (this.beginCol+this.colSpans>=this.cols) j=this.cols;

    }
    if(i==0)
    {
     //标题栏
     this.oSheet.Range(this.oSheet.Cells(1,1), this.oSheet.Cells(1,1)).Font.Size=20; 
     this.oSheet.Range(this.oSheet.Cells(1,1), this.oSheet.Cells(1,1)).Font.Bold = true; 
     this.oSheet.Range(this.oSheet.Cells(1,1), this.oSheet.Cells(1,1)).HorizontalAlignment = -4108; //居中
     this.oSheet.Range(this.oSheet.Cells(1,1), this.oSheet.Cells(1,1)).Rows.RowHeight = 40;
    }
     //自动调整行高
   }


   //最后一行是否空色
   try{
    this.oSheet.Range(this.oSheet.Cells(this.rows,1), this.oSheet.Cells(this.rows,1)).Font.Color=this.lastRowColor;
   }catch(e){}
   this.oSheet.Range(this.oSheet.Cells(this.fromrow+2,1), this.oSheet.Cells(this.fromrow+this.rows,this.cols)).Rows.RowHeight=20; 
   this.oSheet.Range(this.oSheet.Cells(this.fromrow+2,1), this.oSheet.Cells(this.fromrow+this.rows,this.cols)).Font.Size=10;
   //自动换行
   this.oSheet.Range(this.oSheet.Cells(this.fromrow+2,1), this.oSheet.Cells(this.fromrow+this.rows,this.cols)).WrapText = true;
   //自动调整列宽
   this.oSheet.Range(this.oSheet.Cells(this.fromrow+1,1), this.oSheet.Cells(this.fromrow+this.rows,this.cols)).Columns.AutoFit();
   //点虚线
   this.oSheet.Range(this.oSheet.Cells(this.fromrow+1,1), this.oSheet.Cells(this.fromrow+this.rows,this.cols)).Borders.LineStyle = -4118;


   return this.rows;
}

方法二:

该方法不用对IE浏览器做参数设置,但是不能导出带有合并单元格的EXCEl,兼容性相对上一个函数要好一些!但是也是只能在IE浏览器下面运行,该方法只能导出table中的excel。

原理:循环获取table中的数据,然后把数据存放到一个自定义网页窗口中,再把该数据 xlsWin.document.execCommand保存到excel中。

代码如下:

function getXlsFromTbl(inTblId, inWindow) {
     try {
         var allStr = "";
         var curStr = "";
         //alert("getXlsFromTbl");
         if (inTblId != null && inTblId != "" && inTblId != "null") {
             curStr = getTblData(inTblId, inWindow);
         }
         if (curStr != null) {
             allStr += curStr;
        }
        else {
            alert("你要导出的表不存在!");
            return;
        }
        var fileName = getExcelFileName();
        doFileExport(fileName, allStr);
    }
    catch(e) {
        alert("导出发生异常:" + e.name + "->" + e.description + "!");
    }
}
function getTblData(inTbl, inWindow) {
    var rows = 0;
    //alert("getTblData is " + inWindow);
    var tblDocument = document;
    if (!!inWindow && inWindow != "") {
        if (!document.all(inWindow)) {
            return null;
        }
        else {
            tblDocument = eval(inWindow).document;
        }
    }
    var curTbl = tblDocument.getElementById(inTbl);
    var outStr = "";
    if (curTbl != null) {
        for (var j = 0; j < curTbl.rows.length; j++) {
            for (var i = 0; i < curTbl.rows[j].cells.length; i++) {
                if (i == 0 && rows > 0) {
                    outStr += " \t";
                    rows -= 1;
                }
                outStr += curTbl.rows[j].cells[i].innerText + "\t";
                if (curTbl.rows[j].cells[i].colSpan > 1) {
                    for (var k = 0; k < curTbl.rows[j].cells[i].colSpan - 1; k++) {
                        outStr += " \t";
                    }
                }
                if (i == 0) {
                    if (rows == 0 && curTbl.rows[j].cells[i].rowSpan > 1) {
                        rows = curTbl.rows[j].cells[i].rowSpan - 1;
                    }
                }
            }
            outStr += "\r\n";
        }
    }
    else {
        outStr = null;
        alert(inTbl + "不存在!");
    }
    return outStr;
}
function getExcelFileName() {
    var d = new Date();
    var curYear = d.getYear();
    var curMonth = "" + (d.getMonth() + 1);
    var curDate = "" + d.getDate();
    var curHour = "" + d.getHours();
    var curMinute = "" + d.getMinutes();
    var curSecond = "" + d.getSeconds();
    if (curMonth.length == 1) {
        curMonth = "0" + curMonth;
    }
    if (curDate.length == 1) {
        curDate = "0" + curDate;
    }
    if (curHour.length == 1) {
        curHour = "0" + curHour;
    }
    if (curMinute.length == 1) {
        curMinute = "0" + curMinute;
    }
    if (curSecond.length == 1) {
        curSecond = "0" + curSecond;
    }
    var fileName = "91zaojia" + "_" + curYear + curMonth + curDate + "_"
            + curHour + curMinute + curSecond + ".xls";
    return fileName;
}
function doFileExport(inName, inStr) {
    var xlsWin = null;
    if (!!document.all("glbHideFrm")) {
        xlsWin = glbHideFrm;
    }
    else {
        var width = 6;
        var height = 4;
        var openPara = "left=" + (window.screen.width / 2 - width / 2)
                + ",top=" + (window.screen.height / 2 - height / 2)
                + ",scrollbars=no,width=" + width + ",height=" + height;
        xlsWin = window.open("", "_blank", openPara);
    }
    xlsWin.document.write(inStr);
    xlsWin.document.close();
    xlsWin.document.execCommand('Saveas', true, inName);
    xlsWin.close();
}

调用很简单,直接用就可以onclick="getXlsFromTbl('functionclickExcel',null);就可以了!

前端神器-sublime text3插件安装及使用

作为前端人员,要找一个很顺手的编辑器真的不容易,以前我用同事推荐的netbeans,很好用,但是它主要是用于php开发,且软件太大,运行起来比较慢,后来又用前端开发的webStrom,也不错,很好用,他的历史记录等功能比较强大,但是还是有一个缺点,就是软件有点大,运行起来有点慢。

我在我向大家推荐一款实用的前端开发神器,不但占地小,且插件很多,很强大。下面我向大家介绍一下它的安装及插件的使用方法。

一、安装及安装emmet插件

首先,去sublime官网下载软件:http://www.sublimetext.com/ ,

软件很小,我用的是最新版的text3,大家可以用目前稳定版text2。打开它的官网,我们就可以看到几个动画,演示sublime的强大功能。

其次,软件安装好了之后,我们来安装一个插件,推荐使用package control组件来安装插件,很方便。

安装方法如下:

按快捷键ctrl+~ 调出命名控制行:然后如果是text2输入如下命令:

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')

如果是text3输入如下命令:

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)

具体安装您也可以查看:https://sublime.wbond.net/installation#st3

安装好了之后,在Preferences会看到package control,如下如:

enter image description here

最后,有了package control,你就可以安装您想要的插件了!很简单,sublime下面有很多插件,一般编辑器有的,sublime都会以插件的形式出现,下面我们最先介绍[Emmet][2]。

打开package control 输入install package 然后找到emmet,点击安装,重启sublime就可以了,具体请看:https://github.com/sergeche/emmet-sublime#readme

sublime Emmet的用法请点击

第二,sublime常用插件:

ZenCoding

不得不用的一款前端开发方面的插件,Write less , show more.安装后可直接使用,Tab键触发,Alt+Shift+W是个代码机器。

Alignment

代码对齐,如写几个变量,选中这几行,Ctrl+Alt+A,哇,齐了。

Prefixr

写 CSS可自动添加 -webkit 等私有词缀,Ctrl+Alt+X触发。

Tag

Html格式化,右键Auto-Format Tags on Ducument。一般是用ctrl +Alt +F 触发,若触发不了,查看是不是html文件,是否选中,是否有快捷键冲突!

Clipboard History

剪贴板历史记录,显示更多历史复制,Ctrl+Shift+V触发。

SideBarEnhancements

侧栏右键功能增强,非常实用

Theme – Soda

完美的编码主题,用过的都说好,Setting user里面添加”theme”: “Soda Dark.sublime-theme”

GBK to UTF8

将文件编码从GBK转黄成UTF8,菜单 – File里面找

SFTP

直接编辑 FTP 或 SFTP 服务器上的文件,绝对FTP浮云

WordPress

集成一些WordPress的函数,对于像我这种经常要写WP模版和插件的人特别有用

PHPTidy

整理排版PHP代码

YUI Compressor

压缩JS和CSS文件

Ctags

函数跳转,我的电脑上是Alt+点击 函数名称,会跳转到相应的函数

nodejs博客的nginx配置

首先感谢我同事,参考他的博客,我才完成了我的nodejs博客的配置。
nodejs运行之后,关掉链接,网站运行就会断开,需要安装forever,后台执行。
安装方法如下(在windows和Linux下都能运行):

//forever的安装:
npm install forever -g
//使用forever启动守护进程:
forever start your_app.js
//关闭守护进程:
forever stop your_app.js
//重启守护进程:
forever restart your_app.js
//如果需要记录输出日志和错误:
forever start -l forever.log -o out.log -e err.log your_app.js
//查看正在运行的程序:
forever list

然后再修改nginx配置文件(nginx.conf)
用nginx绑定多个域名,一个是nodejs的1000端口,一个是apache+php+mysql,端口8090,两个应用是用nginx代理转发到对于的端口上的。

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

upstream nginx.haorooms.com {
server localhost:1000;
}

    server {
        listen       80;
        server_name   haorooms.com www.haorooms.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
           proxy_pass http://nginx.haorooms.com;
           # root   html;
           #index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
server {
        listen       80;
        server_name  about.haorooms.com;
        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
             proxy_pass http://about.haorooms.com:8090;
          # root   html;
         # index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

Ecshop解决与jquery冲突问题

易造价商城后台是用Ecshop开发的,但是易造价前台中您看不出ecshop的任何端倪。对于Ecshop,我一开始也是小白,近期才少有深入了解。但是我同事是ECSHOP的大神,他的博客中有不少关于ecshop的文章,鉴于他的博客,我对ecshop相关问题也写一下,以便后来只用!

切入正题,jquery是我们PC端开发必不可少的工具,但是jquery和ECSHOP有一定的兼容问题,给我们带来了不少的不便,下面这篇文章就叫你如何解决ecshop和jquery的冲突问题:

大体思路是屏蔽ECshop扩展的toJSONString方法,用别的函数代替。

1.首先复制一份 transport.js 改名为 transport.org.js 提供给后台使用

2.屏蔽掉transport.js里的toJSON功能 行数大概有497-737行之间

//修改352行为:
legalParams = 'JSON=' + $.toJSON(params);
//修改408行为:
result = $.evalJSON(result);

3.修改index.js文件

//44行改为:
var res = $.evalJSON(result);

4.修改common.js文件

 //第34行改为:
 Ajax.call('flow.php?step=add_to_cart', 'goods=' + $.toJSON(goods), addToCartResponse, 'POST', 'JSON');
 //第850行改为:
 Ajax.call('flow.php?step=add_package_to_cart', 'package_info=' + $.toJSON(package_info), addPackageToCartResponse, 'POST', 'JSON');
 //第1056行改为:
 Ajax.call('flow.php?step=add_to_cart', 'goods=' + $.toJSON(goods), addToCartResponse, 'POST', 'JSON');

5.修改compare.js文件

//第49行改为:
this.data = $.evalJSON(cookieValue);
//第67行改为:
var obj = $.evalJSON(cookieValue);
//第133行改为:
document.setCookie('compareItems', $.toJSON(this.data));

6.修改global.js文件

//第16行改函数名 :
function $e()

//第114和126行都改为:    
var element = $e(element);
<!———–路径修改———–>

修改后台头部引入transport.js路径 admin/templates/pageheader.htm

//第9行改为: 
{insert_scripts files='../js/transport.org.js,common.js'}
//修改themes/default/library/page_header.lbi文件在{insert_scripts files='transport.js,utils.js'}上面加上如下代码

{insert_scripts files='jquery-1.5.2.min.js,jquery.json-1.3.js'}
//修改文件 library/comment_list.lbi

//第188行 :
Ajax.call('comment.php', 'cmt=' + $.toJSON(cmt), commentResponse, 'POST', 'JSON');

compare.dwt

//第20行 :
var obj = $.evalJSON(document.getCookie('compareItems'));
//第24行 :
document.setCookie('compareItems', $.toJSON(obj));

flow.dwt

//第138行 :
Ajax.call('flow.php?step=add_to_cart', 'goods=' + $.toJSON(goods), collect_to_flow_response, 'POST', 'JSON');
//第199行 :
Ajax.call('flow.php?step=add_to_cart', 'goods=' + $.toJSON(goods), fittings_to_flow_response, 'POST', 'JSON');
<!—–jquery文件需置顶的dwt文件—-jquery.js文件需要在compare.js文件加载前加载,否则会报错—–> brand.dwt

brand_list.dwt

category.dwt

exchange_list.dwt

search.dwt
如:

{* 包含脚本文件 *}

{insert_scripts files='jquery-1.5.2.min.js,jquery.json-1.3.js'}

{insert_scripts files='common.js,global.js,compare.js'}

PHP在dede后台增加批量上传和导出报表的功能

之前在做dedecms后台二次开发的时候,有需求是批量导入客户内容,然后导出报表,因此用到了php导出excel的功能,我做的是导出csv文件,其实csv文件和excel文件一样,都能用excel表格打开,csv的容量相比excel要大一些。我的方法如下:

导出csv文件

<?php
           require_once (dirname(__FILE__) . "/../include/common.inc.php");
            $output = fopen('','w') or die("can't open ");
                        header('Content-Type: application/csv');
                        header('Content-Disposition: attachment; filename="认证列表.csv"');
                        $arrkeys = array(
                            iconv('utf-8','gb2312','姓名'),
                            iconv('utf-8','gb2312','电话')//文件表头
                            );
                        fputcsv($output, $arrkeys);
                        //取得符合条件的数组
                         $sql = "SELECT * FROM dede_test";
                           $dsql->Execute('me',$sql);
                       while($row = $dsql->GetArray('me')){
                                $name =$row['name'];
                                $mobile= $row['mobile']; //循环

                                $arrkeys = array(
                                    iconv('utf-8','gb2312',$name),
                                    iconv('utf-8','gb2312',$mobile)
                                    );
                                fputcsv($output, $arrkeys);
                            }

                    fclose($output) or die("can't close ");
                    exit();
?>

导入xls文件

<?php
           require_once (dirname(__FILE__) . "/../include/common.inc.php");
           include_once("excel/reader.php");
                 $tmp = $_FILES['file']['tmp_name'];
                 if (empty ($tmp)) {
                       ShowMsg("请选择要导入的Excel文件!","test.php");
                         exit;
                 }

                 $save_path = "xls/";
                 $file_name = $save_path.date('Ymdhis') . ".xls";
                 if (copy($tmp, $file_name)) {
                         $xls = new Spreadsheet_Excel_Reader();
                         $xls->setOutputEncoding('utf-8');
                         $xls->read($file_name);
                         for ($i=2; $i<=$xls->sheets[0]['numRows']; $i++) {
                                 $name = $xls->sheets[0]['cells'][$i][1];
                                 $mobile = $xls->sheets[0]['cells'][$i][2]
                                 $data_values .= "('$name','$mobile'),";
                         }
                         $data_values = substr($data_values,0,-1);
                         $sql= "INSERT INTO dede_test (name,mobile) VALUES $data_values";
                        $dsql->ExecuteNoneQuery($sql);
                         $lastInsertID = $dsql->GetLastID();
                     if($dsql){
                            ShowMsg("成功导入!","test.php");
                     }else{
                            ShowMsg("导入失败!","test.php");
                     }
                 }
               exit();
?>

有问题可以留言交流,具体demo后期会贴上,急需要demo的可以留言!

前端js和css的压缩合并之grunt

关于css和js压缩和合并的方法,记得我在前端面试题目中有写道。方法很多,今天主要介绍grunt方法。

使用前提

grunt是基于node的,要在你电脑上使用grunt,电脑上必须已安装node环境。具体node环境的安装和搭建。centos请看,windows安装相对简单,下载安装包安装就可以了。关于mac的安装,后面有时间在详细介绍。

新建package.json

package.json放在根目录下,它包含了该项目的一些元信息,如项目名称、描述、版本号,插件等。

{
  "name": "haorooms.com",
  "version": "v0.1.0",
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-jshint": "~0.10.0",
    "grunt-contrib-nodeunit": "~0.4.1",
    "grunt-contrib-uglify": "~0.5.0",
    "grunt-contrib-concat": "~0.5.1",
    "grunt-contrib-cssmin": "~0.12.3",
    "grunt-htmlhint": "~0.9.2"
  }
}

grunt-contrib-jshint(js语法检查)、grunt-contrib-concat(js合并)、grunt-contrib-uglify(采用UglifyJS压缩js)、grunt-contrib-cssmin(Css压缩合并)、grunt-htmlhint(html语法验查),以上都是常用的插件。

更多插件,请访问:http://gruntjs.com/plugins

插件安装

安装:uglify

npm install grunt-contrib-uglify

安装concat

npm install grunt-contrib-concat

安装:cssmin

npm install grunt-contrib-cssmin

插件安装完成后,查看根目录,会发现node_modules目录,包含了相应的插件目录。

新建Gruntfile.js

Gruntfile.js由以下内容组成

1、wrapper函数,结构如下,这是Node.js的典型写法,使用exports公开API

   module.exports = function(grunt) {
      // Do grunt-related things in here
    };

2、项目和任务配置

3、载入grunt插件和任务

4、定制执行任务

例如:

 module.exports = function(grunt) {
  //配置参数
  grunt.initConfig({
     pkg: grunt.file.readJSON('package.json'),
     concat: {
         options: {
             separator: ';',
             stripBanners: true
         },
         dist: {
             src: [
                 "js/config.js",
                 "js/smeite.js",
                 "js/index.js"
             ],
             dest: "assets/js/default.js"
         }
     },
     uglify: {
         options: {
         },
         dist: {
             files: {
                 'assets/js/default.min.js': 'assets/js/default.js'
             }
         }
     },
     cssmin: {
         options: {
             keepSpecialComments: 0
         },
         compress: {
             files: {
                 'assets/css/default.css': [
                     "css/global.css",
                     "css/pops.css",
                     "css/index.css"
                 ]
             }
         }
     }
  });

  //载入concat和uglify插件,分别对于合并和压缩
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');

  //注册任务
  grunt.registerTask('default', ['concat', 'uglify', 'cssmin']);
}

也可以单独压缩js和css,不进行合并,例如:

module.exports = function (grunt) {

    // 构建任务配置
    grunt.initConfig({

        //读取package.json的内容,形成个json数据
        pkg: grunt.file.readJSON('package.json'),

        //压缩js
        uglify: {
            //文件头部输出信息
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            my_target: {
                files: [
                    {
                        expand: true,
                        //相对路径
                        cwd: 'js/',
                        src: '*.js',
                       //src: ['**/*.js', '!**/*.min.js'],  //不包含某个js,某个文件夹下的js
                        dest: 'dest/js/',
                        rename: function (dest, src) {  
                                  var folder = src.substring(0, src.lastIndexOf('/'));  
                                  var filename = src.substring(src.lastIndexOf('/'), src.length);  
                                  //  var filename=src;  
                                  filename = filename.substring(0, filename.lastIndexOf('.'));  
                                  var fileresult=dest + folder + filename + '.min.js';  
                                  grunt.log.writeln("现处理文件:"+src+"  处理后文件:"+fileresult);  

                                  return fileresult;  
                                  //return  filename + '.min.js';  
                              } 
                    }
                ]
            }
        },

        //压缩css
        cssmin: {
            //文件头部输出信息
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
                //美化代码
                beautify: {
                    //中文ascii化,非常有用!防止中文乱码的神配置
                    ascii_only: true
                }
            },
            my_target: {
                files: [
                    {
                        expand: true,
                        //相对路径
                        cwd: 'css/',
                        src: '*.css',
                        dest: 'dest/css/',
                        rename: function (dest, src) {  
                                var folder = src.substring(0, src.lastIndexOf('/'));  
                                var filename = src.substring(src.lastIndexOf('/'), src.length);  
                                //  var filename=src;  
                                filename = filename.substring(0, filename.lastIndexOf('.'));  
                                var fileresult=dest + folder + filename + '.min.css';  
                                grunt.log.writeln("现处理文件:"+src+"  处理后文件:"+fileresult);  

                                return fileresult;  
                              //return  filename + '.min.js';
                                }
                    }
                ]
            }
        }

    });

    // 加载指定插件任务
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');

    // 默认执行的任务
    grunt.registerTask('default', ['uglify', 'cssmin']);

};

grunt api文档:http://gruntjs.com/api/grunt

grunt.initConfig方法

用于模块配置,它接受一个对象作为参数。该对象的成员与使用的同名模块一一对应。

每个目标的具体设置,需要参考该模板的文档。就cssmin来讲,minify目标的参数具体含义如下:

expand:如果设为true,就表示下面文件名的占位符(即*号)都要扩展成具体的文件名。

cwd:需要处理的文件(input)所在的目录。

src:表示需要处理的文件。如果采用数组形式,数组的每一项就是一个文件名,可以使用通配符。

dest:表示处理后的文件名或所在目录。

ext:表示处理后的文件后缀名。

grunt常用函数说明:

grunt.initConfig:定义各种模块的参数,每一个成员项对应一个同名模块。

grunt.loadNpmTasks:加载完成任务所需的模块。

grunt.registerTask:定义具体的任务。第一个参数为任务名,第二个参数是一个数组, 表示该任务需要依次使用的模块。

命令行执行grunt任务

进入到项目根目录,敲:

grunt

就会按Gruntfile配置的文件进行压缩合并。

也可以单独执行,例执行js压缩命令:

grunt uglify

css压缩命令

grunt cssmin

视频教程

sublime Emmet的用法及相关语法

上一节,我们讲了 前端神器-sublime text3插件安装及使用,讲了Emmet插件。

本节来讲一下Emmet插件的用法及相关语法。

Emmet插件极大的提高了编程员的编程速度,下面我们来讲讲它的具体语法:

一、生成 HTML 文档初始结构

HTML 文档的初始结构,就是包括 doctype、html、head、body 以及 meta 等内容。你只需要输入一个 “!” 就可以生成一个 HTML5 的标准文档初始结构,你没有看错,输入一个感叹号(当然是英文符号),然后摁下 ctrl+E 键,就会发现生成了下面的结构:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
</html>

这就是一个 HTML5 的标准结构,也是默认的 HTML 结构。如果你想生成 HTML4 的过渡型结构,那么输入指令 html:xt,然后ctrl+E, 即可生成如下结构:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>Document</title>
</head>
<body>

</body>
</html>

Emmet 会自动把 doctype 给你补全了,怎么样,这样的功能会不会让你动心?简单总结一下常用的 HTML 结构指令:

html:5 或者 ! 生成 HTML5 结构

html:xt 生成 HTML4 过渡型

html:4s 生成 HTML4 严格型

二、生成带有 id 、class 的 HTML 标签

Emmet 的语法有点类似 CSS 的语法,生成 id 为 aaa 的 div 标签,我们只需要编写下面指令:

#aaa

Emmet 默认的标签为 div ,如果我们不给出标签名称的话,默认就生成 div 标签。如果编写一个 class 为 bbb 的 span 标签,我们需要编写下面指令:

span.bbb

然后就生成了对应的结构。同理,如果想要编写一个 id 为 ccc 的 class 为 ddd 的 ul 标签,我们可以这样写:

ul#ccc.ddd

很简单吧?比你用手写 id 、class 方便多了吧

三、生成后代:>

大于号表示后面要生成的内容是当前标签的后代。例如我要生成一个无序列表,而且被 class 为 aaa 的 div 包裹,那么可以使用下面指令:

div.aaa>ul>li

可以生成如下的结构:

<div>
    <ul>
        <li></li>
    </ul>
</div>

四、生成兄弟:+

上面是生成下级元素,如果想要生成平级的元素,就需要使用 + 号。例如下面指令:

div+p+bq

就可以生成如下的 HTML 结构:

<div></div>
<p></p>
<blockquote></blockquote>

五、生成上级元素:^

上级 (Climb-up)元素是什么意思呢?前面咱们说过了生成下级元素的符号“>”,当使用 div>ul>li 的指令之后,再继续写下去,那么后续内容都是在 li 下级的。如果我想编写一个跟 ul 平级的 span 标签,那么我需要先用 “^” 提升一下层次。例如:

div>ul>li^span

就会生成如下结构:

<div>
    <ul>
        <li></li>
    </ul>
    <span></span>
</div>

如果我想相对与 div 生成一个平级元素,那么就再上升一个层次,多用一个“^”符号:

div>ul>li^^span

六、重复生成多份:

特别是一个无序列表,ul 下面的 li 肯定不只是一份,通常要生成很多个 li 标签。那么我们可以直接在 li 后面 * 上一些数字:

ul>li*5

这样就直接生成五个项目的无序列表了。如果想要生成多份其他结构,方法类似。

七、生成分组:()、

用括号进行分组,这样可以更加明确要生成的结构,特别是层次关系,例如:

div>(header>ul>li*2>a)+footer>p

这样很明显就可以看出层次关系和并列关系,生成如下结构:

<div>
    <header>
        <ul>
            <li><a href=""></a></li>
            <li><a href=""></a></li>
        </ul>
    </header>
    <footer>
        <p></p>
    </footer>
</div>

八、此外,分组还可以很方便的结合上面说的 “*” 符号生成重复结构:

(div>dl>(dt+dd)*3)+footer>p

生成结构:

<div>
    <dl>
        <dt></dt>
        <dd></dd>
        <dt></dt>
        <dd></dd>
        <dt></dt>
        <dd></dd>
    </dl>
</div>
<footer>
    <p></p>
</footer>

九、生成自定义属性:[attr]

a 标签中往往需要附带 href 属性和 title 属性,如果我们想生成一个 href 为 “http://www.haorooms.com/ ,title 为“haorooms 博客”的 a 标签,可以这样写:

a[href="http://www.haorooms.com/" title="haorooms 博客"]

其他标签和属性都类似。

十、对生成内容编号:$

例如无序列表,我想为五个个 li 增加一个 class 属性值 item1 ,然后依次递增从 1-5,那么就需要使用 $ 符号:

ul>li.item$*5

这样就生成了如下结构:

<ul>
 <li class="item1"></li>
 <li class="item2"></li>
 <li class="item3"></li>
 <li class="item4"></li>
 <li class="item5"></li>
</ul>

$ 就表示一位数字,只出现一个的话,就从1开始。如果出现多个,就从0开始。如果我想生成三位数的序号,那么要写三个 $:

ul>li.item$$$*5

输出:

<ul>
    <li class="item001"></li>
    <li class="item002"></li>
    <li class="item003"></li>
    <li class="item004"></li>
    <li class="item005"></li>
</ul>

只能这样单调的生成序号?对于强大的 Emmet 来说,肯定不会会了,我们也可以在 $ 后面增加 @- 来实现倒序排列:

ul>li.item$@-*5

生成如下结构:

<ul>
    <li class="item5"></li>
    <li class="item4"></li>
    <li class="item3"></li>
    <li class="item2"></li>
    <li class="item1"></li>
</ul>

同样,我们也可以使用 @n 指定开始的序号:

ul>li.item$@3*5

这样就会从 3 开始排序,生成如下代码:

<ul>
    <li class="item3"></li>
    <li class="item4"></li>
    <li class="item5"></li>
    <li class="item6"></li>
    <li class="item7"></li>
</ul>

配合上面倒序输出,可以这样写:

ul>li.item$@-3*5

生成的就是以 3 为底倒序:

<ul>
    <li class="item7"></li>
    <li class="item6"></li>
    <li class="item5"></li>
    <li class="item4"></li>
    <li class="item3"></li>
</ul>

十一、生成文本内容:{}

上面讲解了如何生成 HTML 标签,那里面的内容呢?当然也可以生成了:

a[href="http://www.haorooms.com/"]{点击这里到 haorooms 的博客}

这样就生成了一个到我博客的超链接了。在生成内容的时候,特别要注意前后的符号关系,虽然 a>{Click me} 和 a{Click me} 生成的结构是相同的,但是加上其他的内容就不一定了,例如:

<!-- a{click}+b{here} -->
<a href="">click</a><b>here</b>

<!-- a>{click}+b{here} -->
<a href="">click<b>here</b></a>

这样就生成了完全不同的结构,注意这些小细节哦。

不要有空格

在写指令的时候,你可能为了代码的可读性,使用一些空格什么的排版一下。这就会导致代码无法使用。例如下面这句:

(header > ul.nav > li*5) + footer

而去掉空格之后,就可以正常执行生成结构了。

jquery中$.proxy及wrap()的使用

jquery其实真的没有什么,关键是应用的熟练程度,面试的时候有时候会问你jquery源码研究过没有。我前段时间看了一下,其实jquery的源码写的还是满通俗易懂的。

说到应用,我今天主要说下jquery中$.proxy及wrap()的使用,因为这两个我用的比较少,今天在项目中应用了,所以拿出来说一下!

jquery中$.proxy

我们先看个例子:

//正常的this使用
$('#Haorooms').click(function() {

    // 这个this是我们所期望的,当前元素的this.

    $(this).addClass('aNewClass');

});
//并非所期望的this
$('#Haorooms').click(function() {

    setTimeout(function() {

          // 这个this指向的是settimeout函数内部,而非之前的html元素

        $(this).addClass('aNewClass');

    }, 1000);

});

这时候怎么办呢,通常的一种做法是这样的:

$('#Haorooms').click(function() {
    var that = this;   //设置一个变量,指向这个需要的this

    setTimeout(function() {

          // 这个this指向的是settimeout函数内部,而非之前的html元素

        $(that).addClass('aNewClass');

    }, 1000);

});

但是,在使用了jquery框架的情况下, 有一种更好的方式,就是使用$.proxy函数。

jQuery.proxy(),接受一个函数,然后返回一个新函数,并且这个新函数始终保持了特定的上下文(context )语境。

有两种语法:

jQuery.proxy( function, context )
/**function将要改变上下文语境的函数。
** context函数的上下文语境(`this`)会被设置成这个 object 对象。
**/

jQuery.proxy( context, name )
/**context函数的上下文语境会被设置成这个 object 对象。
**name将要改变上下文语境的函数名(这个函数必须是前一个参数 ‘context’ **对象的属性)
**/

上面的例子使用这种方式就可以修改成:

$('#Haorooms').click(function() {

    setTimeout($.proxy(function() {

        $(this).addClass('aNewClass');  

    }, this), 1000);

});

jquery中wrap()方法

wrap(),顾名思义,就是包裹的意思,就是在你所在器外层包裹一层东西。

<div class="container">
  <div class="inner">Hello</div>
  <div class="inner">Goodbye</div>
</div>

$( ".inner" ).wrap(function() {
  return "<div class='" + $( this ).text() + "'></div>";
});

结果如下:

<div class="container">
  <div class="Hello">
    <div class="inner">Hello</div>
  </div>
  <div class="Goodbye">
    <div class="inner">Goodbye</div>
  </div>
</div>

类似的用法还有.wrapAll()、.wrapInner()、.unwrap()等等!

jquery好多方法,关键看你运用的熟练程度,在做dom操作的时候,尽量用最简单,最有效的方法!

css常用效果总结

css有不少常用的效果,你在平时浏览网站的时候可能会看到,但是真的要自己写的时候,有时候会突然忘记,今天稍微对那些常见的效果做一下小结。

1、每逢大的灾难的时候,很多网站变成了灰色,如何让网站快速变灰?css代码是很简单的,用的是css的filter功能。

代码如下:

html {
   filter: grayscale(100%);//IE浏览器
  -webkit-filter: grayscale(100%);//谷歌浏览器
  -moz-filter: grayscale(100%);//火狐
  -ms-filter: grayscale(100%);
  -o-filter: grayscale(100%);
  filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
  -webkit-filter: grayscale(1);//谷歌浏览器
}

有一些网站FLASH动画的颜色不能被CSS滤镜控制,可以在FLASH代码的<object …>和之间插入:

<param value="false" name="menu"/>
<param value="opaque" name="wmode"/>

2、DIV可编辑,就是让一个div变成一个类似input输入框的效果。

在div中添加contentEditable="true" 属性就可以了,如下:

<div id="div1" contentEditable="true"  ></div>  

<div id="div2" contentEditable="true" ></div>  

 <div contentEditable="true"  id="div3"></div> 

其中,我后面有篇编辑器的文章 http://www.haorooms.com/post/js_guangbiao 就用到了这个功能!这个是获得iframe光标所在位置的父节点名称,iframe中就用到了contentEditable="true" 属性。

3、有些网站为了不让用户复制,设置了div禁止选择的功能,设置如下属性:

unselectable="on" onselectstart="return false;"

具体代码:

<div unselectable="on" onselectstart="return false;">
sdfsdfswerwer324234234234
</div>

这样,DIV里面的东西就不能选择复制了!

4、CSS 中form表单两端对齐

做form表单的时候,前面经常有姓名,年龄,公司名称等等,有的是2个字,有的是4个字,如何让字对齐呢?有的人的做法是打几个空格,但是这样不是很准确,最好的办法是如下:

css代码:

 .test1 {
            text-align:justify;
            text-justify:distribute-all-lines;/*ie6-8*/
            text-align-last:justify;/* ie9*/
            -moz-text-align-last:justify;/*ff*/
            -webkit-text-align-last:justify;/*chrome 20+*/
        }
        @media screen and (-webkit-min-device-pixel-ratio:0){/* chrome*/
            .test1:after{
                content:".";
                display: inline-block;
                width:100%;
                overflow:hidden;
                height:0;
            }
        }

html代码:

<div class="box1">
    <div class="test1">姓 名</div>
    <div class="test1">姓 名 姓 名</div>
    <div class="test1">姓 名 名</div>
    <div class="test1">所 在 地</div>
    <div class="test1">工 作 单 位</div>
</div>

5、input声音录入按钮,(紧支持谷歌)

如下图红色框框中的按钮

enter image description here

代码如下:

<input type="text" class="box" name="s" id="s" class="inputText" placeholder="输入关键词"  x-webkit-speech>

添加 x-webkit-speech 属性就可以了。

6、给input的placeholder设置颜色

设置方法如下:

::-webkit-input-placeholder { /* WebKit browsers */
    color:    #999;
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
    color:    #999;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
    color:    #999;
}
:-ms-input-placeholder { /* Internet Explorer 10+ */
    color:    #999;
}

7、[css3实现一个div设置多张背景图片及background-image属性][2]

8、[CSS选中状态修改,谷歌滚动轴修改][3]

9、[css input\[type=file\] 样式美化,input上传按钮美化][4]

10、CSS :after 和:before选择器

after选择器通常在clear中使用,用法如下:

.clearfix:after{display:block;visibility:hidden;clear:both;height:0;content:'.';font-size:0}

写了这个clearfix,可以让外层div包裹整个内层,符合谷歌闭合机制。

也可以在某个元素前面或者后面追加,例如:

p:after
{ 
content:"haorooms:-";
background-color:yellow;
color:red;
font-weight:bold;
}

每个p标签后面都加了一个 -haorooms

11、透明度

opacity: .9; 
filter:alpha(opacity=90)

IE7和IE6中opacity是没有用的,在IE6中DIV透明的方法一般用filter;

.haorooms{opacity: 0; cursor:pointer;  -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter: alpha(opacity=0);}

12、超出长度显示省略号

一般要指定宽度,然后给如下四个属性。

display:bolck;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;

案例代码:

.haorooms{width:200px;display:bolck;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}

13、阴影效果

-webkit-box-shadow: 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: 0 1px 1px rgba(0,0,0,.2);
box-shadow: 0 1px 1px rgba(0,0,0,.2);

14、CSS强制换行和不换行

自动换行

div{ 
word-wrap: break-word; 
word-break: normal; 
}

强制英文单词断行

div{
word-break:break-all;
}

强制不换行

div{
white-space:nowrap;
}

15、CSS 圆角

IE 9、Opera 10.5、Safari 5、Chrome 4和Firefox 4,都支持上述的border-radius属性。早期版本的Safari和Chrome,支持-webkit-border-radius属性,早期版本的Firefox支持-moz-border-radius属性。
目前来看,为了保证兼容性,只需同时设置-moz-border-radius和border-radius即可。

-moz-border-radius: 15px;
border-radius: 15px;

(注意:border-radius必须放在最后声明,否则可能会失效。)

另外,早期版本Firefox的单个圆角的语句,与标准语法略有不同。

-moz-border-radius-topleft(标准语法:border-top-left-radius)
-moz-border-radius-topright(标准语法:border-top-right-radius)
-moz-border-radius-bottomleft(标准语法:border-bottom-left-radius)
-moz-border-radius-bottomright(标准语法:border-bottom-right-radius)

16、[css浏览器兼容问题的一些总结(IE6等)][5]

17、[IE6 中png背景透明的最好方法及谈谈IE6和我的博客][6]

18、css3弹性盒子

#haorooms ul { //父亲
            display: -moz-box;
            display: -webkit-box;
            display: box;
            -moz-box-orient: horizontal;
            -webkit-box-orient: horizontal;
            box-orient: horizontal;
        }
        #haorooms  ul li{ //儿子设置
            -moz-box-flex: 1;
            -webkit-box-flex: 1;
            box-flex: 1;
            float:none;
}

关于css3弹性盒子模型之box-flex,我在博客中暂时没有写相关文章,因为这个属性不支持IE,所以我很少用到。

我一般用别的方法来代替这个属性。想达到弹性盒子的要求,jquery mobile 有一套网格布局法,很不错,支持IE的,有时间可以参考一下,或者研究一下他们是怎么写的,参照他们的方法可以自己改写一下!

关于弹性盒子式的布局,大家也可以看下bootstrap,bootstrap提出栅格类的一个说法,你引进他的css之后,可以用col-mid-*来进行布局。例如:

<div class="row">
  <div class="col-md-6">.col-md-6</div>
  <div class="col-md-6">.col-md-6</div>
</div>

各站一半!

<div class="row">
  <div class="col-md-8">.col-md-8</div>
  <div class="col-md-4">.col-md-4</div>
</div>

前面的是整个宽度的三分之二,后面是整个宽度的三分之一!

具体可以看看bootstrap的样式解释:http://v3.bootcss.com/css/

19、textarea禁止拖动

resize: none; //禁止拖动

以下是resize属性的的各个取值:

none:用户不能操纵机制调节元素的尺寸;
both:用户可以调节元素的宽度和高度;
horizontal:用户可以调节元素的宽度;
vertical:让用户可以调节元素的高度;
inherit:默认继承。

20、div垂直居中的方法总结

div垂直居中的方法,看我写的一篇文章吧!http://www.haorooms.com/post/css_div_juzhong

21、css固定宽高DIV内部元素垂直居中的方法

和上面的20不同,这里说的是一个div内部元素如何垂直居中,具体请看:http://www.haorooms.com/post/div_guding_inner_center

22、纯css制作鼠标移上去显示图片效果

具体请看我的一篇文章:http://www.haorooms.com/post/css_hover_jqs

23、CSS3的一些前缀总结

css3为了更好的兼容多个浏览器,通常前面加一大堆前缀,有时候感觉很烦,前缀也容易忘记或者漏掉。下面总结一下!

-webkit  /*为Chrome/Safari*/
-moz  /*为Firefox*/
-ms   /*为IE*/
-o  /*为Opera*/

以旋转为例

-webkit-transform:rotate(-3deg); /*为Chrome/Safari*/
-moz-transform:rotate(-3deg); /*为Firefox*/
-ms-transform:rotate(-3deg); /*为IE*/
-o-transform:rotate(-3deg); /*为Opera*/
transform:rotate(-3deg); /*为nothing*/

以border-radius为例(本文上面案例15,CSS 圆角已经提过圆角的问题,下面我们再来重提一下):

-moz-border-radius: 12px; /* FF1-3.6 */
-webkit-border-radius: 12px; /* Saf3-4, iOS 1-3.2, Android <1.6 */
border-radius: 12px; /* Opera 10.5, IE9, Saf5, Chrome, FF4, iOS 4, Android 2.1+ */

FF4、Saf5以及Chrome都支持border-radius属性了,我们就没有必要写以上两条了,代码变成:

border-radius: 12px;

所以有些常用的CSS3效果,由于浏览器都支持了,就不需要前缀,但是为了保险起见,你也可以加上前缀!

24、css3的box-sizing

给了两个并排带边框的div百分比宽度,假如不用box-sizing,边框的宽度会在行内显示。用box-sizing:border-box,可以去除边框的占位。

浏览器支持IE9以上及火狐、谷歌、Opera等等。

案例如下:

<style> 
div.container
{
width:30em;
border:1em solid;
}
div.box
{
box-sizing:border-box;
-moz-box-sizing:border-box; /* Firefox */
-webkit-box-sizing:border-box; /* Safari */
width:50%;
border:1em solid red;
float:left;
}
</style>
</head>
<body>

<div class="container">
<div class="box">这个 div 占据左半部分。</div>
<div class="box">这个 div 占据右半部分。</div>
</div>

语法:

box-sizing: content-box|border-box|inherit;

Css3的Media Query方法总结—让您的网站兼容手机

最近几年,大屏幕手机和ipad等移动设备的流行,使你的网页兼容移动设备已成为一种流行!移动设备的屏幕大小是五花八门,各式各样!要想很好的兼容移动设备,Css3的media技术是功不可没。

我的博客,应用了CSS3的media技术,使其在手机等移动设备上面也可以查看。当然,只凭css3的media技术,做好手机网站是远远不够的,手机网站注意事项和总结,后面会陆续出一些文章,欢迎持续关注!

好了,废话少说,下面进入正题:

一、Css3的Media Queries 翻译成中文是“媒体查询”,有如下几种引入方式:

1、直接head中引用,其实media在css2中已经存在,不过,他的主要作用您没有关注,兼容所有媒体等。你肯定见到过如下的写法:

 <link href="css/style.css" rel="stylesheet" type="text/css" media="all" />

现在,我们为了兼容屏幕的大小,可以这么写:

<link rel="stylesheet" media="screen and (max-width: 600px)" href="smallscreen.css" />

在屏幕最大是600px的时候加载“smallscreen.css”

2、@import 方式引用,这种方式的引用,要在style中,写法如下:

<style type="text/css" media="screen"> 或者写成<style type="text/css" media="screen and (max-width: 600px)"> 
    @import url("css/style.css");
  </style>

也就是在特定屏幕下加载style.css

3、我最常用的是第三种方法,也就是下面的这种方法:

  @media screen and (max-width: 600px) {
    选择器 {
      属性:属性值;
    }
  }

直接在样式中写@media屏幕控制。

二、Media Queries的具体使用方式

1、最大宽度Max Width

   <link rel="stylesheet" media="screen and (max-width:600px)" href="small.css" type="text/css" />

上面表示的是:当屏幕小于或等于600px时,将采用small.css样式来渲染Web页面。

2、最小宽度Min Width

   <link rel="stylesheet" media="screen and (min-width:900px)" href="big.css" type="text/css"  />

上面表示的是:当屏幕大于或等于900px时,将采用big.css样式来渲染Web页面。

3、多个Media Queries使用

  <link rel="stylesheet" media="screen and (min-width:600px) and (max-width:900px)" href="style.css" type="text/css" />

Media Query可以结合多个媒体查询,换句话说,一个Media Query可以包含0到多个表达式,表达式又可以包含0到多个关键字,以及一种Media Type。正如上面的其表示的是当屏幕在600px-900px之间时采用style.css样式来渲染web页面。

4、设备屏幕的输出宽度Device Width

<link rel="stylesheet" media="screen and (max-device-width: 480px)" href="iphone.css" type="text/css" />

上面的代码指的是iphone.css样式适用于最大设备宽度为480px,比如说iPhone上的显示,这里的max-device-width所指的是设备的实际分辨率,也就是指可视面积分辨率

5、iPhone4

<link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" type="text/css" href="iphone4.css" />

上面的样式是专门针对iPhone4的移动设备写的。

6、iPad

  <link rel="stylesheet" media="all and (orientation:portrait)" href="portrait.css" type="text/css" /> 
  <link rel="stylesheet" media="all and (orientation:landscape)" href="landscape.css"  type="text/css" />

在大数情况下,移动设备iPad上的Safari和在iPhone上的是相同的,只是他们不同之处是iPad声明了不同的方向,比如说上面的例子,在纵向(portrait)时采用portrait.css来渲染页面;在横向(landscape)时采用landscape.css来渲染页面。

7、android

 /*240px的宽度*/
  <link rel="stylesheet" media="only screen and (max-device-width:240px)" href="android240.css" type="text/css" />
  /*360px的宽度*/
  <link rel="stylesheet" media="only screen and (min-device-width:241px) and (max-device-width:360px)" href="android360.css" type="text/css" />
  /*480px的宽度*/
  <link rel="stylesheet" media="only screen and (min-device-width:361px) and (max-device-width:480px)" href="android480.css" type="text/css" />

我们可以使用media query为android手机在不同分辨率提供特定样式,这样就可以解决屏幕分辨率的不同给android手机的页面重构问题。

8、not关键字

 <link rel="stylesheet" media="not print and (max-width: 1200px)" href="print.css" type="text/css" />

not关键字是用来排除某种制定的媒体类型,换句话来说就是用于排除符合表达式的设备。

9、only关键字

<link rel="stylesheet" media="only screen and (max-device-width:240px)" href="android240.css" type="text/css" />

only用来定某种特定的媒体类型,可以用来排除不支持媒体查询的浏览器。其实only很多时候是用来对那些不支持Media Query但却支持Media Type的设备隐藏样式表的。其主要有:支持媒体特性(Media Queries)的设备,正常调用样式,此时就当only不存在;对于不支持媒体特性(Media Queries)但又支持媒体类型(Media Type)的设备,这样就会不读了样式,因为其先读only而不是screen;另外不支持Media Qqueries的浏览器,不论是否支持only,样式都不会被采用。

10、其他

在Media Query中如果没有明确指定Media Type,那么其默认为all,如:

<link rel="stylesheet" media="(min-width: 701px) and (max-width: 900px)" href="medium.css" type="text/css" />

另外还有使用逗号(,)被用来表示并列或者表示或,如下

<link rel="stylesheet" type="text/css" href="style.css" media="handheld and (max-width:480px), screen and (min-width:960px)" />

上面代码中style.css样式被用在宽度小于或等于480px的手持设备上,或者被用于屏幕宽度大于或等于960px的设备上。

总结:常用的Media Query总结起来有如下属性:
enter image description here

支持和不支持min 和max都在表中可以看出。

浏览器不兼容IE7和IE8,具体兼容情况如下:

enter image description here

通过上面的文章,您对css3的media属性了解了没有?欢迎留言交流!

蕙兰瑜伽沙龙心得

![enter image description here](http://www.haorooms.com/uploads/images/huilan.jpg) 我以前了解过瑜伽,但是一直以为瑜伽就是做几个动作,练练身体。瑜伽是女孩子练习的东西,不适合男孩子。“老婆”大人在家练习瑜伽的时候,我有时候也跟着做几个动作。通过“老婆”那里,我知道了张蕙兰,并知道了她是**瑜伽之母,对于具体瑜伽的练习,瑜伽语音,我也只是随便听听。。只当好玩。

2014年8月23日,在上海举办的蕙兰瑜伽沙龙活动,“老婆”大人拉我一起报名,我也只当是陪她,去参加了蕙兰瑜伽沙龙。刚刚开始,是李英老师在上面讲一些蕙兰瑜伽的基本动作,讲到了上班族应该如何放松,如何进行颈部练习等,我感觉瑜伽对我的生活健康还是有用的。当进行冥想练习的时候,我感觉,蕙兰瑜伽就是运用心理学,让人在心理上得到放松罢了,不过我也确实是放松了很多。

当第二节,张蕙兰的女儿莎媞雅,给我们讲瑜伽歌舞的时候,让我们彻底放松了。在这里,在这个小小空间里,你可以跟着音乐,尽情的跳呀,唱呀,没有一个人笑话你,每一个人都是平等的,莎媞雅老师,李英老师和瑜伽志愿者们和我们一起跳了起来。在这时,我们的烦恼彻底抛在了脑后,随之而来的只有欢乐!欢乐!在这个全员跳舞的房间里,你可以看到上有六七十岁的老爷爷,下有四五岁的小朋友,每一个人都在用自己的方式表达快乐,在这样的氛围中,你也会不自然的快乐起来,跟着大家一起跳起来,唱起来!这个画面让我想到了电视剧里面八路军解放区里面的画面,每一个人都是那么欢乐,虽然你我不认识,但是不自然的牵起手来,相互大声高歌起来,让我们彻底忘掉了大城市的冷漠,更多的给我们带来的是欢乐和人们心与心交流的温暖!

当看到蕙兰瑜伽学习休闲活动的视频的时候,我想到了我“老婆”大人!她是参加过这个活动的,而且在北京和武汉参加过两次。在这个休闲活动视频中,我看到了洗鼻壶,这个洗鼻壶让我印象很深刻,因为“老婆”大人现在还在每天用它洗鼻子。在“老婆”大人的劝说之下,我现在也渐渐地开始使用这个洗鼻壶了。其次让我印象深刻的是瑜伽倡导素食,瑜伽的很多食物里面都没有肉类,但是瑜伽素食中的营养搭配也是很好的。

所以,让我深深的感受到,瑜伽不仅仅是几个动作练习,而是一种健康的生活习惯!一种心理的放松!一种高压生活节奏下释压的方式!

js和jquery懒加载之可视区域加载

haorooms博客地址:http://www.haorooms.com/post/js_jquery_lazyload_viewload

javascript懒加载之可视区域加载

在制作js可视区域加载之前,我们首先必须了解各种高度,我之前的一篇文章javascript的height总结,大家可以看一下,复习一下!

了解了各种高度之后,我们开始我们的js代码吧!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>haorooms前端博客-可视区域加载之 javascript</title>
    <style>
    img{width:100%;margin-bottom: 30px; min-height: 400px; background-color: #ddd;}

    </style>
</head>
<body>
    <img haoroomslazyload="Chrysanthemum.jpg" src="" >
    <img haoroomslazyload="Desert.jpg" src="" >
    <img haoroomslazyload="Hydrangeas.jpg" src="" >
    <img haoroomslazyload="Koala.jpg" src="" >
    <img haoroomslazyload="Lighthouse.jpg" src="" >
    <img haoroomslazyload="Penguins.jpg" src="" >
    <img haoroomslazyload="Tulips.jpg" src="" >
    <script>
    var imgNum=document.getElementsByTagName('img').length;
    var imgObj=document.getElementsByTagName("img");
    var l=0;

        window.onscroll=function(){
                var seeHeight = document.documentElement.clientHeight;
                var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                for(var i=l;i<imgNum;i++){
                    if(imgObj[i].offsetTop < seeHeight + scrollTop){
                        console.log(imgObj[i].getAttribute("src"));
                        console.log(imgObj[i].src );
                        if(imgObj[i].getAttribute("src") == ""){
                            imgObj[i].src = imgObj[i].getAttribute("haoroomslazyload");
                        }
                    }
                    if(imgObj[i].offsetTop > seeHeight + scrollTop){
                        l=i;
                        break;
                    }
                }
        }

</script>

大家注意看我的两个console输出,console.log(imgObj[i].src );获取的是整个浏览器地址!

jquery懒加载之可视区域加载

上面的js用jquery翻译版!

var l=0
//js方法翻译版
$(window).bind("scroll", function(event){

                for(var i=l;i<$("img").length;i++){
                    if($("img").eq(i).offset().top < parseInt($(window).height()) + parseInt($(window).scrollTop())){
                        if($("img").eq(i).attr("src") == ""){
                            var lazyloadsrc=$('img').eq(i).attr("haoroomslazyload");
                            $("img").eq(i).attr("src",lazyloadsrc);
                        }
                    }
                    if($("img").eq(i).offset().top  > parseInt($(window).height()) + parseInt($(window).scrollTop())){
                        l=i;
                        break;
                    }
                }

 });

另外一种方法,可以参考我之前写的一个延迟加载的插件:http://www.haorooms.com/post/touchweb_canvas_lazyload

其中是这么写的。

我把这个写法拎了出来,如下:

$(window).bind("scroll", function(event){
$("img").each(function(){
          //窗口的高度+看不见的顶部的高度=屏幕低部距离最顶部的高度  
            var thisButtomTop = parseInt($(window).height()) + parseInt($(window).scrollTop());  
            var thisTop = parseInt($(window).scrollTop()); //屏幕顶部距离最顶部的高度  
                var PictureTop = parseInt($(this).offset().top);  
                 if (PictureTop >= thisTop && PictureTop <= thisButtomTop && $(this).attr("haoroomslazyload") != $(this).attr("src")) {
                   $(this).attr("src", $(this).attr("haoroomslazyload")); 
                 }
});

})

可视区域加载延伸

例如一个动画效果,或者一个canvas图片,我想达到的效果是,初始进来不加载,当滚动到这个动画或者图表上面的时候,进行加载,那么我们就可以根据上面的代码进行如下改进:

$(window).bind("scroll", function(event){

          //窗口的高度+看不见的顶部的高度=屏幕低部距离最顶部的高度  
            var thisButtomTop = parseInt($(window).height()) + parseInt($(window).scrollTop());  
            var thisTop = parseInt($(window).scrollTop()); //屏幕顶部距离最顶部的高度  
                var PictureTop = parseInt($("你的要滚动加载的ID").offset().top);  
                 if (PictureTop >= thisTop && PictureTop <= thisButtomTop) {
                  //  $("#你的要滚动加载的ID").attr("src", $("#你的要滚动加载的ID").attr("haoroomslazyload")); 

                   //此处可以执行你的加载函数,加载函数由原来的document.ready中,移到这里来!



                 }
})

MAC电脑的一些常用命令

今天在我的mac电脑上操作grunt,突然发现我用命令行进不了移动硬盘了,因为我的nodejs文件是放在移动硬盘里面,mac命令行如何进入移动硬盘?

怪自己是mac的菜鸟,网上查了查,才知道桌面上看到的硬盘都挂在 /Volumes 下

为了让我这个mac菜鸟在今后mac命令行操作的时候,更快地找到相应地命令,现在总结一下MAC电脑的一些常用命令。

mac电脑常用文件位置

移动硬盘的位置 :

cd /Volumes/硬盘名字

根目录位置是:

cd   /
ls

驱动所在位置 :

/Systme/Library/Extensions 

用户文件夹位置:

 /Users/用户名 

桌面的位置

/Users/用户名/Desktop 

获得权限

为了防止误操作破坏系统,再用户状态下时没有权限操作系统重要文件的,所以先要取得root权限

sudo -s 

然后输入密码,输入密码时没有任何回显,连星号都没有,只管输完回车就行了。

常用命令

列出文件

ls 参数 目录名 
例: 想看看跟目录下有什么, 
ls / 
想看看驱动目录下有什么, 
ls /System/Library/Extensions 
参数 -w 显示中文,-l 详细信息, -a 包括隐藏文件 

转换目录

cd 
例:想到驱动目录下溜达一圈 
cd /System/Library/Extensions 

建立新目录

mkdir 目录名 
例:在驱动目录下建一个备份目录 backup 
mkdir /System/Library/Extensions/backup 
在桌面上建一个备份目录 backup 
mkdir /User/用户名/Desktop/backup 

拷贝文件

cp 参数 源文件 目标文件 
例:想把桌面的Natit.kext 拷贝到驱动目录中 
cp -R /Users/用户名/Desktop/Natit.kext /System/Library/Extensions 
参数R表示对目录进行递归操作,kext在图形界面下看起来是个文件,实际上是个文件夹。 
把驱动目录下的所有文件备份到桌面backup 
cp -R /System/Library/Extensions/* /Users/用户名/Desktop/backup 

删除文件

rm 参数 文件 
例:想删除驱动的缓存 
rm -rf /System/Library/Extensions.kextcache 
rm -rf /System/Library/Extensions.mkext 
参数-rf 表示递归和强制,千万要小心使用,如果执行了 rm -rf / 你的系统就全没了 

移动文件

mv 文件 
例:想把AppleHDA.Kext 移到桌面 
mv /System/Library/Extensions/AppleHDA.kext /User/用户名/Desktop 
想把AppleHDA.Kext 移到备份目录中 
mv /System/Library/Extensions/AppleHDA.kext /System/Library/Extensions/backup 

更改文件权限

chmod 参数 权限 文件 
例:把驱动目录下所有文件设定到root读写,其他用户只读 
chmod -R 755 /System/Library/Extensions 
参数R 表示递归,755表示各用户的权限 

更改文件属主

chown 参数 用户:组 文件 
例:把驱动目录下的所有文件属主改成根用户 
chown -R root:wheel /System/Library/Extensions 
参数R 表示递归操作 

修复整个系统中文件的权限

diskutil repairpermissions / 
严格的说这不是一个unix 命令,而是osx一个软件,记得修改或添加的驱动就执行一次。 

文本编辑

nano 文件名 
例:编辑natit Info.plist 
nano /System/Library/Extensions/Natit.kext/Info.plist 
编辑完成后 用 Ctrl +O 存盘,Ctrl+X 退出 
另一个文本编辑软件是 vi,操作有些古怪,熟了是非常好用的,而且在所有类Unix系统中都它,走遍天下都不怕了。 

运行脚本命令

sh 脚本文件名 
例 修改驱动后所有需要的操作存成一个脚本,以后修改了驱动后只要运行一次这个脚本就可以了,方便吧 ,步骤如下:
1. 终端中运行nano /clean 
2. 把下列代码粘贴到 nano 中 
rm -rf /System/Library/Extensions.kextcache 
rm -rf /System/Library/Extensions.mkext 
chown -R root:wheel /System/Library/Extensions 
chmod -R 755 /System/Library/Extensions 
diskutil repairpermissions / 
kextcache -k /System/Library/Extensions/ 
3. Ctrl +O 存盘,Ctrl+X 退出 
4. 以后只要动了驱动,就在终端中运行一次 sh /clean 

苹果系统式unix系统,和linux系统操作差不多,假如您对linux系统操作很熟练,详细操作苹果系统肯定也是如鱼得水!

HTML5中的GPS定位之getCurrentPosition

html5中的GPS定位功能主要用的是getCurrentPosition, 该方法封装在 navigator.geolocation 属性里,是 navigator.geolocation 对象的方法。

getCurrentPosition()函数简介

getCurrentPosition(successCallback,errorCallback,positionOptions)

successCallback

表示调用getCurrentPosition函数成功以后的回调函数,该函数带有一个参数,对象字面量格式,表示获取到的用户位置数据。该对象包含两个属性 coords 和 timestamp。其中 coords 属性包含以下7个值:

accuracy:精确度
latitude:纬度
longitude:经度
altitude:海拔
altitudeAcuracy:海拔高度的精确度
heading:朝向
speed:速度

errorCallback

和 successCallback 函数一样带有一个参数,对象字面量格式,表示返回的错误代码。它包含以下两个属性:

1、message:错误信息
2、 code:错误代码。

其中错误代码包括以下四个值:

1、UNKNOW_ERROR:表示不包括在其它错误代码中的错误,这里可以在 message 中查找错误信息
2、PERMISSION_DENIED:表示用户拒绝浏览器获取位置信息的请求
3、 POSITION_UNAVALIABLE:表示网络不可用或者连接不到卫星
4、TIMEOUT:表示获取超时。必须在options中指定了timeout值时才有可能发生这种错误

positionOptions

positionOptions 的数据格式为JSON,有三个可选的属性:

1、enableHighAcuracy — 布尔值: 表示是否启用高精确度模式,如果启用这种模式,浏览器在获取位置信息时可能需要耗费更多的时间。
2、timeout — 整数: 表示浏览需要在指定的时间内获取位置信息,否则触发errorCallback。
3、maximumAge — 整数/常量: 表示浏览器重新获取位置信息的时间间隔。

getCurrentPosition()函数定位应用

<!DOCTYPE HTML>
   <head>
      <script type="text/javascript">

         function showLocation(position) {
            var latitude = position.coords.latitude;
            var longitude = position.coords.longitude;
            alert("Latitude : " + latitude + " Longitude: " + longitude);
         }

         function errorHandler(err) {
            if(err.code == 1) {
               alert("Error: Access is denied!");
            }else if( err.code == 2) {
               alert("Error: Position is unavailable!");
            }
         }

         function getLocation(){

            if(navigator.geolocation){
               // timeout at 60000 milliseconds (60 seconds)
               var options = {timeout:60000};
               navigator.geolocation.getCurrentPosition(showLocation, errorHandler, options);
            }else{
               alert("Sorry, browser does not support geolocation!");
            }
         }

      </script>

   </head>

   <html>
      <body>
         <form>
            <input type="button" onclick="getLocation();" value="Get Location"/>
         </form>
      </body>
   </html>

点击按钮,就可以回提示是否获取当前位置,允许之后,可以获取你所在位置的经纬度!

javascript execCommand,复文本框神器

下面我们来介绍一下javascript execCommand方法,可以说javascript execCommand是复文本框必不可少的方法。今天上午的文章js复文本函数,是用自己封装的函数方法来写的,通常项目中一般不这么写,复文本加粗,倾斜,下划线,字体等等方法,大多是用document.execCommand方法。

下面对document.execCommand方法做一下简单介绍:

当document对象被转换为设计模式的时候(选中,设置contentEditable等),document对象提供了一个execCommand方法,通过给这个方法传递参数命令可以操作可编辑区域的内容。这个方法的命令大多数是对document选中区域的操作 (如bold, italics等), 也可以插入一个元素(如增加一个a链接) 或者修改一个完整行 (如缩进).。当元素被设置了contentEditable,通过执行execCommand 方法可以对当前活动元素进行很多操作。

语法

execCommand(String aCommandName, Boolean aShowDefaultUI, String aValueArgument)

参数

String aCommandName  //命令名称
Boolean aShowDefaultUI  // 是否展示用户界面,默认为false。Mozilla没有实现
String aValueArgument  // 一些命令需要一些额外的参数值(如insertimage需要提供这个image的url)。默认为null。

命令名称介绍(第一个参数)

backColor (用法:document.execCommand(”BackColor”,”false”,sColor); )
改变文档的背景颜色。 在styleWithCss模式,它影响的是包含元素的背景。 这个命令要求提供一个颜色值作为第三个参数 (Internet Explorer 使用这个命令设置文本背景色)
bold (用法: document.execCommand(”Bold”,”false”,null); )
对选中文本或者插入元素设置、取消粗体显示. (Internet Explorer 使用STRONG 标签 而不是 B标签。)
contentReadOnly
转化文档进入只读或者可编辑模式. 这个命令要求提供给一个boolean值给第3个参数(ie不支持)。
copy   用法:document.execCommand(”Copy”,”false”,null); 
把当前选中区域复制 到系统剪贴板。使用这个命令需要首先在 user.js 接口中进行激活。
createLink
当有选中区域的时候,使用这个命令转化选中区域为一个锚点,需要提供一个URI给第3个参数. 这个URI必须至少包含一个字符,空白字符也可。(Internet Explorer 会创建一个URI为空的a标签)
cut     用法:document.execCommand(”Cut”,”false”,null); 
剪切选中文本到剪切板. 同copy一样需要开启剪切板功能。
decreaseFontSize
给选中文本或者插入元素添加一个small标签。(Internet Explorer不支持)
delete
删除当前选中区域
enableInlineTableEditing
开启或禁用表的行和列的插入删除功能 ( Internet Explorer不支持)
enableObjectResizing
开启或禁用图片或者其他可resize元素的resize功能 ( Internet Explorer不支持)
fontName  用法:document.execCommand(”FontName”,”false”,sFontName); 
改变选中文本或者插入元素的字体。需要给第3个参数提供一个字体值
fontSize  用法:document.execCommand(”FontSize”,”false”,sSize|iSize); 
改变选中文本或者插入元素的字体大小。需要给第3个参数提供一个数字
foreColor
改变选中文本或者插入元素的字体颜色。需要给第3个参数提供一个颜色值

上面是最常用的命令,其他命令暂不列举!

看到上面的用法,大家心动了吧,我现在给大家举几个简单的例子:

demo1:

<head>
    <script type="text/javascript">
        function SetToBold () {
            document.execCommand ('bold', false, null);
        }
    </script>
</head>
<body>
    <div contenteditable="true" onmouseup="SetToBold ();">选择文本加粗,放开文本不加粗,哈哈哈,haorooms</div>
</body>

demo2, 用iframe方法,模仿编辑器

<head>
    <script type="text/javascript">
        var editorDoc;
        function InitEditable () {
            var editor = document.getElementById ("editor");
            editorDoc = editor.contentWindow.document;          
            var editorBody = editorDoc.body;

                // turn off spellcheck
            if ('spellcheck' in editorBody) {    // Firefox
                editorBody.spellcheck = false;
            }

            if ('contentEditable' in editorBody) {
                    // allow contentEditable
                editorBody.contentEditable = true;
            }
            else {  // Firefox earlier than version 3
                if ('designMode' in editorDoc) {
                        // turn on designMode
                    editorDoc.designMode = "on";                
                }
            }
        }

        function ToggleBold () {
            editorDoc.execCommand ('bold', false, null);
        }
    </script>
</head>
<body onload="InitEditable ();">
    首先在编辑器中选中文本
    <br />
    <iframe id="editor" src="editable.htm"></iframe>
    <br /><br />
    点击加粗,我会变粗,选中,点击加粗,我会不加粗!
    <br />
    <button onclick="ToggleBold ();">加粗</button>
</body>

editable.htm

<!DOCTYPE html>
<html>
<head>
    <title>Editable 例子</title>
    <meta charset="utf-8" />
</head>
<body>
   haorooms在编辑器中
</body>
</html>

demo3, 用iframe方法,模仿编辑器,用的是一个iframe啊,你可以复制上面的内容,代码如下,[案例预览][2]

<head>
    <script type="text/javascript">
        var editorDoc;
        function InitEditable () {
            var editor = document.getElementById ("editor");

            if (editor.contentDocument)
                editorDoc = editor.contentDocument;
            else
                editorDoc = editor.contentWindow.document;

            var editorBody = editorDoc.body;

                // turn off spellcheck
            if ('spellcheck' in editorBody) {    // Firefox
                editorBody.spellcheck = false;
            }

            if ('contentEditable' in editorBody) {
                    // allow contentEditable
                editorBody.contentEditable = true;
            }
            else {  // Firefox earlier than version 3
                if ('designMode' in editorDoc) {
                        // turn on designMode
                    editorDoc.designMode = "on";                
                }
            }
        }

        function ToggleBold () {
            editorDoc.execCommand ('bold', false, null);
        }
        function ToggleItalic () {
            editorDoc.execCommand ('italic', false, null);
        }
        function SetRed () {
            editorDoc.execCommand ('foreColor', false, "#ff0000");
        }
        function Delete () {
            editorDoc.execCommand ('delete', false, null);
        }
    </script>
</head>
<body onload="InitEditable ();">
    First, write and select some text in the editor.
    <br />
    <iframe id="editor" src="editable.htm"></iframe>
    <br /><br />
    You can use the following buttons to change the appearance of the selected text:
    <br /><br />
    <button onclick="ToggleBold ();">加粗</button>
    <button onclick="ToggleItalic ();">斜体</button>
    <button onclick="SetRed ();">红色</button>
    <button onclick="Delete ();">删除</button>
</body>

demo4,直接对文本进行操作,[案例预览][3]

<head>
    <script type="text/javascript">
        function GetNextLeaf (node) {
            while (!node.nextSibling) {
                node = node.parentNode;
                if (!node) {
                    return node;
                }
            }
            var leaf = node.nextSibling;
            while (leaf.firstChild) {
                leaf = leaf.firstChild;
            }
            return leaf;
        }

        function GetPreviousLeaf (node) {
            while (!node.previousSibling) {
                node = node.parentNode;
                if (!node) {
                    return node;
                }
            }
            var leaf = node.previousSibling;
            while (leaf.lastChild) {
                leaf = leaf.lastChild;
            }
            return leaf;
        }

            // If the text content of an element contains white-spaces only, then does not need to colorize
        function IsTextVisible (text) {
            for (var i = 0; i < text.length; i++) {
                if (text[i] != ' ' && text[i] != '\t' && text[i] != '\r' && text[i] != '\n')
                    return true;
            }
            return false;
        }

        function ColorizeLeaf (node, color) {
            if (!IsTextVisible (node.textContent))
                return;

            var parentNode = node.parentNode;
                // if the node does not have siblings and the parent is a span element, then modify its color
            if (!node.previousSibling && !node.nextSibling) {
                if (parentNode.tagName.toLowerCase () == "span") {
                    parentNode.style.color = color;
                    return;
                }
            }

                // Create a span element around the node
            var span = document.createElement ("span");
            span.style.color = color;
            var nextSibling = node.nextSibling;
            parentNode.removeChild (node);
            span.appendChild (node);
            parentNode.insertBefore (span, nextSibling);
        }

        function ColorizeLeafFromTo (node, color, from, to) {
            var text = node.textContent;
            if (!IsTextVisible (text))
                return;

            if (from < 0)
                from = 0;
            if (to < 0)
                to = text.length;

            if (from == 0 && to >= text.length) {
                    // to avoid unnecessary span elements
                ColorizeLeaf (node, color);
                return;
            }

            var part1 = text.substring (0, from);
            var part2 = text.substring (from, to);
            var part3 = text.substring (to, text.length);

            var parentNode = node.parentNode;
            var nextSibling = node.nextSibling;

            parentNode.removeChild (node);
            if (part1.length > 0) {
                var textNode = document.createTextNode (part1);
                parentNode.insertBefore (textNode, nextSibling);
            }
            if (part2.length > 0) {
                var span = document.createElement ("span");
                span.style.color = color;
                var textNode = document.createTextNode (part2);
                span.appendChild (textNode);
                parentNode.insertBefore (span, nextSibling);
            }
            if (part3.length > 0) {
                var textNode = document.createTextNode (part3);
                parentNode.insertBefore (textNode, nextSibling);
            }
        }

        function ColorizeNode (node, color) {
            var childNode = node.firstChild;
            if (!childNode) {
                ColorizeLeaf (node, color);
                return;
            }

            while (childNode) {
                    // store the next sibling of the childNode, because colorizing modifies the DOM structure
                var nextSibling = childNode.nextSibling;
                ColorizeNode (childNode, color);
                childNode = nextSibling;
            }
        }

        function ColorizeNodeFromTo (node, color, from, to) {
            var childNode = node.firstChild;
            if (!childNode) {
                ColorizeLeafFromTo (node, color, from, to);
                return;
            }

            for (var i = from; i < to; i++) {
                ColorizeNode (node.childNodes[i], color);
            }
        }

        function ColorizeSelection (color) {

            if (window.getSelection) {  // all browsers, except IE before version 9
                var selectionRange = window.getSelection ();

                if (selectionRange.isCollapsed) {
                    alert ("Please select some content first!");
                }
                else {
                    var range = selectionRange.getRangeAt (0);
                        // store the start and end points of the current selection, because the selection will be removed
                    var startContainer = range.startContainer;
                    var startOffset = range.startOffset;
                    var endContainer = range.endContainer;
                    var endOffset = range.endOffset;
                        // because of Opera, we need to remove the selection before modifying the DOM hierarchy
                    selectionRange.removeAllRanges ();

                    if (startContainer == endContainer) {
                        ColorizeNodeFromTo (startContainer, color, startOffset, endOffset);
                    }
                    else {
                        if (startContainer.firstChild) {
                            var startLeaf = startContainer.childNodes[startOffset];
                        }
                        else {
                            var startLeaf = GetNextLeaf (startContainer);
                            ColorizeLeafFromTo (startContainer, color, startOffset, -1);
                        }

                        if (endContainer.firstChild) {
                            if (endOffset > 0) {
                                var endLeaf = endContainer.childNodes[endOffset - 1];
                            }
                            else {
                                var endLeaf = GetPreviousLeaf (endContainer);
                            }
                        }
                        else {
                            var endLeaf = GetPreviousLeaf (endContainer);
                            ColorizeLeafFromTo (endContainer, color, 0, endOffset);
                        }

                        while (startLeaf) {
                            var nextLeaf = GetNextLeaf (startLeaf);
                            ColorizeLeaf (startLeaf, color);
                            if (startLeaf == endLeaf) {
                                break;
                            }
                            startLeaf = nextLeaf;
                        }
                    }
                }
            }
            else {
                    // Internet Explorer before version 9
                alert ("Your browser does not support this example!");
            }
        }
    </script>
</head>
<body>
   用设置红色和蓝色的按钮,分别来操作文档中的文字哦!<br /><br />
    <button onclick="ColorizeSelection ('#FF0000');">设置红色</button>
    <button onclick="ColorizeSelection ('#0000FF');">设置蓝色</button>
    <br />
    <div>haorooms我是来呗选择的啊!</div>
    <div><b>我是来被加粗的啊!</b></div>
</body>

上面就是javascript execCommand 作为复文本框,是不是很强大啊!

手机网站表层div滑动,导致底层body滑动(touchmove的阻止)

案例描述

body很长,可以滑动,body头部有一个模拟下拉的选择框。下拉选择有滚动轴,如下图。

![enter image description here](http://www.haorooms.com/uploads/images/slide.png)

我给body一个overflow:hidden和高度是没有用的。手机网站上背景还是可以滑动,然后我给body一个touchmove的preventdefault()阻止事件,body滑动组织了,PC上面是可以了,但是手机上面滑动div还是会导致底部body的滑动,我给div 一个阻止冒泡的事件stopPropagation(),手机网站上面还是不可以。

关于preventdefault和stopPropagation,后面有时间会讲解其区别。

解决方案

我经过反复测试,返现滚动轴滚到底部的时候,会触发body的滑动,那么我就在事件滚到底部的时候对表层的div做一个touchmove的阻止。到达滚动轴底部,向下滑动,阻止事件,向上滑动,开启事件。为此就要判断touchmove的方向了。

$("body").on("touchstart", function(e) {
    e.preventDefault();
    startX = e.originalEvent.changedTouches[0].pageX,
    startY = e.originalEvent.changedTouches[0].pageY;
});
$("body").on("touchmove", function(e) {
    e.preventDefault();
    moveEndX = e.originalEvent.changedTouches[0].pageX,
    moveEndY = e.originalEvent.changedTouches[0].pageY,
    X = moveEndX - startX,
    Y = moveEndY - startY;

    if ( Math.abs(X) > Math.abs(Y) && X > 0 ) {
        alert("left 2 right");
    }
    else if ( Math.abs(X) > Math.abs(Y) && X < 0 ) {
        alert("right 2 left");
    }
    else if ( Math.abs(Y) > Math.abs(X) && Y > 0) {
        alert("top 2 bottom");
    }
    else if ( Math.abs(Y) > Math.abs(X) && Y < 0 ) {
        alert("bottom 2 top");
    }
    else{
        alert("just touch");
    }
});

上面的方法是判断touchmove的滑动方向。

      $('#haorooms底层背景').bind("touchmove", function (e) {
            e.preventDefault();
        });
        $(".滚动的父亲").bind("touchstart", function (events) {
            startY = events.originalEvent.changedTouches[0].pageY;
        });
        $(".滚动的父亲 ul").bind("touchmove", function (e) {
            var ulheight = $(this).height();
            var scrollTop = $(this).scrollTop();
            var scrollheight = $(this)[0].scrollHeight;
            if (ulheight + scrollTop + 20 >= scrollheight) { //滚到底部20px左右
                $(".滚动的父亲").bind("touchmove", function (event) {
                    moveEndY = event.originalEvent.changedTouches[0].pageY,
                            theY = moveEndY - startY;
                    if (theY > 0) { //用上面的abs()更加准确!
                        $(".滚动的父亲").unbind("touchmove");
                    }
                    if (theY < 0) {
                        event.preventDefault();
                    }
                })
            }
            if (scrollTop < 20) {//滚到顶部20px左右
                $(".滚动的父亲").bind("touchmove", function (event) {
                    moveEndY = event.originalEvent.changedTouches[0].pageY,
                            theY = moveEndY - startY;
                    if (theY > 0) {
                        event.preventDefault();
                    }
                    if (theY < 0) {
                        $(".滚动的父亲").unbind("touchmove");
                    }
                })
            }
        });

以上方法基本上能够阻止body的滚动,但是,有时候还是会有问题,期待更好的解决方案!

jquery对表格行列的操作-jquery动态增加表格行或者列

jquery对表格的操作是老生常谈的问题。最近项目中用到了,今天在这里分享一下!

效果大体如下:

enter image description here

分享一下代码吧!

html

<div class="table-responsive" id="Bk_table" style="display:none;">
                    <table class="table table-hover table-bordered">
                        <thead>
                            <tr>
                                <th>
                        <div class="out"> 
                            <b>板块</b> 
                            <em>维度</em> 
                        </div>
                        </th>
                        </tr>
                        </thead>
                        <tbody>
                        </tbody>
                    </table>
 </div>

js操作如下:

 deleteLie: function () { //删除一列
            var index = $(this).parent().index();
            for (var i = 0; i < $(".table tr").length; i++) {
                $($(".table tr")[i]).children().eq(index).remove();
            }
            if ($(".table tr").length == 1 && $(".table tr").eq(0).children().length == 1) {
                $("#Bk_table").hide();
                $(".blankShow").show();
            }
        },
        deleteOneline: function () { //删除一行
            $(this).parent().parent().remove();
            if ($(".table tr").length == 1 && $(".table tr").eq(0).children().length == 1) {
                $("#Bk_table").hide();
                $(".blankShow").show();
            }
        },
        addOneBk: function () { //增加一列
            if ($("#Bk_table").is(":hidden")) {
                $("#Bk_table").show();
            }
            if ($(".blankShow").is(":visible")) {
                $(".blankShow").hide();
            }
            var firstLie = ' <th class="hovershow"><span class="font_zs" style="display:none">中弘西岸3</span>' +
                    '<input type="text" class="form-control getPrevalue" placeholder="填写板块名称" />' +
                    '<a class="glyphicon glyphicon-remove bkdelete delete_lie"></a></th>';
            $(".table>thead>tr").eq(0).append(firstLie);
            var otherLie = '<td><input type="text" class="form-control" value="" placeholder="1-5之间数字" ' +
                    'onkeyup="if(isNaN(value)||parseFloat(value)>5||parseFloat(value)<1)execCommand(\'undo\')"' +
                    'onafterpaste="if(isNaN(value)||parseFloat(value)>5||parseFloat(value)<1)execCommand(\'undo\')" /></td>';
            $(".table>tbody>tr").append(otherLie);
        },
        addWd: function () { //增加一行
            if ($("#Bk_table").is(":hidden")) {
                $("#Bk_table").show();
            }
            if ($(".blankShow").is(":visible")) {
                $(".blankShow").hide();
            }
            var Wdhtml_1 = '<tr>' +
                    ' <th scope="row" class="hovershow">' +
                    '<span class="font_zs t1" style="display:none">维度三</span>' +
                    '<input type="text" class="form-control getPrevalue" placeholder="填写维度名称"  />' +
                    '<a class="glyphicon glyphicon-remove bkdelete deleteoneline"></a>' +
                    '</th>';
            var Wdhtml_2 = "";
            var LieLength = $(".table>thead>tr").children().length - 1;
            if (LieLength > 0) {
                for (var i = 0; i < LieLength; i++) {
                    Wdhtml_2 = Wdhtml_2 + ' <td><input type="text" class="form-control" value="" placeholder="1-5之间数字" onkeyup="if(isNaN(value)||parseFloat(value)>5||parseFloat(value)<1)execCommand(\'undo\')" onafterpaste="if(isNaN(value)||parseFloat(value)>5||parseFloat(value)<1)execCommand(\'undo\')" /></td>';
                }
            }
            var Wdhtml_3 = '</tr>';
            var allWd = Wdhtml_1 + Wdhtml_2 + Wdhtml_3;
            $(".table>tbody").append(allWd);
}

以上贴出的是部分代码,有问题可以交流!

PHP防止XSS注入

我们在做网站的时候,经常有input提交,通常前端对input中的内容不做判断,只做不为空等简单的操作。但是,有的input中会提交一些javascript或者html,会给网站造成一定的危害。为此,防止XSS注入的任务交给了后端,后端防止XSS注入函数如下:

function RemoveXSS($val) { 
   // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed 
   // this prevents some character re-spacing such as <java\0script> 
   // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs 
   $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val); 

   // straight replacements, the user should never need these since they're normal characters 
   // this prevents like <IMG SRC=@avascript:alert('XSS')> 
   $search = 'abcdefghijklmnopqrstuvwxyz';
   $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
   $search .= '1234567890!@#$%^&*()';
   $search .= '~`";:?+/={}[]-_|\'\\';
   for ($i = 0; $i < strlen($search); $i++) {
      // ;? matches the ;, which is optional
      // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars

      // @ @ search for the hex values
      $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
      // @ @ 0{0,7} matches '0' zero to seven times 
      $val = preg_replace('/(�{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
   }

   // now the only remaining whitespace attacks are \t, \n, and \r
   $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
   $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
   $ra = array_merge($ra1, $ra2);

   $found = true; // keep replacing as long as the previous round replaced something
   while ($found == true) {
      $val_before = $val;
      for ($i = 0; $i < sizeof($ra); $i++) {
         $pattern = '/';
         for ($j = 0; $j < strlen($ra[$i]); $j++) {
            if ($j > 0) {
               $pattern .= '('; 
               $pattern .= '(&#[xX]0{0,8}([9ab]);)';
               $pattern .= '|'; 
               $pattern .= '|(�{0,8}([9|10|13]);)';
               $pattern .= ')*';
            }
            $pattern .= $ra[$i][$j];
         }
         $pattern .= '/i'; 
         $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag 
         $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags 
         if ($val_before == $val) { 
            // no replacements were made, so exit the loop 
            $found = false; 
         } 
      } 
   } 
   return $val; 
}

将前端传来的数据,调用这个函数,过滤一下就可以了。此函数来源于网络,但是已经经过项目测试,可以运行,可以过滤XSS注入!要是有什么不对或者有什么意见和建议,请留言~~

SASS入门教程及用法指南

作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家都知道,js中可以自定义变量,css仅仅是一个标记语言,不是编程语言,因此不可以自定义变量,不可以引用等等。面对这些问题,我们现在来引进一个SASS,简单的说,他是css的升级版,他可以自定义变量,可以有if语句,还可以嵌套等等,很神奇吧!那下面我们就来介绍这个神奇的SASS!

![enter image description here](http://www.haorooms.com/uploads/images/sass.png)

一、什么是SASS

SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。
本文总结了SASS的主要用法。我的目标是,有了这篇文章,日常的一般使用就不需要去看官方文档了。

二、安装和使用

2.1 安装

SASS是Ruby语言写的,但是两者的语法没有关系。不懂Ruby,照样使用。只是必须先安装Ruby,然后再安装SASS。

window下面安装ruby

https://www.ruby-lang.org/en/documentation/installation/#homebrew

下载rubyinstaller.exe 安装就可以了。

mac下面安装ruby

$ curl -L https://get.rvm.io | bash -s stable

$ source ~/.rvm/scripts/rvm

 $ rvm -v

$ rvm install 2.0.0

$ gem -v

可以看到版本号,说明安装成功!

假定你已经安装好了Ruby,接着在命令行输入下面的命令:

gem install sass

然后,就可以使用了。

若gem命令出行错误,请看 http://www.haorooms.com/post/gem_not_use

2.2 使用

SASS文件就是普通的文本文件,里面可以直接使用CSS语法。文件后缀名是.scss,意思为Sassy CSS。
下面的命令,可以在屏幕上显示.scss文件转化的css代码。(假设文件名为test。)

sass test.scss

如果要将显示结果保存成文件,后面再跟一个.css文件名。

sass test.scss test.css

SASS提供四个编译风格的选项:

* nested:嵌套缩进的css代码,它是默认值。
* expanded:没有缩进的、扩展的css代码。
* compact:简洁格式的css代码。
* compressed:压缩后的css代码。

生产环境当中,一般使用最后一个选项。

sass --style compressed test.sass test.css

你也可以让SASS监听某个文件或目录,一旦源文件有变动,就自动生成编译后的版本。

// watch a file
sass --watch input.scss:output.css
// watch a directory
sass --watch app/sass:public/stylesheets

SASS的官方网站,提供了一个在线转换器。你可以在那里,试运行下面的各种例子。

三、基本用法

3.1 变量

SASS允许使用变量,所有变量以$开头。

$blue : #1875e7; 
div {
   color : $blue;
}

如果变量需要镶嵌在字符串之中,就必须需要写在#{}之中。

$side : left;
 .rounded {
     border-#{$side}-radius: 5px;
     }

3.2 计算功能

SASS允许在代码中使用算式:

body {
    margin: (14px/2);
    top: 50px + 100px;
    right: $var * 10%;
  }

3.3 嵌套

SASS允许选择器嵌套。比如,下面的CSS代码:

  div h1 {
    color : red;
  }
//可以写成:
  div {
    hi {
      color:red;
    }
  }
//属性也可以嵌套,比如border-color属性,可以写成:
  p {
    border: {
      color: red;
    }
  }

//注意,border后面必须加上冒号。

在嵌套的代码块内,可以使用$引用父元素。比如a:hover伪类,可以写成:

a {
    &:hover { color: #ffb3ff; }
  }

3.4 注释

SASS共有两种注释风格。

标准的CSS注释 /* comment */ ,会保留到编译后的文件。

单行注释 // comment,只保留在SASS源文件中,编译后被省略。

在/*后面加一个感叹号,表示这是"重要注释"。即使是压缩模式编译,也会保留这行注释,通常可以用于声明版权信息。

/*! 
    重要注释!
*/

四、代码的重用

4.1 继承

SASS允许一个选择器,继承另一个选择器。比如,现有class1:

.class1 {
    border: 1px solid #ddd;
  }

class2要继承class1,就要使用@extend命令:

.class2 {
    @extend .class1;
    font-size:120%;
  }

4.2 Mixin

Mixin有点像C语言的宏(macro),是可以重用的代码块。

使用@mixin命令,定义一个代码块。

@mixin left {
    float: left;
    margin-left: 10px;
  }

使用@include命令,调用这个mixin。

div {
    @include left;
  }

mixin的强大之处,在于可以指定参数和缺省值。

@mixin left($value: 10px) {
    float: left;
    margin-right: $value;
  }

使用的时候,根据需要加入参数:

div {
    @include left(20px);
  }

下面是一个mixin的实例,用来生成浏览器前缀。

@mixin rounded($vert, $horz, $radius: 10px) {
    border-#{$vert}-#{$horz}-radius: $radius;
    -moz-border-radius-#{$vert}#{$horz}: $radius;
    -webkit-border-#{$vert}-#{$horz}-radius: $radius;
  }

使用的时候,可以像下面这样调用:

#navbar li { @include rounded(top, left); }
#footer { @include rounded(top, left, 5px); }

4.3 颜色函数

SASS提供了一些内置的颜色函数,以便生成系列颜色。

lighten(#cc3, 10%) // #d6d65c
darken(#cc3, 10%) // #a3a329
grayscale(#cc3) // #808080
complement(#cc3) // #33c

4.4 插入文件

@import命令,用来插入外部文件。

@import "path/filename.scss";

如果插入的是.css文件,则等同于css的import命令。

@import "foo.css";

五、高级用法

5.1 条件语句

@if可以用来判断:

p {
        @if 1 + 1 == 2 { border: 1px solid; }
        @if 5 < 3 { border: 2px dotted; }
      }

配套的还有@else命令:

@if lightness($color) > 30% {
        background-color: #000;
      } @else {
        background-color: #fff;
      }

5.2 循环语句

SASS支持for循环:

@for $i from 1 to 10 {
    .border-#{$i} {
      border: #{$i}px solid blue;
    }
  }

也支持while循环:

$i: 6;
  @while $i > 0 {
    .item-#{$i} { width: 2em * $i; }
    $i: $i - 2;
  }

each命令,作用与for类似:

@each $member in a, b, c, d {
    .#{$member} {
      background-image: url("/image/#{$member}.jpg");
    }
  }

5.3 自定义函数

SASS允许用户编写自己的函数。

@function double($n) {
    @return $n * 2;
  }
  #sidebar {
    width: double(5px);
  }

看我上面的文章,大家有什么感受呢?你可以按照描述,安装好sass,然后边看边自己用记事本把上面的案例敲一遍,运行一遍,经过这一遍学习之后,相信您已经SASS入门了,将来的SASS进阶,请看后面的文章了!

要是您有什么问题,可以留言交流!

手机网站的几点注意

对于手机网站建设,总结了如下几点注意:

1、 安卓浏览器看背景图片,有些设备会模糊。

用同等比例的图片在PC机上很清楚,但是手机上很模糊,原因是什么呢?

经过研究,是devicePixelRatio作怪,因为手机分辨率太小,如果按照分辨率来显示网页,这样字会非常小,所以苹果当初就把iPhone 4的960_640分辨率,在网页里只显示了480_320,这样devicePixelRatio=2。现在android比较乱,有1.5的,有2的也有3的。

想让图片在手机里显示更为清晰,必须使用2x的背景图来代替img标签(一般情况都是用2倍)。例如一个div的宽高是100_100,背景图必须得200_200,然后background-size:contain;,这样显示出来的图片就比较清晰了。

代码可以如下:

    background:url(../images/icon/all.png) no-repeat center center;
  -webkit-background-size:50px 50px;
  background-size: 50px 50px;display:inline-block; width:100%; height:50px;   

或者指定 background-size:contain;都可以,大家试试!

2、图片加载

若您遇到图片加载很慢的问题,对这种情况,手机开发一般用canvas方法加载:

具体的canvas API 参见:http://javascript.ruanyifeng.com/htmlapi/canvas.html

下面举例说明一个canvas的例子:

<li><canvas></canvas></li>  

s动态加载图片和li
总共举例17张图片!

var total=17;  
var zWin=$(window);  
var render=function(){  
   var padding=2;  
   var winWidth=zWin.width();  
   var picWidth=Math.floor((winWidth-padding*3)/4);  
   var tmpl ='';  
   for (var i=1;i<=totla;i++){  
    var p=padding;  
    var imgSrc='img/'+i+'.jpg';  
    if(i%4==1){  
      p=0;  
    }  
    tmpl +='<li style="width:'+picWidth+'px;height:'+picWidth+'px;padding-left:'+p+'px;padding-top:'+padding+'px;"><canvas id="cvs_'+i+'"></canvas></li>';  
    var imageObj = new Image();  
    imageObj.index = i;  
    imageObj.onload = function(){  
       var cvs =$('#cvs_'+this.index)[0].getContext('2d');  
       cvs.width = this.width;  
       cvs.height=this.height;  
       cvs.drawImage(this,0,0);  
    }  
    imageObj.src=imgSrc;  
   }  

}  
render(); 

3、假如手机网站不用兼容IE浏览器,一般我们会使用zeptojs。zeptojs内置Touch events方法,具体可以看http://zeptojs.com/#Touch events

看了一下zeptio新版的API,已经支持IE10以上浏览器,对zeptojs可以选择使用!

4、防止手机中网页放大和缩小,这点是最基本的,最为手机网站开发者来说应该都知道的,就是设置meta中的viewport

还有就是,有些手机网站我们看到如下声明:

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">

设置了DTD的方式是XHTML的写法,假如我们页面运用的是html5,可以不用设置DTD,直接声明。

使用viewport使页面禁止缩放。 通常把user-scalable设置为0来关闭用户对页面视图缩放的行为。

<meta name="viewport" content="user-scalable=0" />

但是为了更好的兼容,我们会使用完整的viewport设置。

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />

当然,user-scalable=0,有的人也写成user-scalable=no,都可以的。

5、apple-mobile-web-app-capable

apple-mobile-web-app-capable是设置Web应用是否以全屏模式运行。

语法:

<meta name="apple-mobile-web-app-capable" content="yes">

说明:

如果content设置为yes,Web应用会以全屏模式运行,反之,则不会。content的默认值是no,表示正常显示。你可以通过只读属性window.navigator.standalone来确定网页是否以全屏模式显示。

兼容性:

iOS 2.1 +

6、format-detection

format-detection 启动或禁用自动识别页面中的电话号码。

语法:

<meta name="format-detection" content="telephone=no">

说明:

默认情况下,设备会自动识别任何可能是电话号码的字符串。设置telephone=no可以禁用这项功能。

兼容性

iOS 1.0 +

7、html5调用安卓或者ios的拨号功能

html5提供了自动调用拨号的标签,只要在a标签的href中添加tel:就可以了。

如下:

 <a href="tel:4008106999,1034">400-810-6999 转 1034</a>

拨打手机直接如下

 <a href="tel:15677776767">点击拨打15677776767</a>

8、html5GPS定位功能

具体请看:http://www.haorooms.com/post/html5_GPS_getCurrentPosition

9、上下拉动滚动条时卡顿、慢

 body {
    -webkit-overflow-scrolling: touch;
    overflow-scrolling: touch;
}

Android3+和iOS5+支持CSS3的新属性为overflow-scrolling

10、禁止复制、选中文本

Element {
    -webkit-user-select: none;
    -moz-user-select: none;
    -khtml-user-select: none;
     user-select: none;
}

解决移动设备可选中页面文本(视产品需要而定)

11、长时间按住页面出现闪退

element {
    -webkit-touch-callout: none;
}

12、iphone及ipad下输入框默认内阴影

Element{
    -webkit-appearance: none; 
}

13、ios和android下触摸元素时出现半透明灰色遮罩

Element {
    -webkit-tap-highlight-color:rgba(255,255,255,0)
}

设置alpha值为0就可以去除半透明灰色遮罩,备注:transparent的属性值在android下无效。

后面一篇文章有详细介绍,地址:http://www.haorooms.com/post/phone_web_ysk

14、active兼容处理

<body ontouchstart="">

15、动画定义3D启用硬件加速

Element {
    -webkit-transform:translate3d(0, 0, 0)
    transform: translate3d(0, 0, 0);
}

注意:3D变形会消耗更多的内存与功耗

16、Retina屏的1px边框

Element{
    border-width: thin;
}

17、webkit mask 兼容处理

某些低端手机不支持css3 mask,可以选择性的降级处理。

比如可以使用js判断来引用不同class:

if( 'WebkitMask' in document.documentElement.style){
    alert('支持mask');
} else {
    alert('不支持mask');
}

18、旋转屏幕时,字体大小调整的问题

html, body, form, fieldset, p, div, h1, h2, h3, h4, h5, h6 {
    -webkit-text-size-adjust:100%;
}

19、transition闪屏

/*设置内嵌的元素在 3D 空间如何呈现:保留3D */

-webkit-transform-style: preserve-3d;

/* 设置进行转换的元素的背面在面对用户时是否可见:隐藏 */

-webkit-backface-visibility:hidden;

20、圆角bug

某些Android手机圆角失效

background-clip: padding-box;

21、顶部状态栏背景色

<meta name="apple-mobile-web-app-status-bar-style" content="black" />

说明:

除非你先使用apple-mobile-web-app-capable指定全屏模式,否则这个meta标签不会起任何作用。

如果content设置为default,则状态栏正常显示。如果设置为blank,则状态栏会有一个黑色的背景。如果设置为blank-translucent,则状态栏显示为黑色半透明。如果设置为default或blank,则页面显示在状态栏的下方,即状态栏占据上方部分,页面占据下方部分,二者没有遮挡对方或被遮挡。如果设置为blank-translucent,则页面会充满屏幕,其中页面顶部会被状态栏遮盖住(会覆盖页面20px高度,而iphone4和itouch4的Retina屏幕为40px)。默认值是default。

兼容性
iOS 2.1 +

22、设置缓存

<meta http-equiv="Cache-Control" content="no-cache" />

手机页面通常在第一次加载后会进行缓存,然后每次刷新会使用缓存而不是去重新向服务器发送请求。如果不希望使用缓存可以设置no-cache。

23、桌面图标

<link rel="apple-touch-icon" href="touch-icon-iphone.png" />
<link rel="apple-touch-icon" sizes="76x76" href="touch-icon-ipad.png" />
<link rel="apple-touch-icon" sizes="120x120" href="touch-icon-iphone-retina.png" />
<link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad-retina.png" />

iOS下针对不同设备定义不同的桌面图标。如果不定义则以当前屏幕截图作为图标。

24、启动画面

<link rel="apple-touch-startup-image" href="start.png"/>

iOS下页面启动加载时显示的画面图片,避免加载时的白屏。

可以通过madia来指定不同的大小:

<!--iPhone-->
<link href="apple-touch-startup-image-320x460.png" media="(device-width: 320px)" rel="apple-touch-startup-image" />

<!-- iPhone Retina -->
<link href="apple-touch-startup-image-640x920.png" media="(device-width: 320px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />

<!-- iPhone 5 -->
<link rel="apple-touch-startup-image" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)" href="apple-touch-startup-image-640x1096.png">

<!-- iPad portrait -->
<link href="apple-touch-startup-image-768x1004.png" media="(device-width: 768px) and (orientation: portrait)" rel="apple-touch-startup-image" />

<!-- iPad landscape -->
<link href="apple-touch-startup-image-748x1024.png" media="(device-width: 768px) and (orientation: landscape)" rel="apple-touch-startup-image" />

<!-- iPad Retina portrait -->
<link href="apple-touch-startup-image-1536x2008.png" media="(device-width: 1536px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />

<!-- iPad Retina landscape -->
<link href="apple-touch-startup-image-1496x2048.png"media="(device-width: 1536px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)"rel="apple-touch-startup-image" />

25、浏览器私有及其它meta

以下属性在项目中没有应用过,可以写一个demo测试以下!

QQ浏览器私有

全屏模式

<meta name="x5-fullscreen" content="true">

强制竖屏

<meta name="x5-orientation" content="portrait">

强制横屏

<meta name="x5-orientation" content="landscape">

应用模式

<meta name="x5-page-mode" content="app">

UC浏览器私有

全屏模式

<meta name="full-screen" content="yes">

强制竖屏

<meta name="screen-orientation" content="portrait">

强制横屏

<meta name="screen-orientation" content="landscape">

应用模式

<meta name="browsermode" content="application">

其它

针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓

<meta name="HandheldFriendly" content="true">

微软的老式浏览器

<meta name="MobileOptimized" content="320">

windows phone 点击无高光

<meta name="msapplication-tap-highlight" content="no">

26、 IOS中input键盘事件keyup、keydown、keypress支持不是很好

问题是这样的,用input search做模糊搜索的时候,在键盘里面输入关键词,会通过ajax后台查询,然后返回数据,然后再对返回的数据进行关键词标红。用input监听键盘keyup事件,在安卓手机浏览器中是可以的,但是在ios手机浏览器中变红很慢,用输入法输入之后,并未立刻相应keyup事件,只有在通过删除之后才能相应!

解决办法:

可以用html5的oninput事件去代替keyup

<input type="text" id="testInput">
<script type="text/javascript">
    document.getElementById('testInput').addEventListener('input', function(e){
        var value = e.target.value;
    });
</script>

然后就达到类似keyup的效果!

暂时整理以上几点有关手机网站建设更多的注意事项,后面会陆续补充!

js复文本函数及常用的js验证

我们在做后台发布文章或者输入的时候,通常用复文本框,我前面文章总结了前端常用的复文本,但是,我们在前台用户输入的时候,通常限制复文本的输入,当然,你也可以允许用户用复文本,不过要在提交的时候或者后台对提交的内容进行过滤或者审核。

下面我们来总结一下前端js复文本常用的函数。

下面是斜体、下划线、居中、粗体,插入图片、创建工具条的函数

//斜体
function italicize(obj) {
if (document.selection && document.selection.type == "Text") {
   AddTxt="[i]"+text+"[/i]";
   AddText(obj,AddTxt);
} else {
   txt=prompt('文字将变斜体','文字');
   if (txt!=null) {
    AddTxt="[i]"+txt+"[/i]";
    AddText(obj,AddTxt);
   }
}
}
//下划线
function underline(obj) {
    if (document.selection && document.selection.type == "Text") {
   AddTxt="[u]"+text+"[/u]";
   AddText(obj,AddTxt);
} else {
   txt=prompt('下划线文字','文字');
   if (txt!=null) {
    AddTxt="[u]"+txt+"[/u]";
    AddText(obj,AddTxt);
   }
}
}
//居中
function center(obj) {
   if (document.selection && document.selection.type == "Text") {
   AddTxt="[align=center]"+text+"[/align]";
   AddText(obj,AddTxt);
} else {
   txt2=prompt('对齐样式\n输入 ’center’ 表示居中, ’left’ 表示左对齐, ’right’ 表示右对齐.',"center");
   while ((txt2!="") && (txt2!="center") && (txt2!="left") && (txt2!="right") && (txt2!=null)) {
    txt2=prompt('错误!\n类型只能输入 ’center’ 、 ’left’ 或者 ’right’.',"");
   }
   txt=prompt('要对齐的文本','文字');
   if (txt!=null) {
    AddTxt="[align="+txt2+"]"+txt+"[/align]";
    AddText(obj,AddTxt);
   }
}
}
//粗体
function bold(obj) {
if (document.selection && document.selection.type == "Text") {
   AddTxt="[b]"+text+"[/b]";
   AddText(obj,AddTxt);
} else {
   txt=prompt('文字将被变粗.','文字');
   if (txt!=null) {
    AddTxt="[b]"+txt+"[/b]";
    AddText(obj,AddTxt);
   }
}
}
//插入图片
function insimg(obj){
if (document.selection && document.selection.type == "Text") {
   AddTxt="[img]"+text+"[/img]";
   AddText(obj,AddTxt);
} else {
   txt=prompt('请输入图片完整URL地址:','http://');
   if (txt!=null) {
    AddTxt="[img]"+txt+"[/img]";
    AddText(obj,AddTxt);
   }
}
}
//插入URL
function insurl(obj,is){
if (document.selection && document.selection.type == "Text") {
   AddTxt="[url]"+text+"[/url]";
   AddText(obj,AddTxt);
} else {
   if(is==1){
    txt=prompt('请输入本站站内URL:','http://www.haorooms.com');
   }else{
    txt=prompt('请输入URL地址:','http://');
   }
   if (txt!=null) {
    AddTxt="[url]"+txt+"[/url]";
    AddText(obj,AddTxt);
   }
}
}
//创建工具条
function ToolBars(areaname,isimg,insite){
document.write("<a onClick=\"bold(document.getElementByIdx_xx('"+areaname+"'))\"><img title=\"粗体\" src=\"/image/post1.gif\" ></a>");
document.write(" <a onClick=\"italicize(document.getElementByIdx_xx('"+areaname+"'))\"><img title=\"斜体\" src=\"/image/post2.gif\" ></a>");
document.write(" <a onClick=\"underline(document.getElementByIdx_xx('"+areaname+"'))\"><img title=\"下划线\" src=\"/image/post3.gif\" ></a>");
document.write(" <a onClick=\"center(document.getElementByIdx_xx('"+areaname+"'))\"><img title=\"居中\" src=\"/image/post4.gif\" ></a>");
if(isimg){
   document.write(" <a onClick=\"insimg(document.getElementByIdx_xx('"+areaname+"'))\"><img title=\"插入图片\" src=\"/image/post5.gif\" ></a>");
}
if(insite){
   document.write(" <a onClick=\"insurl(document.getElementByIdx_xx('"+areaname+"'),0)\"><img title=\"插入url\" src=\"/image/post6.gif\" ></a>");
}else{
   document.write(" <a onClick=\"insurl(document.getElementByIdx_xx('"+areaname+"'),1)\"><img title=\"插入url\" src=\"/image/post6.gif\" ></a>");
}
document.write("<br /><a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=001]')\"><img src=\"/image/em/001.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=002]')\"><img src=\"/image/em/002.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=003]')\"><img src=\"/image/em/003.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=004]')\"><img src=\"/image/em/004.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=005]')\"><img src=\"/image/em/005.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=006]')\"><img src=\"/image/em/006.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=007]')\"><img src=\"/image/em/007.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=008]')\"><img src=\"/image/em/008.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=009]')\"><img src=\"/image/em/009.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=010]')\"><img src=\"/image/em/010.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=011]')\"><img src=\"/image/em/011.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=012]')\"><img src=\"/image/em/012.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=013]')\"><img src=\"/image/em/013.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=014]')\"><img src=\"/image/em/014.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=015]')\"><img src=\"/image/em/015.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=016]')\"><img src=\"/image/em/016.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=017]')\"><img src=\"/image/em/017.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=018]')\"><img src=\"/image/em/018.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=019]')\"><img src=\"/image/em/019.gif\"></a>");
document.write("<a onclick=\"AddText(document.getElementByIdx_xx('"+areaname+"'),'[em=020]')\"><img src=\"/image/em/020.gif\"></a>");
}

注意,用js的selection 对象 来监听文字是否选中。用法如上:document.selection

下面来看下复文本的一些验证操作:

//输入数字拦截
function InputNum(event){
//48~57 主键盘数字 96~105 小键盘数字 144 小键盘数字切换键 110 小键盘 点
if((event.keyCode>=48 && event.keyCode<=57) || (event.keyCode>=96 && event.keyCode<=105) || event.keyCode==144 || event.keyCode==110 || event.keyCode==190 || event.keyCode==8 || event.keyCode==46 || event.keyCode==39 || event.keyCode==37 || event.keyCode==13){
   return true;
}else{
   return false;
}
}
//检查输入是否为FLOAT数字
function CheckFloat(obj,pre){
thisfloat=parseFloat(obj.value);
if(isNaN(thisfloat)){
   obj.value="0";
}else{
   obj.value=Math.ceil(thisfloat*Math.pow(10,pre))/Math.pow(10,pre);
}
}
//检查file表单项是否为图片
function CheckImg(ImgFile){
if(ImgFile){
   if(ImgFile.lastIndexOf(".")>=0){
    ext=ImgFile.substr(ImgFile.lastIndexOf(".")).toLowerCase();
    exts="|.jpeg|.jpg|.gif|.png|";
    if(exts.indexOf("|"+ext+"|")<0){
     return false;
    }else{
     return true;
    }
   }else{
    return false;
   }
}else{
   return true;
}
}
//检查图片文件的尺寸
function CheckSize(ImgFile,MaxSize){
if(ImgFile){
   var img=null;
   if(img)img.removeNode(true);
   img=document.createElement_x("img");
   img.style.position="absolute";
   img.style.display="none";
   if(window.attachEvent){
    img.attachEvent("onreadystatechange",orsc);
    img.attachEvent("onerror",oe);
    document.body.insertAdjacentElement("beforeend",img);
   }else{
    img.addEventListener("onreadystatechange",orsc,false);
    img.addEventListener("onerror",oe,false);
    document.body.appendChild(img)
   }

   img.src=ImgFile;
}
function oe(){
   alert("指定图片载入失败");
}
function orsc(){
   if(img.readyState!="complete"){return false;};
   if(parseInt(img.fileSize)>MaxSize*1000){
    alert("当前图片文件 "+img.fileSize/1000+" K\n超过最大限制"+MaxSize+"K\n\n强制提交将可能造成超时失败");
   }
}
}
//获得字节长度
function ByteLength(string){
return string.replace(/[^\x00-\xff]/g,"00").length;
}

除此之外,我们为了让用户避免第二次输入用户名和密码,经常是用cookie来进行用户名的临时存储下面是js读取cookie和写入cookie的操作

//读取Cookie
function getCookie(Name){
var re=new RegExp(Name+"=[^;]+", "i");
if (document.cookie.match(re)){
   return document.cookie.match(re)[0].split("=")[1];
}else{
   return "";
}  
}
//写入COOKIE
function setCookie(name, value){
document.cookie = name+"="+value
}

为了让用户操作爽一些,还有一些快捷键操作,对ctrl+enter的操作等等,如下:

//实现Ctrl+Enter 提交的效果
function QuickPost(event){
if((event.ctrlKey && event.keyCode == 13)||(event.altKey && event.keyCode == 83)){
   event.srcElement.form.submit();
}
}

还有一些简单的js验证和收藏:

//判断用户名是否符合要求
function usernamecheck(string){
if((string.length<4)||(string.length>20)){return false;}
var re;
re=new RegExp("^[a-z|A-Z|0-9][a-z|A-Z|0-9|-]+$");
return re.test(string);
}
//判断密码是否符合规范
function passwordcheck(string){
var re;
re=new RegExp("^[0-9]+$");
return !re.test(string);
}
//收藏指定页面
function addBookmark(title,url) {
if (window.sidebar) {
   window.sidebar.addPanel(title, url,"");
} else if( document.all ) {
   window.external.AddFavorite( url, title);
} else if( window.opera && window.print ) {
   return true;
}
}
//判断字符中是否包含有URL地址
function urlcheck(string){
var re;
re=new RegExp("http://");
return re.test(string.toLowerCase());
}
//判断电子邮箱是否符合规范
function emailcheck(string){
var re;
re=new RegExp("^[\\w-_\\.]+@([a-z|0-9|-]+\\.)+[a-z]{2,5}$");
return re.test(string.toLowerCase());
}
//向某个对象发送一个Click事件
function toclick(objid){
var obj=document.getElementByIdx_xx(objid);
if(document.all){
   obj.fireEvent("onclick");
}else{
     var e=document.createEvent('MouseEvent');
     e.initEvent('click',false,false);
     obj.dispatchEvent(e);
}
}

//判断字符串的字节数
function strlen(string){
       var str="";
       str=string;
       str=str.replace(/[^\x00-\xff]/g,"**");
       return str.length;
}

//一个可以实现key value 功能的对象
function GSArrays(){
   this.keys=new Array();
   this.values=new Array();
   this.set=function (key,value){
    for(i=0;i<this.keys.length;i++){
     if(this.keys[i]==key){
      this.values[i]=value;
      return true;
     }
    }
    this.keys[this.keys.length]=key;
    this.values[this.values.length]=value;
   }
   this.get=function (key){
    for(i=0;i<this.keys.length;i++){
     if(this.keys[i]==key){
      return this.values[i];
     }
    }
   }
}
//将固定格式的Ajax传递数据拆分成 key value 的对象
function SplitToArray(str){
   var strs,tems;
   var MyGs=new GSArrays();
   strs=str.split("\n");
   var arrays=new Array();
   for(i=0;i<strs.length;i++){
    tems=strs[i].split("\t");
    if(tems.length==1){
     MyGs.set(tems[0],"");
    }else if(tems.length==2){
     MyGs.set(tems[0],tems[1]);
    }
   }
   return MyGs;
}

var text = "";
//选框
function getActiveText(selectedtext) {
   text = (document.all) ? document.selection.createRange().text : document.getSelection();
   if (selectedtext.createTextRange) {
     selectedtext.caretPos = document.selection.createRange().duplicate();
   }
return true;
}
//插入文本
function AddText(obj,NewCode)
{
if (obj.createTextRange && obj.caretPos)
{
   var caretPos = obj.caretPos;
   caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? NewCode + ' ' : NewCode;
}
else
{
   obj.value+=NewCode
}
setfocus(obj);
}
//获得焦点
function setfocus(obj)
{
obj.focus();
}

上面就是我对js复文本函数及常用的js验证做的总结,朋友们有什么问题的话,可以相互交流!欢迎留言!

webapp开发相关jquery手势事件之jGestures

手机开发中,除了我们平时用的jquery基本事件之外,还有很多手势,今天介绍一款jquery手势插件jGestures,地址是:http://jgestures.codeplex.com/

这个插件的强大之处在于它可以监听以下事件'pinch'(缩放手势), 'rotate'(旋转手势), 'swipe'(滑动手势), 'tap'(轻触) 以及 'orientationchange'(改变设备方向)。等等,有了这个插件,手机web开发就更加方便了。

事件简介

orientationchange
代表设备顺时针或者逆时针旋转.此事件可以被设备触发,可能使用的是重力传感器.

pinch
缩放手势(两个手指在屏幕上的相对运动)

rotate
旋转手势(两个手指顺时针或者逆时针旋转)

swipemove
在正在滑动时触发(在设备屏幕上移动手指,比如:拖动)

swipeone
单点滑动手势,滑动完成后触发(一个手指在屏幕上移动)

swipetwo
两点滑动(两个手指在屏幕上方向一致的滑动)

swipethree
三点滑动(三个手指在屏幕上方向一致的滑动)

swipefour
四点滑动(四个手指在屏幕上方向一致的滑动)

swipeup
向上滑动,在严格的向上滑动手势完成后触发

swiperightup
向右上角滑动,在向右且向上的滑动手势完成后触发

swiperight
向右滑动,在严格的向右滑动手势完成后触发

swiperightdown
向右下角滑动,在向右且向下的滑动手势完成后触发

swipedown
向下滑动,在严格的向下滑动手势完成后触发

swipeleftdown
向左下角滑动,在向左且向下的滑动手势完成后触发

swipeleft
向左滑动,在严格的向左滑动手势完成后触发

swipeleftup
向左上角滑动,在向左且向上的滑动手势完成后触发

tapone
在单个手指轻点的手势后触发

taptwo
在两个手指一起轻点的手势后触发

tapthree
在三个手指一起轻点的手势后触发

pinchopen
撑开手势,当两个手指撑大并离开设备时触发.

pinchclose
捏紧手势,当两个手指捏紧并离开设备时触发.

rotatecw
两个手指顺时针旋转并且离开屏幕时触发(two fingers rotating clockwise)

rotateccw
两个手指逆时针旋转并且离开屏幕时触发 (two fingers rotating counterclockwise)

shake
当检测到设备正在摇晃时触发

shakefrontback
当检测到摇晃动作,且可以被解读为前后移动之时触发.

shakeleftright
当检测到摇晃动作,且可以被解读为左右移动之时触发.

shakeupdown
当检测到摇晃动作,且可以被解读为上下移动之时触发.

关于swipe,我上一篇文章已经介绍过了,http://www.haorooms.com/post/jquery_scroll_upanddown

当页面有滚动条的时候,swipe的up,down,left,right可能会不触发!事件会被滚动事件覆盖掉!

事件用法

<script>
jQuery(document).ready(function () {
             jQuery(window).bind('shakeupdown',function(event_,data_){
                alert('shake: '+ data_.description)
            })
    })
</script>

官方案例如下:

 <script>
function log(event_, obj) {
// ignore bubbled handlers
//      if ( obj.originalEvent.currentTarget !== obj.originalEvent.target ) { return; }
    obj.originalEvent.preventDefault();
    jQuery('#logger')
        .find('li')
            .slice(1,jQuery('#logger').find('li').size()-8)
                .animate({'opacity':'0', 'height':'0'},function(){jQuery(this).remove()})
            .end()
        .end()
        .append('<li><b>'+jQuery(obj.originalEvent.currentTarget).attr('id')+'</b>: '+obj.description+ ' : '+obj.type +'</li>')

}

function manipulate(event_, obj) {
// ignore bubbled handlers
//      if ( obj.originalEvent.currentTarget !== obj.originalEvent.target ) { return; }
    event_.preventDefault();
    obj.originalEvent.preventDefault();
    log(event_, obj)

    var _a = obj.description.split(':');

    jQuery(obj.originalEvent.currentTarget).css('zIndex','1000')
    switch(_a[0]) {
        case 'pinch':
            //jQuery(obj.originalEvent.currentTarget).css('-webkit-transform','scale('+ ( obj.direction * obj.delta[0].moved ) +')');
        break;
        case  'rotate':
            //jQuery(obj.originalEvent.currentTarget).css('-webkit-transform','rotate('+ (  obj.delta[0].moved ) +'deg)');
        break;

        case  'swipemove':
            if(_a[1] != 1) {break;}
            jQuery(obj.originalEvent.currentTarget).css('-webkit-transition','');
            jQuery(obj.originalEvent.currentTarget).css('left', parseInt(jQuery(obj.originalEvent.currentTarget).css('left')) + obj.delta[0].startX );
            jQuery(obj.originalEvent.currentTarget).css('top', parseInt(jQuery(obj.originalEvent.currentTarget).css('top')) + obj.delta[0].startY );
//          jQuery(obj.originalEvent.currentTarget).data('moving',true)
        break;

        case 'swipe' :
//          if(_a[1] != 1 || jQuery(obj.originalEvent.currentTarget).data('moving') } {break;}
            jQuery(obj.originalEvent.currentTarget).css('-webkit-transition','all 1s ease-out').css('left', parseInt(jQuery(obj.originalEvent.currentTarget).css('left')) + obj.delta[0].startX );
            jQuery(obj.originalEvent.currentTarget).css('-webkit-transition','all 1s ease-out').css('top', parseInt(jQuery(obj.originalEvent.currentTarget).css('top')) + obj.delta[0].startY );
        break;
      }
      jQuery(obj.originalEvent.currentTarget).css('zIndex','')
}

    function BlockMove(event) {
        // Tell Safari not to move the window.
        event.preventDefault() ;
    }


jQuery(document).ready(function() {


    jQuery('#tap').bind('tapone',log);
    jQuery('#tap').bind('taptwo',log);
    jQuery('#tap').bind('tapthree',log);
    jQuery('#tap').bind('tapfour',log);


    jQuery('#swipe').bind('swipeone',log);
    jQuery('#swipe').bind('swipetwo',log);
    jQuery('#swipe').bind('swipethree',log);
    jQuery('#swipe').bind('swipefour',log);

    jQuery('#swipe').bind('swipeup',log);
    jQuery('#swipe').bind('swiperightup',log);
    jQuery('#swipe').bind('swiperight',log);
    jQuery('#swipe').bind('swiperightdown',log);

    jQuery('#swipe').bind('swipedown',log);
    jQuery('#swipe').bind('swipeleftdown',log);
    jQuery('#swipe').bind('swipeleft',log);
    jQuery('#swipe').bind('swipeleftup',log);

    jQuery('#change').bind('pinchopen',manipulate);
    jQuery('#change').bind('pinchclose',manipulate);
    jQuery('#change').bind('rotatecw',manipulate);
    jQuery('#change').bind('rotateccw',manipulate);
    jQuery('#change').bind('swipeone',manipulate);

    jQuery('#livechange').bind('swipeone',manipulate);
    jQuery('#livechange').bind('swipemove',manipulate);
    jQuery('#livechange').bind('pinch',manipulate);
    jQuery('#livechange').bind('rotate',manipulate);

})
 </script>

Centos6.5安装配置mongodb

mongodb官网上下载最新版本的mongodb,按照官网上的说明进行安装:

首先运行如下命令:

curl -O http://downloads.mongodb.org/linux/mongodb-linux-x86_64-2.6.3.tgz

其次,运用tar 进行解压缩,按照如下命令

tar -zxvf mongodb-linux-x86_64-2.6.3.tgz

第三,新建mongodb文件夹,把解压了的mongodb-linux-x86_64-2.6.3复制到mongodb下面。

按照如下命令

mkdir -p mongodb
cp -R -n mongodb-linux-x86_64-2.6.3/ mongodb

第四,更改环境变量,在路径 /etc/下面,找到bashrc文件

export PATH=<mongodb-install-directory>:$PATH

替换成你的mongodb路径就可以了

第五,创建mongodb的dbdata的路径

mkdir -p  /usr/local/mongo/data  
mongod --dbpath /usr/local/mongo/data

第六,进入mongo的文件夹,运行mongo命令,启动mongo就可以了。

上面的安装方法比较简单,但是有个问题,就是mongo启动必须同时制定data,也就是要运行mongod --dbpath /usr/local/mongo/data,比较繁琐,下面介绍一种一劳永逸的安装办法,把mongo的启动添加到服务当中。但是必须制定安装的版本,本例以mongodb-src-r1.8.1.tar.gz
具体可以参考博客:http://www.9958.pw/post/centos_mongodb
注:每个版本必须和博客中一致,下面对rin博客的这篇文章做一下转载!

下载所需软件(下载到/usr/local/src目录)

#wget http://downloads.mongodb.org/src/mongodb-src-r1.8.1.tar.gz
#wget http://ftp.mozilla.org/pub/mozilla.org/js/js-1.7.0.tar.gz
#wget http://sourceforge.net/projects/pcre/files/pcre/8.12/pcre-8.12.tar.bz2

安装 python

(注:scons必须是2.0.1的,具体下载地址是http://prdownloads.sourceforge.net/scons/scons-2.0.1.tar.gz):

#yum install -y python-devel  
安装scons: 下载scons(http://www.scons.org/download.php)
tar zxf scons-2.0.1.tar.gz
cd scons-2.0.1
python setup.py install

安装spidermonkey库,

下载支持c的js api库 js-1.7.0.tar.gz(http://ftp.mozilla.org/pub/mozilla.org/js/)

yum install -y boost boost-devel

tar zxvf js-1.7.0.tar.gz
cd js/src/
export CFLAGS="-DJS_C_STRINGS_ARE_UTF8"
make -f Makefile.ref
JS_DIST=/usr gmake -f Makefile.ref export
cd ../.. 

安装pcre

tar zxf pcre-8.12.tar.gz
cd pcre-8.12
./configure --enable-utf8 --enable-unicode-properties
make && make install
cd ..

安装MongoDB

tar zxf mongodb-src-r1.8.1.tar.gz
 cd mongodb-src-r1.8.1
scons all   // scons可能出现找不到pcre库的现象(修改/etc/ld.so.conf也无用,是scons自身的问题),这时需要打开mongodb-src-r1.8.0下的SConstruct,查找【 linux2"== os.sys.platform:】,在LIBPATH后面添加上pcrecpp库的安装路径,在LIBS后添加上pcrecpp库名,再重新scons all即可(操作:vim SConstruct;原来:env.Append( LIBPATH=["/usr/lib64" , "/lib64" ] ) ;修改后env.Append( LIBPATH=["/usr/lib64" , "/lib64" ,"/usr/local/pcre/lib"]);  接下来在env.Append( LIBS=["pthread"] )后面添加 env.Append( LIBS=["libpcrecpp"] )  )
scons --prefix=/usr/local/mongo install
如果需要安装lib和head,使用如下方式安装
scons --prefix=/usr/local/mongo --full install

创建配置文件

mkdir -p /usr/local/mongo/etc /usr/local/mongo/data /usr/local/mongo/log/ /usr/local/mongo/repair
vim  /usr/local/mongo/etc/mongo.conf
在mongo.conf中添加下面的内容
dbpath = /usr/local/mongo/data
logpath = /usr/local/mongo/mongodb.log
repairpath = /usr/local/mongo/repair
pidfilepath = /usr/local/mongo/mongodb.pid
directoryperdb = true
logappend = true
noauth = true
port = 27017
maxConns = 1024
fork = true
rest = true
quota = true
quotaFiles = 1024
nssize = 16
启动mongodb

ln -s /usr/local/mongo/bin/mongod /usr/bin/mongod
mongod -f /usr/local/mongo/etc/mongo.conf

看看是不是启动起来了,但是使用这种方式管理mongodb服务器很不明智,我们完善一下:

mkdir -p /usr/local/mongo/srv
vim /usr/local/mongo/srv/mongodb-start

添加下面的内容

#!/bin/sh
mongod -f /usr/local/mongo/etc/mongo.conf

vim /usr/local/mongo/srv/mongodb-stop

添加下面的内容

#!/bin/bash
pid=`ps -o pid,command ax | grep mongod | awk '!/awk/ && !/grep/ {print $1}'`;
if [ "${pid}" != "" ]; then
    kill -2 ${pid};
fi

添加执行权限

chmod a+x /usr/local/mongo/srv/mongodb-start
chmod a+x /usr/local/mongo/srv/mongodb-stop
vim /etc/rc.d/init.d/mongodb

添加下面的内容

#! /bin/sh
#
# mongodb – this script starts and stops the mongodb daemon
#
# chkconfig: - 85 15
# description: MongoDB is a non-relational database storage system.
# processname: mongodb
# config: /usr/local/mongo/etc/mongo.conf
# pidfile: /usr/local/mongo/mongodb.pid
PATH=/usr/local/mongo/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAME=mongodb
test -x $DAEMON || exit 0
set -e
case "$1" in
  start)
        echo -n "Starting MongoDB... "
        /usr/local/mongo/srv/mongodb-start
        ;;
  stop)
        echo -n "Stopping MongoDB... "
        /usr/local/mongo/srv/mongodb-stop
        ;;
      *)
            N=/etc/init.d/$NAME
            echo "Usage: $N {start|stop}" >&2
            exit 1
            ;;
    esac
    exit 0

添加服务

chmod a+x /etc/rc.d/init.d/mongodb
chkconfig --add mongodb
chkconfig --level 345 mongodb on
/etc/rc.d/init.d/mongodb start

javascript时间戳函数-时间戳总结

javascript时间戳经常用到,现在总结一下。

一、时间戳函数

<script>   
function getLocalTime(nS) {   
   return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/,' ');   
}   
alert(getLocalTime(1293072805));   
</script> 

也可以用如下,想取几位就几位,注意,空格也算!

<script>   
function getLocalTime(nS) {   
    return new Date(parseInt(nS) * 1000).toLocaleString().substr(0,14)}   
alert(getLocalTime(1293072805));   
</script>   

如果想弹出:2014-08-20 10:00:00这个格式的也好办

<script>   
function getLocalTime(nS) {   
   return new Date(parseInt(nS) * 1000).toLocaleString().replace(/年|月/g, "-").replace(/日/g, " ");    
}   
alert(getLocalTime(1177824835));   
</script>

另外,也可以这么写:

function   formatDate(now)   {   
          var   year=now.getYear();   
          var   month=now.getMonth()+1;   
          var   date=now.getDate();   
          var   hour=now.getHours();   
          var   minute=now.getMinutes();   
          var   second=now.getSeconds();   
          return   year+"-"+month+"-"+date+"   "+hour+":"+minute+":"+second;   
          }   

          var   d=new   Date(1230999938);   
          alert(formatDate(d));

二、知识普及

1、当前系统区域设置格式(toLocaleDateString和toLocaleTimeString)

例子:(new Date()).toLocaleDateString() + " " + (new Date()).toLocaleTimeString() 
结果: 2008年1月29日 16:13:11 

2.普通字符串(toDateString和toTimeString)

例子: (new Date()).toDateString() + " " + (new Date()).toTimeString() 
结果:Tue Jan 29 2008 16:13:11 UTC+0800 

3.格林威治标准时间(toGMTString)

例子: (new Date()).toGMTString() 
结果:Tue, 29 Jan 2008 08:13:11 UTC 

4.全球标准时间(toUTCString)

例子: (new Date()).toUTCString() 
结果:Tue, 29 Jan 2008 08:13:11 UTC 

5.Date对象字符串(toString)

例子: (new Date()).toString() 
结果:Tue Jan 29 16:13:11 UTC+0800 2008

Date对象构造函数 
Date对象具有多种构造函数。 
new Date() 
new Date(milliseconds) 
new Date(datestring) 
new Date(year, month) 
new Date(year, month, day) 
new Date(year, month, day, hours) 
new Date(year, month, day, hours, minutes) 
new Date(year, month, day, hours, minutes, seconds) 
new Date(year, month, day, hours, minutes, seconds, microseconds) 
Date对象构造函数参数说明 
milliseconds - 距离JavaScript内部定义的起始时间1970年1月1日的毫秒数 
datestring - 字符串代表的日期与时间。此字符串可以使用Date.parse()转换 
year - 四位数的年份,如果取值为0-99,则在其之上加上1900 
month - 0(代表一月)-11(代表十二月)之间的月份 
day - 1-31之间的日期 
hours - 0(代表午夜)-23之间的小时数 
minutes - 0-59之间的分钟数 
seconds - 0-59之间的秒数 
microseconds - 0-999之间的毫秒数 
Date对象返回值 
如果没有任何参数,将返回当前日期 
如果参数为一个数字,将数字视为毫秒值,转换为日期 
如果参数为一个字符串,将字符串视为日期的字符串表示,转换为日期 
还可以使用六个构造函数精确定义,并返回时间 
示例 
var d1 = new Date(); 
document.write(d1.toString()); 
var d2 = new Date("2009-08-08 12:12:12); 
document.write(d2.toString()); 
var d3 = new Date(2009, 8, 8); 
document.write(d3.toString()); 
Date做为JavaScript的一种内置对象,必须使用new的方式创建。 
Date对象在JavaScript内部的表示方式是,距1970年1月1日午夜(GMT时间)的毫秒数(时间戳),我们在这里也把Date的内部表示形式称为时间戳。可以使用getTime()将Date对象转换为Date的时间戳,方法setTime()可以把Date的时间戳转换为Date的标准形式。 
Date函数使用语法 
date.方法名(参数1,参数2,...); 
Date.方法名(); 
date代表一个日期对象的实例,Date代表日期对象,date.方法名调用的为对象的成员函数 
Date.方法名调用的为对象的静态函数 
示例 
var d=new Date(); 
var d2=Date.UTC(); 
JavaScript_Date函数按功能分类 
日期获取类函数 
Date() 函数 -- Date对象的构造函数 
getDate() 函数 -- 返回date对象中的月份中的天数(1-31) 
getDay()函数 -- 返回date对象中的星期中的天数(0-6) 
getFullYear() 函数 -- 返回date对象中的四位数年份 
getHours()函数 -- 返回date对象中的小时数(0-23) 
getMilliseconds() 函数 -- 返回date对象中的毫秒数(0-999) 
getMinutes() 函数 -- 返回date对象中的分钟数(0-59) 
getMonth() 函数 -- 返回date对象中的月份数(0-11) 
getSeconds() 函数 -- 返回date对象中的秒数(0-59) 
getTime() 函数 -- 返回date对象的时间戳表示法(毫秒表示) 
getTimezoneOffset() 函数 -- 返回本地时间与用UTC表示当前日期的时间差,以分钟为单位 
getUTCDate() 函数 -- 返回date对象中用世界标准时间(UTC)表示的月份中的一天(1-31) 
getUTCDay() 函数 -- 返回date对象中用世界标准时间(UTC)表示的周中的一天(0-6) 
getUTCFullYear() 函数 -- 返回date对象中用世界标准时间(UTC)表示的四位年份 
getUTCHours() 函数 -- 返回date对象中用世界标准时间(UTC)表示的小时数(0-23) 
getUTCMilliseconds() 函数 -- 返回date对象中用世界标准时间(UTC)表示的毫秒数(0-999) 
getUTCMinutes() 函数 -- 返回date对象中用世界标准时间(UTC)表示的分钟数(0-59) 
getUTCMonth() 函数 -- 返回date对象中用世界标准时间(UTC)表示的月份数(0-11) 
getUTCSeconds() 函数 -- 返回date对象中用世界标准时间(UTC)表示的秒数(0-59) 
getYear() 函数 -- 返回date对象的年份(真实年份减去1900) 
Date.UTC()函数 -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳) 
日期设置类函数 
setDate() 函数 -- 设置date对象中月份的一天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setFullYear() 函数 -- 设置date对象中的年份,月份和天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setHours() 函数 -- 设置date对象的小时,分钟,秒和毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setMilliseconds() 函数 -- 设置date对象的毫秒数,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setMinutes() 函数 -- 设置date对象的分钟,秒,毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setMonth() 函数 -- 设置date对象中月份,天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setSeconds() 函数 -- 设置date对象中月份的一天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setTime() 函数 -- 使用毫秒数设置date对象,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCDate() 函数 -- 设置date对象中用世界标准时间(UTC)表示的月份的一天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCFullYear() 函数 -- 设置date对象中用世界标准时间(UTC)表示的年份,月份和天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCHours() 函数 --- 设置date对象中用世界标准时间(UTC)表示的小时,分钟,秒和毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCMilliseconds() 函数 -- 设置date对象中用世界标准时间(UTC)表示的毫秒数,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCMinutes() 函数 -- 设置date对象中用世界标准时间(UTC)表示的分钟,秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCMonth() 函数 -- 设置date对象中用世界标准时间(UTC)表示的月份,天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCSeconds() 函数 -- 设置date对象中用世界标准时间(UTC)表示的秒,毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setYear() 函数 -- 设置date对象的年份(真实年份减去1900) 
日期打印类函数 
toDateString() 函数 -- 返回date对象的日期部分的字符串表示 
toGMTString() 函数 -- 返回date对象的格林威治时间(GMT)的字符串表示 
toLocaleDateString函数 -- 返回date对象的日期部分的本地化字符串 
toLocaleTimeString函数 -- 返回date对象的时间部分的本地化字符串 
toTimeString()函数 -- 返回date对象的时间部分的字符串 
toUTCString函数 -- 返回date对象的世界标准时间(UTC)的字符串表示 
日期解析类函数 
Date.parse() 函数 -- 解析一个日期的字符串,并返回该日期距1970年1月1日午夜之间的毫秒数(时间戳) 
JavaScript_Date函数按照字母分类 
Date() 函数 -- Date对象的构造函数 
getDate() 函数 -- 返回date对象中的月份中的天数(1-31) 
getDay()函数 -- 返回date对象中的星期中的天数(0-6) 
getFullYear() 函数 -- 返回date对象中的四位数年份 
getHours()函数 -- 返回date对象中的小时数(0-23) 
getMilliseconds() 函数 -- 返回date对象中的毫秒数(0-999) 
getMinutes() 函数 -- 返回date对象中的分钟数(0-59) 
getMonth() 函数 -- 返回date对象中的月份数(0-11) 
getSeconds() 函数 -- 返回date对象中的秒数(0-59) 
getTime() 函数 -- 返回date对象的时间戳表示法(毫秒表示) 
getTimezoneOffset() 函数 -- 返回本地时间与用UTC表示当前日期的时间差,以分钟为单位 
getUTCDate() 函数 -- 返回date对象中用世界标准时间(UTC)表示的月份中的一天(1-31) 
getUTCDay() 函数 -- 返回date对象中用世界标准时间(UTC)表示的周中的一天(0-6) 
getUTCFullYear() 函数 -- 返回date对象中用世界标准时间(UTC)表示的四位年份 
getUTCHours() 函数 -- 返回date对象中用世界标准时间(UTC)表示的小时数(0-23) 
getUTCMilliseconds() 函数 -- 返回date对象中用世界标准时间(UTC)表示的毫秒数(0-999) 
getUTCMinutes() 函数 -- 返回date对象中用世界标准时间(UTC)表示的分钟数(0-59) 
getUTCMonth() 函数 -- 返回date对象中用世界标准时间(UTC)表示的月份数(0-11) 
getUTCSeconds() 函数 -- 返回date对象中用世界标准时间(UTC)表示的秒数(0-59) 
getYear() 函数 -- 返回date对象的年份(真实年份减去1900) 
Date.parse() 函数 -- 解析一个日期的字符串,并返回该日期距1970年1月1日午夜之间的毫秒数(时间戳) 
setDate() 函数 -- 设置date对象中月份的一天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setFullYear() 函数 -- 设置date对象中的年份,月份和天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setHours() 函数 -- 设置date对象的小时,分钟,秒和毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setMilliseconds() 函数 -- 设置date对象的毫秒数,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setMinutes() 函数 -- 设置date对象的分钟,秒,毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setMonth() 函数 -- 设置date对象中月份,天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setSeconds() 函数 -- 设置date对象中月份的一天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setTime() 函数 -- 使用毫秒数设置date对象,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCDate() 函数 -- 设置date对象中用世界标准时间(UTC)表示的月份的一天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCFullYear() 函数 -- 设置date对象中用世界标准时间(UTC)表示的年份,月份和天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCHours() 函数 --- 设置date对象中用世界标准时间(UTC)表示的小时,分钟,秒和毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCMilliseconds() 函数 -- 设置date对象中用世界标准时间(UTC)表示的毫秒数,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCMinutes() 函数 -- 设置date对象中用世界标准时间(UTC)表示的分钟,秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCMonth() 函数 -- 设置date对象中用世界标准时间(UTC)表示的月份,天,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setUTCSeconds() 函数 -- 设置date对象中用世界标准时间(UTC)表示的秒,毫秒,并返回date对象距1970年1月1日午夜之间的毫秒数(时间戳) 
setYear() 函数 -- 设置date对象的年份(真实年份减去1900) 
toDateString() 函数 -- 返回date对象的日期部分的字符串表示 
toGMTString() 函数 -- 返回date对象的格林威治时间(GMT)的字符串表示 
toLocaleDateString函数 -- 返回date对象的日期部分的本地化字符串 
toLocaleTimeString函数 -- 返回date对象的时间部分的本地化字符串 
toTimeString()函数 -- 返回date对象的时间部分的字符串 
toUTCString函数 -- 返回date对象的世界标准时间(UTC)的字符串表示 
Date.UTC()函数 -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳)

三、Javascript的时间戳和php的时间戳转换

js的时间戳通常是13位,php的时间戳是10位,转换函数如下:

var nowtime = (new Date).getTime();/*当前时间戳*/   
/*转换时间,计算差值*/   
function comptime(beginTime,endTime){   
    var secondNum = parseInt((endTime-beginTime*1000)/1000);//计算时间戳差值      

    if(secondNum>=0&&secondNum<60){   
        return secondNum+'秒前';   
    }   
    else if (secondNum>=60&&secondNum<3600){   
        var nTime=parseInt(secondNum/60);   
        return nTime+'分钟前';   
    }   
    else if (secondNum>=3600&&secondNum<3600*24){   
        var nTime=parseInt(secondNum/3600);   
        return nTime+'小时前';   
    }   
    else{   
        var nTime = parseInt(secondNum/86400);   
        return nTime+'天前';   
    }   
}   

t = comptime("1324362556",nowtime);//timestamp为PHP通过ajax回传的时间戳   

alert(t); 

iOS下的 Fixed + Input 调用键盘的时候fixed无效问题解决方案

做touchweb开发的时候,做头疼的是,电脑上面时候好的,有些手机上面也是好的,个别手机和浏览器出现问题,对于这些,只能慢慢调试,找问题。

今天说一下比较老的IOS的问题,那就是“iOS下的 Fixed + Input 调用键盘的时候fixed无效问题”。

案例如下

<body class="layout-fixed">
    <!-- fixed定位的头部 -->
    <header>

    </header>

    <!-- 可以滚动的区域 -->
    <main>
        <!-- 内容在这里... -->
    </main>

    <!-- fixed定位的底部 -->
    <footer>
        <input type="text" placeholder="Footer..."/>
        <button class="submit">提交</button>
    </footer>
</body>

对应的样式如下:

header, footer, main {
    display: block;
}

header {
    position: fixed;
    height: 50px;
    left: 0;
    right: 0;
    top: 0;
}

footer {
    position: fixed;
    height: 34px;
    left: 0;
    right: 0;
    bottom: 0;
}

main {
    margin-top: 50px;
    margin-bottom: 34px;
    height: 2000px
}

然后看起来就是下面这个样子。拖动页面时 header 和 footer 已经定位在了对应的位置,目测没问题了。

![enter image description here](http://www.haorooms.com/uploads/images/fixed.png)

但接下来问题就来了!如果底部输入框软键盘被唤起以后,再次滑动页面,就会看到如下图所示:

![enter image description here](http://www.haorooms.com/uploads/images/fixed_bug_1.png)

我们看到 fixed 定位好的元素跟随页面滚动了起来… fixed 属性失效了!

这是为什么呢?简单解释下: > 软键盘唤起后,页面的 fixed 元素将失效(即无法浮动,也可以理解为变成了 absolute 定位),所以当页面超过一屏且滚动时,失效的 fixed 元素就会跟随滚动了。

这便是 iOS 上 fixed 元素和输入框的 bug 。其中不仅限于 type=text 的输入框,凡是软键盘(比如时间日期选择、select 选择等等)被唤起,都会遇到同样地问题。

虽然 isScroll.js 可以很好的解决 fixed 定位滚动的问题,但是不在万不得已的情况下,我们尽量尝试一下不依赖第三方库的布局方案,以简化实现方式。这里抛砖引玉作为参考。

解决思路

既然在 iOS 下由于软键盘唤出后,页面 fixed 元素会失效,导致跟随页面一起滚动,那么假如——页面不会过长出现滚动,那么即便 fixed 元素失效,也无法跟随页面滚动,也就不会出现上面的问题了。

那么按照这个思路,如果使 fixed 元素的父级不出现滚动,而将原 body 滚动的区域域移到 main 内部,而 header 和 footer 的样式不变,代码如下:

<body class="layout-scroll-fixed">
    <!-- fixed定位的头部 -->
    <header>

    </header>

    <!-- 可以滚动的区域 -->
    <main>
        <div class="content">
        <!-- 内容在这里... -->
        </div>
    </main>

    <!-- fixed定位的底部 -->
    <footer>
        <input type="text" placeholder="Footer..."/>
        <button class="submit">提交</button>
    </footer>
</body>
header, footer, main {
    display: block;
}

header {
    position: fixed;
    height: 50px;
    left: 0;
    right: 0;
    top: 0;
}

footer {
    position: fixed;
    height: 34px;
    left: 0;
    right: 0;
    bottom: 0;
}

main {
/* main绝对定位,进行内部滚动 */
position: absolute;
top: 50px;
bottom: 34px;
/* 使之可以滚动 */
 overflow-y: scroll;
  /* 增加该属性,可以增加弹性,是滑动更加顺畅 */
  -webkit-overflow-scrolling: touch;   
}

main .content {
    height: 2000px;
}

另外,这里的 header 和 footer 使用的是 fixed 定位,如果考虑到更老一些的 iOS 系统不支持 fixed 元素,完全可以把 fixed 替换成 absolute 。测试后效果是一样的。

按照上面布局,就不会出现问题了!

PHP GD 生成图片验证码+session获取储存验证码

我们在做登录的时候,为了防止机器不停的刷和提交,有了登录验证码,相信大家都不陌生,验证码一般有数字和字母加干扰点和干扰线,或者图片验证码,或者汉字验证码。汉字验证码必须要有中文字体,否则不成功。图片验证码一般是事先定义好的图片,给出名称和值,进行验证。下面我们来写一个最常见的字母加数字验证码。

效果图如下:

![enter image description here](http://www.haorooms.com/uploads/images/yzm.jpg)

该验证码技术运用了PHP的CD技术,详细请看:http://www.php.net/manual/zh/book.image.php

后台图片代码如下:

<?php
session_start(); //启动session

$image = imagecreatetruecolor(100,30);//创建一个宽100,高度30的图片
$bgcolor=imagecolorallocate($image,255,255,255);//图片背景是白色
imagefill($image,0,0,$bgcolor);//图片填充白色
//随机数,下面的例子是只是数字的验证码
/**
for($i=0;$i<4;$i++){
  $fontsize=6;
  $fontcolor=imagecolorallocate($image,rand(0,120),rand(0,120),rand(0,120));
  $fontcontent=rand(0,9);
  $x=($i*100/4)+ rand(5,10);
  $y=rand(5,10);
  imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor);
}
**/
//随机数据,下面的例子是随机数据,包括字母和数字
$captch_code='';
for($i=0;$i<4;$i++){
  $fontsize=6;
  $fontcolor=imagecolorallocate($image,rand(0,120),rand(0,120),rand(0,120));
  $data='asdfdfglfg74erf21854hgfhgfhkg4ljkghjtrtywiqpoqpwepdfgvnjytyut12313345645667686797800';
  $fontcontent=substr($data,rand(0,strlen($data)),1);
  $captch_code.=$fontcontent;

  $x=($i*100/4)+ rand(5,10);
  $y=rand(5,10);
  imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor);
}
$_SESSION['authcode']=$captch_code;

//随机点,生成干扰点
for($i=0;$i<200;$i++){
  $pointcolor=imagecolorallocate($image,rand(50,120),rand(50,120),rand(50,120));
  imagesetpixel($image,rand(1,99),rand(1,99),$pointcolor);
}
//随机线,生成干扰线
for($i=0;$i<3;$i++){
  $linecolor=imagecolorallocate($image,rand(80,220),rand(80,220),rand(80,220));
  imageline($image,rand(1,99),rand(1,29),rand(1,99),rand(1,29),$linecolor);
}
header("content-type:image/png");
imagepng($image);

imagedestory($image);


?>

前台代码如下:

<?php
   if(isset($_REQUEST['autocode'])){
      session_start();
      if(strtolower($_POST['autocode']) == $_SESSION['authcode']){
       echo '正确';
      }else{
      echo'错误';
      }

   exit();
   }

?>
<!DOCTYPE html>
<html>
  <head>
   <meta chartset="utf-8">
  </head>
  <body>
     <form method="post"  action="form.php">
       <p>验证码图片:<img border="1" src="captcha.php?r="<?php echo rand();?> width="100" height="30"  /></p>

       <p>输入内容:<input type="text" name="autocode" value="" /></p>

    <p><input type="submit"  value="提交" style="padding:6px 20px;"/></p>


     </form>
  </body>


</html>

验证图片点击更换:

  <p>验证码图片:<img border="1" id="capthcha_img" onclick="this.src='captcha.php?r='+Math.random()" src="captcha.php?r="<?php echo rand();?> width="100" height="30"  /> <a href="javascript:void(0)" onclick="document.getElementById('capthcha_img').src='captcha.php?r='+Math.random()">换一个</a></p>

php导出excel日期出现41395问题解决

最近在做php excel导出的时候,不知道为什么,日期栏全都是41395,经过查证,原来是日期是一种凯撒日计数,具体什么是凯撒日计数,我也不是很清楚,你可以谷歌或者百度一下。要把我们运用的从1970年开始的日期运用函数GregorianToJD(),转换为凯撒日计数。哎。。看下面代码吧。

function exceltimtetophp($days,$time=false)  
{  
 if(is_numeric($days))  
 {  
  $jd = GregorianToJD(1, 1, 1970);  
  $gregorian = JDToGregorian($jd+intval($days)-25569);  
  $gregorian = strtotime($gregorian);  
  $gregorian = date("Y年m月d日",$gregorian);  
//  $myDate = explode('\\',$gregorian);  
//  $myDateStr = str_pad($myDate[2],4,'0', STR_PAD_LEFT)."-".str_pad($myDate[0],2,'0',STR_PAD_LEFT)."-".str_pad($myDate[1],2,'0', STR_PAD_LEFT).($time?"00:00:00":'\\');  
  return $gregorian;  
 }  
 return $time;  
}  

把41395的日期,调用这个函数就可以了。方法试过了,可以用的。

这个函数方法来源于网络,但是我经过调试以后,把没有用的2行注销掉,然后稍加改动,在我的代码中就可以用了。上面就是我的修改之后的代码,有不对的地方,大家可以留言,谢谢!

重新拎一遍js的正则表达式

前言

js的正则表达式是前端中比较重要的部分,加入你要去面试,正则的题目必不可少。我之前的这篇文章中提及过。具体可以看:http://www.haorooms.com/post/qianduan_mianshi

正则表达式规则

一、普通字符

字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。

举例:

表达式 "o",在匹配字符串 "haorooms"
时,匹配结果是:成功;匹配到的内容是:"o";匹配到的位置是:开始于2,结束于3。[注:o匹配一般只匹配第一个,假如要匹配所有的,那么表达式要加"/g",就可以找到全局所有的。]

二、简单的转义字符

一些不便书写的字符,采用在前面加 "/" 的方法。这些字符其实我们都已经熟知了。

表达式

可匹配

/r, /n

代表回车和换行符

/t

制表符

//

代表 "/" 本身

还有其他一些在后边章节中有特殊用处的标点符号,在前面加 "/" 后,就代表该符号本身。比如:^, $ 都有特殊意义,如果要想匹配字符串中 "^" 和 "$" 字符,则表达式就需要写成 "/^" 和 "/$"。

表达式

可匹配

/^

匹配 ^ 符号本身

/$

匹配 $ 符号本身

/.

匹配小数点(.)本身

举例1:表达式 "/$d",在匹配字符串 "haorooms$de"
时,匹配结果是:成功;匹配到的内容是:"$d";匹配到的位置是:开始于8,结束于10。

三、能够与 '多种字符' 匹配的表达式

正则表达式中的一些表示方法,可以匹配 '多种字符' 其中的任意一个字符。比如,表达式 "/d" 可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。

表达式

可匹配

/d

任意一个数字,0~9 中的任意一个

/w

任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个

/s

包括空格、制表符、换页符等空白字符的其中任意一个

.

小数点可以匹配除了换行符(/n)以外的任意一个字符

举例1:表达式 "/d/d",在匹配 "abc123"
时,匹配的结果是:成功;匹配到的内容是:"12";匹配到的位置是:开始于3,结束于5。

举例2:表达式 "a./d",在匹配 "aaa100"
时,匹配的结果是:成功;匹配到的内容是:"aa1";匹配到的位置是:开始于1,结束于4。

四、自定义能够匹配 '多种字符' 的表达式

使用方括号 [ ] 包含一系列字符,能够匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能够匹配其中字符之外的任意一个字符。同样的道理,虽然可以匹配其中任意一个,但是只能是一个,不是多个。

表达式

可匹配

[ab5@]

匹配 "a" 或 "b" 或 "5" 或 "@"

[^abc]

匹配 "a","b","c" 之外的任意一个字符

[f-k]

匹配 "f"~"k" 之间的任意一个字母

[^A-F0-3]

匹配 "A"~"F","0"~"3" 之外的任意一个字符

举例1:表达式 "[bcd][bcd]" 匹配 "abc123"
时,匹配的结果是:成功;匹配到的内容是:"bc";匹配到的位置是:开始于1,结束于3。

举例2:表达式 "[^abc]" 匹配 "abc123"
时,匹配的结果是:成功;匹配到的内容是:"1";匹配到的位置是:开始于3,结束于4。

五、修饰匹配次数的特殊符号

前面章节中讲到的表达式,无论是只能匹配一种字符的表达式,还是可以匹配多种字符其中任意一个的表达式,都只能匹配一次。如果使用表达式再加上修饰匹配次数的特殊符号,那么不用重复书写表达式就可以重复匹配。

使用方法是:"次数修饰"放在"被修饰的表达式"后边。比如:"[bcd][bcd]" 可以写成 "[bcd]{2}"。

表达式

作用

{n}

表达式重复n次,比如:"/w{2}" 相当于 "/w/w""a{5}" 相当于 "aaaaa"

{m,n}

表达式至少重复m次,最多重复n次,比如:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa"

{m,}

表达式至少重复m次,比如:"/w/d{2,}"可以匹配 "a12","_456","M12344"...

?

匹配表达式0次或者1次,相当于 {0,1},比如:"a[cd]?"可以匹配 "a","ac","ad"

+

表达式至少出现1次,相当于 {1,},比如:"a+b"可以匹配 "ab","aab","aaab"...

\*

表达式不出现或出现任意次,相当于 {0,},比如:"/^\*b"可以匹配 "b","^^^b"...


六、其他一些代表抽象意义的特殊符号

一些符号在表达式中代表抽象的特殊意义:

表达式

作用

^

与字符串开始的地方匹配,不匹配任何字符

$

与字符串结束的地方匹配,不匹配任何字符

/b

匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符

进一步的文字说明仍然比较抽象,因此,举例帮助大家理解。

**举例1:**表达式 "^aaa" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "^"
要求与字符串开始的地方匹配,因此,只有当 "aaa" 位于字符串的开头的时候,"^aaa" 才能匹配,比如:"aaa xxx xxx"。

**举例2:**表达式 "aaa$" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "$"
要求与字符串结束的地方匹配,因此,只有当 "aaa" 位于字符串的结尾的时候,"aaa$" 才能匹配,比如:"xxx xxx aaa"。

**举例3:**表达式 "./b." 在匹配 "@@@abc" 时,匹配结果是:成功;匹配到的内容是:"@A";匹配到的位置是:开始于2,结束于4。
进一步说明:"/b" 与 "^" 和 "$" 类似,本身不匹配任何字符,但是它要求它在匹配结果中所处位置的左右两边,其中一边是 "/w" 范围,另一边是 非"/w" 的范围。

**举例4:**表达式 "/bend/b" 在匹配 "weekend,endfor,end"
时,匹配结果是:成功;匹配到的内容是:"end";匹配到的位置是:开始于15,结束于18。

一些符号可以影响表达式内部的子表达式之间的关系:

表达式

作用

|

左右两边表达式之间 "或" 关系,匹配左边或者右边

( )

(1). 在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰
(2). 取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到

**举例5:**表达式 "Tom|Jack" 在匹配字符串 "I'm Tom, he is Jack" 时,匹配结果是:成功;匹配到的内容是:"Tom";匹配到的位置是:开始于4,结束于7。匹配下一个时,匹配结果是:成功;匹配到的内容是:"Jack";匹配到的位置时:开始于15,结束于19。

**举例6:*表达式 "(go/s)+" 在匹配 "Let's go go go!" 时,匹配结果是:成功;匹配到内容是:"go go go";匹配到的位置是:开始于6,结束于14。

**举例7:*表达式 "¥(/d+/.?/d)" 在匹配 "$10.9,¥20.5" 时,匹配的结果是:成功;匹配到的内容是:"¥20.5";匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:"20.5"。

正则表达式中的一些高级规则

一、 匹配次数中的贪婪与非贪婪

在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数,比如:"{m,n}", "{m,}", "?", "*", "+",具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配。比如,针对文本 "dxxxdxxxd",举例如下:

表达式

匹配结果

(d)(/w+)

"/w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"

(d)(/w+)(d)

"/w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "/w+" 也能够匹配上最后一个 "d",但是为了使整个表达式匹配成功,"/w+" 可以 "让出" 它本来能够匹配的最后一个 "d"

由此可见,"/w+" 在匹配的时候,总是尽可能多的匹配符合它规则的字符。虽然第二个举例中,它没有匹配最后一个 "d",但那也是为了让整个表达式能够匹配成功。同理,带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配,带 "?" 的表达式在可匹配可不匹配的时候,也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。

非贪婪模式:

在修饰匹配次数的特殊符号后再加上一个 "?" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式,也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。举例如下,针对文本 "dxxxdxxxd" 举例:

表达式

匹配结果

(d)(/w+?)

"/w+?" 将尽可能少的匹配第一个 "d" 之后的字符,结果是:"/w+?" 只匹配了一个 "x"

(d)(/w+?)(d)

为了让整个表达式匹配成功,"/w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配,从而使整个表达式匹配成功。因此,结果是:"/w+?" 匹配 "xxx"

更多的情况,举例如下:

举例1:表达式 "<td>(.*)</td>" 与字符串 "<td><p>aa</p></td> <td><p>bb</p></td>" 匹配时,匹配的结果是:成功;匹配到的内容是 "<td><p>aa</p></td> <td><p>bb</p></td>" 整个字符串, 表达式中的 "</td>" 将与字符串中最后一个 "</td>" 匹配。 

举例2:相比之下,表达式 "<td>(.*?)</td>" 匹配举例1中同样的字符串时,将只得到 "<td><p>aa</p></td>", 再次匹配下一个时,可以得到第二个 "<td><p>bb</p></td>"。

二、反向引用

表达式在匹配时,表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。这一点,在前面的举例中,已经多次展示了。在实际应用场合中,当用某种边界来查找,而所要获取的内容又不包含边界时,必须使用小括号来指定所要的范围。比如前面的 "(.*?)"。

其实,"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用,在匹配过程中也可以使用。表达式后边的部分,可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "/" 加上一个数字。"/1" 引用第1对括号内匹配到的字符串,"/2" 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 "(" 在前,那这一对就先排序号。

举例如下:

举例1:表达式 "('|")(.*?)(/1)" 在匹配 " 'Hello', "World" " 时,匹配结果是:成功;匹配到的内容是:" 'Hello' "。再次匹配下一个时,可以匹配到 " "World" "。

举例2:表达式 "(/w)/1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 时,匹配结果是:成功;匹配到的内容是 "ccccc"。再次匹配下一个时,将得到 999999999。这个表达式要求 "/w" 范围的字符至少重复5次,注意与 "/w{5,}" 之间的区别。

举例3:表达式 "<(/w+)/s*(/w+(=('|").*?/4)?/s*)*>.*?<//1>" 在匹配 "<td id='td1' style="bgcolor:white"></td>" 时,匹配结果是成功。如果 "<td>" 与 "</td>" 不配对,则会匹配失败;如果改成其他配对,也可以匹配成功。

三、预搜索,不匹配;反向预搜索,不匹配

前面的章节中,我讲到了几个代表抽象意义的特殊符号:"^","$","/b"。它们都有一个共同点,那就是:它们本身不匹配任何字符,只是对 "字符串的两头" 或者 "字符之间的缝隙" 附加了一个条件。理解到这个概念以后,本节将继续介绍另外一种对 "两头" 或者 "缝隙" 附加条件的,更加灵活的表示方法。

正向预搜索:"(?=xxxxx)","(?!xxxxx)"

格式:"(?=xxxxx)",在被匹配的字符串中,它对所处的 "缝隙" 或者 "两头" 附加的条件是:所在缝隙的右侧,必须能够匹配上 xxxxx 这部分的表达式。因为它只是在此作为这个缝隙上附加的条件,所以它并不影响后边的表达式去真正匹配这个缝隙之后的字符。这就类似 "/b",本身不匹配任何字符。"/b" 只是将所在缝隙之前、之后的字符取来进行了一下判断,不会影响后边的表达式来真正的匹配。

举例1:表达式 "Windows (?=NT|XP)" 在匹配 "Windows 98, Windows NT, Windows 2000" 时,将只匹配 "Windows NT" 中的 "Windows ",其他的 "Windows " 字样则不被匹配。

举例2:表达式 "(/w)((?=/1/1/1)(/1))+" 在匹配字符串 "aaa ffffff 999999999" 时,将可以匹配6个"f"的前4个,可以匹配9个"9"的前7个。这个表达式可以读解成:重复4次以上的字母数字,则匹配其剩下最后2位之前的部分。当然,这个表达式可以不这样写,在此的目的是作为演示之用。

格式:"(?!xxxxx)",所在缝隙的右侧,必须不能匹配 xxxxx 这部分表达式。

举例3:表达式 "((?!/bstop/b).)+" 在匹配 "fdjka ljfdl stop fjdsla fdj" 时,将从头一直匹配到 "stop" 之前的位置,如果字符串中没有 "stop",则匹配整个字符串。

举例4:表达式 "do(?!/w)" 在匹配字符串 "done, do, dog" 时,只能匹配 "do"。在本条举例中,"do" 后边使用 "(?!/w)" 和使用 "/b" 效果是一样的。

反向预搜索:"(?<=xxxxx)","(?<!xxxxx)"

这两种格式的概念和正向预搜索是类似的,反向预搜索要求的条件是:所在缝隙的 "左侧",两种格式分别要求必须能够匹配和必须不能够匹配指定表达式,而不是去判断右侧。与 "正向预搜索" 一样的是:它们都是对所在缝隙的一种附加条件,本身都不匹配任何字符。

举例5:表达式 "(?<=/d{4})/d+(?=/d{4})" 在匹配 "1234567890123456" 时,将匹配除了前4个数字和后4个数字之外的中间8个数字。由于 JScript.RegExp 不支持反向预搜索,因此,本条举例不能够进行演示。很多其他的引擎可以支持反向预搜索,比如:Java 1.4 以上的 java.util.regex 包,.NET 中System.Text.RegularExpressions 命名空间,以及本站推荐的最简单易用的 DEELX 正则引擎。

其他通用规则

还有一些在各个正则表达式引擎之间比较通用的规则,在前面的讲解过程中没有提到。

表达式中,可以使用 "/xXX" 和 "/uXXXX" 表示一个字符("X" 表示一个十六进制数)

形式

字符范围

/xXX

编号在 0 ~ 255 范围的字符,比如:空格可以使用 "/x20" 表示

/uXXXX

任何字符可以使用 "/u" 再加上其编号的4位十六进制数表示,比如:"/中"

在表达式 "/s","/d","/w","/b" 表示特殊意义的同时,对应的大写字母表示相反的意义

表达式

可匹配

/S

匹配所有非空白字符("/s" 可匹配各个空白字符)

/D

匹配所有的非数字字符

/W

匹配所有的字母、数字、下划线以外的字符

/B

匹配非单词边界,即左右两边都是 "/w" 范围或者左右两边都不是 "/w" 范围时的字符缝隙

在表达式中有特殊意义,需要添加 "/" 才能匹配该字符本身的字符汇总

字符

说明

^

匹配输入字符串的开始位置。要匹配 "^" 字符本身,请使用 "/^"

$

匹配输入字符串的结尾位置。要匹配 "$" 字符本身,请使用 "/$"

( )

标记一个子表达式的开始和结束位置。要匹配小括号,请使用 "/(" 和 "/)"

[ ]

用来自定义能够匹配 '多种字符' 的表达式。要匹配中括号,请使用 "/[" 和 "/]"

{ }

修饰匹配次数的符号。要匹配大括号,请使用 "/{" 和 "/}"

.

匹配除了换行符(/n)以外的任意一个字符。要匹配小数点本身,请使用 "/."

?

修饰匹配次数为 0 次或 1 次。要匹配 "?" 字符本身,请使用 "/?"

+

修饰匹配次数为至少 1 次。要匹配 "+" 字符本身,请使用 "/+"

\*

修饰匹配次数为 0 次或任意次。要匹配 "\*" 字符本身,请使用 "/*"

|

左右两边表达式之间 "或" 关系。匹配 "|" 本身,请使用 "/|"

定义正则表达式

定义正则表达式有两种形式,一种是普通方式,一种是构造函数方式。

普通方式:var reg=/表达式/附加参数

表达式:一个字符串,代表了某种规则,其中可以使用某些特殊字符,来代表特殊的规则,后面会详细说明。

附加参数:用来扩展表达式的含义,目前主要有三个参数:

g:代表可以进行全局匹配。
i:代表不区分大小写匹配。
m:代表可以进行多行匹配。

上面三个参数,可以任意组合,代表复合含义,当然也可以不加参数。

例子:

var reg=/a*b/;
var reg=/abc+f/g;

构造函数方式:var reg=new RegExp(“表达式”,”附加参数”);

其中“表达式”与“附加参数”的含义与上面那种定义方式中的含义相同。

例子:

var reg=new RegExp(“a*b”);
var reg=new RegExp(“abc+f”,”g”);

关于这里,我在前面的一篇文章中写过!http://www.haorooms.com/post/js_replace_bl 有变量的话,用表达式的方式!

普通方式中的表达式必须是一个常量字符串,而构造函数中的表达式可以是常量字符串,也可以是一个js变量,这也是普通方式与构造函数方式的区别。

小结

正则表达式很高深,学好了可以干很多事情,一定要温故而知新!多多复习,多多练习才能逐步掌握!今天就写到这里!

解决国内gem不能用的问题

最近在安装SASS的时候,用到gem命令,但是运行出行如下错误!

C:\Users\len>gem install sass
ERROR:  While executing gem ... (Gem::RemoteFetcher::FetchError)
    Errno::ETIMEDOUT: A connection attempt failed because the connected party di
d not properly respond after a period of time, or established connection failed
because connected host has failed to respond. - connect(2) for "rubygems.global.
ssl.fastly.net" port 443 (https://api.rubygems.org/quick/Marshal.4.8/sass-3.4.13
.gemspec.rz)

原因是ruby 的gem被和谐了,现在淘宝的ruby工程师架设了rubygems的国内镜像。使用方法如下:

$ gem sources --remove https://rubygems.org/
$ gem sources -a https://ruby.taobao.org/
$ gem sources -l
*** CURRENT SOURCES ***

https://ruby.taobao.org

然后在运行gem命令就可以了!

C:\Users\len>gem install sass
Fetching: sass-3.4.13.gem (100%)
Successfully installed sass-3.4.13
Parsing documentation for sass-3.4.13
Installing ri documentation for sass-3.4.13
Done installing documentation for sass after 5 seconds
1 gem installed

关于sass入门教程请看:http://www.haorooms.com/post/sass_css

jquery的checkbox,radio,select等方法总结

jquery的checkbox,radio,和select是jquery操作的一个难点和重点,很多前端新手对其了解不是很透彻。时间久了不用,我在写的时候有时也难免对某些操作支支吾吾,记不清楚,现在,对其做一些简单的总结!

1、checkbox日常jquery操作。

现在我们以下面的html为例进行checkbox的操作。

<input id="checkAll" type="checkbox" />全选
        <input name="subBox" type="checkbox" />项1
        <input name="subBox" type="checkbox" />项2
        <input name="subBox" type="checkbox" />项3
        <input name="subBox" type="checkbox" />项4

全选和全部选代码:

<script type="text/javascript">
        $(function() {
           $("#checkAll").click(function() {
                $('input[name="subBox"]').attr("checked",this.checked); 
            });
            var $subBox = $("input[name='subBox']");
            $subBox.click(function(){
                $("#checkAll").attr("checked",$subBox.length == $("input[name='subBox']:checked").length ? true : false);
            });
        });
    </script>

checkbox属性:

var val = $("#checkAll").val();// 获取指定id的复选框的值  
var isSelected = $("#checkAll").attr("checked"); // 判断id=checkAll的那个复选框是否处于选中状态,选中则isSelected=true;否则isSelected=false;  
$("#checkAll").attr("checked", true);// or  
$("#checkAll").attr("checked", 'checked');// 将id=checkbox_id3的那个复选框选中,即打勾  
$("#checkAll").attr("checked", false);// or  
$("#checkAll").attr("checked", '');// 将id=checkbox_id3的那个复选框不选中,即不打勾  
$("input[name=subBox][value=3]").attr("checked", 'checked');// 将name=subBox, value=3 的那个复选框选中,即打勾  
$("input[name=subBox][value=3]").attr("checked", '');// 将name=subBox, value=3 的那个复选框不选中,即不打勾  
$("input[type=checkbox][name=subBox]").get(2).checked = true;// 设置index = 2,即第三项为选中状态  
$("input[type=checkbox]:checked").each(function(){ //由于复选框一般选中的是多个,所以可以循环输出选中的值  
    alert($(this).val());  
}); 

2、radio的jquery日常操作及属性

我们仍然以下面的html为例:

<input type="radio" name="radio" id="radio1" value="1" />1  
<input type="radio" name="radio" id="radio2" value="2" />2  
<input type="radio" name="radio" id="radio3" value="3" />3  
<input type="radio" name="radio" id="radio4" value="4" />4 

radio操作如下:

$("input[name=radio]:eq(0)").attr("checked",'checked'); //这样就是第一个选中咯。
  //jquery中,radio的选中与否和checkbox是一样的。
$("#radio1").attr("checked","checked");
$("#radio1").removeAttr("checked");
$("input[type='radio'][name='radio']:checked").length == 0 ? "没有任何单选框被选中" : "已经有选中";  
$('input[type="radio"][name="radio"]:checked').val(); // 获取一组radio被选中项的值  
$("input[type='radio'][name='radio'][value='2']").attr("checked", "checked");// 设置value = 2的一项为选中  
$("#radio2").attr("checked", "checked"); // 设置id=radio2的一项为选中  
$("input[type='radio'][name='radio']").get(1).checked = true; // 设置index = 1,即第二项为当前选中  
var isChecked = $("#radio2").attr("checked");// id=radio2的一项处于选中状态则isChecked = true, 否则isChecked = false;  
var isChecked = $("input[type='radio'][name='radio'][value='2']").attr("checked");// value=2的一项处于选中状态则isChecked = true, 否则isChecked = false;  

3、select下拉框的日常jquery操作

select操作相比checkbox和radio要相对麻烦一些,我们仍然以下面的html为例来说明:

<select name="select" id="select_id" style="width: 100px;">  
    <option value="1">11</option>  
    <option value="2">22</option>  
    <option value="3">33</option>  
    <option value="4">44</option>  
    <option value="5">55</option>  
    <option value="6">66</option>  
</select> 

看select的如下属性:

    $("#select_id").change(function(){                         // 1.为Select添加事件,当选择其中一项时触发   
        //code...  
    });  
    var checkValue = $("#select_id").val();                    // 2.获取Select选中项的Value  
    var checkText = $("#select_id :selected").text();          // 3.获取Select选中项的Text   
    var checkIndex = $("#select_id").attr("selectedIndex");    // 4.获取Select选中项的索引值,或者:$("#select_id").get(0).selectedIndex;  
    var maxIndex = $("#select_id :last").attr("index");        // 5.获取Select最大的索引值,或者:$("#select_id :last").get(0).index;  
    /** 
     * jQuery设置Select的选中项 
     */  
    $("#select_id").get(0).selectedIndex = 1;                  // 1.设置Select索引值为1的项选中  
    $("#select_id").val(4);                                    // 2.设置Select的Value值为4的项选中  
    /** 
     * jQuery添加/删除Select的Option项 
     */  
    $("#select_id").append("<option value='新增'>新增option</option>");    // 1.为Select追加一个Option(下拉项)   
    $("#select_id").prepend("<option value='请选择'>请选择</option>");   // 2.为Select插入一个Option(第一个位置)  
    $("#select_id").get(0).remove(1);                                      // 3.删除Select中索引值为1的Option(第二个)  
    $("#select_id :last").remove();                                        // 4.删除Select中索引值最大Option(最后一个)   
    $("#select_id [value='3']").remove();                                  // 5.删除Select中Value='3'的Option   
    $("#select_id").empty();             

   $("#select_id").find("option:selected").text(); // 获取select 选中的 text :

   $("#select_id").val(); // 获取select选中的 value:

     $("#select_id").get(0).selectedIndex; // 获取select选中的索引:

     $("#select_id").get(0).selectedIndex=index;//index为索引值

 //设置select 选中的value:
    $("#select_id").attr("value","Normal“);
    $("#select_id").val("Normal");
    $("#select_id").get(0).value = value;

 //设置select 选中的text,通常可以在select回填中使用
var numId=33 //设置text==33的选中!
var count=$("#select_id  option").length;
  for(var i=0;i<count;i++)  
     {           if($("#select_id").get(0).options[i].text == numId)  
        {  
            $("#select_id").get(0).options[i].selected = true;  
            break;  
        }  
    }

通过上面的总结,应该对jquery的checkbox,radio和select有了一定的了解了吧,温故而知新,用多了就会变的熟练起来,即使有时候忘记了,也可以来翻一翻!

时隔多年,个人网站重新上线

2010年,在天路集团公司实习的时候,学习了SEO,老师是利为汇的蒋辉(现在利为汇SEO已经被k了),当时接触到了网赚的一些知识,因此,自己萌生了做网站赚钱的想法。搭建了我人生的第一个网站discuz论坛,名字是跳*市场,域名是www.tiaosaoshichang.net,当时的想法就是为上海的在校大学生制作一个毕业二手物品论坛。因为学习了SEO的缘故,经过几个月的努力,百度和谷歌的“跳蚤市场”、"跳*市场"、"跳*论坛"等关键词都排首页。但是,好景不长,我后期的很多工作就是删除垃圾帖子。网站盈利成了嘘谈!

后来,我在我的虚拟机上上传了自己的一个纯FLSHA博客,博客很炫,但是没有内容,因为是flash的,所以添加文章什么的都不方便,后来虚拟机和域名到期之后就没有再续费!

2011年,淘宝客是一个比较火的网赚项目,很多做减肥的淘宝客网赚,赚到了很大的一笔,我萌生冲动,建立了babygeili.com的淘宝客网站,主要想卖一些早教产品,但是,后来还是因为没有盈利而荒废!

与之前不同的是,本次个人网站,采用了nodejs+mongodb制作,同时,此时本人已有几年网站建设经验,对网站运营方面也有了一定的了解。

很多个人网站在刚刚建的时候热情比较高,但是很难坚持,本次个人网站,本人一定坚持写博客的同时,逐步完善网站结构,使本人的个人网站成为一个比较成功的网站!

javascript获取iframe中光标所在位置的父节点名称

项目背景:

最近在做一个客服聊天系统后台,聊天窗口中,有字体加粗,倾斜,下划线等等。这个效果可以在我的上一篇文章中简单的实现,具体请看javascript execCommand,复文本框神器案例请看

但是需求方有额外的要求,要求iframe中字体加粗的话,鼠标点在上面,我们按钮有选中状态。对于这个按钮的选中状态怎么办呢?

思路和方法:

一开始我想找到javascript execCommand的一个返回状态,但是最终以失败告终。

在和同事的研究交流过程中,找到了如下方法,封装了一个函数,从而获得iframe中选中的文本,及光标所在位置的父级元素的节点名称。

代码如下:

 var isIE = navigator.userAgent.indexOf("MSIE")>0;

var Q_EDITFORM_DOCUMENT = null;
var Q_SELECTION = null;
var Q_RANGE = null;
var Q_RANGE_TEXT = "";

function getParentNode()
{
        if(isIE)
        {
                return document.selection.createRange().parentElement();
        }
        else
        {                
                var startRangeNode = Q_RANGE.startContainer;
                if (startRangeNode.nodeType == 3) 
                {
                        var textNode = startRangeNode;
                        startRangeNode = textNode.parentNode;
                } 
                else 
                {
                        if (startRangeNode.tagName.toLowerCase() == 

'html') 
                        {
                                startRangeNode = 

startRangeNode.childNodes[0].nextSibling;
                        } 
                }
                return startRangeNode;
        }
}

//插入div的相关处理函数
function QEditformDocument()
{
        if (isIE) 
        {
                Q_EDITFORM_DOCUMENT = document;
        } 
        else 
        {
                Q_EDITFORM_DOCUMENT = document;
        }
}

function QSelection()
{
        if (isIE) 
        {
                Q_SELECTION = Q_EDITFORM_DOCUMENT.selection;
                Q_RANGE = Q_SELECTION.createRange();
                Q_RANGE_TEXT = Q_RANGE.text;
                //alert(Q_RANGE_TEXT);
        } 
        else 
        {
                Q_SELECTION = Q_EDITFORM_DOCUMENT.getSelection();
        Q_RANGE = Q_SELECTION.getRangeAt(0);
                Q_RANGE_TEXT = Q_RANGE.toString();
                //console.dir(Q_RANGE_TEXT);
        }
}

使用方法:

        //HtmlEditor为编辑器iframe的id
        //调用getParentNode()前必须初始化文档对象
        QEditformDocument();
        QSelection();
        var parentobj = getParentNode();
          console.dir(parentobj);
        //parentobj是一个object,获取它的名称,用parentobj.tagName就可以获取到元素的名称,注意,名称是大写的!!

demo[案例预览][4]

输出可以用谷歌浏览器查看console ,alert看不清楚。

小结

通过这个方法,我们可以很简单的制作出加粗,倾斜,和下划线等的选中效果了。这个效果我已经在项目中实现了,具体demo没有写!大家可以看我开头的这个案例请看 案例,结合案例预览这个案例,当选择某个文字或者标签的时候,给相应加粗,倾斜和下划线等一个不一样的样式,就可以做到了!

IE6 中png背景透明的最好方法及谈谈IE6和我的博客

说到IE6,很多前端都很头大,我刚刚开始做网页的时候,也为之痛苦不堪。其中,我也总结了一下IE6中常见的问题,想margin了,padding了,ul li中点的显示问题了,弹出层被select选择框挡住了,等等。要查看详情,后续文章到时候有时候会把这些整理上去吧。(浏览器兼容问题的一些总结)可以看下!

本文的题目是IE6中png背景透明最好的方法,好吧,网上有很多,但是实践下来,这种DDPngMin.js效果最好。

应用方式:(网站尾部加上如下代码)

<!--[if IE 6]>
<script src="js/DDPngMin.js"></script>
<script>DD_belatedPNG.fix('.ad_img img,#banner_ctr ul');</script>
<![endif]--> 

引进这个DDPngMin.js。后面是针对某个png做处理。

DDPngMin.js 下载

好了,png背景透明说好了,谈谈IE6吧,随着微软宣布停止对XP做系统支持,XP逐渐淡出历史舞台,IE6和他的小伙伴IE7也渐渐将消失,但是时下,IE6和IE7的用户还是很多,如果是普通的网站,兼容IE6和IE7还是必要的。

关于我的博客,浏览人群大都是前端技术人员或者网络人员,故不考虑IE6,IE7和IE8的兼容性,将浏览器直接跳到IE9,只有IE9及其以上还有谷歌内核浏览器,及火狐和苹果浏览器才有比较好的效果。

css浏览器兼容问题的一些总结(IE6等)

说到浏览器兼容问题,所有前端开发人员肯定都遇到过,这个问题需要面对,也必须得面对。

记得2011年年底,刚刚来兴安得力实习的时候,做的第一个页面是一个信息港的页面,布局完这个页面之后。领导第一次让我考虑浏览器兼容问题,让我下载了IEtester。对各个浏览器进行测试,也是这一次,我才了解到,做网站还要考虑浏览器兼容,不同浏览器可能有不同的效果。在这个时候,我刚刚接触IE6,对IE6是既爱又恨,爱它使我增长了不少见识,恨他是有很多问题让我浪费了大量的时间,且达不到我想要的效果。在这个时候,由于我代码书写规范问题,大量运用float和margin,写出的网站存在很多兼容问题。假如有一个小时布局页面,同时也要花一个小时来调整兼容问题。搞得我很痛苦。

现在想起来,新手做网站布局,一定要注意书写规范问题,多看看一些规范网站布局,千万不要闭门造车。举一个最简单的例子:写html的时候,要注意顺序结构,在万不得已的情况下。li标签下面不要再嵌套多个div,ul的最合理结构是ul >li >a>span 假如你在ul标签下面不停的嵌套多个div,很可能造成IE低版本浏览器问题。

先说说IE浏览器版本吧,每个版本的IE浏览器有两种模式IE(Q)、IE(S),其中Q代表Quirks mode 怪异模式或混杂模式,这种模式很恶心。另一种是标准模式Standards mode,通常网上见到的很多代码和hack都是针对IE(S)来说的,一旦用户不小心切换到IE(Q),就可能造成意想不到的效果!

我们下面来看一下IE版本的不同hack吧,如下图:

![enter image description here](http://www.haorooms.com/uploads/images/IEhack.jpg)

看到网上很多资料写的“_”下划线是IE6特有的hack,不错,在IE6标准模式下面,是的。这样写没有问题。加入页面中IE6和IE7出现同样的问题的时候,我们可以用下划线,说不定IE6调好了,IE7也会跟着好了起来。

经过我实践发现“-”中划线的确是IE6特有的hack,你可以在你的页面中用中划线随便写针对IE6问题的代码,其他浏览器不会出现问题。

IE7特有的hack,一般认为是“*+”,星号和加号一起写。例如 :

aaa{height:25px;-height:30px;*+height:31px;} /* 普通高度是25像素,IE6是30像素,IE7是31像素  */

还有一种引进css的写法,也可以作为调整网站hack的办法,写法如下:

<!--[if IE 6]>
    <link href="ie/ie6.css" rel="stylesheet" type="text/css" />
<![endif]-->
<!--[if IE 9]>
    <link href="ie/ie9.css" rel="stylesheet" type="text/css" />
<![endif]-->
<!--[if IE 8]>
    <link href="ie/ie8.css" rel="stylesheet" type="text/css" />
<![endif]-->
<!--[if IE 7]>
    <link href="ie/ie7.css" rel="stylesheet" type="text/css" />
<![endif]-->
<!--[if IE]>
    <link href="ie/ie.css" rel="stylesheet" type="text/css" />
<![endif]-->
<!--[if lt IE 9]>
    <script src="html5_shrrr.js"></script>
<![endif]-->

其他IE的hack就不具体举例子了。

关于IE6,有很多问题,最常见的是png背景透明,之前的一篇文章我写了ie6 png背景透明最好的办法 大家可以看一下。

**其次我想IE6的最大问题是不识别max 和min,就是最大宽度和最小高度等等。**对于这个问题的解决方案是,最好不要用最大宽度和最小高度。要是你做的网站需要兼容IE6的话,说明肯定是大众化的网站,(像淘宝网现在用IE6打开的话,都会提示,网站浏览器版本比较低。),那么,大众性的网站的话,根本就不需要用最大高度和最小宽度。有些刚刚布局网站不久的同学,在做分页的时候,像1,2,3,4,5这样的单数的时候,很喜欢给个最小宽度,这样看起来比较好看。这种方式根本不用最小宽度,你为什么不用padding呢?分页用padding了以后,不就达到了你想要的最小宽度的效果吗?

你在网上搜索IE6最大宽度和最小高度,有的说法是用表达式expression_r,但是你实践就会发现,很多情况下表达式是没有效果的。也有说把高度设置成auto或者100%的,你试了以后就会发现,通常情况下是没有效果的或者效果不是很好!

我想IE6还有问题就是弹出层没有把select选择框挡住这个问题吧。

这个问题的解决方案如下:

   <iframe style='position:absolute;visibility:inherit;top:0;left:0; border:0;z-index:-1;FILTER:alpha(opacity=0); width:320px; height:250px;'></iframe>

用一个iframe把弹出层挡住,让iframe置于弹出层底部,就可以了,上面iframe的高度和宽带就是你弹出层的高度和宽带。

例如,我的代码如下:dialog 弹出层

<!--添加dialog -->
<div id="dialog " style="display:none;">
    <iframe style='position:absolute;visibility:inherit;top:0;left:0; border:0;z-index:-1;FILTER:alpha(opacity=0); width:400px; height:280px;'></iframe>
    <form class="dialogform">
        <table width="100%" border="0" cellspacing="0" cellpadding="0">
            <tr>
                <td width="20%">邮箱:</td>
                <td width="80%"><input type="text" value="" style="width:165px;"></td>
            </tr>
            <tr>
                <td>姓名</td>
                <td><input type="text" value="" style="width:165px;"></td>
            </tr>
            <tr>
                <td>性别:</td>
                <td>
                    <select style="width:165px;">
                        <option>男</option>
                        <option>女</option>
                        <option>未知</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td> </td>
                <td><input type="button" value="添加" class="add"></td>
            </tr>
        </table>


    </form>

</div>

关于IE6,就是中文字体的问题,很多时候,你在css中写字体,一般是用英文,现在附上常见字体中英文对照表:

华文细黑:STHeiti Light [STXihei]
华文黑体:STHeiti
华文楷体:STKaiti
华文宋体:STSong
华文仿宋:STFangsong
俪黑 Pro:LiHei Pro Medium
俪宋 Pro:LiSong Pro Light
标楷体:BiauKai
苹果俪中黑:Apple LiGothic Medium
苹果俪细宋:Apple LiSung Light
Windows的一些:
新细明体:PMingLiU
细明体:MingLiU
标楷体:DFKai-SB
黑体:SimHei
宋体:SimSun
新宋体:NSimSun
仿宋:FangSong
楷体:KaiTi
仿宋_GB2312:FangSong_GB2312
楷体_GB2312:KaiTi_GB2312
微软正黑体:Microsoft JhengHei
微软雅黑体:Microsoft YaHei
装Office会生出来的一些:
隶书:LiSu
幼圆:YouYuan
华文细黑:STXihei
华文楷体:STKaiti
华文宋体:STSong
华文中宋:STZhongsong
华文仿宋:STFangsong
方正舒体:FZShuTi
方正姚体:FZYaoti
华文彩云:STCaiyun
华文琥珀:STHupo
华文隶书:STLiti
华文行楷:STXingkai
华文新魏:STXinwei

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.