筆記 Modernizr

前言

功能概述

  • 他提供了超過40種的新世代功能,而且一切都發生在毫秒間
  • It creates a JavaScript object (named Modernizr) that contains the results of these tests as boolean properties
  • 他會將他支援及不支援(前綴no-功能名稱)的功能新增到html的class上
  • It provides a script loader so you can pull in polyfills to backfill functionality in old browsers

使用方法

放在head裡而且最好緊貼在css後面(而某些功能要在<body>前生效)

Modernizr.load() tutorial

在下面的例子中,Modernizr會判斷Broswer支不支援geolocation
如果是的話則載入geo.js,否則載入geo-polyfill.js這個降級用的js

Modernizr.load({
  test: Modernizr.geolocation,
  yep : 'geo.js',
  nope: 'geo-polyfill.js'
});

使用Modernizr並不會影響效能,甚至可籍由同行的異步載入來提升一些效能,但是效能的變因非常多,Modernizr建議還是多試幾個方案來找到效能的最佳化。

下面的範例中展示了,但需要多個Moderniz相容測式要使用時的例子
testyep還有nope都能接收多個陣列

// Give Modernizr.load a string, an object, or an array of strings and objects

Modernizr.load([
  // Presentational polyfills

  {
    // Logical list of things we would normally need

    test : Modernizr.fontface && Modernizr.canvas && Modernizr.cssgradients,
    // Modernizr.load loads css and javascript by default

    nope : ['presentational-polyfill.js', 'presentational.css']
  },
  // Functional polyfills

  {
    // This just has to be truthy

    test : Modernizr.websockets && window.JSON,
    // socket-io.js and json2.js

    nope : 'functional-polyfills.js',
    // You can also give arrays of resources to load.

    both : [ 'app.js', 'extra.js' ],
    complete : function () {
      // Run this after everything in this group has downloaded

      // and executed, as well everything in all previous groups

      myApp.init();
    }
  },
  // Run your analytics after you've already kicked off all the rest

  // of your app.

  'post-analytics.js'
]);

所有Modernizr.load可以作的事都已發佈在yepnope.js,但他的規格是與Modernizr一起訂制,並且經過經秘的測試,你可以在yepnopejs.com.看到所有詳細的規格。

Modernizr.load還有一個重要的功能,就是將JS的譯取與執行去耦合化,這可能對你不代表什麼,Html5的開發人員,在開發中使用JQuery fallback的Google CDN方案,他的語法看起來如下。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js">\x3C/script>')</script>

這個語法的目的是用來載入GOOGLE提供的線上script,並且馬上去偵測JQuery物件是否可用,如果不行,他會讀取一個JQuery的本地副本作為後備,這在script-loaders通常都是不容易的,但Modernizr.load將會幫我們Hold住這一且執行緒。

Modernizr.load([
  {
    load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js',
    complete: function () {
      if ( !window.jQuery ) {
            Modernizr.load('js/libs/jquery-1.7.1.min.js');
      }
    }
  },
  {
    // This will wait for the fallback to load and

    // execute if it needs to.

    load: 'needs-jQuery.js'
  }
]);

提醒一下:
只使用這個技術作為fallbacks的方法,不然可能會使平行的讀取機制被取代掉而產生效能問題。

Modernizr.load是可以擴張的,你可以為你的js訂制你的prefixes以及filters。更多進一步的功能資訊,你可以從 yepnopejs.com homepage獲得,你甚至可以複寫他的loading程序的核心邏輯,但要珍惜位元數?(檔案大小?)XD

How Modernizr works

經由許多的測試,Modernizr籍由創造元素來施展他的魔法,设置一个特定的Style,然後立即檢索他,Browsers理解的話將會回傳一些可辦識的東西,Browsers如果不理解的話,將會回傳“undefined”甚至是不回傳任何東西。(然後他很臭屁的話他有許多可以用的東西,甚至他的用途多會因為你的想象你給限制住 = ﹃ =)

如果你對他的細節有興趣,可以查看modernizr.js的source code,更多的偵查功能可以查看dig into the project on GitHub.

HTML 5 elements in IE

Modernizr 在JS裡運行一個小迴圈,去激活各式各樣的HTML5元素在IE可以正常呈現,例如abbr,要注意的是,這不代表IE突然就可以支援Video這種元素,這只代表他在IE可以正常的被佈局,所以你不用再去作the HTML5 Boilerplate CSS 這樣的事。
他也可以讓一些HTML5元素可以在IE6-8被正常顯示,雖然當你的CSS超過100kb的時後,你可能會想試著查看效能。

