Another massive commit:
1. Major improvements to the responsive styling. 2. Toggleable sidebar 3. Upgraded to modernizr 2.0 which includes Respond.js 4. IE7-9 testing and fixes 5. New theming system which should make forkers happy 6. New rake task for installing Octopress themes 7. Magic
This commit is contained in:
parent
8698a276f9
commit
d8b796acb9
68 changed files with 68 additions and 6890 deletions
File diff suppressed because it is too large
Load diff
8
source/javascripts/libs/ender.min.js
vendored
8
source/javascripts/libs/ender.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
@ -1,292 +0,0 @@
|
|||
/*
|
||||
* respond.js - A small and fast polyfill for min/max-width CSS3 Media Queries
|
||||
* Copyright 2011, Scott Jehl, scottjehl.com
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* Usage: Check out the readme file or github.com/scottjehl/respond
|
||||
*/
|
||||
(function( win, mqSupported ){
|
||||
//exposed namespace
|
||||
win.respond = {};
|
||||
|
||||
//define update even in native-mq-supporting browsers, to avoid errors
|
||||
respond.update = function(){};
|
||||
|
||||
//expose media query support flag for external use
|
||||
respond.mediaQueriesSupported = mqSupported;
|
||||
|
||||
//if media queries are supported, exit here
|
||||
if( mqSupported ){ return; }
|
||||
|
||||
//define vars
|
||||
var doc = win.document,
|
||||
docElem = doc.documentElement,
|
||||
mediastyles = [],
|
||||
rules = [],
|
||||
appendedEls = [],
|
||||
parsedSheets = {},
|
||||
resizeThrottle = 30,
|
||||
head = doc.getElementsByTagName( "head" )[0] || docElem,
|
||||
links = head.getElementsByTagName( "link" ),
|
||||
requestQueue = [],
|
||||
|
||||
//loop stylesheets, send text content to translate
|
||||
ripCSS = function(){
|
||||
var sheets = links,
|
||||
sl = sheets.length,
|
||||
i = 0,
|
||||
//vars for loop:
|
||||
sheet, href, media, isCSS;
|
||||
|
||||
for( ; i < sl; i++ ){
|
||||
sheet = sheets[ i ],
|
||||
href = sheet.href,
|
||||
media = sheet.media,
|
||||
isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
|
||||
|
||||
//only links plz and prevent re-parsing
|
||||
if( !!href && isCSS && !parsedSheets[ href ] ){
|
||||
if( !/^([a-zA-Z]+?:(\/\/)?(www\.)?)/.test( href )
|
||||
|| href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){
|
||||
requestQueue.push( {
|
||||
href: href,
|
||||
media: media
|
||||
} );
|
||||
}
|
||||
else{
|
||||
parsedSheets[ href ] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
makeRequests();
|
||||
|
||||
},
|
||||
|
||||
//recurse through request queue, get css text
|
||||
makeRequests = function(){
|
||||
if( requestQueue.length ){
|
||||
var thisRequest = requestQueue.shift();
|
||||
|
||||
ajax( thisRequest.href, function( styles ){
|
||||
translate( styles, thisRequest.href, thisRequest.media );
|
||||
parsedSheets[ thisRequest.href ] = true;
|
||||
makeRequests();
|
||||
} );
|
||||
}
|
||||
},
|
||||
|
||||
//find media blocks in css text, convert to style blocks
|
||||
translate = function( styles, href, media ){
|
||||
var qs = styles.match( /@media ([^\{]+)\{((?!@media)[\s\S])*(?=\}[\s]*\/\*\/mediaquery\*\/)/gmi ),
|
||||
ql = qs && qs.length || 0,
|
||||
//try to get CSS path
|
||||
href = href.substring( 0, href.lastIndexOf( "/" )),
|
||||
repUrls = function( css ){
|
||||
return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" );
|
||||
},
|
||||
useMedia = !ql && media,
|
||||
//vars used in loop
|
||||
i = 0,
|
||||
j, fullq, thisq, eachq, eql;
|
||||
|
||||
//if path exists, tack on trailing slash
|
||||
if( href.length ){ href += "/"; }
|
||||
|
||||
//if no internal queries exist, but media attr does, use that
|
||||
//note: this currently lacks support for situations where a media attr is specified on a link AND
|
||||
//its associated stylesheet has internal CSS media queries.
|
||||
//In those cases, the media attribute will currently be ignored.
|
||||
if( useMedia ){
|
||||
ql = 1;
|
||||
}
|
||||
|
||||
|
||||
for( ; i < ql; i++ ){
|
||||
j = 0;
|
||||
|
||||
//media attr
|
||||
if( useMedia ){
|
||||
fullq = media;
|
||||
rules.push( repUrls( styles ) );
|
||||
}
|
||||
//parse for styles
|
||||
else{
|
||||
fullq = qs[ i ].match( /@media ([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1;
|
||||
rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
|
||||
}
|
||||
|
||||
eachq = fullq.split( "," );
|
||||
eql = eachq.length;
|
||||
|
||||
|
||||
for( ; j < eql; j++ ){
|
||||
thisq = eachq[ j ];
|
||||
mediastyles.push( {
|
||||
media : thisq.match( /(only\s+)?([a-zA-Z]+)(\sand)?/ ) && RegExp.$2,
|
||||
rules : rules.length - 1,
|
||||
minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9]+)px[\s]*\)/ ) && parseFloat( RegExp.$1 ),
|
||||
maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9]+)px[\s]*\)/ ) && parseFloat( RegExp.$1 )
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
applyMedia();
|
||||
},
|
||||
|
||||
lastCall,
|
||||
|
||||
resizeDefer,
|
||||
|
||||
//enable/disable styles
|
||||
applyMedia = function( fromResize ){
|
||||
var name = "clientWidth",
|
||||
docElemProp = docElem[ name ],
|
||||
currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
|
||||
styleBlocks = {},
|
||||
dFrag = doc.createDocumentFragment(),
|
||||
lastLink = links[ links.length-1 ],
|
||||
now = (new Date()).getTime();
|
||||
|
||||
//throttle resize calls
|
||||
if( fromResize && lastCall && now - lastCall < resizeThrottle ){
|
||||
clearTimeout( resizeDefer );
|
||||
resizeDefer = setTimeout( applyMedia, resizeThrottle );
|
||||
return;
|
||||
}
|
||||
else {
|
||||
lastCall = now;
|
||||
}
|
||||
|
||||
for( var i in mediastyles ){
|
||||
var thisstyle = mediastyles[ i ];
|
||||
if( !thisstyle.minw && !thisstyle.maxw ||
|
||||
( !thisstyle.minw || thisstyle.minw && currWidth >= thisstyle.minw ) &&
|
||||
(!thisstyle.maxw || thisstyle.maxw && currWidth <= thisstyle.maxw ) ){
|
||||
if( !styleBlocks[ thisstyle.media ] ){
|
||||
styleBlocks[ thisstyle.media ] = [];
|
||||
}
|
||||
styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
|
||||
}
|
||||
}
|
||||
|
||||
//remove any existing respond style element(s)
|
||||
for( var i in appendedEls ){
|
||||
if( appendedEls[ i ] && appendedEls[ i ].parentNode === head ){
|
||||
head.removeChild( appendedEls[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
//inject active styles, grouped by media type
|
||||
for( var i in styleBlocks ){
|
||||
var ss = doc.createElement( "style" ),
|
||||
css = styleBlocks[ i ].join( "\n" );
|
||||
|
||||
ss.type = "text/css";
|
||||
ss.media = i;
|
||||
|
||||
if ( ss.styleSheet ){
|
||||
ss.styleSheet.cssText = css;
|
||||
}
|
||||
else {
|
||||
ss.appendChild( doc.createTextNode( css ) );
|
||||
}
|
||||
dFrag.appendChild( ss );
|
||||
appendedEls.push( ss );
|
||||
}
|
||||
|
||||
//append to DOM at once
|
||||
head.insertBefore( dFrag, lastLink.nextSibling );
|
||||
},
|
||||
//tweaked Ajax functions from Quirksmode
|
||||
ajax = function( url, callback ) {
|
||||
var req = xmlHttp();
|
||||
if (!req){
|
||||
return;
|
||||
}
|
||||
req.open( "GET", url, true );
|
||||
req.onreadystatechange = function () {
|
||||
if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){
|
||||
return;
|
||||
}
|
||||
callback( req.responseText );
|
||||
}
|
||||
if ( req.readyState == 4 ){
|
||||
return;
|
||||
}
|
||||
req.send();
|
||||
},
|
||||
//define ajax obj
|
||||
xmlHttp = (function() {
|
||||
var xmlhttpmethod = false,
|
||||
attempts = [
|
||||
function(){ return new ActiveXObject("Microsoft.XMLHTTP") },
|
||||
function(){ return new XMLHttpRequest() }
|
||||
],
|
||||
al = attempts.length;
|
||||
|
||||
while( al-- ){
|
||||
try {
|
||||
xmlhttpmethod = attempts[ al ]();
|
||||
}
|
||||
catch(e) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return function(){
|
||||
return xmlhttpmethod;
|
||||
};
|
||||
})();
|
||||
|
||||
//translate CSS
|
||||
ripCSS();
|
||||
|
||||
//expose update for re-running respond later on
|
||||
respond.update = ripCSS;
|
||||
|
||||
//adjust on resize
|
||||
function callMedia(){
|
||||
applyMedia( true );
|
||||
}
|
||||
if( win.addEventListener ){
|
||||
win.addEventListener( "resize", callMedia, false );
|
||||
}
|
||||
else if( win.attachEvent ){
|
||||
win.attachEvent( "onresize", callMedia );
|
||||
}
|
||||
})(
|
||||
this,
|
||||
(function( win ){
|
||||
|
||||
//for speed, flag browsers with window.matchMedia support and IE 9 as supported
|
||||
if( win.matchMedia ){ return true; }
|
||||
|
||||
var bool,
|
||||
doc = document,
|
||||
docElem = doc.documentElement,
|
||||
refNode = docElem.firstElementChild || docElem.firstChild,
|
||||
// fakeBody required for <FF4 when executed in <head>
|
||||
fakeUsed = !doc.body,
|
||||
fakeBody = doc.body || doc.createElement( "body" ),
|
||||
div = doc.createElement( "div" ),
|
||||
q = "only all";
|
||||
|
||||
div.id = "mq-test-1";
|
||||
div.style.cssText = "position:absolute;top:-99em";
|
||||
fakeBody.appendChild( div );
|
||||
|
||||
div.innerHTML = '_<style media="'+q+'"> #mq-test-1 { width: 9px; }</style>';
|
||||
if( fakeUsed ){
|
||||
docElem.insertBefore( fakeBody, refNode );
|
||||
}
|
||||
div.removeChild( div.firstChild );
|
||||
bool = div.offsetWidth == 9;
|
||||
if( fakeUsed ){
|
||||
docElem.removeChild( fakeBody );
|
||||
}
|
||||
else{
|
||||
fakeBody.removeChild( div );
|
||||
}
|
||||
return bool;
|
||||
})( this )
|
||||
);
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
/*!
|
||||
* selectivizr v1.0.1 - (c) Keith Clark, freely distributable under the terms of the MIT license.
|
||||
* selectivizr.com
|
||||
*/
|
||||
var k=true,p=false;(function(A){function N(a){return a.replace(O,q).replace(P,function(b,e,c){b=c.split(",");c=0;for(var g=b.length;c<g;c++){var h=Q(b[c].replace(R,q).replace(S,q))+w,f=[];b[c]=h.replace(T,function(d,l,m,j,i){if(l){if(f.length>0){d=f;var x;i=h.substring(0,i).replace(U,o);if(i==o||i.charAt(i.length-1)==w)i+="*";try{x=y(i)}catch(ha){}if(x){i=0;for(m=x.length;i<m;i++){j=x[i];for(var B=j.className,C=0,V=d.length;C<V;C++){var r=d[C];if(!RegExp("(^|\\s)"+r.className+"(\\s|$)").test(j.className))if(r.b&&(r.b===k||r.b(j)===k))B=E(B,r.className,k)}j.className=B}}f=[]}return l}else{if(l=m?W(m):!F||F.test(j)?{className:G(j),b:k}:null){f.push(l);return"."+l.className}return d}})}return e+b.join(",")})}function W(a){var b=k,e=G(a.slice(1)),c=a.substring(0,5)==":not(",g,h;if(c)a=a.slice(5,-1);var f=a.indexOf("(");if(f>-1)a=a.substring(0,f);if(a.charAt(0)==":")switch(a.slice(1)){case "root":b=function(d){return c?d!=H:d==H};break;case "target":if(s==8){b=function(d){function l(){var m=location.hash,j=m.slice(1);return c?m==""||d.id!=j:m!=""&&d.id==j}t(A,"hashchange",function(){u(d,e,l())});return l()};break}return p;case "checked":b=function(d){X.test(d.type)&&t(d,"propertychange",function(){event.propertyName=="checked"&&u(d,e,d.checked!==c)});return d.checked!==c};break;case "disabled":c=!c;case "enabled":b=function(d){if(Y.test(d.tagName)){t(d,"propertychange",function(){event.propertyName=="$disabled"&&u(d,e,d.a===c)});z.push(d);d.a=d.disabled;return d.disabled===c}return a==":enabled"?c:!c};break;case "focus":g="focus";h="blur";case "hover":if(!g){g="mouseenter";h="mouseleave"}b=function(d){t(d,c?h:g,function(){u(d,e,k)});t(d,c?g:h,function(){u(d,e,p)});return c};break;default:if(!Z.test(a))return p}return{className:e,b:b}}function G(a){return I+"-"+(s==6&&$?aa++:a.replace(ba,function(b){return b.charCodeAt(0)}))}function Q(a){return a.replace(J,q).replace(ca,w)}function u(a,b,e){var c=a.className;b=E(c,b,e);if(b!=c){a.className=b;a.parentNode.className+=o}}function E(a,b,e){var c=RegExp("(^|\\s)"+b+"(\\s|$)"),g=c.test(a);return e?g?a:a+w+b:g?a.replace(c,q).replace(J,q):a}function t(a,b,e){a.attachEvent("on"+b,e)}function D(a,b){if(/^https?:\/\//i.test(a))return b.substring(0,b.indexOf("/",8))==a.substring(0,a.indexOf("/",8))?a:null;if(a.charAt(0)=="/")return b.substring(0,b.indexOf("/",8))+a;var e=b.split("?")[0];if(a.charAt(0)!="?"&&e.charAt(e.length-1)!="/")e=e.substring(0,e.lastIndexOf("/")+1);return e+a}function K(a){if(a){v.open("GET",a,p);v.send();return(v.status==200?v.responseText:o).replace(da,o).replace(ea,function(b,e,c,g,h){return K(D(c||h,a))}).replace(fa,function(b,e,c){e=e||"";return" url("+e+D(c,a)+e+") "})}return o}function ga(){var a,b;a=n.getElementsByTagName("BASE");for(var e=a.length>0?a[0].href:n.location.href,c=0;c<n.styleSheets.length;c++){b=n.styleSheets[c];if(b.href!=o)if(a=D(b.href,e))b.cssText=N(K(a))}z.length>0&&setInterval(function(){for(var g=0,h=z.length;g<h;g++){var f=z[g];if(f.disabled!==f.a)if(f.disabled){f.disabled=p;f.a=k;f.disabled=k}else f.a=f.disabled}},250)}if(!/*@cc_on!@*/true){var n=document,H=n.documentElement,v=function(){if(A.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(a){return null}}(),s=/MSIE ([\d])/.exec(navigator.userAgent)[1];if(!(n.compatMode!="CSS1Compat"||s<6||s>8||!v)){var L={NW:"*.Dom.select",DOMAssistant:"*.$",Prototype:"$$",YAHOO:"*.util.Selector.query",MooTools:"$$",Sizzle:"*",jQuery:"*",dojo:"*.query"},y,z=[],aa=0,$=k,I="slvzr",M=I+"DOMReady",da=/(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)\s*/g,ea=/@import\s*(?:(?:(?:url\(\s*(['"]?)(.*)\1)\s*\))|(?:(['"])(.*)\3))[^;]*;/g,fa=/\burl\(\s*(["']?)([^"')]+)\1\s*\)/g,Z=/^:(empty|(first|last|only|nth(-last)?)-(child|of-type))$/,O=/:(:first-(?:line|letter))/g,P=/(^|})\s*([^\{]*?[\[:][^{]+)/g,T=/([ +~>])|(:[a-z-]+(?:\(.*?\)+)?)|(\[.*?\])/g,U=/(:not\()?:(hover|enabled|disabled|focus|checked|target|active|visited|first-line|first-letter)\)?/g,ba=/[^\w-]/g,Y=/^(INPUT|SELECT|TEXTAREA|BUTTON)$/,X=/^(checkbox|radio)$/,F=s>6?/[\$\^*]=(['"])\1/:null,R=/([(\[+~])\s+/g,S=/\s+([)\]+~])/g,ca=/\s+/g,J=/^\s*((?:[\S\s]*\S)?)\s*$/,o="",w=" ",q="$1";n.write("<script id="+M+" defer src='//:'><\/script>");n.getElementById(M).onreadystatechange=function(){if(this.readyState=="complete"){a:{var a,b;for(b in L)if(A[b]&&(a=eval(L[b].replace("*",b)))){y=a;break a}y=p}if(y){ga();this.parentNode.removeChild(this)}}}}}})(this);
|
|
@ -1,20 +0,0 @@
|
|||
// https://gist.github.com/901295
|
||||
// By @mathias, @cheeaun and @jdalton
|
||||
|
||||
(function(doc) {
|
||||
var addEvent = 'addEventListener',
|
||||
type = 'gesturestart',
|
||||
qsa = 'querySelectorAll',
|
||||
scales = [1, 1],
|
||||
meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : [];
|
||||
function fix() {
|
||||
meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1];
|
||||
doc.removeEventListener(type, fix, true);
|
||||
}
|
||||
if ((meta = meta[meta.length - 1]) && addEvent in doc) {
|
||||
fix();
|
||||
scales = [.25, 1.6];
|
||||
doc[addEvent](type, fix, true);
|
||||
}
|
||||
}(document));
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
// jXHR.js (JSON-P XHR)
|
||||
// v0.1 (c) Kyle Simpson
|
||||
// MIT License
|
||||
|
||||
(function(global){
|
||||
var SETTIMEOUT = global.setTimeout, // for better compression
|
||||
doc = global.document,
|
||||
callback_counter = 0;
|
||||
|
||||
global.jXHR = function() {
|
||||
var script_url,
|
||||
script_loaded,
|
||||
jsonp_callback,
|
||||
scriptElem,
|
||||
publicAPI = null;
|
||||
|
||||
function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
|
||||
|
||||
function reset() {
|
||||
script_loaded = false;
|
||||
script_url = "";
|
||||
removeScript();
|
||||
scriptElem = null;
|
||||
fireReadyStateChange(0);
|
||||
}
|
||||
|
||||
function ThrowError(msg) {
|
||||
try { publicAPI.onerror.call(publicAPI,msg,script_url); } catch (err) { throw new Error(msg); }
|
||||
}
|
||||
|
||||
function handleScriptLoad() {
|
||||
if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
|
||||
this.onload = this.onreadystatechange = null; // prevent memory leak
|
||||
script_loaded = true;
|
||||
if (publicAPI.readyState !== 4) ThrowError("Script failed to load ["+script_url+"].");
|
||||
removeScript();
|
||||
}
|
||||
|
||||
function fireReadyStateChange(rs,args) {
|
||||
args = args || [];
|
||||
publicAPI.readyState = rs;
|
||||
if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
|
||||
}
|
||||
|
||||
publicAPI = {
|
||||
onerror:null,
|
||||
onreadystatechange:null,
|
||||
readyState:0,
|
||||
open:function(method,url){
|
||||
reset();
|
||||
internal_callback = "cb"+(callback_counter++);
|
||||
(function(icb){
|
||||
global.jXHR[icb] = function() {
|
||||
try { fireReadyStateChange.call(publicAPI,4,arguments); }
|
||||
catch(err) {
|
||||
publicAPI.readyState = -1;
|
||||
ThrowError("Script failed to run ["+script_url+"].");
|
||||
}
|
||||
global.jXHR[icb] = null;
|
||||
};
|
||||
})(internal_callback);
|
||||
script_url = url.replace(/=\?/,"=jXHR."+internal_callback);
|
||||
fireReadyStateChange(1);
|
||||
},
|
||||
send:function(){
|
||||
SETTIMEOUT(function(){
|
||||
scriptElem = doc.createElement("script");
|
||||
scriptElem.setAttribute("type","text/javascript");
|
||||
scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
|
||||
scriptElem.setAttribute("src",script_url);
|
||||
doc.getElementsByTagName("head")[0].appendChild(scriptElem);
|
||||
},0);
|
||||
fireReadyStateChange(2);
|
||||
},
|
||||
setRequestHeader:function(){}, // noop
|
||||
getResponseHeader:function(){return "";}, // basically noop
|
||||
getAllResponseHeaders:function(){return [];} // ditto
|
||||
};
|
||||
|
||||
reset();
|
||||
|
||||
return publicAPI;
|
||||
};
|
||||
})(window);
|
||||
|
|
@ -1,481 +0,0 @@
|
|||
/*
|
||||
http://www.JSON.org/json2.js
|
||||
2011-02-23
|
||||
|
||||
Public Domain.
|
||||
|
||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
|
||||
See http://www.JSON.org/js.html
|
||||
|
||||
|
||||
This code should be minified before deployment.
|
||||
See http://javascript.crockford.com/jsmin.html
|
||||
|
||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||
NOT CONTROL.
|
||||
|
||||
|
||||
This file creates a global JSON object containing two methods: stringify
|
||||
and parse.
|
||||
|
||||
JSON.stringify(value, replacer, space)
|
||||
value any JavaScript value, usually an object or array.
|
||||
|
||||
replacer an optional parameter that determines how object
|
||||
values are stringified for objects. It can be a
|
||||
function or an array of strings.
|
||||
|
||||
space an optional parameter that specifies the indentation
|
||||
of nested structures. If it is omitted, the text will
|
||||
be packed without extra whitespace. If it is a number,
|
||||
it will specify the number of spaces to indent at each
|
||||
level. If it is a string (such as '\t' or ' '),
|
||||
it contains the characters used to indent at each level.
|
||||
|
||||
This method produces a JSON text from a JavaScript value.
|
||||
|
||||
When an object value is found, if the object contains a toJSON
|
||||
method, its toJSON method will be called and the result will be
|
||||
stringified. A toJSON method does not serialize: it returns the
|
||||
value represented by the name/value pair that should be serialized,
|
||||
or undefined if nothing should be serialized. The toJSON method
|
||||
will be passed the key associated with the value, and this will be
|
||||
bound to the value
|
||||
|
||||
For example, this would serialize Dates as ISO strings.
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
return this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z';
|
||||
};
|
||||
|
||||
You can provide an optional replacer method. It will be passed the
|
||||
key and value of each member, with this bound to the containing
|
||||
object. The value that is returned from your method will be
|
||||
serialized. If your method returns undefined, then the member will
|
||||
be excluded from the serialization.
|
||||
|
||||
If the replacer parameter is an array of strings, then it will be
|
||||
used to select the members to be serialized. It filters the results
|
||||
such that only members with keys listed in the replacer array are
|
||||
stringified.
|
||||
|
||||
Values that do not have JSON representations, such as undefined or
|
||||
functions, will not be serialized. Such values in objects will be
|
||||
dropped; in arrays they will be replaced with null. You can use
|
||||
a replacer function to replace those with JSON values.
|
||||
JSON.stringify(undefined) returns undefined.
|
||||
|
||||
The optional space parameter produces a stringification of the
|
||||
value that is filled with line breaks and indentation to make it
|
||||
easier to read.
|
||||
|
||||
If the space parameter is a non-empty string, then that string will
|
||||
be used for indentation. If the space parameter is a number, then
|
||||
the indentation will be that many spaces.
|
||||
|
||||
Example:
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||
// text is '["e",{"pluribus":"unum"}]'
|
||||
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||
|
||||
text = JSON.stringify([new Date()], function (key, value) {
|
||||
return this[key] instanceof Date ?
|
||||
'Date(' + this[key] + ')' : value;
|
||||
});
|
||||
// text is '["Date(---current time---)"]'
|
||||
|
||||
|
||||
JSON.parse(text, reviver)
|
||||
This method parses a JSON text to produce an object or array.
|
||||
It can throw a SyntaxError exception.
|
||||
|
||||
The optional reviver parameter is a function that can filter and
|
||||
transform the results. It receives each of the keys and values,
|
||||
and its return value is used instead of the original value.
|
||||
If it returns what it received, then the structure is not modified.
|
||||
If it returns undefined then the member is deleted.
|
||||
|
||||
Example:
|
||||
|
||||
// Parse the text. Values that look like ISO date strings will
|
||||
// be converted to Date objects.
|
||||
|
||||
myData = JSON.parse(text, function (key, value) {
|
||||
var a;
|
||||
if (typeof value === 'string') {
|
||||
a =
|
||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||
if (a) {
|
||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||
+a[5], +a[6]));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||
var d;
|
||||
if (typeof value === 'string' &&
|
||||
value.slice(0, 5) === 'Date(' &&
|
||||
value.slice(-1) === ')') {
|
||||
d = new Date(value.slice(5, -1));
|
||||
if (d) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
|
||||
This is a reference implementation. You are free to copy, modify, or
|
||||
redistribute.
|
||||
*/
|
||||
|
||||
/*jslint evil: true, strict: false, regexp: false */
|
||||
|
||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||
test, toJSON, toString, valueOf
|
||||
*/
|
||||
|
||||
|
||||
// Create a JSON object only if one does not already exist. We create the
|
||||
// methods in a closure to avoid creating global variables.
|
||||
|
||||
var JSON;
|
||||
if (!JSON) {
|
||||
JSON = {};
|
||||
}
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
if (typeof Date.prototype.toJSON !== 'function') {
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
|
||||
return isFinite(this.valueOf()) ?
|
||||
this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z' : null;
|
||||
};
|
||||
|
||||
String.prototype.toJSON =
|
||||
Number.prototype.toJSON =
|
||||
Boolean.prototype.toJSON = function (key) {
|
||||
return this.valueOf();
|
||||
};
|
||||
}
|
||||
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
gap,
|
||||
indent,
|
||||
meta = { // table of character substitutions
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
},
|
||||
rep;
|
||||
|
||||
|
||||
function quote(string) {
|
||||
|
||||
// If the string contains no control characters, no quote characters, and no
|
||||
// backslash characters, then we can safely slap some quotes around it.
|
||||
// Otherwise we must also replace the offending characters with safe escape
|
||||
// sequences.
|
||||
|
||||
escapable.lastIndex = 0;
|
||||
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
|
||||
var c = meta[a];
|
||||
return typeof c === 'string' ? c :
|
||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
}) + '"' : '"' + string + '"';
|
||||
}
|
||||
|
||||
|
||||
function str(key, holder) {
|
||||
|
||||
// Produce a string from holder[key].
|
||||
|
||||
var i, // The loop counter.
|
||||
k, // The member key.
|
||||
v, // The member value.
|
||||
length,
|
||||
mind = gap,
|
||||
partial,
|
||||
value = holder[key];
|
||||
|
||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||
|
||||
if (value && typeof value === 'object' &&
|
||||
typeof value.toJSON === 'function') {
|
||||
value = value.toJSON(key);
|
||||
}
|
||||
|
||||
// If we were called with a replacer function, then call the replacer to
|
||||
// obtain a replacement value.
|
||||
|
||||
if (typeof rep === 'function') {
|
||||
value = rep.call(holder, key, value);
|
||||
}
|
||||
|
||||
// What happens next depends on the value's type.
|
||||
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return quote(value);
|
||||
|
||||
case 'number':
|
||||
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||
|
||||
return isFinite(value) ? String(value) : 'null';
|
||||
|
||||
case 'boolean':
|
||||
case 'null':
|
||||
|
||||
// If the value is a boolean or null, convert it to a string. Note:
|
||||
// typeof null does not produce 'null'. The case is included here in
|
||||
// the remote chance that this gets fixed someday.
|
||||
|
||||
return String(value);
|
||||
|
||||
// If the type is 'object', we might be dealing with an object or an array or
|
||||
// null.
|
||||
|
||||
case 'object':
|
||||
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||
// so watch out for that case.
|
||||
|
||||
if (!value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
// Make an array to hold the partial results of stringifying this object value.
|
||||
|
||||
gap += indent;
|
||||
partial = [];
|
||||
|
||||
// Is the value an array?
|
||||
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
|
||||
// The value is an array. Stringify every element. Use null as a placeholder
|
||||
// for non-JSON values.
|
||||
|
||||
length = value.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
partial[i] = str(i, value) || 'null';
|
||||
}
|
||||
|
||||
// Join all of the elements together, separated with commas, and wrap them in
|
||||
// brackets.
|
||||
|
||||
v = partial.length === 0 ? '[]' : gap ?
|
||||
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
|
||||
'[' + partial.join(',') + ']';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
|
||||
// If the replacer is an array, use it to select the members to be stringified.
|
||||
|
||||
if (rep && typeof rep === 'object') {
|
||||
length = rep.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (typeof rep[i] === 'string') {
|
||||
k = rep[i];
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Otherwise, iterate through all of the keys in the object.
|
||||
|
||||
for (k in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Join all of the member texts together, separated with commas,
|
||||
// and wrap them in braces.
|
||||
|
||||
v = partial.length === 0 ? '{}' : gap ?
|
||||
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
|
||||
'{' + partial.join(',') + '}';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
// If the JSON object does not yet have a stringify method, give it one.
|
||||
|
||||
if (typeof JSON.stringify !== 'function') {
|
||||
JSON.stringify = function (value, replacer, space) {
|
||||
|
||||
// The stringify method takes a value and an optional replacer, and an optional
|
||||
// space parameter, and returns a JSON text. The replacer can be a function
|
||||
// that can replace values, or an array of strings that will select the keys.
|
||||
// A default replacer method can be provided. Use of the space parameter can
|
||||
// produce text that is more easily readable.
|
||||
|
||||
var i;
|
||||
gap = '';
|
||||
indent = '';
|
||||
|
||||
// If the space parameter is a number, make an indent string containing that
|
||||
// many spaces.
|
||||
|
||||
if (typeof space === 'number') {
|
||||
for (i = 0; i < space; i += 1) {
|
||||
indent += ' ';
|
||||
}
|
||||
|
||||
// If the space parameter is a string, it will be used as the indent string.
|
||||
|
||||
} else if (typeof space === 'string') {
|
||||
indent = space;
|
||||
}
|
||||
|
||||
// If there is a replacer, it must be a function or an array.
|
||||
// Otherwise, throw an error.
|
||||
|
||||
rep = replacer;
|
||||
if (replacer && typeof replacer !== 'function' &&
|
||||
(typeof replacer !== 'object' ||
|
||||
typeof replacer.length !== 'number')) {
|
||||
throw new Error('JSON.stringify');
|
||||
}
|
||||
|
||||
// Make a fake root object containing our value under the key of ''.
|
||||
// Return the result of stringifying the value.
|
||||
|
||||
return str('', {'': value});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// If the JSON object does not yet have a parse method, give it one.
|
||||
|
||||
if (typeof JSON.parse !== 'function') {
|
||||
JSON.parse = function (text, reviver) {
|
||||
|
||||
// The parse method takes a text and an optional reviver function, and returns
|
||||
// a JavaScript value if the text is a valid JSON text.
|
||||
|
||||
var j;
|
||||
|
||||
function walk(holder, key) {
|
||||
|
||||
// The walk method is used to recursively walk the resulting structure so
|
||||
// that modifications can be made.
|
||||
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
|
||||
|
||||
// Parsing happens in four stages. In the first stage, we replace certain
|
||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||
|
||||
text = String(text);
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
|
||||
// In the second stage, we run the text against regular expressions that look
|
||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||
// because they can cause invocation, and '=' because it can cause mutation.
|
||||
// But just to be safe, we want to reject all unexpected forms.
|
||||
|
||||
// We split the second stage into 4 regexp operations in order to work around
|
||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||
// we look to see that the remaining characters are only whitespace or ']' or
|
||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||
|
||||
if (/^[\],:{}\s]*$/
|
||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
|
||||
// In the third stage we use the eval function to compile the text into a
|
||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||
// in parens to eliminate the ambiguity.
|
||||
|
||||
j = eval('(' + text + ')');
|
||||
|
||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||
// each name/value pair to a reviver function for possible transformation.
|
||||
|
||||
return typeof reviver === 'function' ?
|
||||
walk({'': j}, '') : j;
|
||||
}
|
||||
|
||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
}());
|
||||
|
964
source/javascripts/libs/modernizr-1.7.js
vendored
964
source/javascripts/libs/modernizr-1.7.js
vendored
|
@ -1,964 +0,0 @@
|
|||
/*!
|
||||
* Modernizr v1.7
|
||||
* http://www.modernizr.com
|
||||
*
|
||||
* Developed by:
|
||||
* - Faruk Ates http://farukat.es/
|
||||
* - Paul Irish http://paulirish.com/
|
||||
*
|
||||
* Copyright (c) 2009-2011
|
||||
* Dual-licensed under the BSD or MIT licenses.
|
||||
* http://www.modernizr.com/license/
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Modernizr is a script that detects native CSS3 and HTML5 features
|
||||
* available in the current UA and provides an object containing all
|
||||
* features with a true/false value, depending on whether the UA has
|
||||
* native support for it or not.
|
||||
*
|
||||
* Modernizr will also add classes to the <html> element of the page,
|
||||
* one for each feature it detects. If the UA supports it, a class
|
||||
* like "cssgradients" will be added. If not, the class name will be
|
||||
* "no-cssgradients". This allows for simple if-conditionals in your
|
||||
* CSS, giving you fine control over the look & feel of your website.
|
||||
*
|
||||
* @author Faruk Ates
|
||||
* @author Paul Irish
|
||||
* @copyright (c) 2009-2011 Faruk Ates.
|
||||
* @contributor Ben Alman
|
||||
*/
|
||||
|
||||
window.Modernizr = (function(window,document,undefined){
|
||||
|
||||
var version = '1.7',
|
||||
|
||||
ret = {},
|
||||
|
||||
/**
|
||||
* !! DEPRECATED !!
|
||||
*
|
||||
* enableHTML5 is a private property for advanced use only. If enabled,
|
||||
* it will make Modernizr.init() run through a brief while() loop in
|
||||
* which it will create all HTML5 elements in the DOM to allow for
|
||||
* styling them in Internet Explorer, which does not recognize any
|
||||
* non-HTML4 elements unless created in the DOM this way.
|
||||
*
|
||||
* enableHTML5 is ON by default.
|
||||
*
|
||||
* The enableHTML5 toggle option is DEPRECATED as per 1.6, and will be
|
||||
* replaced in 2.0 in lieu of the modular, configurable nature of 2.0.
|
||||
*/
|
||||
enableHTML5 = true,
|
||||
|
||||
|
||||
docElement = document.documentElement,
|
||||
docHead = document.head || document.getElementsByTagName('head')[0],
|
||||
|
||||
/**
|
||||
* Create our "modernizr" element that we do most feature tests on.
|
||||
*/
|
||||
mod = 'modernizr',
|
||||
modElem = document.createElement( mod ),
|
||||
m_style = modElem.style,
|
||||
|
||||
/**
|
||||
* Create the input element for various Web Forms feature tests.
|
||||
*/
|
||||
inputElem = document.createElement( 'input' ),
|
||||
|
||||
smile = ':)',
|
||||
|
||||
tostring = Object.prototype.toString,
|
||||
|
||||
// List of property values to set for css tests. See ticket #21
|
||||
prefixes = ' -webkit- -moz- -o- -ms- -khtml- '.split(' '),
|
||||
|
||||
// Following spec is to expose vendor-specific style properties as:
|
||||
// elem.style.WebkitBorderRadius
|
||||
// and the following would be incorrect:
|
||||
// elem.style.webkitBorderRadius
|
||||
|
||||
// Webkit ghosts their properties in lowercase but Opera & Moz do not.
|
||||
// Microsoft foregoes prefixes entirely <= IE8, but appears to
|
||||
// use a lowercase `ms` instead of the correct `Ms` in IE9
|
||||
|
||||
// More here: http://github.com/Modernizr/Modernizr/issues/issue/21
|
||||
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
|
||||
|
||||
ns = {'svg': 'http://www.w3.org/2000/svg'},
|
||||
|
||||
tests = {},
|
||||
inputs = {},
|
||||
attrs = {},
|
||||
|
||||
classes = [],
|
||||
|
||||
featurename, // used in testing loop
|
||||
|
||||
|
||||
|
||||
// todo: consider using http://javascript.nwbox.com/CSSSupport/css-support.js instead
|
||||
testMediaQuery = function(mq){
|
||||
|
||||
var st = document.createElement('style'),
|
||||
div = document.createElement('div'),
|
||||
ret;
|
||||
|
||||
st.textContent = mq + '{#modernizr{height:3px}}';
|
||||
docHead.appendChild(st);
|
||||
div.id = 'modernizr';
|
||||
docElement.appendChild(div);
|
||||
|
||||
ret = div.offsetHeight === 3;
|
||||
|
||||
st.parentNode.removeChild(st);
|
||||
div.parentNode.removeChild(div);
|
||||
|
||||
return !!ret;
|
||||
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* isEventSupported determines if a given element supports the given event
|
||||
* function from http://yura.thinkweb2.com/isEventSupported/
|
||||
*/
|
||||
isEventSupported = (function(){
|
||||
|
||||
var TAGNAMES = {
|
||||
'select':'input','change':'input',
|
||||
'submit':'form','reset':'form',
|
||||
'error':'img','load':'img','abort':'img'
|
||||
};
|
||||
|
||||
function isEventSupported(eventName, element) {
|
||||
|
||||
element = element || document.createElement(TAGNAMES[eventName] || 'div');
|
||||
eventName = 'on' + eventName;
|
||||
|
||||
// When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
|
||||
var isSupported = (eventName in element);
|
||||
|
||||
if (!isSupported) {
|
||||
// If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
|
||||
if (!element.setAttribute) {
|
||||
element = document.createElement('div');
|
||||
}
|
||||
if (element.setAttribute && element.removeAttribute) {
|
||||
element.setAttribute(eventName, '');
|
||||
isSupported = is(element[eventName], 'function');
|
||||
|
||||
// If property was created, "remove it" (by setting value to `undefined`)
|
||||
if (!is(element[eventName], undefined)) {
|
||||
element[eventName] = undefined;
|
||||
}
|
||||
element.removeAttribute(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
element = null;
|
||||
return isSupported;
|
||||
}
|
||||
return isEventSupported;
|
||||
})();
|
||||
|
||||
|
||||
// hasOwnProperty shim by kangax needed for Safari 2.0 support
|
||||
var _hasOwnProperty = ({}).hasOwnProperty, hasOwnProperty;
|
||||
if (!is(_hasOwnProperty, undefined) && !is(_hasOwnProperty.call, undefined)) {
|
||||
hasOwnProperty = function (object, property) {
|
||||
return _hasOwnProperty.call(object, property);
|
||||
};
|
||||
}
|
||||
else {
|
||||
hasOwnProperty = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
|
||||
return ((property in object) && is(object.constructor.prototype[property], undefined));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* set_css applies given styles to the Modernizr DOM node.
|
||||
*/
|
||||
function set_css( str ) {
|
||||
m_style.cssText = str;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_css_all extrapolates all vendor-specific css strings.
|
||||
*/
|
||||
function set_css_all( str1, str2 ) {
|
||||
return set_css(prefixes.join(str1 + ';') + ( str2 || '' ));
|
||||
}
|
||||
|
||||
/**
|
||||
* is returns a boolean for if typeof obj is exactly type.
|
||||
*/
|
||||
function is( obj, type ) {
|
||||
return typeof obj === type;
|
||||
}
|
||||
|
||||
/**
|
||||
* contains returns a boolean for if substr is found within str.
|
||||
*/
|
||||
function contains( str, substr ) {
|
||||
return (''+str).indexOf( substr ) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_props is a generic CSS / DOM property test; if a browser supports
|
||||
* a certain property, it won't return undefined for it.
|
||||
* A supported CSS property returns empty string when its not yet set.
|
||||
*/
|
||||
function test_props( props, callback ) {
|
||||
for ( var i in props ) {
|
||||
if ( m_style[ props[i] ] !== undefined && ( !callback || callback( props[i], modElem ) ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* test_props_all tests a list of DOM properties we want to check against.
|
||||
* We specify literally ALL possible (known and/or likely) properties on
|
||||
* the element including the non-vendor prefixed one, for forward-
|
||||
* compatibility.
|
||||
*/
|
||||
function test_props_all( prop, callback ) {
|
||||
|
||||
var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1),
|
||||
props = (prop + ' ' + domPrefixes.join(uc_prop + ' ') + uc_prop).split(' ');
|
||||
|
||||
return !!test_props( props, callback );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests
|
||||
* -----
|
||||
*/
|
||||
|
||||
tests['flexbox'] = function() {
|
||||
/**
|
||||
* set_prefixed_value_css sets the property of a specified element
|
||||
* adding vendor prefixes to the VALUE of the property.
|
||||
* @param {Element} element
|
||||
* @param {string} property The property name. This will not be prefixed.
|
||||
* @param {string} value The value of the property. This WILL be prefixed.
|
||||
* @param {string=} extra Additional CSS to append unmodified to the end of
|
||||
* the CSS string.
|
||||
*/
|
||||
function set_prefixed_value_css(element, property, value, extra) {
|
||||
property += ':';
|
||||
element.style.cssText = (property + prefixes.join(value + ';' + property)).slice(0, -property.length) + (extra || '');
|
||||
}
|
||||
|
||||
/**
|
||||
* set_prefixed_property_css sets the property of a specified element
|
||||
* adding vendor prefixes to the NAME of the property.
|
||||
* @param {Element} element
|
||||
* @param {string} property The property name. This WILL be prefixed.
|
||||
* @param {string} value The value of the property. This will not be prefixed.
|
||||
* @param {string=} extra Additional CSS to append unmodified to the end of
|
||||
* the CSS string.
|
||||
*/
|
||||
function set_prefixed_property_css(element, property, value, extra) {
|
||||
element.style.cssText = prefixes.join(property + ':' + value + ';') + (extra || '');
|
||||
}
|
||||
|
||||
var c = document.createElement('div'),
|
||||
elem = document.createElement('div');
|
||||
|
||||
set_prefixed_value_css(c, 'display', 'box', 'width:42px;padding:0;');
|
||||
set_prefixed_property_css(elem, 'box-flex', '1', 'width:10px;');
|
||||
|
||||
c.appendChild(elem);
|
||||
docElement.appendChild(c);
|
||||
|
||||
var ret = elem.offsetWidth === 42;
|
||||
|
||||
c.removeChild(elem);
|
||||
docElement.removeChild(c);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
// On the S60 and BB Storm, getContext exists, but always returns undefined
|
||||
// http://github.com/Modernizr/Modernizr/issues/issue/97/
|
||||
|
||||
tests['canvas'] = function() {
|
||||
var elem = document.createElement( 'canvas' );
|
||||
return !!(elem.getContext && elem.getContext('2d'));
|
||||
};
|
||||
|
||||
tests['canvastext'] = function() {
|
||||
return !!(ret['canvas'] && is(document.createElement( 'canvas' ).getContext('2d').fillText, 'function'));
|
||||
};
|
||||
|
||||
// This WebGL test false positives in FF depending on graphics hardware. But really it's quite impossible to know
|
||||
// wether webgl will succeed until after you create the context. You might have hardware that can support
|
||||
// a 100x100 webgl canvas, but will not support a 1000x1000 webgl canvas. So this feature inference is weak,
|
||||
// but intentionally so.
|
||||
tests['webgl'] = function(){
|
||||
return !!window.WebGLRenderingContext;
|
||||
};
|
||||
|
||||
/*
|
||||
* The Modernizr.touch test only indicates if the browser supports
|
||||
* touch events, which does not necessarily reflect a touchscreen
|
||||
* device, as evidenced by tablets running Windows 7 or, alas,
|
||||
* the Palm Pre / WebOS (touch) phones.
|
||||
*
|
||||
* Additionally, Chrome (desktop) used to lie about its support on this,
|
||||
* but that has since been rectified: http://crbug.com/36415
|
||||
*
|
||||
* We also test for Firefox 4 Multitouch Support.
|
||||
*
|
||||
* For more info, see: http://modernizr.github.com/Modernizr/touch.html
|
||||
*/
|
||||
|
||||
tests['touch'] = function() {
|
||||
|
||||
return ('ontouchstart' in window) || testMediaQuery('@media ('+prefixes.join('touch-enabled),(')+'modernizr)');
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* geolocation tests for the new Geolocation API specification.
|
||||
* This test is a standards compliant-only test; for more complete
|
||||
* testing, including a Google Gears fallback, please see:
|
||||
* http://code.google.com/p/geo-location-javascript/
|
||||
* or view a fallback solution using google's geo API:
|
||||
* http://gist.github.com/366184
|
||||
*/
|
||||
tests['geolocation'] = function() {
|
||||
return !!navigator.geolocation;
|
||||
};
|
||||
|
||||
// Per 1.6:
|
||||
// This used to be Modernizr.crosswindowmessaging but the longer
|
||||
// name has been deprecated in favor of a shorter and property-matching one.
|
||||
// The old API is still available in 1.6, but as of 2.0 will throw a warning,
|
||||
// and in the first release thereafter disappear entirely.
|
||||
tests['postmessage'] = function() {
|
||||
return !!window.postMessage;
|
||||
};
|
||||
|
||||
// Web SQL database detection is tricky:
|
||||
|
||||
// In chrome incognito mode, openDatabase is truthy, but using it will
|
||||
// throw an exception: http://crbug.com/42380
|
||||
// We can create a dummy database, but there is no way to delete it afterwards.
|
||||
|
||||
// Meanwhile, Safari users can get prompted on any database creation.
|
||||
// If they do, any page with Modernizr will give them a prompt:
|
||||
// http://github.com/Modernizr/Modernizr/issues/closed#issue/113
|
||||
|
||||
// We have chosen to allow the Chrome incognito false positive, so that Modernizr
|
||||
// doesn't litter the web with these test databases. As a developer, you'll have
|
||||
// to account for this gotcha yourself.
|
||||
tests['websqldatabase'] = function() {
|
||||
var result = !!window.openDatabase;
|
||||
/* if (result){
|
||||
try {
|
||||
result = !!openDatabase( mod + "testdb", "1.0", mod + "testdb", 2e4);
|
||||
} catch(e) {
|
||||
}
|
||||
} */
|
||||
return result;
|
||||
};
|
||||
|
||||
// Vendors have inconsistent prefixing with the experimental Indexed DB:
|
||||
// - Firefox is shipping indexedDB in FF4 as moz_indexedDB
|
||||
// - Webkit's implementation is accessible through webkitIndexedDB
|
||||
// We test both styles.
|
||||
tests['indexedDB'] = function(){
|
||||
for (var i = -1, len = domPrefixes.length; ++i < len; ){
|
||||
var prefix = domPrefixes[i].toLowerCase();
|
||||
if (window[prefix + '_indexedDB'] || window[prefix + 'IndexedDB']){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// documentMode logic from YUI to filter out IE8 Compat Mode
|
||||
// which false positives.
|
||||
tests['hashchange'] = function() {
|
||||
return isEventSupported('hashchange', window) && ( document.documentMode === undefined || document.documentMode > 7 );
|
||||
};
|
||||
|
||||
// Per 1.6:
|
||||
// This used to be Modernizr.historymanagement but the longer
|
||||
// name has been deprecated in favor of a shorter and property-matching one.
|
||||
// The old API is still available in 1.6, but as of 2.0 will throw a warning,
|
||||
// and in the first release thereafter disappear entirely.
|
||||
tests['history'] = function() {
|
||||
return !!(window.history && history.pushState);
|
||||
};
|
||||
|
||||
tests['draganddrop'] = function() {
|
||||
return isEventSupported('dragstart') && isEventSupported('drop');
|
||||
};
|
||||
|
||||
tests['websockets'] = function(){
|
||||
return ('WebSocket' in window);
|
||||
};
|
||||
|
||||
|
||||
// http://css-tricks.com/rgba-browser-support/
|
||||
tests['rgba'] = function() {
|
||||
// Set an rgba() color and check the returned value
|
||||
|
||||
set_css( 'background-color:rgba(150,255,150,.5)' );
|
||||
|
||||
return contains( m_style.backgroundColor, 'rgba' );
|
||||
};
|
||||
|
||||
tests['hsla'] = function() {
|
||||
// Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
|
||||
// except IE9 who retains it as hsla
|
||||
|
||||
set_css('background-color:hsla(120,40%,100%,.5)' );
|
||||
|
||||
return contains( m_style.backgroundColor, 'rgba' ) || contains( m_style.backgroundColor, 'hsla' );
|
||||
};
|
||||
|
||||
tests['multiplebgs'] = function() {
|
||||
// Setting multiple images AND a color on the background shorthand property
|
||||
// and then querying the style.background property value for the number of
|
||||
// occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
|
||||
|
||||
set_css( 'background:url(//:),url(//:),red url(//:)' );
|
||||
|
||||
// If the UA supports multiple backgrounds, there should be three occurrences
|
||||
// of the string "url(" in the return value for elem_style.background
|
||||
|
||||
return new RegExp("(url\\s*\\(.*?){3}").test(m_style.background);
|
||||
};
|
||||
|
||||
|
||||
// In testing support for a given CSS property, it's legit to test:
|
||||
// `elem.style[styleName] !== undefined`
|
||||
// If the property is supported it will return an empty string,
|
||||
// if unsupported it will return undefined.
|
||||
|
||||
// We'll take advantage of this quick test and skip setting a style
|
||||
// on our modernizr element, but instead just testing undefined vs
|
||||
// empty string.
|
||||
|
||||
|
||||
tests['backgroundsize'] = function() {
|
||||
return test_props_all( 'backgroundSize' );
|
||||
};
|
||||
|
||||
tests['borderimage'] = function() {
|
||||
return test_props_all( 'borderImage' );
|
||||
};
|
||||
|
||||
|
||||
// Super comprehensive table about all the unique implementations of
|
||||
// border-radius: http://muddledramblings.com/table-of-css3-border-radius-compliance
|
||||
|
||||
tests['borderradius'] = function() {
|
||||
return test_props_all( 'borderRadius', '', function( prop ) {
|
||||
return contains( prop, 'orderRadius' );
|
||||
});
|
||||
};
|
||||
|
||||
// WebOS unfortunately false positives on this test.
|
||||
tests['boxshadow'] = function() {
|
||||
return test_props_all( 'boxShadow' );
|
||||
};
|
||||
|
||||
// FF3.0 will false positive on this test
|
||||
tests['textshadow'] = function(){
|
||||
return document.createElement('div').style.textShadow === '';
|
||||
};
|
||||
|
||||
|
||||
tests['opacity'] = function() {
|
||||
// Browsers that actually have CSS Opacity implemented have done so
|
||||
// according to spec, which means their return values are within the
|
||||
// range of [0.0,1.0] - including the leading zero.
|
||||
|
||||
set_css_all( 'opacity:.55' );
|
||||
|
||||
// The non-literal . in this regex is intentional:
|
||||
// German Chrome returns this value as 0,55
|
||||
// https://github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
|
||||
return /^0.55$/.test(m_style.opacity);
|
||||
};
|
||||
|
||||
|
||||
tests['cssanimations'] = function() {
|
||||
return test_props_all( 'animationName' );
|
||||
};
|
||||
|
||||
|
||||
tests['csscolumns'] = function() {
|
||||
return test_props_all( 'columnCount' );
|
||||
};
|
||||
|
||||
|
||||
tests['cssgradients'] = function() {
|
||||
/**
|
||||
* For CSS Gradients syntax, please see:
|
||||
* http://webkit.org/blog/175/introducing-css-gradients/
|
||||
* https://developer.mozilla.org/en/CSS/-moz-linear-gradient
|
||||
* https://developer.mozilla.org/en/CSS/-moz-radial-gradient
|
||||
* http://dev.w3.org/csswg/css3-images/#gradients-
|
||||
*/
|
||||
|
||||
var str1 = 'background-image:',
|
||||
str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
|
||||
str3 = 'linear-gradient(left top,#9f9, white);';
|
||||
|
||||
set_css(
|
||||
(str1 + prefixes.join(str2 + str1) + prefixes.join(str3 + str1)).slice(0,-str1.length)
|
||||
);
|
||||
|
||||
return contains( m_style.backgroundImage, 'gradient' );
|
||||
};
|
||||
|
||||
|
||||
tests['cssreflections'] = function() {
|
||||
return test_props_all( 'boxReflect' );
|
||||
};
|
||||
|
||||
|
||||
tests['csstransforms'] = function() {
|
||||
return !!test_props([ 'transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform' ]);
|
||||
};
|
||||
|
||||
|
||||
tests['csstransforms3d'] = function() {
|
||||
|
||||
var ret = !!test_props([ 'perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective' ]);
|
||||
|
||||
// Webkit’s 3D transforms are passed off to the browser's own graphics renderer.
|
||||
// It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
|
||||
// some conditions. As a result, Webkit typically recognizes the syntax but
|
||||
// will sometimes throw a false positive, thus we must do a more thorough check:
|
||||
if (ret && 'webkitPerspective' in docElement.style){
|
||||
|
||||
// Webkit allows this media query to succeed only if the feature is enabled.
|
||||
// `@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }`
|
||||
ret = testMediaQuery('@media ('+prefixes.join('transform-3d),(')+'modernizr)');
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
tests['csstransitions'] = function() {
|
||||
return test_props_all( 'transitionProperty' );
|
||||
};
|
||||
|
||||
|
||||
// @font-face detection routine by Diego Perini
|
||||
// http://javascript.nwbox.com/CSSSupport/
|
||||
tests['fontface'] = function(){
|
||||
|
||||
var
|
||||
sheet, bool,
|
||||
head = docHead || docElement,
|
||||
style = document.createElement("style"),
|
||||
impl = document.implementation || { hasFeature: function() { return false; } };
|
||||
|
||||
style.type = 'text/css';
|
||||
head.insertBefore(style, head.firstChild);
|
||||
sheet = style.sheet || style.styleSheet;
|
||||
|
||||
var supportAtRule = impl.hasFeature('CSS2', '') ?
|
||||
function(rule) {
|
||||
if (!(sheet && rule)) return false;
|
||||
var result = false;
|
||||
try {
|
||||
sheet.insertRule(rule, 0);
|
||||
result = (/src/i).test(sheet.cssRules[0].cssText);
|
||||
sheet.deleteRule(sheet.cssRules.length - 1);
|
||||
} catch(e) { }
|
||||
return result;
|
||||
} :
|
||||
function(rule) {
|
||||
if (!(sheet && rule)) return false;
|
||||
sheet.cssText = rule;
|
||||
|
||||
return sheet.cssText.length !== 0 && (/src/i).test(sheet.cssText) &&
|
||||
sheet.cssText
|
||||
.replace(/\r+|\n+/g, '')
|
||||
.indexOf(rule.split(' ')[0]) === 0;
|
||||
};
|
||||
|
||||
bool = supportAtRule('@font-face { font-family: "font"; src: url(data:,); }');
|
||||
head.removeChild(style);
|
||||
return bool;
|
||||
};
|
||||
|
||||
|
||||
// These tests evaluate support of the video/audio elements, as well as
|
||||
// testing what types of content they support.
|
||||
//
|
||||
// We're using the Boolean constructor here, so that we can extend the value
|
||||
// e.g. Modernizr.video // true
|
||||
// Modernizr.video.ogg // 'probably'
|
||||
//
|
||||
// Codec values from : http://github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
|
||||
// thx to NielsLeenheer and zcorpan
|
||||
|
||||
// Note: in FF 3.5.1 and 3.5.0, "no" was a return value instead of empty string.
|
||||
// Modernizr does not normalize for that.
|
||||
|
||||
tests['video'] = function() {
|
||||
var elem = document.createElement('video'),
|
||||
bool = !!elem.canPlayType;
|
||||
|
||||
if (bool){
|
||||
bool = new Boolean(bool);
|
||||
bool.ogg = elem.canPlayType('video/ogg; codecs="theora"');
|
||||
|
||||
// Workaround required for IE9, which doesn't report video support without audio codec specified.
|
||||
// bug 599718 @ msft connect
|
||||
var h264 = 'video/mp4; codecs="avc1.42E01E';
|
||||
bool.h264 = elem.canPlayType(h264 + '"') || elem.canPlayType(h264 + ', mp4a.40.2"');
|
||||
|
||||
bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"');
|
||||
}
|
||||
return bool;
|
||||
};
|
||||
|
||||
tests['audio'] = function() {
|
||||
var elem = document.createElement('audio'),
|
||||
bool = !!elem.canPlayType;
|
||||
|
||||
if (bool){
|
||||
bool = new Boolean(bool);
|
||||
bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"');
|
||||
bool.mp3 = elem.canPlayType('audio/mpeg;');
|
||||
|
||||
// Mimetypes accepted:
|
||||
// https://developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
|
||||
// http://bit.ly/iphoneoscodecs
|
||||
bool.wav = elem.canPlayType('audio/wav; codecs="1"');
|
||||
bool.m4a = elem.canPlayType('audio/x-m4a;') || elem.canPlayType('audio/aac;');
|
||||
}
|
||||
return bool;
|
||||
};
|
||||
|
||||
|
||||
// Firefox has made these tests rather unfun.
|
||||
|
||||
// In FF4, if disabled, window.localStorage should === null.
|
||||
|
||||
// Normally, we could not test that directly and need to do a
|
||||
// `('localStorage' in window) && ` test first because otherwise Firefox will
|
||||
// throw http://bugzil.la/365772 if cookies are disabled
|
||||
|
||||
// However, in Firefox 4 betas, if dom.storage.enabled == false, just mentioning
|
||||
// the property will throw an exception. http://bugzil.la/599479
|
||||
// This looks to be fixed for FF4 Final.
|
||||
|
||||
// Because we are forced to try/catch this, we'll go aggressive.
|
||||
|
||||
// FWIW: IE8 Compat mode supports these features completely:
|
||||
// http://www.quirksmode.org/dom/html5.html
|
||||
// But IE8 doesn't support either with local files
|
||||
|
||||
tests['localstorage'] = function() {
|
||||
try {
|
||||
return !!localStorage.getItem;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
tests['sessionstorage'] = function() {
|
||||
try {
|
||||
return !!sessionStorage.getItem;
|
||||
} catch(e){
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
tests['webWorkers'] = function () {
|
||||
return !!window.Worker;
|
||||
};
|
||||
|
||||
|
||||
tests['applicationcache'] = function() {
|
||||
return !!window.applicationCache;
|
||||
};
|
||||
|
||||
|
||||
// Thanks to Erik Dahlstrom
|
||||
tests['svg'] = function(){
|
||||
return !!document.createElementNS && !!document.createElementNS(ns.svg, "svg").createSVGRect;
|
||||
};
|
||||
|
||||
tests['inlinesvg'] = function() {
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = '<svg/>';
|
||||
return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
|
||||
};
|
||||
|
||||
// Thanks to F1lt3r and lucideer
|
||||
// http://github.com/Modernizr/Modernizr/issues#issue/35
|
||||
tests['smil'] = function(){
|
||||
return !!document.createElementNS && /SVG/.test(tostring.call(document.createElementNS(ns.svg,'animate')));
|
||||
};
|
||||
|
||||
tests['svgclippaths'] = function(){
|
||||
// Possibly returns a false positive in Safari 3.2?
|
||||
return !!document.createElementNS && /SVG/.test(tostring.call(document.createElementNS(ns.svg,'clipPath')));
|
||||
};
|
||||
|
||||
|
||||
// input features and input types go directly onto the ret object, bypassing the tests loop.
|
||||
// Hold this guy to execute in a moment.
|
||||
function webforms(){
|
||||
|
||||
// Run through HTML5's new input attributes to see if the UA understands any.
|
||||
// We're using f which is the <input> element created early on
|
||||
// Mike Taylr has created a comprehensive resource for testing these attributes
|
||||
// when applied to all input types:
|
||||
// http://miketaylr.com/code/input-type-attr.html
|
||||
// spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
|
||||
ret['input'] = (function(props) {
|
||||
for (var i = 0, len = props.length; i<len; i++) {
|
||||
attrs[ props[i] ] = !!(props[i] in inputElem);
|
||||
}
|
||||
return attrs;
|
||||
})('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
|
||||
|
||||
// Run through HTML5's new input types to see if the UA understands any.
|
||||
// This is put behind the tests runloop because it doesn't return a
|
||||
// true/false like all the other tests; instead, it returns an object
|
||||
// containing each input type with its corresponding true/false value
|
||||
|
||||
// Big thanks to @miketaylr for the html5 forms expertise. http://miketaylr.com/
|
||||
ret['inputtypes'] = (function(props) {
|
||||
|
||||
for (var i = 0, bool, inputElemType, defaultView, len=props.length; i < len; i++) {
|
||||
|
||||
inputElem.setAttribute('type', inputElemType = props[i]);
|
||||
bool = inputElem.type !== 'text';
|
||||
|
||||
// We first check to see if the type we give it sticks..
|
||||
// If the type does, we feed it a textual value, which shouldn't be valid.
|
||||
// If the value doesn't stick, we know there's input sanitization which infers a custom UI
|
||||
if (bool){
|
||||
|
||||
inputElem.value = smile;
|
||||
inputElem.style.cssText = 'position:absolute;visibility:hidden;';
|
||||
|
||||
if (/^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined){
|
||||
|
||||
docElement.appendChild(inputElem);
|
||||
defaultView = document.defaultView;
|
||||
|
||||
// Safari 2-4 allows the smiley as a value, despite making a slider
|
||||
bool = defaultView.getComputedStyle &&
|
||||
defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
|
||||
// Mobile android web browser has false positive, so must
|
||||
// check the height to see if the widget is actually there.
|
||||
(inputElem.offsetHeight !== 0);
|
||||
|
||||
docElement.removeChild(inputElem);
|
||||
|
||||
} else if (/^(search|tel)$/.test(inputElemType)){
|
||||
// Spec doesnt define any special parsing or detectable UI
|
||||
// behaviors so we pass these through as true
|
||||
|
||||
// Interestingly, opera fails the earlier test, so it doesn't
|
||||
// even make it here.
|
||||
|
||||
} else if (/^(url|email)$/.test(inputElemType)) {
|
||||
// Real url and email support comes with prebaked validation.
|
||||
bool = inputElem.checkValidity && inputElem.checkValidity() === false;
|
||||
|
||||
} else if (/^color$/.test(inputElemType)) {
|
||||
// chuck into DOM and force reflow for Opera bug in 11.00
|
||||
// github.com/Modernizr/Modernizr/issues#issue/159
|
||||
docElement.appendChild(inputElem);
|
||||
docElement.offsetWidth;
|
||||
bool = inputElem.value != smile;
|
||||
docElement.removeChild(inputElem);
|
||||
|
||||
} else {
|
||||
// If the upgraded input compontent rejects the :) text, we got a winner
|
||||
bool = inputElem.value != smile;
|
||||
}
|
||||
}
|
||||
|
||||
inputs[ props[i] ] = !!bool;
|
||||
}
|
||||
return inputs;
|
||||
})('search tel url email datetime date month week time datetime-local number range color'.split(' '));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// End of test definitions
|
||||
// -----------------------
|
||||
|
||||
|
||||
|
||||
// Run through all tests and detect their support in the current UA.
|
||||
// todo: hypothetically we could be doing an array of tests and use a basic loop here.
|
||||
for ( var feature in tests ) {
|
||||
if ( hasOwnProperty( tests, feature ) ) {
|
||||
// run the test, throw the return value into the Modernizr,
|
||||
// then based on that boolean, define an appropriate className
|
||||
// and push it into an array of classes we'll join later.
|
||||
featurename = feature.toLowerCase();
|
||||
ret[ featurename ] = tests[ feature ]();
|
||||
|
||||
classes.push( ( ret[ featurename ] ? '' : 'no-' ) + featurename );
|
||||
}
|
||||
}
|
||||
|
||||
// input tests need to run.
|
||||
if (!ret.input) webforms();
|
||||
|
||||
|
||||
|
||||
// Per 1.6: deprecated API is still accesible for now:
|
||||
ret.crosswindowmessaging = ret.postmessage;
|
||||
ret.historymanagement = ret.history;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Addtest allows the user to define their own feature tests
|
||||
* the result will be added onto the Modernizr object,
|
||||
* as well as an appropriate className set on the html element
|
||||
*
|
||||
* @param feature - String naming the feature
|
||||
* @param test - Function returning true if feature is supported, false if not
|
||||
*/
|
||||
ret.addTest = function (feature, test) {
|
||||
feature = feature.toLowerCase();
|
||||
|
||||
if (ret[ feature ]) {
|
||||
return; // quit if you're trying to overwrite an existing test
|
||||
}
|
||||
test = !!(test());
|
||||
docElement.className += ' ' + (test ? '' : 'no-') + feature;
|
||||
ret[ feature ] = test;
|
||||
return ret; // allow chaining.
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset m.style.cssText to nothing to reduce memory footprint.
|
||||
*/
|
||||
set_css( '' );
|
||||
modElem = inputElem = null;
|
||||
|
||||
//>>BEGIN IEPP
|
||||
// Enable HTML 5 elements for styling in IE.
|
||||
// fyi: jscript version does not reflect trident version
|
||||
// therefore ie9 in ie7 mode will still have a jScript v.9
|
||||
if ( enableHTML5 && window.attachEvent && (function(){ var elem = document.createElement("div");
|
||||
elem.innerHTML = "<elem></elem>";
|
||||
return elem.childNodes.length !== 1; })()) {
|
||||
// iepp v1.6.2 by @jon_neal : code.google.com/p/ie-print-protector
|
||||
(function(win, doc) {
|
||||
var elems = 'abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video',
|
||||
elemsArr = elems.split('|'),
|
||||
elemsArrLen = elemsArr.length,
|
||||
elemRegExp = new RegExp('(^|\\s)('+elems+')', 'gi'),
|
||||
tagRegExp = new RegExp('<(\/*)('+elems+')', 'gi'),
|
||||
ruleRegExp = new RegExp('(^|[^\\n]*?\\s)('+elems+')([^\\n]*)({[\\n\\w\\W]*?})', 'gi'),
|
||||
docFrag = doc.createDocumentFragment(),
|
||||
html = doc.documentElement,
|
||||
head = html.firstChild,
|
||||
bodyElem = doc.createElement('body'),
|
||||
styleElem = doc.createElement('style'),
|
||||
body;
|
||||
function shim(doc) {
|
||||
var a = -1;
|
||||
while (++a < elemsArrLen)
|
||||
// Use createElement so IE allows HTML5-named elements in a document
|
||||
doc.createElement(elemsArr[a]);
|
||||
}
|
||||
function getCSS(styleSheetList, mediaType) {
|
||||
var a = -1,
|
||||
len = styleSheetList.length,
|
||||
styleSheet,
|
||||
cssTextArr = [];
|
||||
while (++a < len) {
|
||||
styleSheet = styleSheetList[a];
|
||||
// Get css from all non-screen stylesheets and their imports
|
||||
if ((mediaType = styleSheet.media || mediaType) != 'screen') cssTextArr.push(getCSS(styleSheet.imports, mediaType), styleSheet.cssText);
|
||||
}
|
||||
return cssTextArr.join('');
|
||||
}
|
||||
// Shim the document and iepp fragment
|
||||
shim(doc);
|
||||
shim(docFrag);
|
||||
// Add iepp custom print style element
|
||||
head.insertBefore(styleElem, head.firstChild);
|
||||
styleElem.media = 'print';
|
||||
win.attachEvent(
|
||||
'onbeforeprint',
|
||||
function() {
|
||||
var a = -1,
|
||||
cssText = getCSS(doc.styleSheets, 'all'),
|
||||
cssTextArr = [],
|
||||
rule;
|
||||
body = body || doc.body;
|
||||
// Get only rules which reference HTML5 elements by name
|
||||
while ((rule = ruleRegExp.exec(cssText)) != null)
|
||||
// Replace all html5 element references with iepp substitute classnames
|
||||
cssTextArr.push((rule[1]+rule[2]+rule[3]).replace(elemRegExp, '$1.iepp_$2')+rule[4]);
|
||||
// Write iepp custom print CSS
|
||||
styleElem.styleSheet.cssText = cssTextArr.join('\n');
|
||||
while (++a < elemsArrLen) {
|
||||
var nodeList = doc.getElementsByTagName(elemsArr[a]),
|
||||
nodeListLen = nodeList.length,
|
||||
b = -1;
|
||||
while (++b < nodeListLen)
|
||||
if (nodeList[b].className.indexOf('iepp_') < 0)
|
||||
// Append iepp substitute classnames to all html5 elements
|
||||
nodeList[b].className += ' iepp_'+elemsArr[a];
|
||||
}
|
||||
docFrag.appendChild(body);
|
||||
html.appendChild(bodyElem);
|
||||
// Write iepp substitute print-safe document
|
||||
bodyElem.className = body.className;
|
||||
// Replace HTML5 elements with <font> which is print-safe and shouldn't conflict since it isn't part of html5
|
||||
bodyElem.innerHTML = body.innerHTML.replace(tagRegExp, '<$1font');
|
||||
}
|
||||
);
|
||||
win.attachEvent(
|
||||
'onafterprint',
|
||||
function() {
|
||||
// Undo everything done in onbeforeprint
|
||||
bodyElem.innerHTML = '';
|
||||
html.removeChild(bodyElem);
|
||||
html.appendChild(body);
|
||||
styleElem.styleSheet.cssText = '';
|
||||
}
|
||||
);
|
||||
})(window, document);
|
||||
}
|
||||
//>>END IEPP
|
||||
|
||||
// Assign private properties to the return object with prefix
|
||||
ret._enableHTML5 = enableHTML5;
|
||||
ret._version = version;
|
||||
|
||||
// Remove "no-js" class from <html> element, if it exists:
|
||||
docElement.className = docElement.className.replace(/\bno-js\b/,'')
|
||||
+ ' js '
|
||||
|
||||
// Add the new classes to the <html> element.
|
||||
+ classes.join( ' ' );
|
||||
|
||||
return ret;
|
||||
|
||||
})(this,this.document);
|
|
@ -1,48 +0,0 @@
|
|||
function pinboardNS_fetch_script(url) {
|
||||
console.log(url);
|
||||
document.writeln('<s'+'cript type="text/javascript" src="' + url + '"></s'+'cript>');
|
||||
}
|
||||
|
||||
function pinboardNS_show_bmarks(r) {
|
||||
var lr = new Pinboard_Linkroll();
|
||||
lr.set_items(r);
|
||||
lr.show_bmarks();
|
||||
}
|
||||
|
||||
function Pinboard_Linkroll() {
|
||||
var items;
|
||||
|
||||
this.set_items = function(i) {
|
||||
this.items = i;
|
||||
}
|
||||
this.show_bmarks = function() {
|
||||
var lines = [];
|
||||
for (var i = 0; i < this.items.length; i++) {
|
||||
var item = this.items[i];
|
||||
var str = this.format_item(item);
|
||||
lines.push(str);
|
||||
}
|
||||
document.getElementById(linkroll).innerHTML = lines.join("\n");
|
||||
}
|
||||
this.cook = function(v) {
|
||||
return v.replace('<', '<').replace('>', '>>');
|
||||
}
|
||||
|
||||
this.format_item = function(it) {
|
||||
var str = "<li class=\"pin-item\">";
|
||||
if (!it.d) { return; }
|
||||
str += "<p><a class=\"pin-title\" href=\"" + this.cook(it.u) + "\">" + this.cook(it.d) + "</a>";
|
||||
if (it.n) {
|
||||
str += "<span class=\"pin-description\">" + this.cook(it.n) + "</span>\n";
|
||||
}
|
||||
if (it.t.length > 0) {
|
||||
for (var i = 0; i < it.t.length; i++) {
|
||||
var tag = it.t[i];
|
||||
str += " <a class=\"pin-tag\" href=\"http://pinboard.in/u:"+ this.cook(it.a) + "/t:" + this.cook(tag) + "\">" + this.cook(tag).replace(/^\s+|\s+$/g, '') + "</a> ";
|
||||
}
|
||||
}
|
||||
str += "</p></li>\n";
|
||||
return str;
|
||||
}
|
||||
}
|
||||
Pinboard_Linkroll.prototype = new Pinboard_Linkroll();
|
|
@ -1,30 +0,0 @@
|
|||
function addDivLines(){
|
||||
$('div.highlight pre code').each(function(el){
|
||||
var content = bonzo(el).html();
|
||||
var lines = content.split('\n');
|
||||
var count = lines.length;
|
||||
bonzo(lines).each(function(line, index){
|
||||
if(line == '') line = ' ';
|
||||
lines[index] = '<div class="line">' + line + '</div>';
|
||||
});
|
||||
$(el).html(lines.join(''));
|
||||
});
|
||||
}
|
||||
function preToTable(){
|
||||
$('div.highlight').each(function(code){
|
||||
var tableStart = '<table cellpadding="0" cellspacing="0"><tbody><tr><td class="gutter">';
|
||||
var lineNumbers = '<pre class="line-numbers">';
|
||||
var tableMiddle = '</pre></td><td class="code" width="100%">';
|
||||
var tableEnd = '</td></tr></tbody></table>';
|
||||
var count = $('div.line', code).length;
|
||||
for (i=1;i<=count; i++){
|
||||
lineNumbers += '<span class="line">'+i+'</span>\n';
|
||||
}
|
||||
table = tableStart + lineNumbers + tableMiddle + '<pre>'+$('pre', code).html()+'</pre>' + tableEnd;
|
||||
$(code).html(table);
|
||||
});
|
||||
}
|
||||
$.domReady(function () {
|
||||
addDivLines();
|
||||
preToTable();
|
||||
});
|
|
@ -1,64 +0,0 @@
|
|||
function getTwitterFeed(success, user, count, replies) {
|
||||
feed = new jXHR();
|
||||
feed.onerror = function (msg,url) { alert(msg); }
|
||||
feed.onreadystatechange = function(data){
|
||||
if (feed.readyState === 4) {
|
||||
var tweets = new Array();
|
||||
for (i in data){
|
||||
if(tweets.length < count){
|
||||
if(replies || data[i].in_reply_to_user_id == null){
|
||||
tweets.push(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
success(tweets);
|
||||
}
|
||||
};
|
||||
feed.open("GET","http://twitter.com/statuses/user_timeline/"+user+".json?trim_user=true&count="+parseInt(count)+25+"&callback=?");
|
||||
feed.send();
|
||||
}
|
||||
|
||||
getTwitterFeed(showTwitterFeed, twitter_user, tweet_count, show_replies);
|
||||
|
||||
function showTwitterFeed(tweets){
|
||||
var timeline = document.getElementById('tweets');
|
||||
timeline.innerHTML='';
|
||||
for (t in tweets){
|
||||
timeline.innerHTML+='<li>'+'<p>'+'<a href="http://twitter.com/'+twitter_user+'/status/'+tweets[t].id_str+'"><span>∞</span><span>'+prettyDate(tweets[t].created_at)+'</span></a>'+linkifyTweet(tweets[t].text)+'</p>'+'</li>';
|
||||
}
|
||||
}
|
||||
function linkifyTweet(text){
|
||||
return text.replace(/(https?:\/\/)([\w\-:;?&=+.%#\/]+)/gi, '<a href="$1$2">$2</a>')
|
||||
.replace(/(^|\W)@(\w+)/g, '$1<a href="http://twitter.com/$2">@$2</a>')
|
||||
.replace(/(^|\W)#(\w+)/g, '$1<a href="http://search.twitter.com/search?q=%23$2">#$2</a>');
|
||||
}
|
||||
|
||||
function prettyDate(date_str){
|
||||
var time_formats = [
|
||||
[60, 'now', 1], // 60
|
||||
[120, '1 min', '1 minute from now'], // 60*2
|
||||
[3600, 'mins', 60], // 60*60, 60
|
||||
[7200, '1 hour', '1 hour from now'], // 60*60*2
|
||||
[86400, 'hours', 3600], // 60*60*24, 60*60
|
||||
[172800, '1 day', 'tomorrow'], // 60*60*24*2
|
||||
[2903040000, 'days', 86400], // 60*60*24*7, 60*60*24
|
||||
];
|
||||
var time = ('' + date_str).replace(/-/g,"/").replace(/[TZ]/g," ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
if(time.substr(time.length-4,1)==".") time =time.substr(0,time.length-4);
|
||||
var seconds = (new Date - new Date(time)) / 1000;
|
||||
var token = 'ago', list_choice = 1;
|
||||
if (seconds < 0) {
|
||||
seconds = Math.abs(seconds);
|
||||
token = 'from now';
|
||||
list_choice = 2;
|
||||
}
|
||||
var i = 0, format;
|
||||
while (format = time_formats[i++])
|
||||
if (seconds < format[0]) {
|
||||
if (typeof format[2] == 'string')
|
||||
return format[list_choice];
|
||||
else
|
||||
return Math.floor(seconds / format[2]) + ' ' + format[1];
|
||||
}
|
||||
return time;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue