利用MapabcAPI实现基于浏览器的地理定位

August 30th, 2010 CoCoWool No comments

现在互联网中有了越来越多的地理位置服务,正在制定中的HTML5规范也试图在浏览器中内置嵌入地理位置共享服务,而且幸运的是,我们已经能够在Firefox 3.5+、Chrome 5.0+、Opera 10.60+、Safari 5.0+ 以及一些移动终端,注入IPhone、Android上使用这项服务,那么这个服务能否有Mapabc的API结合,来实现用户的地理定位呢?

传统上,地图应用上为用户定位的方式一般是:

用户访问时获得用户的IP。
用这个IP到IP库中匹配用户的城市信息。
根据获取的城市信息去已有的城市中心点字典中进行匹配。
匹配完成后将用户地图的中心点进行相应的切换。

这个过程繁琐,而且准确性极大程度上依赖于我们IP库的准确程度。现在有了浏览器的位置共享服务,我们可以更容易的实现用户的地理定位。

Geolocation对象介绍

正如开头所讲的,到目前为止,W3C中deGeolocation API规范已经在非IE的浏览中得到了实现。规范中提到,浏览器提供位置信息的来源是不固定的,可能是GPS、也可能来自于IP地址、RFID、WiFi、蓝牙或者GSM\CDMA的定位信息,也不保证返回的结果一定准确。Geolocation的API同时对“只获得一次”定位和“持续监督”定位都做出了规定。

Geolocation的一些方法

Geolocation对象位于浏览器Navigator对象下,可以通过 navigator.geolcation 来访问,不支持 geolocation 的浏览器不会包含这一对象,不会造成错误,可以用来做浏览器的区分。

if ( navigator.geolcation ){

    alert(‘ Your Browser dosent support geolcocation ‘);

} else{

    alert(‘ Your Browser support geolocation’);

}

在访问 geolocation 对象时,浏览器会进行提示,询问用户使用许可对网站提供位置服务,得到用户的许可后,访问才会继续,否则会被停止。而且,我们可以捕捉到用户同意或者拒绝的事件。

在获得用户的学科之后,就可以利用Geolocation获取当前位置,核心方法如下:

navigator.geolocation.getCurrentPosition( getPositionSuccess , getPositionError );

上面的代码中,调用了 getCurrentPosition 方法,并且传递了两个回调函数的参数,分别用来处理位置获取成功和失败时的情况。实事上,这个函数还可以接受第三个参数,用来传入一些配置信息,包括对于超时的设置等。下面来看两个获取成功和获取失败时,回调函数的处理。

获取地理信息成功的错误处理信息

function getPositionSuccess ( position ) {

  var lat = position.coords.latitude;

  var lng = position.coords.longitude;

  alert( ‘Now you are lat – lng ‘);

}

 

获取地理位置失败的回调函数

function getPositionError( error ){

    switch(error.code)

         case error.TIMEOUT;

          //Do something

          break;

          case error.PERMISSION_DENIED;

          //Do something

          break;

          case error.POSITION_UNAVAILIABLE;

          //Do something

          break;

}

获取地理位置信息的配置变量。在填入获取地理位置信息变量时,能够对获取地理位置的一些细节进行影响。下面是目前包括的几个具体参数

In ECMAScript, the enableHighAccuracy, timeout and maximumAge properties are all optional: when creating a PositionOptions object, the developer may specify any of these properties.

刚才也提到,我们还可以对地理位置进行持续的追踪,这是需要用到 watchPosition 方法。

因为对于移动设备的用户来说,位置并不是固定的,我们需要来处理这种移动客户端的情况,而不是每次要提醒用户去刷新浏览器来更新位置。

navigator.geolocation.watchPosition( refreshPosition );

与Mapabc API的整合

看完上面的关于 geolocation 的介绍之后,我们就可以将这个服务与Mapabc API一起,整合到我们的应用中了。下面是一个具体的实现样例,供参考:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div>
    <div id="mapobj" style="width:500px; height:500px; border:1px solid black;"></div>
    <div id="info"></div>
    <input type="button" id="getPos" value="Get My Position" />
