起因

今天在公司忙活着一个项目,涉及到表单提交,要求在表单提交之前判断几个input的值是否为空,如果是,则阻止表单提交。

我的做法是给form添加了一个submit事件绑定,然后判断,如果有input的值为空则return false 阻止提交。判断input值是否为空,这一块走的正常,可是在判断有空值的时候,表单还是提交了,很是奇怪。

上网看了看大家的一些做法,也都是return false.为啥到我这边就不管用了?后来仔细看了下别人代码和自己的区别,这才找到了原因。

表单提交前判断的常用做法

一般来说,js要实现提交前的判断,有以下三种常见做法:

  1. 监听form标签的submit事件
  2. 监听input[type=submit]按钮的click事件
  3. 监听input[type=button]或者任何指定作为提交按钮的标签的任意事件,在条件符合之后调用form标签的submit()方法

一下是一个简单的例子:

<!DOCTYPE HTML>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>demo-form</title>
</head>
<body>
<form action="answer.php" id="form1" method="post">
    <input type="text" value="" id="txt">
    <input type="submit" value="提交" id="sbtn">
    <input type="button" value="按钮" id="btn">
</form>
<script type="text/javascript">
    var d = document,
        form1 = d.getElementById('form1'),
        txt = d.getElementById('txt'),
        sbtn = d.getElementById('sbtn'),
        btn = d.getElementById('btn');

        // 检测文本框内容是否为空
        function checkIsNull(){
            if(txt.value === ""){
                return false;
            }else{
                return true;
            }
        }
</script>
</body>
</html>

 

对于第三种方法,实现阻止表单提交最简单,只要条件不符合就不调用form标签的submit()方法即可

        btn.addEventListener('click',function(e){
            if(checkIsNull()){
                form1.submit();
            }else{
                alert('文本框内容不能为空');
            }
        });

 

对于第二种方法和第一种方法,就有比较多的可能性了

直接绑定到标签属性上

如果是使用直接绑定到标签属性上的方法,则第一和第二种方法都可以简单的使用return false;的方法去阻止表单提交。

        form1.onsubmit = function(e){
            if(checkIsNull()){
                return true;
            }else{
                alert('文本框内容不能为空');
                return false;
            }
        };

 

        sbtn.onclick = function(e){
            if(checkIsNull()){
                return true;
            }else{
                alert('文本框内容不能为空');
                return false;
            }
        };

 

这种直接注册到标签属性上的方法,方法内部的return false;就会直接作用到整个事件上,这一点我是在下面这个文章里面看到的,有兴趣的同学可以看看,传送门:由表单中onsubmit=”return false;”想到的

可是这种事件注册有个缺点就是没有办法给同一个标签的同一个事件注册多个回调函数函数,这个在某些情况下还是不行的。然后就是通过addEventListener(IE下面是attachEvent)

通过addEventListener/attachEvent注册事件

通过addEventListener方法注册的事件的回调函数,假设是:

form.addeventListener('submit',function doSubmit(e){
    return false;
},false);

 

其实就类似于:

form.onsubmit = function(e){
    doSubmit();
}

 

所以doSubmit()内部的return false;是没办法影响到整个事件的浏览器默认动作

