写写原生JavaScript系列(5)-实现选择祖先元素closest()方法

匹配DOM上级元素,实现closest()方法

从包含自己以及自己的祖先元素中选择出符合条件的元素,closest()类似于jQuery的$.closest() 方法,是一个在现代浏览器中内置支持的一个操作元素的方法,比如在火狐中。

// matches polyfill
this.Element && function(ElementPrototype) {
    ElementPrototype.matches = ElementPrototype.matches ||
    ElementPrototype.matchesSelector ||
    ElementPrototype.webkitMatchesSelector ||
    ElementPrototype.msMatchesSelector ||
    function(selector) {
        var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
        while (nodes[++i] && nodes[i] != node);
        return !!nodes[i];
    }
}(Element.prototype);

// closest polyfill
this.Element && function(ElementPrototype) {
    ElementPrototype.closest = ElementPrototype.closest ||
    function(selector) {
        var el = this;
        while (el.matches && !el.matches(selector)) el = el.parentNode;
        return el.matches ? el : null;
    }
}(Element.prototype);

由于在现代浏览器中内置支持了这些元素,因此我们为了获得更好的性能,我们建议在原生对象上进行拓展,就可以像下面这样直接使用:

var el = document.querySelector('span');
console.log(el.closest('div'));

原文出处

https://plainjs.com/javascript/traversing/match-element-selector-52/

more >>

写写原生JavaScript系列(4)-获取父节点、兄弟节点

元素节点操作

获取节点父元素,直接使用一个兼容各个浏览器的方法

var el = document.querySelector('div');
var parent = el.parentNode;

获取下一个、前一个或者所有的兄弟元素并且根据选择器过滤
获取兄弟元素并过滤

function getSiblings(el, filter) {
    var siblings = [];
    el = el.parentNode.firstChild;
    do { if (!filter || filter(el)) siblings.push(el); } while (el = el.nextSibling);
    return siblings;
}

// example filter function
function exampleFilter(el) {
    return elem.nodeName.toLowerCase() == 'a';
}

用法

el = document.querySelector('div');
// get all siblings of el
var sibs = getSiblings(el);
// get only anchor element siblings of el
var sibs_a = getSiblings(el, exampleFilter);

更快速的获取前一个或者下一个兄弟节点的方法

var previous = el.previousSibling;
var next = el.nextSibling;
Get all following siblings of an element, optionally filtered:

接受一个过滤条件参数的俄获取后面兄弟节点的方法

function getNextSiblings(el, filter) {
    var siblings = [];
    while (el= el.nextSibling) { if (!filter || filter(el)) siblings.push(el); }
    return siblings;
}

接受一个过滤条件参数的俄获取前面兄弟节点的方法

function getPreviousSiblings(el, filter) {
    var siblings = [];
    while (el = el.previousSibling) { if (!filter || filter(el)) siblings.push(el); }
    return siblings;
}

原文出处

https://plainjs.com/javascript/traversing/match-element-selector-52/

more >>

写写原生JavaScript系列(3)-判断当前元素匹配的CSS选择器

为了检查匹配的元素是否符合某个css选择器,现代浏览器提供了一个matches()、matchesSelector()方法,因此我们来写一个通用的方法,检查元素是否匹配某个css选择器。

    // matches polyfill
    this.Element && function(ElementPrototype) {
        ElementPrototype.matches = ElementPrototype.matches ||
        ElementPrototype.matchesSelector ||
        ElementPrototype.webkitMatchesSelector ||
        ElementPrototype.msMatchesSelector ||
        function(selector) {
            var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
            while (nodes[++i] && nodes[i] != node);
            return !!nodes[i];
        }
    }(Element.prototype);

因为现代浏览器提供了一些DOM4级别的内置方法,因此为了让其他浏览器支持,我们写出了通用的方法,但是为了速度更快,推荐使用拓展内置对象的方式实现。

给一个使用的栗子:

    var el = document.querySelector('span');
    console.log(el.matches('.foo'));