</div>
<script src="http://app.mapabc.com/apis?&t=flashmap&v=2.3.4&key=0c3235346b1e00772eafe1c099f4b23fe5ec1202d393f952395e628567934baceedcaf1508ea044f" type="text/javascript"></script>
<script type="text/javascript">
    function getPositionSuccess( position ){
        var lat = position.coords.latitude;
        var lng = position.coords.longitude;
        //alert( "您所在的位置: 经度" + lat + ",纬度" + lng );

        var mapOptions = new MMapOptions();//构建地图辅助类
        mapOptions.zoom=13;//设置地图zoom级别
        mapOptions.center=new MLngLat(lng,lat);   //设置地图中心点
        mapOptions.toolbar = MINI;//工具条
        mapOptions.toolbarPos = new MPoint(15,15);  //工具条偏移
        mapOptions.overviewMap = SHOW;//是否显示鹰眼
        mapOptions.scale = SHOW;//是否显示比例尺
        mapOptions.returnCoordType = COORD_TYPE_OFFSET;//返回偏移明码坐标
        mapOptions.zoomBox = true;//鼠标滚轮缩放和双击放大时是否有红框动画效果。
        mapabc.map=new MMap("mapobj",mapOptions); //地图初始

        if(typeof position.address !== "undefined"){
                var country = position.address.country;
                var province = position.address.region;
                var city = position.address.city;
                alert(’ 您位于 ‘ + country + province + ‘省’ + city +’市’);
        }
    }

    function getPositionError( error ){
        switch(error.code){
            case error.TIMEOUT :
                alert( " 连接超时,请重试 " );
                break;
            case error.PERMISSION_DENIED :
                alert( " 您拒绝了使用位置共享服务,查询已取消 " );
                break;
            case error.POSITION_UNAVAILABLE :
                alert( " 亲爱的火星网友,非常抱歉,我们暂时无法为您所在的星球提供位置服务 " );
                break;
        }
    }

    var dom = {
        btn    : document.getElementById("getPos"),
        info: document.getElementById("info"),
        map    : document.getElementById("mapObj")
    };

    var mapabc = {
        map        : null,
        marker    : null
    };

    dom.btn.onclick = function(){
        if( navigator.geolocation ){
            dom.info.innerHTML = "Waiting for the geolocation result…";
            navigator.geolocation.getCurrentPosition( getPositionSuccess, getPositionError );       
        } else {
            dom.info.innerHTML = "Your browser doesn’t support geolocation.";
        }
    }
</script>
</body>
</html>

上面的代码,会在地图显示后询问用户是否共享位置信息,如果共享则会切换地图中心点到相应的位置。当然,我们可以在自己的应用中更加灵活的使用位置共享服务,既然有了这么 Cool 的服务支持,我们还等什么呢。

 

 

 

参考资料:

1、Blueidea BBS
2、Geolocation API Specification
3、Mapabc API

Categories: WebTech Tags: ,

VIM在多窗口编辑时的几个快捷键

June 25th, 2010 CoCoWool No comments

image

使用VI提供的多窗口编辑在项目文件比较多的情况下非常方便。今天总结了几个比较好用的快捷键。

最基本的是打开分割窗口 :sp a.pl

切换窗口 Ctrl + w 按一次加上下键可以自己选择切换方向,按两次则从上到下自动遍历窗口

扩大窗口 Ctrl-w + 扩大窗口

缩小窗口 Ctrl-w – 缩小当前编辑窗口

在vim中执行shell命令 :! ls 这样可以执行shell命令,或者也可以 :shell top

放大当前窗口,缩小其他窗口 :res ,后面可以设置行数,比如 :res 10 则将当前窗口设置为10行

有了这几个功能,在vim中编辑复杂的项目也变得非常简单了

Categories: WebTech Tags:

设计网事读书笔记

June 13th, 2010 CoCoWool No comments

从三月份的时候开始读,利用零零星星的时间,终于读完了千年的《设计网事》这本书。虽名为书,实则是他最近几年的博文汇集而来。纵观此书,却与阅读单篇感觉很不一样。下面是读书的时候,摘抄的一些句子。

SEO的迎合对象是搜索引擎,而我们主张的迎合对象是用户需求

搜索引擎的需求其实就是用户需求的不完全表述

提供服务的关键是有没有效,而不是叫SEO或UCD

1998年,W3C发布HTML 4.0 Specification

每天都有无数的网站消失、无数页面在改版

改版的目标是平稳过渡,让大家不觉得这么陌生

用户挑剔,说明还在乎

Web Design是跨学科的技艺结合体,将来一定是互联网的世界

通过事物的本质去总结出概念,而不是通过概念放大理解事物的本质

超过90%的原创者无法做到有效积累,同样超过90%的阅读者对内容好坏没有准确判断力

互联网设计不是行业,只是个技术领域,参考立足于传统行业设计

规则有规则的秩序感,不规则有不规则的位置感

做真实的自己,不要想复制别人的生活方式和轨迹

此书并没有长篇累牍的的设计理论,也没有太多枯燥无味的技术教程,加上合理的编排,让我感觉受益良多

1、互联网产品,甚至做任何事情都得有自己的想法。所有事情都需要经过自己的思考提炼,而不是人云亦云。就像有一篇讨论电梯按钮排布的文章,平凡的日常现象,其实背后也有通用的艺术设计原则。我们一则是需要认真的观察,同时还需要融入自己的思考。做事情,不能为完成而完成,加入自己的想法,才能使产品不断地进步。

2、流程化的管理和团队合作非常重要。现在互联网的项目,不再是单枪匹马就能够做出花样的年代。Ajax、CSS、DOM结构、后台,构建一个成熟的Web 2.0应用时,这些东西必不可少,在不可能一个人全完成的情况下,团队协作和流程管理就非常重要。我目前所在的单位,基本上就是按照瀑布式的开发方式来进行的,我想国内多数做互联网的团队应该也都是这个模式。敏捷目前还没试验过,感觉其实现门槛比较高,只有小组成员都具备了敏捷的能力之后,才能谈得上。所以,我相信,规范化的管理流程,是推进提高生产率的关键因素。

3、用户体验,需要用心、细致的去做。在一个趋同的审美背景下,要把自己的产品做到出彩,做到令人过目不忘常回头。在用户体验的界面设计上,必须要用心、细致的去做。互联网产品的产生过程,是一个技术和艺术结合的过程。我们不能只看艺术性而忽略了开发商的难度,也不能只考虑开发上的便捷性,而把一堆丑陋的页面丢给用户。从重要性上来看,应该吧界面设计与交互设计放在技术开发之前。首先,很多需求的产生是来自战略层而不是技术人员,所以需要有足以说服人的细化的原型作为基础。

以上是一些合上书之后的胡思乱想,看来自己的思维系统性和整理性还是有待强化。

Technorati 标签: ,,,,,

PHP性能监测的工具介绍 – XHProf

June 2nd, 2010 CoCoWool No comments

XHProf

这个软件本是Facebook内部的一个应用工具,2009年3月份开源,为PHP的性能监测提供了很好的工具。官方的介绍中提到:

XHProf is a hierarchical profiler for PHP. It reports function-level call counts and inclusive and exclusive metrics such as wall (elapsed) time, CPU time and memory usage.

XHProf’s light-weight nature and aggregation capabilities make it well suited for collecting "function-level" performance statistics from production environments.

 

可以先来看看 XHProf 提供的图形界面的截图

 

XHProf的一些特性:

1、Flat Profile. 提供函数级的汇总信息,比如调用次数、执行时间、内存使用、CPU占用等。

2、Hierarchical Profile。 对每个程序,进行了父级调用和子级调用的分解。

3、Diff Reports(差异报告)。有很多种情况,我们希望能够对比,比如新版本比旧版本提升了多少速度,两个版本的差距究竟在哪里。Diff Report 就是这样的工具,接收两个输入,并且分别给出各自的 Flat Profile 和 Hierarchical Profile 报告。

4、Callgraph View(调用视图)。性能监测的数据可以绘制成调用视图,方便我们查看。

5、Memory Profile(内存监控)。这个特性帮助我们了解PHP如何分配和释放内存。值得注意的是,XHProf并不是严格的监测内存的分配和释放动作,而是计算每个函数进入和退出时的内存状况,这是一个相对简单的实现方式,但是基本上也能够满足我们日常的监控需求。