这个时候,在非IE浏览器下,回调函数函数可以通过传入的event,调用该event对象的preventDefault()方法阻止浏览器的默认动作;如果是在IE浏览器下,则是通过window.event.returnValue = false;方法来阻止浏览器的默认动作。(这段内容参考的网站,传送门:js阻止浏览器的默认行为以及停止事件冒泡(用JQuery实现回车提交,兼容IE、FF浏览器)

所以可行的代码如下:

        function doSubmit(e){
            if(checkIsNull()){
                return true;
            }else{
                alert('文本框内容不能为空');
                //如果提供了事件对象,则这是一个非IE浏览器 
                if(e && e.preventDefault){
                    //阻止默认浏览器动作(W3C)
                    e.preventDefault();
                }else{
                    //IE中阻止函数器默认动作的方式 
                    window.event.returnValue = false;
                }
            }
        }

        // 判断是否支持IE的注册事件方法,如果支持则是IE浏览器,使用attachEvent进行事件注册
        if(sbtn.attachEvent){
            // attachEvent不支持捕捉,所以只有两个参数
            sbtn.attachEvent('click',doSubmit)
        }else{
            sbtn.addEventListener('click',duSubmit,false);
        }

 

form标签的submit事件也是类似的,就不重复写了

总结

return false;是能够阻止表单提交的,不过只能针对直接注册事件到标签属性上面的情况。对于addEventListener/attachEvent注册的事件,则需要通过event.preventDefaule()或window.event.returnValue=false的方式阻止表单的提交。针对其他浏览器默认行为,也大体上类似

今天给公司的编辑们讲解CSS相关的知识,分两节课,上上周讲过一次,简单的介绍了css的引用,选择器,优先级能相关的概念。而今天这节课就专注于css里面比较核心的盒模型和定位同时介绍一下伪类。

很入神的讲到一半的时候,偶然抬头,没几个人在听,有睡眼朦胧的,有互相打趣说悄悄话的,有45度仰望天空出神的。我看了一眼,让后继续盯着屏幕自说自话。

分界线

为什么我要这样骗人骗己的继续讲下去?

我为了这节课准备了前前后后有5、6个小时,真的就只是为了完成公司交代的任务——讲课?

为什么大家会不愿意听?

讲完课之后,听众们收获了什么,我收获了什么?

没有答案

只是警醒自己,别以为埋头干活就是好的,你得时时刻刻清清楚楚的知道自己在干什么,为什么这样干,这样干是为了什么,怎样才能干的更好

需求

最近在忙公司的一个移动端充值的前端部分,今天主要是做页面。需要一个指示用户充值流程的流程条(进度条),大致的效果如下:
progress-bar

思路

如果是平时在pc端的开发,那么可能就会将箭头的区域切出五个状态:

  1. 箭头部分灰色,背景灰色
    arrow-2
  2. 箭头部分蓝色,背景灰色
    arrow-1
  3. 箭头部分灰色,背景蓝色
    arrow-4
  4. 箭头部分蓝色,背景透明
    arrow-5
  5. 箭头部分灰色,背景透明
    arrow-3
  •  

    具体的写法就是:

    默认状态 li下面的.arrow-right显式为第一种:箭头灰色,背景灰色

    选中状态(.on) li下面的.arrow-right显示为第二种状态 箭头蓝色,背景灰色,同时用js实现它的previousSibling的.arrow-right显示为第三种状态:箭头灰色,背景蓝色

    最后一个箭头 因为背景色的不同,独立出来 默认状态是第四种 选中状态是第五种

    需要修改的地方

    三角箭头的css方案

    因为是做移动端开发,所以为这么个功能制作五张图片,哪怕是可以通过css sprite合并,可也是很不划算的。然后我就想起以前看到的一个用css实现三角浮动层尖角的文章,找出来翻了翻,箭头的css化问题就解决了。具体的制作方法我就重复写了,大家可以参看下面的链接:

    CSS常用浮动层的写法

    三种纯CSS实现三角形的方法

    使用css相邻兄弟选择器替换js

    之前的思路是通过js来实现基于选中状态下li,修改相邻li的样式,可以实现,但是感觉上很啰嗦,不够优雅。

    这个项目是在移动端使用的,都是高级浏览器。所以很多平时在pc端网页开发时,因为顾及到IE6、7、8的兼容性而不能使用的css选择器,比如子选择器、相邻兄弟选择器都能够放心的使用了。

    在这个项目中使用到的就是相邻兄弟选择器,在选中状态下影响下一个兄弟节点的样式 .on + li{}

    最终的方案

    先上代码

    HTML:

    • 1.选择充值方式
    • 2.第一步
    • 3.第二步
    • 4.第三步

     

    CSS:

    .progress {
      list-style-type: none;
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    .progress li {
      float: left;
      margin: 0;
      overflow: hidden;
    }
    .progress span {
      display: block;
      float: left;
    }
    .progress .step {
      height: 2.2rem;
      width: 10rem;
      font: bold 1.4rem/2.2rem simsun, arial;
      color: #999;
      text-align: center;
      background: #e3e3e3;
    }
    /* 箭头区域-非箭头部分 背景色 默认灰色 */
    .progress .triangle {
      position: relative;
      height: 2.2rem;
      background: #e3e3e3;
      width: 1.3rem;
      overflow: hidden;
    }
    .progress em,
    .progress i {
      display: block;
      position: absolute;
      top: -2px;
      overflow: hidden;
      width: 0;
      height: 0;
      border-width: 15px;
      border-style: dashed solid dashed dashed;
    }
    /* em 箭头区域-箭头部分 头部边框 白色 */
    .progress em {
      left: 0px;
      border-color: transparent transparent transparent #FFF;
    }
    /* i 箭头区域-箭头部分 背景颜色 默认灰色*/
    .progress i {
      left: -2px;
      border-color: transparent transparent transparent #e3e3e3;
    }
    .progress .first {
      width: 11rem;
      border-radius: 5px 0 0 5px;
    }
    /* 最后一个的背景色透明 */
    .progress .last {
      background: transparent;
    }
    /* 选中状态下 当前节点 左边箭头区域-非箭头部分 颜色蓝色(形成箭尾) */
    .progress .on .triangle-left {
      background: #5fb3dc;
    }
    /* 选中状态下 当前节点 右边箭头区域-箭头部分 颜色蓝色 */
    .progress .on .triangle-right i {
      border-color: transparent transparent transparent #5fb3dc;
    }
    .progress .on .step {
      background: #5fb3dc;
      color: #FFF;
    }
    /* 选中状态下 下一个兄弟节点 左边箭头区域-箭头部分 颜色蓝色 */
    .progress .on + li .triangle-left i {
      border-color: transparent transparent transparent #5fb3dc;
    }

     

    描述

    总共三种li:

    • 左数第一个li 没有箭头区域
    • 右数第一个li 有左边箭头区域和右边箭头区域
    • 上述两个li中间的li 有左边箭头区域

    左数第一个li

    默认状态 文本区域背景色灰色

    如果下一个兄弟节点也是默认状态,则其左边箭头区域-箭头灰色-非箭头灰色first-normal

    如果下一个兄弟节点选中状态,则其左边箭头区域-箭头灰色-非箭头蓝色first-normal-2

    两种状态下,都能保证左数第一个li和其下一个兄弟节点的左边箭头区域的箭头在视觉上成为一体

    选中状态 文本区域蓝色

    下一个兄弟节点只能是默认状态(在流程条中只有一个会是处在选中状态)first-on

    中间li

    默认状态 内容区域灰色 左边箭头区域-非箭头灰色

    middle-normal-3

    middle-normal-4

    middle-normal-2

    注意:这种风格的流程条不存在同时两个选中状态的,但是样式上可以做到
    middle-normal-1

    选中状态 左边箭头区域 非箭头部分蓝色 内容区域蓝色 下一个兄弟节点的左边箭头区域-箭头部分蓝色

    middle-on

    右数第一个li

    默认状态 左边箭头区域-非箭头部分灰色 内容区域灰色 右边箭头区域-箭头部分灰色

    last-normal-2

    last-normal-1

    选中状态 左边箭头区域-非箭头部分蓝色 内容区域蓝色 右边箭头区域-箭头部分蓝色

    last-on

    总结

    总的来说,对于任何一个li,它们的目的是为了形成一个箭的形状,所以必须保证箭尾、箭身和箭头这三者颜色保持一致。在我这个HTML结构里箭尾就是li自身内部的左侧箭头区域-非箭头部分,箭身就是内容区域,箭头就是下一个兄弟节点的左侧箭头区域的箭头部分或者自身右侧箭头区域的箭头部分,只要能保证三者颜色颜色保持一致,那么一个标准的流程条就出来了。:)

    为什么要换空间

    之前使用的空间是刚刚打算建立博客,对相关的事务都不熟悉,谨慎起见,就找了个免费空间,打算试试看看,就算不行也没的损失。可事实证明,很多时候,免费其实比收费还要亏的。

    免费的空间使用期限是一个月,要到处给空间服务商打广告才可能延期,这我是没有时间的,所以打算在一个月快要到期的时候升级到收费空间。傻傻的充了30块钱,可是到处都找不到升级空间的入口,发邮件给空间服务商提供的邮箱,也是石沉大海——没的半点回音。

    无奈之下,为了防止到期之后空间删除会连着自己的网站也没了,只好另找一家。

    空间的选择

    托对网站建设比较了解的同事推荐一下,自己也顺便找找看。

    同事推荐了一个,挺便宜的,空间大小,数据库大小也比自己找的好。可是一看是Windows的,服务器是IIS,就有点不情愿了。因为之前那个免费的空间也是用的IIS,弄的我没法自定义个性化的文章链接,每个链接都是要包含个index.php,看着不舒服,对seo也不好。

    找到最后又找回当初申请域名的西部数码,申请了个港台虚拟主机,最便宜的那种198元/年,100M空间和50M MySQL数据库,想想自己的博客才刚刚开通,这样的配置到也过的去,而且这次学聪明了,专门向客服打听了能不能升级。客服的回应是只要补足当月的差价就行,所以心里也是更加放心了。

    选用的是Linux系统和Apache2.2的,这种虚拟主机可以自定义的配置很少,系统的选择上关系不是很大,不过对于Linux总是有种亲切感。支持.htaccess,可以自定义URL。

    空间的迁移

    文件内容的迁移

    西部这边提供了一个“网站搬家”的功能,就是提供ftp的ip,用户名和密码,他就主动的去把对应目录里面的内容下载到空间里。这样比自己手动下载然后上传要方便不少。

    数据库的迁移

    在迁移之前已经把wordpress相关的数据导出成sql文件了,再次导入也很简单,可以使用西部这边提供的工具,也可以进入phpmyadmin手动的导入。导入之后,因为数据库名,用户名和密码和原先的网站有所不同,这个时候只要打开根目录下面的wp-config.php修改相应的配置就可以了。

    域名的迁移

    因为是自己第一次迁移,也不知道自己的方法对不对。我的做法是先在域名管理商这边把原先域名指向的IP删除,然后连上西部给定的二级域名(西部这边不是提供的ip地址而是一个二级域名,不过都能正常访问,只是不知道这样的处理对网站的seo优化有没有影响,如果有的话,到时候就需要花上100去弄个独立ip了。

    迁移完成后

    迁移完成之后,访问网站,可是却总是提示的首页循环重定向,不明白出这样的原因是什么,最后在http://www.xiangguoqi.com/read/247.html这个网站找到了几种解决方案,试了下第一个方法:
    修改wp-include/template-loader.php

        /**
         * Loads the correct template based on the visitor’s url
         * @package WordPress
         */
        if(defined(‘WP_USE_THEMES’)&& WP_USE_THEMES )
        do_action(‘template_redirect’);
    

    我们只要将后面的一段代码去掉或者注释掉就可以了

        /* 解决首页重定向问题,可能影响到日后升级
        if(defined(‘WP_USE_THEMES’)&& WP_USE_THEMES )
         do_action(‘template_redirect’);
        */
    

    保存之后再次访问网站,正常。

    至此,整个网站迁移完毕。而且相比于之前的美国主机,港台主机在网站访问速度上面有着较明显的提升

    今天查看系统日志发现有如下两个问题:

    1. 服务器 {F9717507-6651-4EDB-BFF7-AE615179BCCF} 没有在要求的超时时间内向 DCOM 注册。
    2.  Provider 
    3.  
    4.    [ Name]  Microsoft-Windows-DistributedCOM 
    5.    [ Guid]  {1B562E86-B7AA-4131-BADC-B6F3A001407E} 
    6.    [ EventSourceName]  DCOM 
    7.  
    8.   - EventID 10010 
    9.  
    10.    [ Qualifiers]  0 
    11.  
    12.    Version 0 
    13.  
    14.    Level 2 
    服务器 {EA022610-0748-4C24-B229-6C507EBDFDBB} 没有在要求的超时时间内向 DCOM 注册。
    Provider 
    
       [ Name]  Microsoft-Windows-DistributedCOM 
       [ Guid]  {1B562E86-B7AA-4131-BADC-B6F3A001407E} 
       [ EventSourceName]  DCOM 
     
      - EventID 10010 
    
       [ Qualifiers]  0 
     
       Version 0 
     
       Level 2 
    

    在网上找到有个人跟我系统差不多同时也是遇到同样问题的,链接如下:
    http://answers.microsoft.com/en-us/windows/forum/windows_7-performance/error-microsoft-windows-distributedcom-id10010/481acdc3-3402-40ac-af9a-330908fd5754

    具体的方式是通过给 Network Service 角色添加相应的权限,步骤如下:
    A. 在“运行”里面输入命令dcomcnfg
    B. 双击“组件服务”->双击“计算机”
    C. 右键点击“我的电脑”,选择“属性”
    D. 点击“COM安全”菜单项
    E. 在“启动和激活权限”的区域内,点击“编辑默认值”
    F. 点击“添加” ,在“输入对象名称来选择”下方区域内输入“Network Service” ,可点击右侧的“检查名称”来规范正确的输入,之后点击“确定”
    G. 确保选中了“NETWORK SERVICE”,点击下方的复选框,保证如下权限的“允许”是选中的:
    H. 本地启动
    I. 远程启动
    J. 本地激活
    K. 远程激活
    L. “确定”->“确定”

    下面的链接是微软官方对Event ID 10010的说明
    http://technet.microsoft.com/en-us/library/cc774175(WS.10).aspx

    机器就按上述的设置了,具体的效果等随后一段时间看看是否还会有上述问题发生,来确定设置是否有效