原文出处

https://plainjs.com/javascript/traversing/match-element-selector-52/

more >>

写写原生JavaScript系列(2)-根据类名选择元素

getElementsByClassName()方法可以在浏览器中快速获取DOM节点,但是需要注意不能在IE8及以下版本浏览器使用该方法。

var list = document.getElementsByClassName('foo');

// get the number of selected elements
console.log(listlength);

// iterate over elements and output their HTML content
for (var i=0; i<list.length; i++)
console.log(list[i].innerHTML);

配合getElementById() 使用,可以快速从一个元素容器中获取一个元素节点数组

var container = document.getElementById('header');
var list = container.getElementByClassName('foo');

这个方法较为性能较好,但是却只能使用class来选择元素,因此限制了它的用处,上一节说的querySelectorAll()则可以根据CSS选择器来选择元素,因此更加方便。

原文

https://plainjs.com/javascript/selecting/select-elements-by-class-name-3/

more >>

基于nodejs的CMS系统

项目地址

https://github.com/linksgo2011/nodecms

介绍

学习nodejs入门项目,数据库使用的MySQL。
使用nodejs 开发定位于企业网站的简易CMS,目标为容易拓展、部署,前端开发者容易使用的CMS系统。

特性

  • 使用nodejs 开发,为前端开发者准备的,前后端都使用JS,做个企业网站就很容易了
  • 简单(其实是懒),主要是首页、根据数据模型的列表页、详情页,单页,满足一般企业站点需要
  • 容易拓展,功能不满足可以容易拓展
  • 多模板
  • 支持不同模型列表、详情指定模板,更加灵活嵌入单页

安装

  • 使用 克隆或直接下载项目到本地

git checkout https://github.com/linksgo2011/nodecms.git

  • 在根目录下使用命令行执行下面代码,安装nodejs 依赖的模块

npm install

  • 在根目录下找到nodecms.sql文件,导入到你的MySQL数据库中

  • 修改config/connections.js 文件,根据上一步的数据库信息,修改数据库连接

修改数据库连接地址
someMysqlServer: {
host: 'localhost',
user: 'root',
password: '',
database: 'nodecms'
},

  • 启动项目

node app.js

预览

demo 地址 http://nodecms.duapp.com/

后台地址 /admin/user/login

默认用户 admin admin

贡献代码

120377843@qq.com

more >>

写写原生JavaScript系列(1)-使用CSS选择器选择元素

PS:基础决定一个人是否能够在技术路线上走的更远,不积跬步,无以至千里,越来越多的公司看中员工技术基础。那么我们在享受jQuery极大便利的时候,也需要记得返璞归真看看原生的JavaScript 能给我带来些什么,有些时候是有好处的例如移动端可以减少额外的库的加载。偶然发现 plainjs.com 的一系列文章,感觉非常不错,跟着学习的同时搬运到博客,不足之处还望指正。

querySelectorAll() 是一个原生javascript (需要注意兼容性)提供的一个类似jquery选择器的方法。

querySelectorAll() 方法根据你传入的选择字符串返回一组匹配的DOM元素列表。
如果你使用过JQuery操作过DOM元素,你可能对下面的写法不会感到意外:

var matches = document.querySelectorAll('div.foo');

for (i=0; i<matches.length; i++)
    console.log(matches[i].innerHTML);

more >>

使用HTML5创建超级马里奥游戏

原文作者在浏览器中实现一个可以玩的著名的跳跃游戏,作者介绍了动画、面向对象、位运算、图片精灵等诸多干货
下载本文项目源文件 - 0.99 MB

简介

article1.png

在历史上很多优秀的电脑游戏被创造出来,同时奠定了游戏行业发展的基础。这些游戏其中包括了超级马里奥。马里奥这个人物形象第一次出现是在大金刚,随后在1983年的马里奥系列中变得非常出名。现在出现了大量的围绕马里奥形象的衍生版本以及3D版本的游戏。在这篇文章中,我们将开发一个非常简单的超级马里奥山寨版本,为了适合讲解,我们设计得更具有拓展性,具有新的敌人、物品、英雄。

游戏的代码使用OOP的方式来组织。虽然目前JavaScript被认为是一种基于原型的脚本语言,面向对象可能有很多坑,但是我们还是可以尝试使用面向对象。我们将介绍一些关于面向对象的知识和约定,这种模式在整个编码过程会极其有用。

背景

youtube.png

最开始的代码是我的两个学生用我给他们提供的“HTML5编程开发Web应用,CSS3和JavaScript”课程代码为基础。他们开发的游戏包括一个关卡编辑器,声音和图形。游戏本身到没有什么BUG,但是性能比较差,并且代码不是很容易拓展,主要原因是使用了jQuery 的插件。主要是我的责任,因为开始我推荐使用最简单的方法去实现,在简单的情况下使用jQuery插件做动画并没啥问题,但是一旦动画多了就会导致性能问题。因为每一个新的动画(即使同时产生)将会占用CPU的时间片段。

more >>

通过单元测试写出高质量的前端代码

编写JavaScript有时候很痛苦。往往从一段简单而有趣的脚本,慢慢的就变得一团糟。我曾经发现我自己陷入到充满回调和耦合的大杂烩中。因此,我想必须寻找一种有效的方式解决这些问题。

简介

编写JavaScript有时候很痛苦。往往从一段简单而有趣的脚本,慢慢的就变得一团糟。我曾经发现我自己陷入到充满回调和耦合的大杂烩中。因此,我想必须寻找一种有效的方式解决这些问题。在这篇文章中,我想通过书写单元测试来探索这种更好的书写Javascript的方式。

我准备了一个demo来演示这种方式。通过精简不必要的逻辑,仅仅包含一个普通的带过滤功能的商品列表。没啥花哨的东西,但是能够表达出我了解到的这种产生高质量代码的解决方案的要点。

Download source code from Github

more >>

为什么我们需要TypeScript

ps:阅读文章前,先引用一段百度百科关于TypeScript的介绍,具体可以搜索TypeScript以及相关的CoffeeScript

TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。

从1.0的发布开始,我已经对TypeScript项目关注了超过一年。它的理念吸引着我,但是正是因为具有了和大多数语言一样的习惯和特性,我还不能确定它最终是否可以发展起来。无论如何,最近的消息称TypeScript可能会被用于创建 AngularJS2.0,给我了相信TypeScript可以成为主流编程语言的可能以及值得去学习的信心。

我认为是时候开始一个小的项目(下面会贴出来)并且开始体验TypeScript的特性了。

当开始创建上面我说过的项目并且开始写这篇文章的时候,我浏览过大量的"介绍TypeScript"的文章。这里我不想写成和他们类似文章,这些文章有相应的定位,而且在事实上,我使用它们来开始我的TypeScript 旅程。无论如何,我想使用一个不同的视角——我想回到看这篇文章读者的位置,回答某些问题的答案和当我开始关注TypeScript项目的时候在我脑中的一些问题:

  1. 为什么你应该在下一个web或者移动项目中使用TypeScript ?
  2. 什么让TypeScript看起来如此美好——如何使你的工作更加简单并且使项目质量提高?
  3. 回到TypeScript本身,它是如何给javascript加上语法糖以及这些特性?

TypeScript可以比我自己创建更好的JavaScript

more >>

ajaxfileupload.js 原理、常见错误及注意事项

刚刚接到一个BUG任务,在IE8中使用ajaxfileupload组件无法上传文件到服务器,根据单步调试(IE的单步调试还是比较有用)并分析了ajaxfileupload组件。

问题
组件抛出错误为“拒绝访问”,使用控制台发现数据已经返回,服务器上已经成功上传,但是客户端无法获取到结果,因此提示上传失败。

QQ Photo20150513194835.jpg

使用该组件

下载该组件 点击下载

$.ajaxFileUpload({
    url: 'upload.php', //上传地址,需要注意跨域问题
    secureuri: false,
    data: data,
    fileElementId: 'fileToUpload', //该上传input 的ID
    dataType: 'json',
    success: function (data) {
        alert(data.msg);

    },
    error: function (data) {
        alert("error");
    }
});

more >>

nodejs 框架express重要接口思维导图

express() 程序入口,启动一个应用,返回application对象
Application 对象
    简介:app应用单例
    app.set(name, value) 设置应用
    app.get(name) 获取应用设置
    app.enable(name) 启用一项设置
    app.disable(name) 禁用一项设置
    app.use([path], function) 使用中间件方法
    settings 可配置项
        env 运行时环境,默认为 process.env.NODE_ENV 或者 "development"
        trust proxy 激活反向代理,默认未激活状态
        jsonp callback name 修改默认?callback=的jsonp回调的名字
        json replacer JSON replacer 替换时的回调, 默认为null
        json spaces JSON 响应的空格数量,开发环境下是2 , 生产环境是0
        case sensitive routing 路由的大小写敏感, 默认是关闭状态, "/Foo" 和"/foo" 是一样的
        strict routing 路由的严格格式, 默认情况下 "/foo" 和 "/foo/" 是被同样对待的
        view cache 模板缓存,在生产环境中是默认开启的
        view engine 模板引擎
        views 模板的目录, 默认是"process.cwd() + ./views"
    app.engine(ext, callback) 模板引擎
    app.param([name], callback) 实现路由方法
    app.VERB(path, [callback...], callback)  根据请求头部类型快捷实现路由方法
    app.all(path, [callback...], callback) 响应所有的路由请求
    app.locals 放置用于渲染给模板的变量对象
    app.render(view, [options], callback) 渲染模板
    app.routes 存放实现的路由方法列表
    app.listen() 启动http监听
Request 对象
    简介:用于存放客户端发起的请求信息
    req.params 例如路由/user/:name 相似的参数表
    req.query urlget 参数
    req.body 请求体参数
    req.files  bodyParser() 中间件提供 的文件上传后的参数体
    req.param(name) 获取参数通用方法
        请求优先级 req.params > req.body > req.query
    req.route 请求的路由信息
    req.cookies  请求的cookie
    req.get(field) 获取头部字段
    req.accepts(types) 获取客户端接收类型
    req.is(type)  头部类型
    req.ip  返回IP注意代理的情况
    req.ips 返回IP和代理IP数组
    req.path 请求路径
    req.host
    req.xhr 是否是ajax请求
    req.protocol 请求协议
    req.subdomains 获取子域
    req.originalUrl 获取url
    req.acceptedCharsets 获取请求字符集
Response 响应客户端对象
    res.status(code) 返回响应码
    res.set(field, [value]) 设置头部
    res.get(field) 获取响应头部信息
    res.cookie(name, value, [options]) 返回cookie
    res.clearCookie(name, [options]) 清除cookie
    res.redirect([status], url)  res.location  重定向
    res.charset 设置字符集
    res.send([body|status], [body]) 发送响应数据
    res.json([status|body], [body]) 
    res.jsonp([status|body], [body])
    res.attachment([filename]) 设置响应类型为附件,系统根据后缀名自动设置http类型
    res.sendfile(path, [options], [fn]]) 发送文件
    res.download(path, [filename], [fn]) 下载
    res.render(view, [locals], callback) 渲染模板
重要的几个中间中间件
    basicAuth()  用户验证
    bodyParser() 请求体解析 对几个常用的中间件再封装
        json()
         urlencoded()
        multipart() 
    compress() 压缩
    cookieParser() cookies解析
    cookieSession() 利用cookies实现的session
    csrf() CSRF 防护中间件
    directory() 目录解析中间件
其他常用模块
    path nodejs提供
    static-favicon icon模块
    morgan 日志模块
    connect-mongo mongodb 模块
    connect-flash 用户提示消息模块
    multer 比较重要的模块,用于文件上传

more >>