6、如何处理外部文件。XHProf将 include,require,include_once,require_once进来的文件视作是一个 function。

XHProf目前只支持一个级别的函数追踪,但是貌似也没有特别大的影响。

XHProf的安装配置

xhprof的安装配置很简单,我们首先在 PECL 的网站上下载 源码包 然后执行安装过程

% cd <xhprof_source_directory>/extension/
% phpize
% ./configure --with-php-config=<path to php-config>
% make
% make install
% make test

php.ini file: You can update your php.ini file to automatically load your extension. Add the following to your php.ini file.

[xhprof]
extension=xhprof.so
;
; directory used by default implementation of the iXHProfRuns
; interface (namely, the XHProfRuns_Default class) for storing
; XHProf runs.
;
xhprof.output_dir=<directory_for_storing_xhprof_runs>

 

xhprof的使用也很简单,只要将需要监控的脚本放在 xhprof_enable() 和 xhprof_disable() 中间,就可以得到相应的结果,同时也提供了一些参数可以让我们设置是否监控 Memory, CPU 的使用,是否监控PHP内置的函数,从 0.9.2 之后,还可以设置跳过一些特定的函数。

XHProf 生成的数据,可以用 XHProf UI 来进行简单的显示。

XHProf使用也很简单,下面是一个官方的例子:

<?php

function bar($x) {

  if ($x > 0) {

    bar($x – 1);

  }

}

function foo() {

  for ($idx = 0; $idx < 2; $idx++) {

    bar($idx);

    $x = strlen("abc");

  }

}

xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);

foo();

$xhprof_data = xhprof_disable();

//

// Saving the XHProf run

// using the default implementation of iXHProfRuns.

//

include_once "xhprof_lib/utils/xhprof_lib.php";

include_once "xhprof_lib/utils/xhprof_runs.php";

$xhprof_runs = new XHProfRuns_Default();

// Save the run under a namespace "xhprof_foo".

//

// **NOTE**:

// By default save_run() will automatically generate a unique

// run id for you. [You can override that behavior by passing

// a run id (optional arg) to the save_run() method instead.]

//

$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");

echo "—————\n".

     "Assuming you have set up the http based UI for \n".

     "XHProf at some address, you can view run at \n".

     "http://<xhprof-ui-address>/index.php?run=$run_id&source=xhprof_foo\n".

     "—————\n";

?>

 

我们可以持久化记录的数据,数据以文件的形式保存在指定的目录,如下图:

image 有了这个工具,我们可以根据其提供的数据,与相应的通知接口整合,在程序运行出现问题时,及时的发送通知信息。

 

PHP性能监控,还有两个可用的工具,一个是 XDebug,另外一个是 ZendServer,我会在接下来继续进行介绍。

Technorati 标签: ,,

参考文档:

1、Speed UP your php with xhprof

2、xhprof document

Categories: WebTech Tags: , , , ,

利用PUT方式上传文件的方法研究

May 30th, 2010 CoCoWool No comments

虽然没有POST方法使用广泛,但是PUT方法却是向服务器上传文件最有效率的方法。POST上传文件时,我们通常需要将所有的信息组合成 multipart 传送过去,然后服务器再解码这些信息,解码过程则必不可少的会消耗内存和CPU资源,这种现象在上传大文件时尤其明显。而PUT方法则允许你通过与服务器建立的socket链接传递文件的内容,而不附带其他的信息。

最近一个项目上需要利用这种方式来进行文件的上传,下面介绍一下在 Apache + PHP 的环境下如何进行PUT方式的文件上传。

Apache 有一个模块 mod_actions,先看看官方的说明:

This module has two directives. The Action directive lets you run CGI scripts whenever a file of a certain MIME content type is requested. The Script directive lets you run CGI scripts whenever a particular method is used in a request. This makes it much easier to execute scripts that process files.

也就是说,这个模块可以指定对于特定 MIME 类型的文件处理,或者对于特定脚本的请求进行指定的处理。我用到的就是 Script 这个选项。

在Apache 配置文件的 Directory 中指定

Script PUT /receive.php

这个含义就是,对于所有对服务器的PUT请求,都交给根目录下的 receive.php 去处理,当然我们也可以选择 perl 或者其他的CGI脚本来进行处理。

