case2/griff_T6.htm
GoldSilverDiamondsGift CardsLayaway PlansDirectionsContactCharms – Under $50Engagement Rings – Under $300Wedding Rings – Under $120Pendants – Under $40
SPECIAL!
This month only – all diamond pendants are 50% off original price.Make Griff's Your One Stop for Jewelry
We know that times are tough for many people, but that doesn't mean that you have to skip the purchase of an engagement ring or not get the wedding rings you want. At Griff Jewelers, we have more than 100 years experience in helping our customers choose just the right jewelry for the most important times of their lives. We have jewelry at every price point that's designed to be kind to every budget, no matter how small. We will get you to the altar in style. We will help you find the perfect jewel or ring at an unbeatable price. We also provide expert jewelry tips, free appraisal, and a knowledge about jewelry in general so that you can make the right choice at the right price.
Only Griff's customers receive exclusive discounts on site, along with unbelievable deals on selected jewels. We give you loads of shopping tips for free. We have thousands of items in stock. Whether you're looking for diamond rings, anniversary rings, gemstone and birthstone jewelry, or friendship rings at the lowest price – make Griff Jewelers your only destination when you are looking for value, quality, and savings. People come to Griff's from all over the South. Whether it's pearls, sapphires, bracelets, or necklaces, we have the largest selection at the prices you can afford. We'll give you a fantastic deal no matter what type of jewelry you are looking for.
✧ Griff Jewelers ✧ 47 Dixie Drive ✧ Little Rock, Arkansas 34678 ✧(555) 456-0998 ✧
case2/grifflogo.jpg
case2/links.css
nav {
width: 926px; /* descendant selector margin values effect this width; subtract 2px for each link */
border: solid 2px black;
background-color: yellow;
text-align: center;
margin-bottom: 10px;
}
nav ul li {
list-style-type: none;
display: inline;
color: black;
margin-right: 2em;
padding: 6px;
}
nav ul li a:link {
background-color: #f6f60d;
}
navbar ul li a:hover {
color: #f4f427;
background-color: #090909;
}
case2/modernizr-2.js
/*!
* Modernizr v2.0.6
* http://www.modernizr.com
*
* Copyright (c) 2009-2011 Faruk Ates, Paul Irish, Alex Sexton
* Dual-licensed under the BSD or MIT licenses: www.modernizr.com/license/
*/
/*
* Modernizr tests which native CSS3 and HTML5 features are available in
* the current UA and makes the results available to you in two ways:
* as properties on a global Modernizr object, and as classes on the
* <html> element. This information allows you to progressively enhance
* your pages with a granular level of control over the experience.
*
* Modernizr has an optional (not included) conditional resource loader
* called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
* To get a build that includes Modernizr.load(), as well as cho ...
1. case2/griff_T6.htm
GoldSilverDiamondsGift CardsLayaway
PlansDirectionsContactCharms – Under $50Engagement Rings –
Under $300Wedding Rings – Under $120Pendants – Under $40
SPECIAL!
This month only – all diamond pendants are 50% off original
price.Make Griff's Your One Stop for Jewelry
We know that times are tough for many people, but that doesn't
mean that you have to skip the purchase of an engagement ring
or not get the wedding rings you want. At Griff Jewelers, we
have more than 100 years experience in helping our customers
choose just the right jewelry for the most important times of
their lives. We have jewelry at every price point that's designed
to be kind to every budget, no matter how small. We will get
you to the altar in style. We will help you find the perfect jewel
or ring at an unbeatable price. We also provide expert jewelry
tips, free appraisal, and a knowledge about jewelry in general so
that you can make the right choice at the right price.
Only Griff's customers receive exclusive discounts on site,
along with unbelievable deals on selected jewels. We give you
loads of shopping tips for free. We have thousands of items in
stock. Whether you're looking for diamond rings, anniversary
rings, gemstone and birthstone jewelry, or friendship rings at
the lowest price – make Griff Jewelers your only destination
when you are looking for value, quality, and savings. People
come to Griff's from all over the South. Whether it's pearls,
sapphires, bracelets, or necklaces, we have the largest selection
at the prices you can afford. We'll give you a fantastic deal no
matter what type of jewelry you are looking for.
✧ Griff Jewelers ✧ 47 Dixie Drive ✧ Little Rock, Arkansas
34678 ✧(555) 456-0998 ✧
case2/grifflogo.jpg
2. case2/links.css
nav {
width: 926px; /* descendant selector margin values effect this
width; subtract 2px for each link */
border: solid 2px black;
background-color: yellow;
text-align: center;
margin-bottom: 10px;
}
nav ul li {
list-style-type: none;
display: inline;
color: black;
margin-right: 2em;
padding: 6px;
}
nav ul li a:link {
background-color: #f6f60d;
}
navbar ul li a:hover {
color: #f4f427;
background-color: #090909;
}
case2/modernizr-2.js
/*!
* Modernizr v2.0.6
* http://www.modernizr.com
*
* Copyright (c) 2009-2011 Faruk Ates, Paul Irish, Alex Sexton
* Dual-licensed under the BSD or MIT licenses:
www.modernizr.com/license/
3. */
/*
* Modernizr tests which native CSS3 and HTML5 features are
available in
* the current UA and makes the results available to you in two
ways:
* as properties on a global Modernizr object, and as classes on
the
* <html> element. This information allows you to
progressively enhance
* your pages with a granular level of control over the
experience.
*
* Modernizr has an optional (not included) conditional resource
loader
* called Modernizr.load(), based on Yepnope.js
(yepnopejs.com).
* To get a build that includes Modernizr.load(), as well as
choosing
* which tests to include, go to www.modernizr.com/download/
*
* Authors Faruk Ates, Paul Irish, Alex Sexton,
* Contributors Ryan Seddon, Ben Alman
*/
window.Modernizr = (function( window, document, undefined )
{
var version = '2.0.6',
Modernizr = {},
// option for enabling the HTML classes to be added
enableClasses = true,
4. 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),
mStyle = 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
5. // 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
// Inject element with style element and some CSS rules
injectElementWithStyles = function( rule, callback, nodes,
testnames ) {
var style, ret, node,
div = document.createElement('div');
if ( parseInt(nodes, 10) ) {
// In order not to give false positives we create a node for
each test
// This also allows the method to scale for unspecified
uses
while ( nodes-- ) {
node = document.createElement('div');
node.id = testnames ? testnames[nodes] : mod +
(nodes + 1);
div.appendChild(node);
}
}
// <style> elements in IE6-9 are considered 'NoScope'
6. elements and therefore will be removed
// when injected with innerHTML. To get around this you
need to prepend the 'NoScope' element
// with a 'scoped' element, in our case the soft-hyphen entity
as it won't mess with our measurements.
// http://msdn.microsoft.com/en-
us/library/ms533897%28VS.85%29.aspx
style = ['­', '<style>', rule, '</style>'].join('');
div.id = mod;
div.innerHTML += style;
docElement.appendChild(div);
ret = callback(div, rule);
div.parentNode.removeChild(div);
return !!ret;
},
// adapted from matchMedia polyfill
// by Scott Jehl and Paul Irish
// gist.github.com/786768
testMediaQuery = function( mq ) {
if ( window.matchMedia ) {
return matchMedia(mq).matches;
}
var bool;
injectElementWithStyles('@media ' + mq + ' { #' + mod + '
{ position: absolute; } }', function( node ) {
bool = (window.getComputedStyle ?
getComputedStyle(node, null) :
node.currentStyle)['position'] == 'absolute';
7. });
return bool;
},
/**
* 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');
8. }
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));
9. };
}
/**
* setCss applies given styles to the Modernizr DOM node.
*/
function setCss( str ) {
mStyle.cssText = str;
}
/**
* setCssAll extrapolates all vendor-specific css strings.
*/
function setCssAll( str1, str2 ) {
return setCss(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);
}
/**
* testProps 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
10. not yet set.
*/
function testProps( props, prefixed ) {
for ( var i in props ) {
if ( mStyle[ props[i] ] !== undefined ) {
return prefixed == 'pfx' ? props[i] : true;
}
}
return false;
}
/**
* testPropsAll 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 testPropsAll( prop, prefixed ) {
var ucProp = prop.charAt(0).toUpperCase() +
prop.substr(1),
props = (prop + ' ' + domPrefixes.join(ucProp + ' ') +
ucProp).split(' ');
return testProps(props, prefixed);
}
/**
* testBundle tests a list of CSS features that require element
and style injection.
* By bundling them together we can reduce the need to
touch the DOM multiple times.
*/
11. /*>>testBundle*/
var testBundle = (function( styles, tests ) {
var style = styles.join(''),
len = tests.length;
injectElementWithStyles(style, function( node, rule ) {
var style =
document.styleSheets[document.styleSheets.length - 1],
// IE8 will bork if you create a custom build that
excludes both fontface and generatedcontent tests.
// So we check for cssRules and that there is a rule
available
// More here:
https://github.com/Modernizr/Modernizr/issues/288 &
https://github.com/Modernizr/Modernizr/issues/293
cssText = style.cssRules && style.cssRules[0] ?
style.cssRules[0].cssText : style.cssText || "",
children = node.childNodes, hash = {};
while ( len-- ) {
hash[children[len].id] = children[len];
}
/*>>touch*/ Modernizr['touch'] = ('ontouchstart'
in window) || hash['touch'].offsetTop === 9; /*>>touch*/
/*>>csstransforms3d*/ Modernizr['csstransforms3d'] =
hash['csstransforms3d'].offsetLeft === 9;
/*>>csstransforms3d*/
/*>>generatedcontent*/Modernizr['generatedcontent'] =
hash['generatedcontent'].offsetHeight >= 1;
/*>>generatedcontent*/
/*>>fontface*/ Modernizr['fontface'] =
/src/i.test(cssText) &&
cssText.indexOf(rule.split(' ')[0]) === 0; /*>>fontface*/
}, len, tests);
13. */
tests['flexbox'] = function() {
/**
* setPrefixedValueCSS 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 setPrefixedValueCSS( element, property, value,
extra ) {
property += ':';
element.style.cssText = (property + prefixes.join(value
+ ';' + property)).slice(0, -property.length) + (extra || '');
}
/**
* setPrefixedPropertyCSS 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.
*/
14. function setPrefixedPropertyCSS( element, property,
value, extra ) {
element.style.cssText = prefixes.join(property + ':' +
value + ';') + (extra || '');
}
var c = document.createElement('div'),
elem = document.createElement('div');
setPrefixedValueCSS(c, 'display', 'box',
'width:42px;padding:0;');
setPrefixedPropertyCSS(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 !!(Modernizr['canvas'] &&
15. is(document.createElement('canvas').getContext('2d').fillText,
'function'));
};
// This WebGL test may false positive.
// But really it's quite impossible to know whether 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.
// It is known to false positive in FF4 with certain hardware
and the iPad 2.
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
16. */
tests['touch'] = function() {
return Modernizr['touch'];
};
/**
* 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
17. // 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 had inconsistent prefixing with the experimental
Indexed DB:
// - Webkit's implementation is accessible through
webkitIndexedDB
// - Firefox shipped moz_indexedDB before FF4b9, but since
then has been mozIndexedDB
// For speed, we don't test the legacy (and beta-only)
indexedDB
18. tests['indexedDB'] = function() {
for ( var i = -1, len = domPrefixes.length; ++i < len; ){
if ( window[domPrefixes[i].toLowerCase() + 'IndexedDB']
){
return true;
}
}
return !!window.indexedDB;
};
// 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');
};
19. // Mozilla is targeting to land MozWebSocket for FF6
// bugzil.la/659324
tests['websockets'] = function() {
for ( var i = -1, len = domPrefixes.length; ++i < len; ){
if ( window[domPrefixes[i] + 'WebSocket'] ){
return true;
}
}
return 'WebSocket' in window;
};
// http://css-tricks.com/rgba-browser-support/
tests['rgba'] = function() {
// Set an rgba() color and check the returned value
setCss('background-color:rgba(150,255,150,.5)');
return contains(mStyle.backgroundColor, 'rgba');
};
tests['hsla'] = function() {
// Same as rgba(), in fact, browsers re-map hsla() to rgba()
internally,
// except IE9 who retains it as hsla
setCss('background-color:hsla(120,40%,100%,.5)');
return contains(mStyle.backgroundColor, 'rgba') ||
contains(mStyle.backgroundColor, 'hsla');
};
tests['multiplebgs'] = function() {
// Setting multiple images AND a color on the background
shorthand property
// and then querying the style.background property value
20. for the number of
// occurrences of "url(" is a reliable method for detecting
ACTUAL support for this!
setCss('background:url(https://),url(https://),red
url(https://)');
// If the UA supports multiple backgrounds, there should
be three occurrences
// of the string "url(" in the return value for
elemStyle.background
return /(urls*(.*?){3}/.test(mStyle.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 testPropsAll('backgroundSize');
};
tests['borderimage'] = function() {
return testPropsAll('borderImage');
};
21. // Super comprehensive table about all the unique
implementations of
// border-radius: http://muddledramblings.com/table-of-css3-
border-radius-compliance
tests['borderradius'] = function() {
return testPropsAll('borderRadius');
};
// WebOS unfortunately false positives on this test.
tests['boxshadow'] = function() {
return testPropsAll('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.
setCssAll('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/comm
23. return contains(mStyle.backgroundImage, 'gradient');
};
tests['cssreflections'] = function() {
return testPropsAll('boxReflect');
};
tests['csstransforms'] = function() {
return !!testProps(['transformProperty', 'WebkitTransform',
'MozTransform', 'OTransform', 'msTransform']);
};
tests['csstransforms3d'] = function() {
var ret = !!testProps(['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){ ... }`
24. ret = Modernizr['csstransforms3d'];
}
return ret;
};
tests['csstransitions'] = function() {
return testPropsAll('transitionProperty');
};
/*>>fontface*/
// @font-face detection routine by Diego Perini
// http://javascript.nwbox.com/CSSSupport/
tests['fontface'] = function() {
return Modernizr['fontface'];
};
/*>>fontface*/
// CSS generated content detection
tests['generatedcontent'] = function() {
return Modernizr['generatedcontent'];
};
// 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 :
25. http://github.com/NielsLeenheer/html5test/blob/9106a8/index.ht
ml#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 = false;
// IE9 Running on Windows Server SKU can cause an
exception to be thrown, bug #224
try {
if ( bool = !!elem.canPlayType ) {
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"');
}
} catch(e) { }
return bool;
};
26. tests['audio'] = function() {
var elem = document.createElement('audio'),
bool = false;
try {
if ( bool = !!elem.canPlayType ) {
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;');
}
} catch(e) { }
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
27. // 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;
};
28. tests['applicationcache'] = function() {
return !!window.applicationCache;
};
// Thanks to Erik Dahlstrom
tests['svg'] = function() {
return !!document.createElementNS &&
!!document.createElementNS(ns.svg, 'svg').createSVGRect;
};
// specifically for SVG inline in HTML, not within XHTML
// test page: paulirish.com/demo/inline-svg
tests['inlinesvg'] = function() {
var div = document.createElement('div');
div.innerHTML = '<svg/>';
return (div.firstChild && div.firstChild.namespaceURI) ==
ns.svg;
};
// Thanks to F1lt3r and lucideer, ticket #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.
29. // 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
// Only input placeholder is tested while textarea's
placeholder is not.
// Currently Safari 4 and Opera 11 have support only for
the input placeholder
// Both tests are available in feature-detects/forms-
placeholder.js
Modernizr['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
30. // Big thanks to @miketaylr for the html5 forms expertise.
http://miketaylr.com/
Modernizr['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
31. // 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;
}
32. }
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();
Modernizr[featureName] = tests[feature]();
classes.push((Modernizr[featureName] ? '' : 'no-') +
featureName);
}
}
// input tests need to run.
Modernizr.input || webforms();
33. /**
* 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
*/
Modernizr.addTest = function ( feature, test ) {
if ( typeof feature == "object" ) {
for ( var key in feature ) {
if ( hasOwnProperty( feature, key ) ) {
Modernizr.addTest( key, feature[ key ] );
}
}
} else {
feature = feature.toLowerCase();
if ( Modernizr[feature] !== undefined ) {
// we're going to quit if you're trying to overwrite an
existing test
// if we were to allow it, we'd do this:
// var re = new RegExp("b(no-)?" + feature + "b");
// docElement.className =
docElement.className.replace( re, '' );
// but, no rly, stuff 'em.
return;
}
test = typeof test == "boolean" ? test : !!test();
34. docElement.className += ' ' + (test ? '' : 'no-') + feature;
Modernizr[feature] = test;
}
return Modernizr; // allow chaining.
};
// Reset modElem.cssText to nothing to reduce memory
footprint.
setCss('');
modElem = inputElem = null;
//>>BEGIN IEPP
// Enable HTML 5 elements for styling (and printing) in IE.
if ( window.attachEvent && (function(){ var elem =
document.createElement('div');
elem.innerHTML =
'<elem></elem>';
return elem.childNodes.length !==
1; })() ) {
// iepp v2 by @jon_neal & afarkas :
github.com/aFarkas/iepp/
(function(win, doc) {
win.iepp = win.iepp || {};
var iepp = win.iepp,
elems = iepp.html5elements ||
'abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|
footer|header|hgroup|mark|meter|nav|output|progress|section|su
mmary|time|video',
elemsArr = elems.split('|'),
elemsArrLen = elemsArr.length,
elemRegExp = new RegExp('(^|s)('+elems+')', 'gi'),
tagRegExp = new RegExp('<(/*)('+elems+')', 'gi'),
35. filterReg = /^s*[{}]s*$/,
ruleRegExp = new
RegExp('(^|[^n]*?s)('+elems+')([^n]*)({[nwW]*?})',
'gi'),
docFrag = doc.createDocumentFragment(),
html = doc.documentElement,
head = html.firstChild,
bodyElem = doc.createElement('body'),
styleElem = doc.createElement('style'),
printMedias = /print|all/,
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]);
}
iepp.getCSS = function(styleSheetList, mediaType) {
if(styleSheetList+'' === undefined){return '';}
var a = -1,
len = styleSheetList.length,
styleSheet,
cssTextArr = [];
while (++a < len) {
styleSheet = styleSheetList[a];
//currently no test for disabled/alternate stylesheets
if(styleSheet.disabled){continue;}
mediaType = styleSheet.media || mediaType;
// Get css from all non-screen stylesheets and their
imports
if (printMedias.test(mediaType))
cssTextArr.push(iepp.getCSS(styleSheet.imports, mediaType),
styleSheet.cssText);
//reset mediaType to all with every new *not
36. imported* stylesheet
mediaType = 'all';
}
return cssTextArr.join('');
};
iepp.parseCSS = function(cssText) {
var cssTextArr = [],
rule;
while ((rule = ruleRegExp.exec(cssText)) != null){
// Replace all html5 element references with iepp
substitute classnames
cssTextArr.push(( (filterReg.exec(rule[1]) ? 'n' :
rule[1]) +rule[2]+rule[3]).replace(elemRegExp,
'$1.iepp_$2')+rule[4]);
}
return cssTextArr.join('n');
};
iepp.writeHTML = function() {
var a = -1;
body = body || doc.body;
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
37. bodyElem.className = body.className;
bodyElem.id = body.id;
// 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');
};
iepp._beforePrint = function() {
// Write iepp custom print CSS
styleElem.styleSheet.cssText =
iepp.parseCSS(iepp.getCSS(doc.styleSheets, 'all'));
iepp.writeHTML();
};
iepp.restoreHTML = function(){
// Undo everything done in onbeforeprint
bodyElem.innerHTML = '';
html.removeChild(bodyElem);
html.appendChild(body);
};
iepp._afterPrint = function(){
// Undo everything done in onbeforeprint
iepp.restoreHTML();
styleElem.styleSheet.cssText = '';
};
// Shim the document and iepp fragment
shim(doc);
shim(docFrag);
//
38. if(iepp.disablePP){return;}
// Add iepp custom print style element
head.insertBefore(styleElem, head.firstChild);
styleElem.media = 'print';
styleElem.className = 'iepp-printshim';
win.attachEvent(
'onbeforeprint',
iepp._beforePrint
);
win.attachEvent(
'onafterprint',
iepp._afterPrint
);
})(window, document);
}
//>>END IEPP
// Assign private properties to the return object with prefix
Modernizr._version = version;
// expose these for the plugin API. Look in the source for
how to join() them against your input
Modernizr._prefixes = prefixes;
Modernizr._domPrefixes = domPrefixes;
// Modernizr.mq tests a given media query, live against the
current state of the window
// A few important notes:
// * If a browser does not support media queries at all (eg.
oldIE) the mq() will always return false
// * A max-width or orientation query will be evaluated
against the current state, which may change later.
// * You must specify values. Eg. If you are testing support
for the min-width media query use:
// Modernizr.mq('(min-width:0)')
39. // usage:
// Modernizr.mq('only screen and (max-width:768)')
Modernizr.mq = testMediaQuery;
// Modernizr.hasEvent() detects support for a given event,
with an optional element to test on
// Modernizr.hasEvent('gesturestart', elem)
Modernizr.hasEvent = isEventSupported;
// Modernizr.testProp() investigates whether a given style
property is recognized
// Note that the property names must be provided in the
camelCase variant.
// Modernizr.testProp('pointerEvents')
Modernizr.testProp = function(prop){
return testProps([prop]);
};
// Modernizr.testAllProps() investigates whether a given style
property,
// or any of its vendor-prefixed variants, is recognized
// Note that the property names must be provided in the
camelCase variant.
// Modernizr.testAllProps('boxSizing')
Modernizr.testAllProps = testPropsAll;
// Modernizr.testStyles() allows you to add custom styles to
the document and test an element afterwards
// Modernizr.testStyles('#modernizr { position:absolute }',
function(elem, rule){ ... })
Modernizr.testStyles = injectElementWithStyles;
// Modernizr.prefixed() returns the prefixed or nonprefixed
40. property name variant of your input
// Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
// Properties must be passed as dom-style camelcase, rather
than `box-sizing` hypentated style.
// Return values will also be the camelCase variant, if you
need to translate that to hypenated style use:
//
// str.replace(/([A-Z])/g, function(str,m1){ return '-' +
m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
// If you're trying to ascertain which transition end event to
bind to, you might do something like...
//
// var transEndEventNames = {
// 'WebkitTransition' : 'webkitTransitionEnd',
// 'MozTransition' : 'transitionend',
// 'OTransition' : 'oTransitionEnd',
// 'msTransition' : 'msTransitionEnd', // maybe?
// 'transition' : 'transitionEnd'
// },
// transEndEventName = transEndEventNames[
Modernizr.prefixed('transition') ];
Modernizr.prefixed = function(prop){
return testPropsAll(prop, 'pfx');
};
// Remove "no-js" class from <html> element, if it exists:
docElement.className =
docElement.className.replace(/bno-jsb/, '')
// Add the new classes to the <html>
element.
42. color: white;
background-color: black;
}
footer a:hover {
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
padding: 5px;
color: black;
background-color: white;
}
footer p {
text-indent: 0;
}
footer h4 {
margin-bottom: 1em;
}
case3/modernizr-2.js
/*!
* Modernizr v2.0.6
* http://www.modernizr.com
*
* Copyright (c) 2009-2011 Faruk Ates, Paul Irish, Alex Sexton
* Dual-licensed under the BSD or MIT licenses:
www.modernizr.com/license/
*/
/*
* Modernizr tests which native CSS3 and HTML5 features are
available in
* the current UA and makes the results available to you in two
ways:
* as properties on a global Modernizr object, and as classes on
43. the
* <html> element. This information allows you to
progressively enhance
* your pages with a granular level of control over the
experience.
*
* Modernizr has an optional (not included) conditional resource
loader
* called Modernizr.load(), based on Yepnope.js
(yepnopejs.com).
* To get a build that includes Modernizr.load(), as well as
choosing
* which tests to include, go to www.modernizr.com/download/
*
* Authors Faruk Ates, Paul Irish, Alex Sexton,
* Contributors Ryan Seddon, Ben Alman
*/
window.Modernizr = (function( window, document, undefined )
{
var version = '2.0.6',
Modernizr = {},
// option for enabling the HTML classes to be added
enableClasses = true,
docElement = document.documentElement,
docHead = document.head ||
document.getElementsByTagName('head')[0],
/**
* Create our "modernizr" element that we do most feature
tests on.
*/
44. mod = 'modernizr',
modElem = document.createElement(mod),
mStyle = 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 = {},
45. attrs = {},
classes = [],
featureName, // used in testing loop
// Inject element with style element and some CSS rules
injectElementWithStyles = function( rule, callback, nodes,
testnames ) {
var style, ret, node,
div = document.createElement('div');
if ( parseInt(nodes, 10) ) {
// In order not to give false positives we create a node for
each test
// This also allows the method to scale for unspecified
uses
while ( nodes-- ) {
node = document.createElement('div');
node.id = testnames ? testnames[nodes] : mod +
(nodes + 1);
div.appendChild(node);
}
}
// <style> elements in IE6-9 are considered 'NoScope'
elements and therefore will be removed
// when injected with innerHTML. To get around this you
need to prepend the 'NoScope' element
// with a 'scoped' element, in our case the soft-hyphen entity
as it won't mess with our measurements.
// http://msdn.microsoft.com/en-
us/library/ms533897%28VS.85%29.aspx
style = ['­', '<style>', rule, '</style>'].join('');
46. div.id = mod;
div.innerHTML += style;
docElement.appendChild(div);
ret = callback(div, rule);
div.parentNode.removeChild(div);
return !!ret;
},
// adapted from matchMedia polyfill
// by Scott Jehl and Paul Irish
// gist.github.com/786768
testMediaQuery = function( mq ) {
if ( window.matchMedia ) {
return matchMedia(mq).matches;
}
var bool;
injectElementWithStyles('@media ' + mq + ' { #' + mod + '
{ position: absolute; } }', function( node ) {
bool = (window.getComputedStyle ?
getComputedStyle(node, null) :
node.currentStyle)['position'] == 'absolute';
});
return bool;
},
/**
47. * 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) ) {
48. 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));
};
}
/**
* setCss applies given styles to the Modernizr DOM node.
*/
function setCss( str ) {
mStyle.cssText = str;
49. }
/**
* setCssAll extrapolates all vendor-specific css strings.
*/
function setCssAll( str1, str2 ) {
return setCss(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);
}
/**
* testProps 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 testProps( props, prefixed ) {
for ( var i in props ) {
if ( mStyle[ props[i] ] !== undefined ) {
return prefixed == 'pfx' ? props[i] : true;
}
}
50. return false;
}
/**
* testPropsAll 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 testPropsAll( prop, prefixed ) {
var ucProp = prop.charAt(0).toUpperCase() +
prop.substr(1),
props = (prop + ' ' + domPrefixes.join(ucProp + ' ') +
ucProp).split(' ');
return testProps(props, prefixed);
}
/**
* testBundle tests a list of CSS features that require element
and style injection.
* By bundling them together we can reduce the need to
touch the DOM multiple times.
*/
/*>>testBundle*/
var testBundle = (function( styles, tests ) {
var style = styles.join(''),
len = tests.length;
injectElementWithStyles(style, function( node, rule ) {
var style =
document.styleSheets[document.styleSheets.length - 1],
51. // IE8 will bork if you create a custom build that
excludes both fontface and generatedcontent tests.
// So we check for cssRules and that there is a rule
available
// More here:
https://github.com/Modernizr/Modernizr/issues/288 &
https://github.com/Modernizr/Modernizr/issues/293
cssText = style.cssRules && style.cssRules[0] ?
style.cssRules[0].cssText : style.cssText || "",
children = node.childNodes, hash = {};
while ( len-- ) {
hash[children[len].id] = children[len];
}
/*>>touch*/ Modernizr['touch'] = ('ontouchstart'
in window) || hash['touch'].offsetTop === 9; /*>>touch*/
/*>>csstransforms3d*/ Modernizr['csstransforms3d'] =
hash['csstransforms3d'].offsetLeft === 9;
/*>>csstransforms3d*/
/*>>generatedcontent*/Modernizr['generatedcontent'] =
hash['generatedcontent'].offsetHeight >= 1;
/*>>generatedcontent*/
/*>>fontface*/ Modernizr['fontface'] =
/src/i.test(cssText) &&
cssText.indexOf(rule.split(' ')[0]) === 0; /*>>fontface*/
}, len, tests);
})([
// Pass in styles to be injected into document
/*>>fontface*/ '@font-face {font-
family:"font";src:url("https://")}' /*>>fontface*/
/*>>touch*/ ,['@media (',prefixes.join('touch-
enabled),('),mod,')',
53. * @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 setPrefixedValueCSS( element, property, value,
extra ) {
property += ':';
element.style.cssText = (property + prefixes.join(value
+ ';' + property)).slice(0, -property.length) + (extra || '');
}
/**
* setPrefixedPropertyCSS 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 setPrefixedPropertyCSS( element, property,
value, extra ) {
element.style.cssText = prefixes.join(property + ':' +
value + ';') + (extra || '');
}
var c = document.createElement('div'),
elem = document.createElement('div');
54. setPrefixedValueCSS(c, 'display', 'box',
'width:42px;padding:0;');
setPrefixedPropertyCSS(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 !!(Modernizr['canvas'] &&
is(document.createElement('canvas').getContext('2d').fillText,
'function'));
};
// This WebGL test may false positive.
// But really it's quite impossible to know whether webgl will
succeed until after you create the context.
// You might have hardware that can support a 100x100
55. webgl canvas, but will not support a 1000x1000 webgl
// canvas. So this feature inference is weak, but intentionally
so.
// It is known to false positive in FF4 with certain hardware
and the iPad 2.
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 Modernizr['touch'];
};
/**
* geolocation tests for the new Geolocation API
56. 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:
57. //
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 had inconsistent prefixing with the experimental
Indexed DB:
// - Webkit's implementation is accessible through
webkitIndexedDB
// - Firefox shipped moz_indexedDB before FF4b9, but since
then has been mozIndexedDB
// For speed, we don't test the legacy (and beta-only)
indexedDB
tests['indexedDB'] = function() {
for ( var i = -1, len = domPrefixes.length; ++i < len; ){
if ( window[domPrefixes[i].toLowerCase() + 'IndexedDB']
){
return true;
}
}
return !!window.indexedDB;
58. };
// 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');
};
// Mozilla is targeting to land MozWebSocket for FF6
// bugzil.la/659324
tests['websockets'] = function() {
for ( var i = -1, len = domPrefixes.length; ++i < len; ){
if ( window[domPrefixes[i] + 'WebSocket'] ){
return true;
}
}
59. return 'WebSocket' in window;
};
// http://css-tricks.com/rgba-browser-support/
tests['rgba'] = function() {
// Set an rgba() color and check the returned value
setCss('background-color:rgba(150,255,150,.5)');
return contains(mStyle.backgroundColor, 'rgba');
};
tests['hsla'] = function() {
// Same as rgba(), in fact, browsers re-map hsla() to rgba()
internally,
// except IE9 who retains it as hsla
setCss('background-color:hsla(120,40%,100%,.5)');
return contains(mStyle.backgroundColor, 'rgba') ||
contains(mStyle.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!
setCss('background:url(https://),url(https://),red
url(https://)');
// If the UA supports multiple backgrounds, there should
60. be three occurrences
// of the string "url(" in the return value for
elemStyle.background
return /(urls*(.*?){3}/.test(mStyle.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 testPropsAll('backgroundSize');
};
tests['borderimage'] = function() {
return testPropsAll('borderImage');
};
// Super comprehensive table about all the unique
implementations of
// border-radius: http://muddledramblings.com/table-of-css3-
border-radius-compliance
tests['borderradius'] = function() {
61. return testPropsAll('borderRadius');
};
// WebOS unfortunately false positives on this test.
tests['boxshadow'] = function() {
return testPropsAll('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.
setCssAll('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/comm
ent/516632
return /^0.55$/.test(mStyle.opacity);
};
tests['cssanimations'] = function() {
return testPropsAll('animationName');
};
63. tests['csstransforms'] = function() {
return !!testProps(['transformProperty', 'WebkitTransform',
'MozTransform', 'OTransform', 'msTransform']);
};
tests['csstransforms3d'] = function() {
var ret = !!testProps(['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 = Modernizr['csstransforms3d'];
}
return ret;
};
tests['csstransitions'] = function() {
return testPropsAll('transitionProperty');
64. };
/*>>fontface*/
// @font-face detection routine by Diego Perini
// http://javascript.nwbox.com/CSSSupport/
tests['fontface'] = function() {
return Modernizr['fontface'];
};
/*>>fontface*/
// CSS generated content detection
tests['generatedcontent'] = function() {
return Modernizr['generatedcontent'];
};
// 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.ht
ml#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.
65. tests['video'] = function() {
var elem = document.createElement('video'),
bool = false;
// IE9 Running on Windows Server SKU can cause an
exception to be thrown, bug #224
try {
if ( bool = !!elem.canPlayType ) {
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"');
}
} catch(e) { }
return bool;
};
tests['audio'] = function() {
var elem = document.createElement('audio'),
bool = false;
try {
if ( bool = !!elem.canPlayType ) {
bool = new Boolean(bool);
bool.ogg = elem.canPlayType('audio/ogg;
66. 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;');
}
} catch(e) { }
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.
67. // 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 &&
68. !!document.createElementNS(ns.svg, 'svg').createSVGRect;
};
// specifically for SVG inline in HTML, not within XHTML
// test page: paulirish.com/demo/inline-svg
tests['inlinesvg'] = function() {
var div = document.createElement('div');
div.innerHTML = '<svg/>';
return (div.firstChild && div.firstChild.namespaceURI) ==
ns.svg;
};
// Thanks to F1lt3r and lucideer, ticket #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
69. // 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
// Only input placeholder is tested while textarea's
placeholder is not.
// Currently Safari 4 and Opera 11 have support only for
the input placeholder
// Both tests are available in feature-detects/forms-
placeholder.js
Modernizr['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/
Modernizr['inputtypes'] = (function(props) {
for ( var i = 0, bool, inputElemType, defaultView, len =
props.length; i < len; i++ ) {
70. 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
71. 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(' '));
}
72. // 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();
Modernizr[featureName] = tests[feature]();
classes.push((Modernizr[featureName] ? '' : 'no-') +
featureName);
}
}
// input tests need to run.
Modernizr.input || webforms();
/**
* 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
*
73. * @param feature - String naming the feature
* @param test - Function returning true if feature is
supported, false if not
*/
Modernizr.addTest = function ( feature, test ) {
if ( typeof feature == "object" ) {
for ( var key in feature ) {
if ( hasOwnProperty( feature, key ) ) {
Modernizr.addTest( key, feature[ key ] );
}
}
} else {
feature = feature.toLowerCase();
if ( Modernizr[feature] !== undefined ) {
// we're going to quit if you're trying to overwrite an
existing test
// if we were to allow it, we'd do this:
// var re = new RegExp("b(no-)?" + feature + "b");
// docElement.className =
docElement.className.replace( re, '' );
// but, no rly, stuff 'em.
return;
}
test = typeof test == "boolean" ? test : !!test();
docElement.className += ' ' + (test ? '' : 'no-') + feature;
Modernizr[feature] = test;
}
return Modernizr; // allow chaining.
};
74. // Reset modElem.cssText to nothing to reduce memory
footprint.
setCss('');
modElem = inputElem = null;
//>>BEGIN IEPP
// Enable HTML 5 elements for styling (and printing) in IE.
if ( window.attachEvent && (function(){ var elem =
document.createElement('div');
elem.innerHTML =
'<elem></elem>';
return elem.childNodes.length !==
1; })() ) {
// iepp v2 by @jon_neal & afarkas :
github.com/aFarkas/iepp/
(function(win, doc) {
win.iepp = win.iepp || {};
var iepp = win.iepp,
elems = iepp.html5elements ||
'abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|
footer|header|hgroup|mark|meter|nav|output|progress|section|su
mmary|time|video',
elemsArr = elems.split('|'),
elemsArrLen = elemsArr.length,
elemRegExp = new RegExp('(^|s)('+elems+')', 'gi'),
tagRegExp = new RegExp('<(/*)('+elems+')', 'gi'),
filterReg = /^s*[{}]s*$/,
ruleRegExp = new
RegExp('(^|[^n]*?s)('+elems+')([^n]*)({[nwW]*?})',
'gi'),
docFrag = doc.createDocumentFragment(),
html = doc.documentElement,
head = html.firstChild,
bodyElem = doc.createElement('body'),
75. styleElem = doc.createElement('style'),
printMedias = /print|all/,
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]);
}
iepp.getCSS = function(styleSheetList, mediaType) {
if(styleSheetList+'' === undefined){return '';}
var a = -1,
len = styleSheetList.length,
styleSheet,
cssTextArr = [];
while (++a < len) {
styleSheet = styleSheetList[a];
//currently no test for disabled/alternate stylesheets
if(styleSheet.disabled){continue;}
mediaType = styleSheet.media || mediaType;
// Get css from all non-screen stylesheets and their
imports
if (printMedias.test(mediaType))
cssTextArr.push(iepp.getCSS(styleSheet.imports, mediaType),
styleSheet.cssText);
//reset mediaType to all with every new *not
imported* stylesheet
mediaType = 'all';
}
return cssTextArr.join('');
};
iepp.parseCSS = function(cssText) {
var cssTextArr = [],
76. rule;
while ((rule = ruleRegExp.exec(cssText)) != null){
// Replace all html5 element references with iepp
substitute classnames
cssTextArr.push(( (filterReg.exec(rule[1]) ? 'n' :
rule[1]) +rule[2]+rule[3]).replace(elemRegExp,
'$1.iepp_$2')+rule[4]);
}
return cssTextArr.join('n');
};
iepp.writeHTML = function() {
var a = -1;
body = body || doc.body;
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;
bodyElem.id = body.id;
// 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');
};
78. iepp._beforePrint
);
win.attachEvent(
'onafterprint',
iepp._afterPrint
);
})(window, document);
}
//>>END IEPP
// Assign private properties to the return object with prefix
Modernizr._version = version;
// expose these for the plugin API. Look in the source for
how to join() them against your input
Modernizr._prefixes = prefixes;
Modernizr._domPrefixes = domPrefixes;
// Modernizr.mq tests a given media query, live against the
current state of the window
// A few important notes:
// * If a browser does not support media queries at all (eg.
oldIE) the mq() will always return false
// * A max-width or orientation query will be evaluated
against the current state, which may change later.
// * You must specify values. Eg. If you are testing support
for the min-width media query use:
// Modernizr.mq('(min-width:0)')
// usage:
// Modernizr.mq('only screen and (max-width:768)')
Modernizr.mq = testMediaQuery;
// Modernizr.hasEvent() detects support for a given event,
with an optional element to test on
// Modernizr.hasEvent('gesturestart', elem)
Modernizr.hasEvent = isEventSupported;
79. // Modernizr.testProp() investigates whether a given style
property is recognized
// Note that the property names must be provided in the
camelCase variant.
// Modernizr.testProp('pointerEvents')
Modernizr.testProp = function(prop){
return testProps([prop]);
};
// Modernizr.testAllProps() investigates whether a given style
property,
// or any of its vendor-prefixed variants, is recognized
// Note that the property names must be provided in the
camelCase variant.
// Modernizr.testAllProps('boxSizing')
Modernizr.testAllProps = testPropsAll;
// Modernizr.testStyles() allows you to add custom styles to
the document and test an element afterwards
// Modernizr.testStyles('#modernizr { position:absolute }',
function(elem, rule){ ... })
Modernizr.testStyles = injectElementWithStyles;
// Modernizr.prefixed() returns the prefixed or nonprefixed
property name variant of your input
// Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
// Properties must be passed as dom-style camelcase, rather
than `box-sizing` hypentated style.
// Return values will also be the camelCase variant, if you
need to translate that to hypenated style use:
//
80. // str.replace(/([A-Z])/g, function(str,m1){ return '-' +
m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
// If you're trying to ascertain which transition end event to
bind to, you might do something like...
//
// var transEndEventNames = {
// 'WebkitTransition' : 'webkitTransitionEnd',
// 'MozTransition' : 'transitionend',
// 'OTransition' : 'oTransitionEnd',
// 'msTransition' : 'msTransitionEnd', // maybe?
// 'transition' : 'transitionEnd'
// },
// transEndEventName = transEndEventNames[
Modernizr.prefixed('transition') ];
Modernizr.prefixed = function(prop){
return testPropsAll(prop, 'pfx');
};
// Remove "no-js" class from <html> element, if it exists:
docElement.className =
docElement.className.replace(/bno-jsb/, '')
// Add the new classes to the <html>
element.
+ (enableClasses ? ' js ' + classes.join(' ') :
'');
return Modernizr;
})(this, this.document);
case3/pg1.jpg
81. case3/pg2.jpg
case3/pg3.jpg
case3/Thumbs.db
case3/ziller_T6.htmThe Ziller Financial Group Journal
The Fallacy of Median Home Prices
With the real estate market continuing to retreat from its peak a
few years ago, let's take a look at what's ahead – or likely – for
the next five years. Of course, everyone wants to know if the
housing market is just in a brief contraction period, or if it is
headed for a more prolonged period of depressed home values.
At present, home prices have for the most part remained stable
in many areas of the country, but those figures might be
deceptive. Builders are luring buyers with add-ons and
incentives to entice buyers into signing on the dotted line. For
example, if a builder tosses in another garage, a solarium, or a
finished basement or if the builder agrees to pay the first year's
property taxes – those incentives are not reflected in the
average home price that the government keeps track of.
Therefore, there is no way at present to record, and therefore
reflect, how those builder incentives are holding up. You can't,
therefore, just look at median home prices sales and say that the
market is firm or steady. Because of that "builder bias," the
median home values – which actually might be falling – are not
reflected in regional or national statistics.What Should You Do?
At this point, there's no clear direction you should take, unless
you want to stay in this for the long haul. Some markets will do
better than others, but if you have invested in a second or third
or fourth home purely on speculation, you might want to
consider limiting your exposure to risk.Divest, Divest, and
Divest
It used to be that the three tenets of real estate were location,
82. location, and location. That no longer is true. By divest, we
mean divesting your interest in those areas that are at greatest
risk for contraction, such as certain areas in the West.It's
Always Hot Somewhere
Of course, areas with limited land are going to be the ones to
ride out this storm the best. There will always be markets,
particularly those such as Hawaii and San Francisco, which can
ride out a downward ripple – or even a wave – in the housing
market.Get Off the Sidelines
Standing on the sidelines is great for football, but not for
investing. There's nothing wrong with buying low in a market
that has dramatically cooled off. Just don't expect to get a sharp
return on investment, as there was during the early part of this
century. The rebound will not be dramatic, but it will be
prolonged, and you will make money in the long run. Just be
patient.
The Global Outlook
Oil prices continue their roller coaster ride. The past six months
saw a steep decline in the price of light sweet crude, but recent
tensions in Africa and South America in particular have roiled
the markets once again.
Still, today with most of the world's infrastructure tied into
fossil fuels, it has been difficult to dislodge the nation's
dependence on fossil fuels. Biofuels, such as ethanol, continue
to gain greater market share, but there is a flip side to those
gains. As the demand for corn increases, so does the price of
corn to feed not only the buying public, but also for the cattle
rancher. Expect to see increases in the price of beef. The same
is true for any product that relies on corn syrup as an ingredient
– and there are many.
If you want to think long term, utilities will start to attract
interest during the third decade — around 2020 — as more
electric vehicles hit the market. All those vehicles will be
tapping into the grid, and someone has to meet the growing
demand for the electricity needed to recharge those vehicles.
83. This might also be a good time to invest in startup companies
that sell ancillary equipment to recharge batteries as well as
those companies that make batteries both domestically and
abroad.The Ziller Financial Group ✵ 2100 Fountain Street ✵
Chicago, IL 34599 ✵ 555-345-9888
FinancialsReal EstateCommoditiesStocksBonds