Supported browsers

  • PC
    • IE6+,
    • Firefox 3.5+,
    • Opera 9.6+,
    • Safari 2+,
    • Chrome.
  • On mobile,
    • iOS's mobile Safari,
    • Android's WebKit browser,
    • Opera Mobile,
    • Firefox Mobile
    • 雖然我們還在測試,但我相信我們支援Blackberry 6+.

Modernizr的功能偵測規格

CSS相關功能

Feature / Modernizr JS object property & CSS classname

  • @font-face / fontface
  • background-size / backgroundsize
  • border-image / borderimage
  • border-radius / borderradius
  • box-shadow / boxshadow
  • Flexible Box Model / flexbox

flexible box model (aka flexbox) 提供不同的方法去定位元素,對於flat-base的東西,需要一些修正

/*預設使用border作陰影,但如果支援boxshadow則用之 */
        .box {
        border-bottom: 1px solid #666;
        border-right: 1px solid #777;
        }
        .boxshadow div.box {
            border: none;
            -webkit-box-shadow: #666 1px 1px 1px;
               -moz-box-shadow: #666 1px 1px 1px;
                    box-shadow: #666 1px 1px 1px;
        }
  • hsla() / hsla
  • Multiple backgrounds / multiplebgs
  • opacity / opacity
  • rgba() / rgba : 這樣你就不用再寫一次像下面這個範例的東西
.my_container {  
            /*background-color: #ccc; 終於不用再寫這一行 */
            background-color: hsla(0, 0%, 100%, .5); /* white with alpha */
        }
  • text-shadow / textshadow
  • CSS Animations / cssanimations:
  • CSS Columns / csscolumns
  • Generated Content / generatedcontent before:after:
  • CSS Gradients / cssgradients
/*因為我們都不希望有額外的http請求,所以在這個範例中,用這個方式避免額外的圖片下載*/
  .no-js .glossy,.no-cssgradients .glossy {
    background: url("images/glossybutton.png");
  }
  .cssgradients .glossy {
    background-image: linear-gradient(top, #555, #333);
  }
  • CSS Reflections / cssreflections
  • CSS 2D Transforms / csstransforms
  • CSS 3D Transforms / csstransforms3d
  • CSS Transitions / csstransitions

Transtions不需使用Modernizr的特別css或是js的特別屬性也可以正常使用,但在某些時後你可能希望瀏覽器支援css3的效果的時後,使用他的原生效果,而在它作不到的時後,使用效能比較差的方案,也許是使用Jquery
Isotope 使用了Modernizr作了這件事

HTML5的相關功能

  • applicationCache / applicationcache
  • Canvas / canvas

    如果Canvas不能運作的話,也許你可以考慮 FlashCanvas or excanvas.

  • Canvas Text / canvastext

  • Drag and Drop / draganddrop

  • hashchange Event / hashchange

  • History Management / history

  • HTML5 Audio / audio
    影片需要不同的格式來符合不同的瀏覽器,Modernizr提供測試 oog,mp3,wav,m4a
    重點提醒:這些屬性的值並不是布林,而是尊照matches the HTML5 spec回傳Browser的信用等級,他們可能是空字串、或是"maybe""probable", 空字串代表了falsy value(null,0),其他表達方式 Modernizr.audio.ogg == '' 而且 '' == false(也就是不支援的意思)

    var audio = new Audio();
    audio.src = Modernizr.audio.ogg ? 'background.ogg' :
    Modernizr.audio.mp3 ? 'background.mp3' :
    'background.m4a';
    audio.play();
    
  • HTML5 Video / video

    你可以參考這篇文章 video_for_everybody,了解如何讓video兼容不同的Browser, 作者使用了Modernizr來偵測支不支援,你可以使用js或是css來增強他的互動介面

    如果Browser支援的話,Modernizr會去評估哪一個格式將會被Browser運行,目前Modernizr支援三種影片格式的測試ogg, webm and h264.

  • IndexedDB/ indexeddb

  • Input Attributes

    HTML介紹一些新的新的表單Attributes,Modernizr支援這些

      autocomplete, autofocus, list, placeholder(占位符), max, min, multiple, pattern, required, step
    

    HTML5 inputs and attribute support是個非常好用的網站,他告訴我們不同的屬性支援度,而且demo了出來

  • Input Types

    Html5有30個新的input類型,
    search, tel, url, email, datetime, date, month, week, time, datetime-local, number, range, color
    不支援的時後降級為普通的text input

  • localStorage / localstorage

  • Cross-window Messaging / postmessage

  • sessionStorage / sessionstorage

  • Web Sockets / websockets

  • Web SQL Database / websqldatabase

  • Web Workers / webworkers

Feature Modernizr JS object property / CSS classname

  • Geolocation API / geolocation
  • Inline SVG / inlinesvg
  • SMIL / smil
  • SVG / svg
  • SVG Clip paths / svgclippaths
  • Touch Events / touch > 只能用來測試裝置支不支援touch event > 所以chorme桌面版 騙人說他可以支援XD我們也只有認了(不過這個BUG已經被處理了),

Modernizr Methods

Modernizr.prefixed()

他會自動把你傳進去的字串加上當前Browser適用的前綴字元,而且是使用駝峰命名回傳。

Modernizr.prefixed('boxSizing')

你可以使用下面這段正規表達式的轉換,來轉換 box-sizing

str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');

下面這段範例展示了,如何取得不同Broswer之間正確的transitionendevent名稱

var transEndEventNames = {
        'WebkitTransition' : 'webkitTransitionEnd',// Saf 6, Android Browser

        'MozTransition'    : 'transitionend',      // only for FF < 15

        'transition'       : 'transitionend'       // IE10, Opera, Chrome, FF 15+, Saf 7+

    },
    transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];

    // ... bind to the transEndEventName event... 

(實作參考範例 tutorial by Andi Smith)

我們也可以使用Modernizr.prefixed,來偵側特定的dom物件的前綴方法或是物件,例如,Modernizr.prefixed('StorageInfo', window) // 回傳object

如果找到的東西回傳的是function,則他會預設綁定bound第二個參數

如果你單純只是想要名字,而不他自動綁定,則設定第三個參數為null

Modernizr.prefixed('requestAnimationFrame', window, false) // 'webkitRequestAnimationFrame'

如果想要了解更多Function.prototype.bind,可以參考Modernizr.prefixed(str,obj) to use Function.prototype.bind

mq() media query testing

JavaScript method:
`Modernizr.mq(str)`
javascript 幾個注意事項: - 如果一個Broswer不支援mq則回傳 false - 一個`max-width`,或是他屏幕的角度(水平/垂直),會遲點回傳 - 你應該指定一個特定的mq type ,雖然 all 通常已經足夠(這句我不太理解,要回頭去查可能是說,如果你是要查目前寬度有沒有超過一個max-width 他應該是 0-400 這樣的概念)
    Modernizr.mq('only all and (max-width: 400px)')
  • 如果你要測試支不支援特定的min-width,你必需給他一個值
    Modernizr.mq('(min-width: 0px)')
  • 如你只是要測試支不支援mq可以使用
        Modernizr.mq('only all'); // true if MQ are supported, false if not
    
    ### Extensibility 可延展性

addTest() Plugin API

JavaScript method:

Modernizr.addTest(str, fn)
Modernizr.addTest(str, bool)
Modernizr.addTest({str: fn, str2: fn2})
Modernizr.addTest({str: bool, str2: fn})

範例如下,你可以增加一個track的測試,籍由在文件中新增一個video
來看看他的 video.addTextTrack 是不是一個 function

// Test for <track> element  support

Modernizr.addTest('track', function(){
  var video = document.createElement('video');
  return typeof video.addTextTrack === 'function'
});

接著你一樣可以使用
Modernizr.track來取得他的回傳值,而HTML同時也會加入.track.no-trackclass到body上

testStyles()

Modernizr.testStyles(str,fn[, nodes, testnames])

你可以使用這個方法,來檢查一組特定的屬性,在Broswer有沒有作用
他會新增一個你指定的dom物件到畫面上供你檢查

這個範例中將會塞入一個id為modernizr的dom物件到畫面上,而且他的css就是你指定的樣式,接著你可以檢查他的位置是不是真的在畫面上的9px
來檢查你的樣式有沒有正常運作

  Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule){
      Modernizr.addTest('width', elem.offsetWidth == 9);
  });

你可以指定塞入多個dom物件,也可以指定塞入特定的tag到這個 #modernizr div裡,這個子物件可以是陣列

unction(elem, rule){
      Modernizr.addTest('width', elem.offsetWidth == 9);
  }, 2, ["video", "image"]);

塞入多個dom物件時,他的id會成為"modernizr[n]"

testProp() 待續

comments powered by Disqus