接下来就是这个 receive.php 脚本的编写了,他的主要任务就是将请求的文件写到指定的位置

<?php
/**
* Process The PUT File, receive and move a file to corresponsed location
* Created by shiqiang<cocowool@gmail.com> at 2010-05-24
*
**/

class Receive {
    var $default_log_file = "logs/error.log";
    var $default_server_info = "logs/server.log";
    var $default_header_info = "logs/header.log";
    var $default_prefix = "/data1/vhosts";    //Default project location prefix;
    var $default_module = "test.cn";
    var $max_filesize = 2048000;
    var $request_uri;

    function Receive(){
        $this->request_uri = $_SERVER['REQUEST_URI'];
    }
    function saveFile(){
        //receive data and save
        $putdata = fopen("php://input", "r");

        $path = $this->getPath($this->request_uri);
        $fp = fopen($path, ‘w’);
        while($data = fread($putdata, 1024) ){
            fwrite($fp, $data);
        }

        fclose($fp);
        fclose($putdata);

        //Log The filesize check and limit check
        if( filesize($path) != $_SERVER['CONTENT_LENGTH'] ){
            $this->errorLog( "[warn] " . date("Y-m-d H:i:s")  . " The file’s ($path) size dosen’t match Server Filesize = " . filesize($path) . "; Put Filesize = " . $_SERVER['CONTENT_LENGTH']. "\r\n" );
            header(’HTTP/1.1 526 Receive Data Error’);
        }

        if( filesize($path) > $this->max_filesize ){
            $this->errorLog( "[warn] " . date("Y-m-d H:i:s")  . " The file’s ($path) size exceed the system limit");
        }
    }

    //Log Error Info
    function errorLog( $info ){
        $f = fopen($this->default_log_file, ‘a+’);
        fwrite($f, $info);
        flcose($f);
    }

    function serverLog(){
        $f = fopen($this->default_server_info, ‘w’);
        $info = $_SERVER;
        $str = "The Last Request Server Info:\r\n";
        foreach ($info as $key => $value){
            $str .= "$key = $value\r\n";
        }
        $str .= $this->getPath($this->request_uri) . "\r\n";
        $str .= "PHP_UPLOADED_FILE_NAME=" . $PHP_UPLOADED_FILE_NAME . "\r\n";
        fwrite($f , $str);
        fclose($f);
    }

    //Log the Request Header info
    function headerLog(){
        $f = fopen($this->default_header_info, ‘w’);
        $info = get_headers();
        $str = "The Last Request header Info:\r\n";
        foreach ($info as $key => $value){
            $str .= "$key = $value\r\n";
        }
        fwrite($f , $str);
        fclose($f);
    }

    //get the path where the file should be
    function getPath($uri){
        $module = $this->defalt_module;    //Default storage module

        $referer = $this->request_uri;
        preg_match(’/(?<=\/)(.*?)(?=\/)/s’, $referer, $match);

        if( !empty($match) && !empty($match[0]) ){
            $module = $match[0];
        }

        $path = $this->default_prefix;
        $path .= ‘/’ . $module . ‘/htdocs’;
        $fullpath = substr($uri, strlen($match[0]) + 1, strlen($uri) );

        $arr = explode(’/', ltrim($fullpath, ‘/’));
        foreach($arr as $v){
            if( !strstr($v, ‘.’) ){
                $path .= ‘/’ . $v;
                //exec("echo $path >> dir.txt");
                if( !is_dir($path) ){
                    //For php > 5.0
                    //mkdir($path, "0766", true);
                    mkdir($path, 0766);
                }
            }else{
                $path .= ‘/’ . $v;
            }
        }

        return $path;
    }

}

$instance = new Receive();
$instance->serverLog();
//$instance->headerLog();
$instance->saveFile();

?>

这个脚本,使用PHP手册中的接收PUT方式的方法,详细的使用,GOOGLE的时候,并没有找到很多,所以可能对于错误情况,考虑的也不是很全面,如果有使用过这个方法的欢迎和我讨论。

Technorati 标签: ,,

参考资料:
1、PUT Upload
2、RFC 2616

Categories: WebTech Tags: , , ,

通过设置双网卡实现VirtualBox虚机上网及主宿互访

May 26th, 2010 CoCoWool No comments

最近,经过一些研究,终于调通了VirtualBox虚拟机互连、主宿机互连、以及主宿机连接互联网。下面分享一下。

1、VirtualBox中的虚拟网卡。VirtualBox安装完成后,会在系统中装一块虚拟网卡,我们在管理->全局设定中可以看到。这块网卡是在 Host-Only 连接方式中,主宿机互访的桥梁。

0GNO4}~D]5R]S32KPW37B}7

2、主机访问虚拟机通过Host Only的方式实现。

主机访问虚拟机这个是最简单的。通过在网络连接1中选择 Host-only Adapter ,我们的虚拟机就可以获得一个内网的地址,主机可以直接访问这个地址。我们可以使用DHCP,也可以自己指定IP,多数情况下,都会指定一个固定的IP。

PUB}7VB28B%2SQS4)E%EXDY

3、现在要想实现虚拟机上网,我们可以为虚拟机再添加一块网卡,通过Bridge方式,达到虚拟机上网的目的。

9)N`XA15%{3UJIGA}D~IW3N

4、但是笔者在这样设置以后,测试 ping www.baidu.com 时,发现网络并没有通,仔细检查后发现,需要在我们的第二块网卡的配置上,指定他的网关。我在 /etc/sysconfig/network-scripts/ifcfg-eth1 中添加

GATEWAY=10.207.0.11

重启网络之后,就可以PING通了。

这样,我们既能访问虚拟机,又可以访问互联网,利用各种在线更新的工具,大大的方便了 Linux 的使用。

基于Mapabc API的周边查询应用

May 23rd, 2010 CoCoWool No comments

现在,越来越多的 Location Based 应用,或者Geolocation的应用出现在网络、手机等各种各样的终端上,为人们的日常生活、出行和工作都提供了不少的便利。最常见的就是出门前,利用地图工具,看看合适的公共交通路线,寻找一个自己最满意的方案,既方便有低碳环保。有时候,对周边环境不熟悉,想要找到周边的医院、银行、学校等一些单位的时候,地图同样可以帮上我们的大忙。

今天,我就做了一个基于Mapabc地图API的周边查询工具,利用Mapabc详尽的基础地物信息,为我查找周边的便民信息提供了有利的帮助。

开始之前,我大概需要知道最后的结果是什么样子的,可以借助传统的纸和笔,也可以用现代的原型工具,当然PS这样的重量级工具就不太需要了。下面是效果图:

1131

有了效果图,接下来需要稍微规划一下代码。Mapabc的API在页面加载完成后,需要初始化地图,所以初始化的操作放在一个函数 pageInit() 中。周边查询的操作,希望通过用户输入一个关键词,然后通过点选地图设置中心点的方式实现。那么就需要一个函数来监听鼠标在地图上的单击事件,然后一个负责查询的函数和一个负责显示结果的函数。程序的结构大致如此,接下来就进入实质的编码过程。

编码的重点函数有以下几个:

mapObj.addEventListener(mapObj, MOUSE_CLICK, searchAround);

对地图添加监听事件。

mls.poiSearchByCenterXY(new MLngLat(cordx, cordy),keyword,citycode,mlsp);

利用中心点坐标查询查找周边信息

利用这两个函数,加上参考Mapabc官方的示例,我们就可以完成这个应用。

1132

通过修改区号和关键字,可以在不同城市之间切换,怎么样,简单吧。

Technorati 标签: ,,,
Categories: WebTech Tags:

Google首页的一个细微变化

May 12th, 2010 CoCoWool No comments

最近发现Google首页左上角那些功能链接都加上了下划线,即便是More点出来的下拉菜单也不例外。

下面用图说话:

0029

但是其他应用中的链接仍然保持了原来的摸样,并没有下划线。

0028

由此可见,虽然已经过了这么多年,我们通过各种技术手段可以对超链接进行各种形式的美化,但是带下划线的文字仍然是最常见、也让用户最容易理解的形式。我觉得这就像筷子,只要有华人的地方,就会有筷子的存在。而只要是有互联网的地方,就一定会有下划线的存在。

Categories: Misc Tags:

Solaris已经死了,Linux万岁

April 6th, 2010 CoCoWool No comments

0074

中午的时候看到这个标题,顿时没了困意,Long Live Linux~~

文中据说窥到了Oracle今后行动的一些端倪,是的从去年以来,我们一直都在等待着这个巨人的行动。

从1993年Linux诞生以来,这个家伙改变了整个IT界,曾经昂贵、封闭的Unix系统,在IBM的倒伐和Google的无视下,现在已经奄奄一息了。

image image

无需多说,看看这个对比吧

就连Unix界的巨人,Sun Microsystems也认识到,昨日的辉煌已经不在了,于是,在2005年我们便有了可以自由下载使用的Solaris 10。

Linus这样说到“A lot of people still like Solaris, but I’m in active competition with them, and so I hope they die.”

Linus应该感到高兴,因为Solaris的新东家 Oracle 宣布,Solaris 将恢复原来的收费。

Oracle修改了Solaris的发布条款,从此以后没有人能够在享受90天以上免费的Solaris。过去,Sun为了保持Solaris的市场份额而采取免费策略,现在Oracle撤销了之前所做的一切努力。确实如此,Oracle在Linux平台上也有支持的版本,所以Solaris收费影响也不大了。

但是,这可苦了那些正在使用Solaris的用户,Oracle已经在Solaris的棺材上钉下了最后一颗钉子,那么Mysql呢?

参考资料:
1、Solaris Is Dead. Long Live Linux

Categories: Misc Tags:

警惕Div和Class的滥用

April 4th, 2010 CoCoWool No comments

大概在06年的时候,我刚接触Div+Css的网站布局,那个时候大家对于标准的热情非常高涨,蓝色论坛里经常为了Table还是Div+Css而争论的热火朝天。现在,大家已经形成了共识,Table用来布局是不行的,但是网页里完全不用Table,也是不好的。

于是大家就开始都用Div+Css布局,这样做的目的本来是为了让网页文档更语义化、结构更加清晰、代码更加少、便于维护,这是一个非常好的目标。但是事实告诉我们,有好的目标,不一定能够做出好的事情来。紧接着,就开始出现了Div和Class的过渡使用。特别是在借用了一些Css框架,诸如960.gs,YUI Grid 这样的CSS框架的时候,我们会不自觉的多使用一些Div。

这些CSS框架为我们提供了一套解决方案,使用框架确实能为我们节省不少的时间(其实,我们如果经常写页面的话,也会积累一些常用的CSS,但是并没有汇集成框架),但同时也减少了我们自主考虑的空间,增加了我们的惰性。

以 960.gs 为例,这是一个很著名的理论,国内的一些博客上曾经做过介绍,其原则就是将960px的宽度进行不同程度分割,来达到标准化、模块化使用的目的。如下图,通过使用 960.gs 只需要一个简单的 class 就可以为我们提供不同的标准分割。

image 在其内部,我们可以按照自己的规划进行布局。

image 可以看到,这套框架非常好用,但同时,我们不可避免要使用很多的Div以及Class,按照这套框架的要求来进行结构的编写,同时,加上我们页面中个性化的内容时,过度就开始了。

为了避免这种情况,有几个原则可以遵循:

1、只使用必要地类。特别是框架提供的类,需要那种布局,就明确使用哪种类;
2、在除了 html、head、meta、param、script、title、style之外的元素上,都可以使用类,所以如果希望实现三栏的布局,不必一定要 <div class="grid_3"><img src… 完全可以直接在 img 标签上使用 class="grid_3",这样,无疑就减少了三对 div 的使用。而且,有时候这样用起来,更加符合语义文本的目标。
3、在父元素中使用类,而不是在每个子元素中都加。这个貌似是地球人都知道的规则,但其实真正在实际过程中,如果没有对于样式结构及其继承关系做规划的话,很容易的就需要在子元素中写上很多的特殊的类。这就要求我们必须具有抽丝剥茧的精神,将可以共用的元素样式都抽取到上一级元素上。

 

参考资料:
1、Fight Div-itis and Class-itis
2、960 Grid System
3、YUI2 Grid CSS

Categories: WebThoery Tags: