聚會時間公告: 因應COSCUP 2011, Kalug 8月份休會一次

三月 28, 2014

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» html5-boilerplate 打算不支援 IE8 瀏覽器

html5 boilerplate 是一套免費前端 Html5 模板,裡面支援 Normalize.cssjQuery (透過 Google CDN 或本地端讀取) 及 Modernizr,目前支援 IE 8 以上瀏覽器,但是最近看到官方正在討論是否該拿掉 IE 8 支援,原因是 Microsoft 今年宣佈 2014 年 4 月 8 日以後將不再支援 Windows XP,討論中也提到目前 IE 8 的市占率,其實還不小,雖然大部分使用者可能來自亞洲

討論列也有人提到,是否可以跟 [Google 一樣直接捨棄 IE8 及 IE9],可以看到

As previously announced, Internet Explorer 11 launched on October 17, 2013, and as a result, we’ve discontinued support for Internet Explorer 9.

Google 的做法相當棒

At Google, we’re committed to developing web applications that go beyond the limits of traditional software. Our engineering teams make use of new capabilities available in modern, up-to-date browsers. That’s why we made the decision last year to support only modern browsers, which also provide improved security and performance.

十二月 7, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Javscript 18 歲生日歷史演進

resin.io 看到這篇 Happy 18th Birthday JavaScript! A look at an unlikely past and bright future. 裡面有些 Javascript 發展史,蠻有趣的,分享給大家看看。18 年前由 Netscape 和 Sun 共同 Release Javscript,在當年18天後,Ruby 也同時發佈了,底下來看看 Javscript 歷史演進。

JavaScript 發展史

1995: 由 Netscape 和 Sun 共同發佈 Javscript,並且命名為 MochaLiveScript,當時參與開發 Javascript 的其中一位負責人 Brendan Eich,現在為 Mozilla CEO。

1996: Microsoft Javscript 版本出現,並且命名為 JScript,同時發佈 Internet Explorer 3.0。這年也是 CSS 釋出第1版

1997ECMA 第1版釋出。

1998: Netscape 將 Netscape browser open source release 出來,並且成立 Mozilla Project。過了幾個月, AOL 買下 Netscape

1999: IE5 提出介紹 XMLHttpRequest

2001: IE6 正式 Release,截至目前為止,IE6 最大用戶還是在中國大陸 XD。

2002: 大家常用的 JSON 在這時候 Release,同時間 Mozilla 發佈 Firefox

2003: Apple 也不甘示弱發佈 Safari Beta Release。

2004: Google 發佈 Gmail released 產品,Gmail 用了大量 AJAX 技術,也造就現今的 Web Application。Google 挑4/1發佈,讓大家以為是惡作劇一場 XD。

2005: Apple open source Webkit,此專案是從 KHTML fork 出來的。同時間 Jesse James Garrett 發佈一篇 AJAX

2006: John Resig 發佈第1版 JQuery,現今的網站超過 90% 都會使用 jQuery,它被視為 “better cross-browser DOM API”。此年 Microsoft 同時發佈 IE 7。

2007: Douglas Crockford 講了一場 keynote 議題名稱為 JavaScript: The good parts 將來成為 O’Reilly 2008 年一本書。同年 Leonard Richardson and Sam Ruby 出了 RESTful Web Services 書。

2008: Google 推出自家瀏覽器 Chrome 和 V8 Engine,帶給瀏覽器不同的衝擊。

2009: 誰說 JavaScript 只能寫在 Client 端,Ryan Dahl 釋出 node.js,帶來用 js 寫 sever side 風潮,同年 PhoneGap 帶來 HTML5 和 JavaScript 整合到 Android 及 iOS。

2010: 一堆 JavaScript Library 同時釋出 NPM, BackboneJS, RequireJS

2012: Single-page app frameworks 出現: AngularJS 1.0, Ember 1.0.pre。

2013: Firefox OS 用 JavaScript 撰寫 UI Layer,並且正式 Release,Mozilla 同時發佈 asm.js

JavaScript 效能

Jan T. Sott 用 Kraken benchmark 發佈一篇 performance 報告,測試環境從 Firefox 3.5 to Chrome 23 同環境下測試

overall_kraken_2012

可以參考原始連結

JavaScript 生態

我們來看看眾多語言的變化

npm

可以發現 Node.js 正在往上衝阿,相信到 2015 年可以追上 Rubygems 及 Maven Central. 除了 55000+ 的 NPM package 及 6000+ package in broser 帶給使用者更好的體驗

另外 Github 也統計用其他語言寫的工具給 JavaScript 用

最後看看 Github repositories 的生態

jsgh 資料來源 Twitter,JavaScript 往上衝阿,難怪全世界都在缺 Frond End Engineer。

總結

現在用 JavaScript 寫 Client-Side 已經不稀奇了,現在有很多 Project 開始設計如何透過 JavaScript 去控制硬體,可以看到 File API and Device API 或者是 Chrome Apps, Mozilla WebAPI, and Tizen Web APIs 等專案,這些專案共通點就是希望開發者可以透過 JavaScript 來控制硬體裝置。另外也可以透過 node-webkit 來溝通。

想了解 EmbeddedJS 可以關注現有的專案或研討會 Nodebots, Nodecopter, Tessel.io, Espruino, Device.js,或者是 application 像是 heimcontrol.js and Google Coder for Raspberry Pi,很難想像 18 年後的 JavaScript 會變成什麼樣子 XD。

十一月 20, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» jquery-serialize-object 不支援 IE7,8 瀏覽器?

最近專案需求用到 jQuery Serialize Object plugin,它能夠自動將 Form 表單內的值,全部轉成 object 或 json 字串,減少開發者每次都要寫抓取 Form 表單內全部欄位的值。此套件安裝及使用方法都很容易,安裝可以透過 Bower 方式,或者是下載 source code 直接 include 即可,在 IE 7 或 8 為什麼沒辦法使用呢,原因是作者使用了 Array.prototype.forEach,此語法需要 JavaScript 1.6 版本,很抱歉,在 IE8 並不支援 forEach 寫法,所以 Mozilla Javascript 開發者文件內有提供 Compatibility 方法:

if (!Array.prototype.forEach) {
    Array.prototype.forEach = function (fn, scope) {
        'use strict';
        var i, len;
        for (i = 0, len = this.length; i < len; ++i) {
            if (i in this) {
                fn.call(scope, this, i, this);
            }
        }
    };
}

但是既然這是 jQuery Plugin,就可以透過 jQuery 內建的 each 函式來解決,最後發了 Pull request 給作者,就看作者收不收了 XD

五月 15, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» IE 6 瀏覽器用戶全球分佈

IE_worldIE_world

此資料來自 The Internet Explorer 6 Countdown,大家注意上面圖示,沒想到台灣高居第二名,佔了 3.5% 僅次於大陸的 24%,大陸不感到意外,但是台灣的比例還真是高,難怪一堆程式開發者,抱怨連連 XD,這是統計到 2013 年 04 月,在這邊紀錄一下,等到明年這個時候再來看看此統計圖。

五月 9, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Backbone Routing pushState in IE

backbonebackbone

Backbone.js 幫忙處理掉所有瀏覽器 Html5 History pushState 功能,除了 IE 9 以下(含 IE 9)不支援 history.pushState()history.replaceState(),其他 Browser 幾乎都支援了,在 Backbone.js 如何處理 URL 變化呢?以往透過 handle URL hash 來決定網頁要處理哪些資料,這也是 Backbone 預設的處理方式,範例如下

URL:

http://xxx/#!/user/list
http://xxx/#!/user/add

Backbone.Router.extend({
  routes: {
    "!/user/:action": "user"
  },
  initialize: function() {

  },
  user: function(action, id) {
   
  }
});
Backbone.history.start();

上面方法是通解,在各種瀏覽器包含 IE 都適用,那如果是使用 history.pushState 請改成底下:

URL:

http://xxx/user/list
http://xxx/user/add

Backbone.Router.extend({
  routes: {
    "/user/:action": "user"
  },
  initialize: function() {

  },
  user: function(action, id) {
   
  }
})
Backbone.history.start({pushState: true, root: '/'});

此作法在支援 html pushState 時候是可以按照您定義的 url 運作,但是在 IE 9 版本,網址就會被改成

URL:

http://xxx/#/user/list
http://xxx/#/user/add

一樣會被加上 hash 值,該如何解決此問題呢,請把 Backbone.history.start 改成

Backbone.history.start({pushState: true, hashChange: false, root: '/'});

設定 hashChange property 為 false,讓 IE 9 不要使用 # 來取代網址,這樣就沒問題了。

四月 12, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» [小技巧] JavaScript Cross Browser Best Practices

ie-logo-smallie-logo-small

先前寫了一篇 modern.IE 的使用方式及介紹,今天在 Facebook 上看到 Eric Shangkuan 說已經有了中文介面,如果你的瀏覽器是中文版,應該就可以直接看到中文介面了,裡面有篇文章非常重要,寫 Web 的工程師都必須注意,那就是 Cross Browser Best Practices,這篇文章教您如何撰寫相容於舊版 IE 瀏覽器的一些小技巧,這些技巧也不只用在 IE 上,更是教您在實做 CSS,JavaScript 的注意事項。我們來看看 Javascript 的小技巧。

不要再使用 navigator.userAgent

為了知道使用者 Browser 資訊,之前有寫篇 jQuery 偵測瀏覽器版本, 作業系統(OS detection),內容使用 navigator.userAgent 來取得使用者瀏覽器及裝置資訊,開發者為了 IE 各版本的相容,所以透過此方式來知道 IE 各版本,進而在 JS 做處理,但是有時候並不是這麼準確,因為目前市面上裝置實在是太多種了,手機,平板,電視一堆等等,為了支援各種裝置,請不要再用 navigator.userAgent 來判斷了,現在取而代之的就是用 Modernizr,用來偵測您的 Browser 有無任何您所想要的功能,像是 Html5 的 Canvas,利用 Modernizr 來判斷是否支援,這時候各種裝置就不會因為 JS 沒有判斷到而產生錯誤 ,尤其是在電視介面或 Android 平板,踩到很多雷阿。詳細資訊可以參考此連結

簡單來說 Canvas 在 IE9 才有支援,所以針對 IE 部份,我們使用 navigator.userAgent 來判斷

<script type="text/javascript">
    function getInternetExplorerVersion()
    // Returns the version of Internet Explorer or a -1 for other browsers.
    {
        var rv = -1;
        if(navigator.appName == 'Microsoft Internet Explorer')
        {
            var ua = navigator.userAgent;
            varre    = newRegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
            if(re.exec(ua) != null)
            rv = parseFloat( RegExp.$1 );
        }
        return rv;
    }
    function onLoad()
    {
        var version = GetInternetExplorerVersion()
        if (version < 9 && version > -1)
        {
            // Code to run in Internet Explorer 9 or earlier.
        }
    }
</script>

但是如果遇到 Safari, Chrome, Android, IPad, IPhone 版本呢,也很好解決,就是一直些判斷式,那為什麼不換個角度去想,直接判斷有無 Cnavas 功能即可,透過 Modernizr 套件可以簡單做到。另外 jQuery 在 1.9 版也直接捨棄了 jQuery.browser API 功能,取而代之的也是推薦 Modernizr

if (Modernizr.canvas) {
  console.info('Your browser support canvas');
}

在 document ready 內不要執行大量 script

現在大部分的網站缺少不了的就是 jQuery,jQuery 提供了 $(document).ready() 在 html load 完成後可以快速執行 JavaScript,在大多的狀況下都可以正確執行的,但是如果在 $(document).ready() 寫入大量及複雜的 Script,只會讓瀏覽器呆滯而不能使用,所以盡可能減少執行的程式碼,等到使用者真正要執行功能的時候在進行呼叫即可。通常像是 tooltip 或 dialog 可以延遲等到要出現的時候在初始化即可。

簡單舉個例子,在 form 表單大家常用的 jQuery Plugin datepicker,通常初始化會透過底下方式來寫:

$(document).ready( function() {
    $("input.date").datepicker({
        minDate: moment().subtract( "months", 1 ).toDate(),
        maxDate: moment().add( "months", 1 ).toDate(),
        dateFormat: "d M, y",
        constrainInput: true,
        beforeShowDay: $.datepicker.noWeekends
    });
});

用這缺點就是當 html 完成載入後,jQuery 會開始找 input 並且符合 class 為 date 的 元件,這會 delay 使用者正常使用網頁,比較好的解決方式就是 bind 在 input 的 focus 事件上。

$(document).on( "focus", "input.date:not(.hasDatepicker)", function() {
    $(this).datepicker({
        minDate: moment().subtract( "months", 1 ).toDate(),
        maxDate: moment().add( "months", 1 ).toDate(),
        dateFormat: "d M, y",
        constrainInput: true,
        beforeShowDay: $.datepicker.noWeekends
    });
});

此寫法有另外的優點就是當如果有建立新的 input.date 元件,可以動態初始化元件。初始過的元件,我們就動態增加 hasDatepicker class 來判斷是否已經初始化。

網頁開始先優先執行 AJAX

由於執行 AJAX 需要一段時間,所以請在 html load 之前就開始執行,並不需要等到 $(document).ready() 後才執行,另外在 AJAX 完成執行後的 Complete function 加入 $(document).ready() 函式確保 html 已載入完成。

延遲載入 social button(Facebook Like, Google +1, Twitter)

現在大多網站都有一大堆分享機制(social networks),像是 Facebook Like、Twitter 等等,但是這些 JS 的載入,都大大影響到網頁的載入時間,其實最主要的解決方式就是務必思考哪些頁面才需要這些 button,能減少載入外部 JS 就是提昇網頁載入速度,在以前載入外部 JS 的作法就是底下

<script>
(function(d, s) {
  var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) {
    if (d.getElementById(id)) {return;}
    js = d.createElement(s); js.src = url; js.id = id;
    fjs.parentNode.insertBefore(js, fjs);
  };
  load('//connect.facebook.net/en_US/all.js#appId=272697932759946&xfbml=1', 'fbjssdk');
  load('http://apis.google.com/js/plusone.js', 'gplus1js');
  load('//platform.twitter.com/widgets.js', 'tweetjs');
}(document, 'script'));
</script>

現在請改寫成底下

<script>
(function(w, d, s) {
  function go(){
    var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) {
      if (d.getElementById(id)) {return;}
      js = d.createElement(s); js.src = url; js.id = id;
      fjs.parentNode.insertBefore(js, fjs);
    };
    load('//connect.facebook.net/en_US/all.js#appId=272697932759946&xfbml=1', 'fbjssdk');
    load('http://apis.google.com/js/plusone.js', 'gplus1js');
    load('//platform.twitter.com/widgets.js', 'tweetjs');
  }
  if (w.addEventListener) { w.addEventListener("load", go, false); }
  else if (w.attachEvent) { w.attachEvent("onload",go); }
}(window, document, 'script'));
</script>

由於各瀏覽器相容問題,所以判斷是否支援 addEventListener 或 attachEvent,在 onload 後才開始執行。更多詳細內容可以參考 requesting these scripts

二月 4, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» 使用不同 IE 版本測試網站

ie-logo-smallie-logo-small

大家還在為了測試不同 IE 版本而安裝虛擬機器 VirtulBoxVMware 嗎?現在不必這麼麻煩了,可以到 modern.IE 直接測試 IE6/7/8/9/10 任何版本,或者是檢查網頁相容性以及 coding practices。

Scan your page

輸入網站 URL 直接開始測試,測試項目其實蠻多的,包含偵測網站使用的 Framework,像是 jQueryModernizr 版本,如果太舊,會跟您回報提示目前最新版本號碼,另外為了相容各 IE 版本,請使用 Standards Mode,也就是在 html 頁面使用 <!DOCTYPE html>,還有檢查是否使用 Responsive web design,就是偵測 media queries。其實測試結果裡面有很多相關連結,有空都可以看看,都蠻不錯的。

Virtual tool

為了測試不同 IE 版本,大家安裝了許多機器,就是要偵測相容性,現在不必這麼麻煩了,請到 BrowserStack.com 註冊新帳號,並且安裝 Firefox AddonChrome Plugin,安裝完成就可以直接選擇您要測試的 IE 版本,瀏覽器就會連上 Cloud based services 顯示各 IE 版本的結果,並且還有模擬滑鼠喔。

最後為了解決這些相容性問題,請務必調整專案的 Coding Standard,先閱讀 20 tips for building modern sites while supporting old versions of IE,按照此篇文章來開發新專案,像是使用 HTML5 Boilerplate,用 IE Compat Inspector,在 IE 瀏覽器上按 F12 debug,或使用 Firebug Lite,另外可以使用線上工具來幫助偵測網站相容性,像是 HTML validators, CSS validators, Uglify, and JSHint, or GruntJS 等。更多詳細資訊可以參考上述連結。

五月 2, 2010

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» [jQuery] 解決 IE6 PNG 透明背景 (Supersleight jQuery Plugin for Transparent PNGs in IE6)

今天無意間看到 Drew McLellan 在 2007 年寫了這篇 Transparent PNGs in Internet Explorer 6,真的是太晚發現這篇了,之前自己寫到一篇:『[CSS] IE 6, 7, 8 FireFox hack 支援透明背景圖 background or img javascript』,雖然 Google 官方網站宣佈完全不支援 IE6 瀏覽器,打算只支援 Microsoft Internet Explorer 7.0+, Mozilla Firefox 3.0+, Google Chrome 4.0+, Safari 3.0+,可是我們這些 Web Developer 還是需要考慮客戶的瀏覽器阿,因為客戶才是最大的,尤其是在一些學術機構,安裝好 XP,預設就是 IE6,從 Google 分析裡面,IE6 也是網站的客戶大群。

先來介紹 Drew McLellan 寫的一支好用 js 來改善所有 png 透明圖檔,最主要是修正 background-image 跟 img tag 所包含的 png 圖檔

1. 先下載:Download SuperSleight,解壓縮放到 js 資料夾

2. 針對 IE6 瀏覽器寫入 html

<!--[if lte IE 6]>
    <script type="text/javascript" src="supersleight-min.js"></script>
<![endif]-->

來分析 supersleight.js 檔案,看它是如何運作,底下是完整程式碼:

var supersleight    = function() {
   
    var root = false;
    var applyPositioning = true;
   
    // Path to a transparent GIF image
    var shim            = 'x.gif';
   
    // RegExp to match above GIF image name
    var shim_pattern    = /x\.gif$/i;
   
   
   
    var fnLoadPngs = function() {
        if (root) {
            root = document.getElementById(root);
        }else{
            root = document;
        }
        for (var i = root.all.length - 1, obj = null; (obj = root.all[i]); i--) {
            // background pngs
            if (obj.currentStyle.backgroundImage.match(/\.png/i) !== null) {
                bg_fnFixPng(obj);
            }
            // image elements
            if (obj.tagName=='IMG' && obj.src.match(/\.png$/i) !== null){
                el_fnFixPng(obj);
            }
            // apply position to 'active' elements
            if (applyPositioning && (obj.tagName=='A' || obj.tagName=='INPUT') && obj.style.position === ''){
                obj.style.position = 'relative';
            }
        }
    };

    var bg_fnFixPng = function(obj) {
        var mode = 'scale';
        var bg  = obj.currentStyle.backgroundImage;
        var src = bg.substring(5,bg.length-2);
        if (obj.currentStyle.backgroundRepeat == 'no-repeat') {
            mode = 'crop';
        }
        obj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='" + mode + "')";
        obj.style.backgroundImage = 'url('+shim+')';
    };

    var el_fnFixPng = function(img) {
        var src = img.src;
        img.style.width = img.width + "px";
        img.style.height = img.height + "px";
        img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='scale')";
        img.src = shim;
    };
   
    var addLoadEvent = function(func) {
        var oldonload = window.onload;
        if (typeof window.onload != 'function') {
            window.onload = func;
        } else {
            window.onload = function() {
                if (oldonload) {
                    oldonload();
                }
                func();
            };
        }
    };
   
    return {
        init: function() {
            addLoadEvent(fnLoadPngs);
        },
       
        limitTo: function(el) {
            root = el;
        },
       
        run: function() {
            fnLoadPngs();
        }
    };
}();

// limit to part of the page ... pass an ID to limitTo:
// supersleight.limitTo('header');

supersleight.init();

bg_fnFixPng: 針對背景圖修正
el_fnFixPng: 針對單一 element 修正
fnLoadPngs: js 主要 function,會使用到上述兩個 function

列出 supersleight 特性:

  • 針對 inline and background images tag 作處理修正
  • 可以針對特定區域進行 PNG 透明修正,加速網站 Performence (預設是針對整個 body 進行轉換)

第二點的意思是說,本來是寫 supersleight.init(); 針對整個 body 作轉換動作,可以改為 supersleight.limitTo(”header”); 假設您知道只有 header element 需要進行 PNG 的轉換,就可以使用此語法來加速網站執行速度。

jQuery Plugin

Supersleight jQuery Plugin for Transparent PNGs in IE6
作者也寫了 jQuery Plugin,造福了 jQuery 使用者,使用方式也相當簡單。

可以針對單一區域進行變換

$('#content').supersleight();

或者是針對整個 body

$('body').supersleight();

因為 plugin 需要 transparent GIF shim image,所以將語法改成:

$('body').supersleight({shim: '/img/transparent.gif'});

Related View

support:

一頁

A Django site.