可以在前端实现的几个地理位置小功能

在Smashing Magazine上看到这篇Entering The Wonderful World of Geo Location,介绍了获取并处理用户地理位置的应用和方法,很有意思。结合原文的内容,加上之前的一些应用,整理了几个可以完全在前端实现的地理位置相关小功能。

1.通过IP获取用户位置

很多时候需要通过IP判断用户的位置,通常的办法是通过自己的后台程序查询数据库得到。如果用户位置只是应用在前端,或者有其他的特殊原因(比如,懒:),也有一些其他办法来快速的获取用户位置。

maxmind.com提供了一个服务,通过引入一个js文件(http://j.maxmind.com/app/geoip.js),可以把他判断到的用户的国家、城市、经纬度等信息加入到页面中来。下面是从青岛访问这个js文件返回的内容:
阅读全文 »

JavaScript单元测试工具 — QUnit

QUnit是jQuery团队开发的JavaScript单元测试工具,使用方便,界面美观。近期试用了一下并进一步了解了JavaScript单元测试,记录一下所思所得。

什么是单元测试

单元测试又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。单元测试主要是用来检验程式的内部逻辑,也称为个体测试、结构测试或逻辑驱动测试。通常由撰写程式码的程式设计师负责进行。

通常来说,程式設計師每修改一次程式就會進行最少一次單元測試,在編寫程式的過程中前後很可能要進行多次單元測試,以證實程式達到軟件規格書(en:Specification)要求的工作目標,沒有臭蟲;雖然单元测试不是什么必须的,但也不坏,這牽涉到專案管理的政策決定。

—— 维基百科 (中文英文)

为什么JavaScript需要单元测试

阅读全文 »

哥写的不是程序,是寂寞

当一群无限的牛人把一门有限的语言玩到一种山穷水尽又柳暗花明的地步,那个时候,他们写的不再是程序,是寂寞。

JavaScript就是这样一种语言,JavaScript背后就有这样一群牛人,这些人大抵分两种:

一种是Douglas Crockford这样的大牛,他们已经技术上登峰造极,生活上名利双收。剩下要做的就是到处演演讲,搞搞活动,偶尔扔出几篇小文章供人崇拜。他们温文尔雅谦卑和蔼的面孔后面,总是藏着那么一种悲天悯人、众人皆醉我独醒的让人忧伤而蛋疼的笑容。他们带着这样一种态度,去讲课,去布道,去度假。。闲云野鹤,悠哉游哉。

Douglas Crockford的寂寞笑容

Douglas Crockford的寂寞笑容

他们是寂寞的,另一种就是在“找寂寞”的。

之前看到有日本人写的JS多线程框架,洋洋洒洒1万5千行代码,把个本来单线程的语言整的像多线程运行一般无二致。粗读代码,令人震精,把传进来个函数拆分组合,顺成一条新的程序去运行,程序严谨,条理清晰。世上函数何止亿万,程序亦分三六九等,他们居然有这个魄力去重建规则。

又见有人写的基于V8的服务器端js框架,V8之快有所耳闻目睹,却从没想过它可以放到服务器上使。asp的时代早已过去,服务端语言变得越来越复杂,让js这个为浏览器而存活的语言去提供网站服务,有魄力,够寂寞。

。。。

这几天看到了太多寂寞的牛人的寂寞程序,每每让我内牛满面欲火焚身。自己皮袍下藏着小顿时暴漏无遗。时时拷问自己,我有什么资格谈寂寞,每思及此,则心情振奋。

撰文以共勉。

Javascript 最佳实践

原文:JavaScript Toolbos

翻译:幸福收藏夹

简介

这个文档是基于Javascript社区众多开发者的意见和经验,在开发Javascript代码上的最佳实践和首选的方案的明细表。因为这是一个推荐的表而非原则性的方案,经验丰富的开发者可能对下面的表达会有略有不同的见解。

文章目录:

阅读全文 »

JavaScript程序执行顺序问题总结

好记星不如烂笔头,适时的总结梳理知识让人更轻松愉快。今天总结下学习和开发中遇到的JavaScript执行顺序的问题,今天挖个坑,以后会慢慢填,也希望抛砖引玉,能学到更多的东西。

顺序可能比较乱,写多了再整理,有些术语可能运用也不恰当,欢迎批评指正。以下使用的示例程序都经过了本人的实际验证,兼容各大浏览器。OK,步入正题。

1. 变量的声明和引用

变量必须先声明后引用,这个大家是都知道的,但还是要说说,因为后面要说到一个相关的问题。

alert(myStr); // 弹出"undefined";
var myStr = "Hello World!";
alert(myStr); // 弹出"Hello World";

2. 函数的声明和调用

阅读全文 »

JavaScript中使用JSON

虽说JavaScript原生支持JSON,但真用到的时候,也遇到了一些麻烦。下面整理一些JSON相关的JS程序。

1. 将JSON字串解析为对象

最简单的方法是使用eval

var jsonStr = '{ "name": "幼学笔记", "url": "oncoding.cn" }'; //定义一个json字符串
var jsonObj = eval( '(' + jsonStr + ')' ); //使用eval解析成对象
console.log(jsonObj);

阅读全文 »

Google Maps Api介绍与基础操作

一. 关于Google Maps Api

“API”,即“应用程序编程接口”,是指软件或网站为第三方开发人员提供的接口,利用这个接口,可以使用软件的一些功能而不必了解它的内部机理。

具体拿Google Maps Api来说,它提供了一个JavaScript库,具体就是我们上节课在页面头部引入的这个url:http://ditu.google.com/maps?file=api&v=2&key=KEY ,它会自动载入地图所需的js文件,Firefox肿的Firebug插件是前端开发必备工具,使用它我们可以方便的查看网页的内容,可以看到Google Maps Api引入的几个JS文件:


( Google Maps Api引入的文件 )
阅读全文 »

Javascript判断浏览器和操作系统类型:Ext中的最全面简洁方法

前端开发中,经常需要判断浏览器或系统类型,以解决兼容性问题。

使用Javascript判断浏览器和操作系统类型是一件很容易的事情,但如何最全面、最简单的做出判断,是不容易的,Ext中的浏览器判断非常全面且简洁,包含了最新的IE8、Chrome浏览器、Air浏览的判断,下面是从Ext 2.2.1众摘录的代码,并添加了注释:

var ua = navigator.userAgent.toLowerCase();
var isStrict = document.compatMode == "CSS1Compat", // 是否定义DOCUMENT类型
    isOpera = ua.indexOf("opera")>-1, // 是Opera
    isChrome = ua.indexOf("chrome")>-1, //是Chrome
    isSafari = !isChrome&&(/webkit|khtml/).test(ua), //是Safari
    isSafari3 = isSafari&&ua.indexOf("webkit/5")! = -1, // Safari3
    isIE = !isOpera&&ua.indexOf("msie")>-1, //IE6
    isIE7 = !isOpera&&ua.indexOf("msie 7")>-1, // IE7
    isIE8 = !isOpera&&ua.indexOf("msie 8")>-1, //IE8
    isGecko = !isSafari&&!isChrome&&ua.indexOf("gecko")>-1, // Gecko内核
    isGecko3 = isGecko&&ua.indexOf("rv:1.9")>-1, // Gecko3内核
    isBorderBox = isIE&&!isStrict, // 使用盒模型
    isWindows = (ua.indexOf("windows")! = -1||ua.indexOf("win32")! = -1), // 是Windows系统
    isMac = (ua.indexOf("macintosh")! = -1||ua.indexOf("mac os x")! = -1), // 是MacOS系统
    isAir = (ua.indexOf("adobeair")! = -1), // 是用Adobe Air浏览
    isLinux = (ua.indexOf("linux")! = -1), // 是Linux系统
    isSecure = window.location.href.toLowerCase().indexOf("https") === 0;  // 是SSL浏览

使用JavaScript+CSS制作伸缩菜单

演示地址:http://www.oncoding.cn/demos/jsmenu/index.html

前段时间项目里用到的,项目已经发布,今天整理一下发出来。

不用框架,纯JavaScript+CSS制作的二级伸缩菜单,简单易懂,具有很强的定制性和重复开发性。

页面调用方法:

<!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">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>JavaScript可伸缩菜单 - Oncoding编码营原创</title>
  <!--引入JS文件-->
  <script type="text/javascript" src="jsmenu.js"></script>

    .....
  <!--加载程序-->
<body onload = "initMenu()">
  <!--此处须定义ID-->
  <div class="jsmenu" id="pm_menu">
    <!--展开的一级分类-->
    <div>
      <span class="fath">业界资讯</span>
      <p class="son">
        <!--class="current"当前所在二级分类-->
        <a class="current" href="#">业界新闻</a>
        <a href="#">技术动态</a>
        <a href="#">八卦评论</a>
      </p>
     </div>
     <!--闭合的一级分类-->
     <div class="collapsed">

       ....

     </div>
     <!--独立的一级分类-->
     <div><span class="single"><a href="#">酷站</a></span></div>

    ....

程序说明:

//在ID为“js_menu”的div内开始程序
function initMenu(){
      var pm_menu = new JSMenu("js_menu");
        pm_menu.init();
    }
//定义主函数
function JSMenu(id) {
    if (!document.getElementById || !document.getElementsByTagName)
        return false;
    this.menu = document.getElementById(id);
    this.submenus = this.menu.getElementsByTagName("div");
}
//引入函数,取得所有span
JSMenu.prototype.init = function() {
    var mainInstance = this;
    for (var i = 0; i < this.submenus.length; i++)
        this.submenus[i].getElementsByTagName("span")[0].onclick = function() {
            mainInstance.toggleMenu(this.parentNode);
        };
    this.expandOne();
};
//展开含"current"的菜单
JSMenu.prototype.expandOne = function() {
    for (var i = 0; i < this.submenus.length; i++) {
        var links = this.submenus[i].getElementsByTagName("a");
        for (var j = 0; j < links.length; j++){
            if (links[j].className == "current")
            this.expandMenu(this.submenus[i]);
            }
        }
};
//变换菜单状态函数
JSMenu.prototype.toggleMenu = function(submenu) {
    if (submenu.className == "collapsed")
        this.expandMenu(submenu);
    else
        this.collapseMenu(submenu);
};
//展开所有菜单函数
JSMenu.prototype.expandMenu = function(submenu) {
    var fullHeight = submenu.getElementsByTagName("span")[0].offsetHeight;
    var links = submenu.getElementsByTagName("a");
    for (var i = 0; i < links.length; i++)
        fullHeight += links[i].offsetHeight;
    var moveBy = Math.round(5 * links.length);

    var mainInstance = this;
    var intId = setInterval(function() {
        var curHeight = submenu.offsetHeight;
        var newHeight = curHeight + moveBy;
        if (newHeight < fullHeight)
            submenu.style.height = newHeight + "px";
        else {
            clearInterval(intId);
            submenu.style.height = "";
            submenu.className = "";
        }
    }, 30);
    this.collapseOthers(submenu);
};
//折叠菜单函数
JSMenu.prototype.collapseMenu = function(submenu) {
    var minHeight = submenu.getElementsByTagName("span")[0].offsetHeight;
    var moveBy = Math.round(5 * submenu.getElementsByTagName("a").length);
    var mainInstance = this;
    var intId = setInterval(function() {
        var curHeight = submenu.offsetHeight;
        var newHeight = curHeight - moveBy;
        if (newHeight > minHeight)
            submenu.style.height = newHeight + "px";
        else {
            clearInterval(intId);
            submenu.style.height = "";
            submenu.className = "collapsed";
        }
    }, 30);
};
//折叠其他菜单函数
JSMenu.prototype.collapseOthers = function(submenu) {
        for (var i = 0; i < this.submenus.length; i++)
            if (this.submenus[i] != submenu && this.submenus[i].className != "collapsed")
                this.collapseMenu(this.submenus[i]);
};

应该解释的比较清楚了,还有不明白的可以在下边问。

打包下载

幼学笔记原创内容,根据CC协议发布,欢迎具名转载。