webshim
Version:
modular capability-based polyfill loading libary, which extends jQuery with HTML5 features in legacy browsers
1,147 lines (1,042 loc) • 96.7 kB
HTML
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=edge" >
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Webshim</title>
<link href="css/styles.css" rel="stylesheet" />
<link rel="stylesheet" href="css/prism.css" />
<!-- don't use async if you don't know how to deal with it!!! -->
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="../js-webshim/minified/polyfiller.js"></script>
<script>
webshim.polyfill();
// load all available polyfills
</script>
<script src="demo-js/demo.js" async=""></script>
</head>
<body>
<div id="sidebar" class="interface">
<a class="toc_title"> Webshim <span class="version">(<span class="ws-version">1.16.0</span>)</span></a>
<ul class="toc_section">
<li>
» <a href="https://github.com/aFarkas/webshim">GitHub Repository</a>
</li>
</ul>
<a class="toc_title" href="#introduction"> Introduction </a>
<a class="toc_title" href="#Guide-installation"> Guide </a>
<ul class="toc_section">
<li>
– <a href="#Guide-installation">Installation</a>
</li>
<li>
– <a href="#Guide-configuration">Configuration</a>
</li>
<li>
- <a href="#Guide-fire-when-ready">Fire When Ready</a>
</li>
<li>
- <a href="#Guide-dom-abstractions">DOM Abstractions</a>
</li>
</ul>
<a class="toc_title" href="#Canvas"> Canvas </a>
<a class="toc_title" href="#DetailsSummary"> Details & Summary </a>
<a class="toc_title" href="#ES5"> ES5 </a>
<a class="toc_title" href="#Forms"> Forms </a>
<ul class="toc_section">
<li>
– <a href="#Forms-forms">forms</a>
</li>
<li>
– <a href="#Forms-forms-ext">forms-ext</a>
</li>
<li>
– <a href="#Forms-extensions">Extensions</a>
</li>
</ul>
<a class="toc_title" href="#FileReader"> FileReader / FormData / XHR2 / CORS </a>
<a class="toc_title" href="#Geolocation"> Geolocation </a>
<a class="toc_title" href="#Shiv"> HTML5 shiv and innerShiv </a>
<ul class="toc_section">
<li>
– <a href="#Shiv-dynamic-html5">Dynamically adding HTML5 Markup</a>
</li>
<li>
– <a href="#Shiv-updatePolyfill">updatePolyfill</a>
</li>
</ul>
<a class="toc_title" href="#Media"> Mediaelements </a>
<ul class="toc_section">
<li>
- <a href="#Media-elements">Audio / Video</a>
</li>
<li>
- <a href="#Media-track">Track Element</a>
</li>
</ul>
<a class="toc_title" href="#matchMedia"> matchMedia </a>
<a class="toc_title" href="#Promise"> Promise </a>
<a class="toc_title" href="#url"> URL </a>
<a class="toc_title" href="#usermedia"> usermedia (getUserMedia)</a>
<a class="toc_title" href="#respimage"> Responsive Images (<code>picture</code>, <code>srcset</code>)</a>
<a class="toc_title" href="#sticky"> sticky (<code>position</code>: <code>sticky</code>)</a>
<a class="toc_title" href="#Enhancement-Strategy">Webshim's opinionated enhancement cross browser / device development strategy</a>
<a class="toc_title" href="#Requirejs-setup">Setup with r.js or other JS optimization tasks</a>
<a class="toc_title" href="#Customizing"> Customizing </a>
<ul class="toc_section">
<li>
- <a href="#Changeing-UI">Customizing styles and UI</a>
</li>
<li>
- <a href="#Customizing-extending">Writing a New Polyfill</a>
</li>
</ul>
</div>
<div class="container">
<p><strong>Important note: Webshim is not compatible with upcoming jQuery 3.x and I do not plan to work on a new major version. I will still fix critical bugs in the future though.</strong></p>
<p>
<img id="logo" src="images/webshim2.png" alt="webshim" />
</p>
<p>
Webshim is a <a href="http://remysharp.com/2010/10/08/what-is-a-polyfill/">polyfill</a> library that enables you to reliably use HTML5 features across browsers, even if native support is lacking.
</p>
<p>
The project is <a href="https://github.com/aFarkas/webshim/">hosted on GitHub</a>, and is available for use under the <a href="http://github.com/aFarkas/webshim/blob/master/MIT-LICENSE.txt">MIT software license</a>.
</p>
<p>
You can report bugs and discuss features on the <a href="https://github.com/aFarkas/webshim/issues">GitHub issues page</a>.
</p>
<h3 id="downloads">Downloads & Dependencies</h3>
<span style="padding-left: 7px; font-size:11px; font-weight: normal;" class="interface">(Right-click, and use "Save As")</span>
<p>
<a href="https://github.com/aFarkas/webshim/archive/1.16.0.zip" class="download-button"> <strong><i>Download</i></strong> </a>
</p>
<p>
Webshim depends on <a href="http://jquery.com/">jQuery</a>.
</p>
<h2 id="introduction" class="header">Introduction</h2>
<p>
There are many appealing HTML5 features such as <a href="http://fiddle.jshell.net/trixta/WPpPy/show/light/">form validation</a>, geolocation, <a href="http://fiddle.jshell.net/trixta/VvmmC/show/light/">mediaelements</a> and <a href="http://fiddle.jshell.net/trixta/VNuct/show/light/">UI widgets</a> which ease the burden of writing rich web applications.
</p>
<p>
<strong>Webshim is a polyfill solution.</strong> It adds these features in a way that is transparent to the end user and developer. It enables coding against the browser standards rather than learning and maintaining abstractions. It results
in less code that is simpler and easier to maintain.
</p>
<p><strong>Webshim is also more than a polyfill, it has become a UI component and widget library</strong>. Webshim enables a developer to also <strong>enhance</strong> HTML5 capable browsers with more <strong>highly customizable, extensible and flexible UI components and widgets</strong>. Its <strong>capability based loading system</strong> enables webshim to only load those files, which are needed for the specific browser/device and only when it is needed (deferred loading), to reduce especially the initial network payload.</p>
<!--
<p>
Many of the examples that follow are runnable. Click the <i>play</i> button to execute them.
</p>
-->
<h3 id="Guide-installation">Installation</h3>
<p>
Take the 'js-webshim' folder and add it to your project. (You will find a minified and a dev folder there. Put the whole folder, not only the polyfiller.js file into your project!) Here is an example showing how to include dependencies and load webshims:
</p>
<pre><code class="language-markup">
<script src="js/jquery.js"></script>
<script src="js-webshim/minified/polyfiller.js"></script>
<script>
//webshim.setOptions('basePath', '/js-webshim/minified/shims/');
//request the features you need:
webshim.polyfill('es5 mediaelement forms');
$(function(){
// use all implemented API-features on DOM-ready
});
</script>
</code></pre>
<h3 id="Guide-configuration">Configuration</h3>
<p>
The polyfill method accepts an optional whitespace-separated feature list. Call it as soon as possible (before DOM ready.)
<code class="i">
webshim.polyfill( "canvas geolocation" );
</code>
</p>
<strong>Available Features</strong>
<ul class="list">
<li>
canvas
</li>
<li>
details
</li>
<li>
es5
</li>
<li>
filereader (implements FileReader, XHR2 (CORS/FormData), FormData, and an input[type="file"] picker)
</li>
<li>
forms (form validation and form features: fieldset[disabled], <input form="idref" />, placeholder...)
</li>
<li>
forms-ext (input wigets)
</li>
<li>
geolocation
</li>
<li>
matchMedia (includes matchMedia and matchMedia.addListener polyfill)
</li>
<li>
mediaelement
</li>
<li>
picture (responsive images: picture andsrcset)
</li>
<li>
promise
</li>
<li>
url (<a href="http://url.spec.whatwg.org">window.URL</a>)
</li>
<li>
usermedia (navigator.getUserMedia)
</li>
<li>
sticky (<code>position</code>: <code>sticky</code>)
</li>
<li>
track (subtitles, catptions and textTrack API)
</li>
<li>
xhr2 (an alias for filereader)
</li>
</ul>
<p>
<code class="i">
setOptions</code>
should always be called before the <code class="i">
polyfill</code>
method.
</p>
<p>
The available options for <code class="i">
webshim.setOptions</code>
:
</p>
<ul>
<li>
<strong>extendNative</strong> Webshims lib will automatically extend DOM-Objects with polyfilled methods and will additionally generate a jQuery plugin with this method name. If extendNative is set to false, webshims lib
won't touch any DOM-Objects and will only implement jQuery plugins. Setting this option to false might improve DOM performance.
<br>
<em>default: false</em>
</li>
<li>
<strong>basePath</strong> The path to your shims folder. This is computed dynamically. <a href="#Requirejs-setup">More information</a>. Example:
<br>
<code class="i">
webshim.setOptions('basePath', '/yourFolderTo/shims/');
</code>
<br>
<em>default: computed path to shims folder</em>
</li>
<li>
<strong>waitReady</strong> Setting this to true delays jQuery's ready-event until all polyfilled features are ready. This option should be set to false, if webshims lib polyfiller.js is loaded asynchronously. This option can also be set to false, if a website is using only HTML5 markup APIs (pure HTML or $.attr) and
doesn't use any DOM-/JS-APIs on DOM-ready. If this feature is set to false, scripted access to polyfilled APIs have to be added inside of a <code class="i"><a href="#Guide-fire-when-ready">
webshim.ready</a></code>
callback.
<br>
<em>default: true</em>
</li>
<li>
<strong>loadStyles</strong> If <code>loadStyles</code> is set <code>false</code> webshims won't load any default styles. In this case a site has to provide all styles for the used widgets. A developer also can copy all used webshim styles into his own stylesheet and minimize requests/only use needed styles for used widgets. See also <a href="#Changeing-UI">Customizing styles and UI</a>
<br>
<em>default: true</em>
</li>
<li>
<strong>debug</strong> Setting <code>debug</code> to true enables debug informations to be printed in the developer console. Note the polyfiller.js in the dev folder has more debug informations and pretty printed code.
<br>
<em>default: undefined</em>
</li>
<li>
<strong>enhanceAuto</strong> If set to <code>true</code> configuration values with the keyword '<code>auto</code>' are treated as true, if this is <code>false</code> the keyword '<code>auto</code>' is treated as <code>false</code>.
<br>
<em>default: dynamically computed (mainly false for Smartphone devices and IE8 otherwise true: <code>window.Audio && (!window.matchMedia || matchMedia('(min-device-width: 721px)').matches)</code>)</em>
</li>
</ul>
<pre><code class="language-javascript">
// enhanceAuto will be false for devices smaller than 720px (i.e. Smartphones or for devices smaller than 1024px and with touchevents (i.e.: Tablets)
webshim.setOptions('enhanceAuto', !(matchMedia('(max-device-width: 720px)').matches || matchMedia('(max-device-width: 1024px)').matches && Modernizr.touchevents) );
webshim.setOptions({
'forms-ext': {
replaceUI: 'auto'
},
'mediaelement', {
replaceUI: 'auto'
}
});
//webshims will implement those features in all browsers/devices
// but will only enhance capable browsers on desktop with custom styleable mediaelement controls and form widgets
webshim.polyfill('forms forms-ext mediaelement');
</code></pre>
<p>
<code class="i">
setOptions</code>
can also take a single options parameter:
</p>
<pre><code class="language-javascript">
webshim.setOptions({
extendNative: true
});
</code></pre>
<p>
Feature specific options are nested options with the feature name as their key.
</p>
<pre><code class="language-javascript">
webshim.setOptions({
// configure generally option
extendNative: true,
// configure canvas-shim
canvas: {
type: 'flash' // use flashcanvas instead of excanvas as polyfill
},
// configure forms-shim
forms: {
lazyCustomMessages: true // implement customValidationMessages
}
});
</code></pre>
<h3 id="Guide-fire-when-ready">Fire When Ready</h3>
<p>
Not every feature is ready immediately in all browsers; some shims might take time to load before you can use them. You can use one of jQuery's <code class="i">
ready</code>
methods to delay working with elements until the DOM and any necessary shims are
ready.
</p>
<pre><code class="language-javascript">
$(function(){
// work with DOM + all implemented features
});
$(document).ready(function(){
// work with DOM + all features
});
</code></pre>
<p>
If you want to use a feature as soon as possible or you have set the <code class="i">
waitReady</code>
option to <code class="i">
false</code>
, you can use <code class="i">
webshim.ready</code>
and pass the feature name(s) and a callback function:
</p>
<pre><code class="language-javascript">
webshim.ready('geolocation es5', function(){
// work with geolocation and es5
});
</code></pre>
<p>
Note that this callback function may be called before the DOM is ready. If you want to use a feature after DOM-Ready, simply pass the string 'DOM':
</p>
<pre><code class="language-javascript">
webshim.ready('DOM canvas', function(){
// work with canvas in the document
});
</code></pre>
<h3 id="Guide-dom-abstractions">DOM Abstractions</h3>
<p>
Due to the fact that we cannot extend accessors of elements in all browsers, we always use jQuery as an extension-wrapper.
</p>
<ul>
<li>
<p>
<strong>Accessing DOM properties/attribute IDLs</strong>: if the feature allows accessing a specific attribute or property, always use jQuery's built-in <code class="i">
$.prop</code>
(in case of IDL attributes/properties) or <code class="i">
$.attr</code>
/<code class="i">
$.removeAttr</code>
(in case of content attributes) methods:
</p>
<pre><code class="language-javascript">
// instead of accessing a property directly (e.g. this.validity),
// use $.fn.prop
$(this).prop('validity');
// or:
//$.prop(this, 'validity');
//setting a property
$('video').prop('currentTime', 200);
// or:
//$.prop(videoElement, 'currentTime', 200);
</code></pre>
</li>
<li>
<p>
<strong>calling a DOM method</strong>: While DOM properties have to be accessed through jQuery's <code class="i">
$.prop/$.attr</code>
methods, DOM methods can be accesed using $.prop and executed in the context of the DOM element.
</p>
<pre><code class="language-javascript">
// "this" refers to a DOM element, not a jQuery object
var fn = $.prop(this, 'checkValidity');
fn.apply(this);
</code></pre>
<p>
To make this more easier Webshims lib also generates a jQuery plugin which wraps the featured method, so you can use jQuery too:
</p>
<pre><code class="language-javascript">
$(this).checkValidity();
$(this).callProp('checkValidity'); // $(this).callProp('play');
</code></pre>
<p>
The jQuerified method can also take some arguments, if specified by the spec.
</p>
<pre><code class="language-javascript">
$('video').addTextTrack('subtitles', 'just a test', 'en');
$('video').callProp('addTextTrack', ['subtitles', 'just a test', 'en']);
</code></pre>
<p>
If you pass a list of nodes and the method doesn't return anything, the method will be called on each element in this list, otherwise it will be called on the first element.
</p>
<p>
In case a developer wants to make method calling "feel 100% native", the general option <code class="i">
extendNative</code>
can be set to <code class="i">
true</code>
.
</p>
<pre><code class="language-javascript">
webshim.setOptions('extendNative', true);
webshim.polyfill('forms');
// ...
this.checkValidity() // or use $(this).callProp('checkValidity')
$('video').get(0).addTextTrack('subtitles', 'just a test', 'en');
</code></pre>
</li>
<li>
<p>
<strong>binding to events</strong>: Always use jQuery's <code class="i">
on</code>
method to register your event listeners. <code class="i">
addEventListener</code>
or inline event handler won't work in polyfilled browsers. Most events in the HTML5 specification are so-called simple events. Simple events do not bubble. Due to the fact that developers really like event delegation and jQuery cannot distinguish between the event phases (capturing/propagation), we use event capturing in the native implementation and <code class="i">
$.fn.trigger</code>
in the shim.
</p>
<p>
This means that some HTML5 events go down the DOM tree in capable browsers and go up the tree in polyfilled browsers. This can create differences if you are calling <code class="i">
event.stopPropagation();</code>
or <code class="i">
return false;</code>
in your event handler. If you only want to prevent the default, don't use <code class="i">
return false;</code>
, use <code class="i">
event.preventDefault();</code>
instead.
</p>
</li>
<li>
<p>
<strong>manipulation methods/dynamically adding HTML5 content</strong>: To insert/copy new HTML5 content dynamically, use <code class="i">
.htmlPolyfill()</code>
, <code class="i">
.appendPolyfill()</code>
, <code class="i">
.prependPolyfill()</code>
, <code class="i">
.afterPolyfill()</code>
, <code class="i">
.beforePolyfill()</code>
, <code class="i">
.replaceWithPolyfill()</code>
and <code class="i">
.clonePolyfill()</code>
:
</p>
<pre><code class="language-javascript">
// three different examples
$('form').appendPolyfill('<fieldset><input type="date" /></fieldset>');
$('#canvas-box').htmlPolyfill('<canvas></canvas>');
$('datalist#list select').prependPolyfill('<option value="new suggestion item" />');
</code></pre>
<p>
<small>See also <a href="#Shiv-dynamic-html5">dynamic HTML5 description</a>.</small>
</p>
</li>
<li>
<p>
<strong>no shadowdom</strong>: Webshims lib sometimes has to add additional DOM elements to mimic the UI of HTML5 elements. This can sometimes create differences, between polyfilled and non polyfilled browsers. Webshims lib gives you a method called 'getShadowElement' to access the shadowelement from the native element and a method called 'getNativeElement' to access the native element from the shadowelement. If the element has no shadowelement the element itself is returned.
</p>
<pre><code class="language-javascript">
// get the UI component element of input[type="date"]
$('input[type="date"]').getShadowElement();
</code></pre>
<p>Another problem can be, that some styles of your website may conflict with webshims styles. This normally happens if a tagname selector without a specific class or attribute is used as last selector part:</p>
<pre><code class=" language-css">/* do not use */
fieldset > div {
/* some styles */
}
/* instead write something like this: */
.form-row {
/* some styles */
}
</code></pre>
<p>
Some styles like float or display: none/block are not reflected by the shadowdom, it is a good approach to do this on a wrapper element or to also add those styles to the generated UI components yourself:
</p>
<pre><code class="language-markup"><!-- instead of -->
<div class="form-field">
<label for="date" style="display: none;">Birthdate</label>
<input type="date" id="date" style="display: none;" />
</div>
<!-- do this: -->
<div class="form-field" style="display: none;">
<label for="date">Birthdate</label>
<input type="date" id="date" />
</div>
<!-- or instead of: -->
<div class="mediaplayer">
<video src="file.mp4" controls style="margin: 0 10px 5px 0; float: left">
</video>
</div>
<!-- do this: -->
<div class="mediaplayer" style="margin: 0 10px 5px 0; float: left">
<video src="file.mp4" controls></video>
</div>
</code></pre>
<p>This could be also fixed by adding those styles to the polyfilled component:</p>
<pre><code class="language-css">/* do not use */
video {
margin: 0 10px 5px 0;
float: left;
}
/* do something like this: */
video,
.polyfill-video {
margin: 0 10px 5px 0;
float: left;
}
/* or better */
.video-wrapper {
margin: 0 10px 5px 0;
float: left;
}
</code></pre>
<p>
<strong>re-rendering shadowelements</strong>: On dynamic websites shadowelements dimensions and/or positions sometimes need to be updated, this can be achieved by triggering the <code class="i">
updateshadowdom</code>
.
</p>
<pre><code class="language-javascript">
$(document).trigger('updateshadowdom');
</code></pre>
<p>
<small>The <code class="i">
updateshadowdom</code> event is automatically and lazily triggered on window.resize/emchange events.</small>
</p>
</li>
</ul>
</p>
<h2 id="Shiv">HTML5 shiv and innershiv</h2>
<p>
IE8- isn't capable of rendering HTML5 elements. Webshims lib in combination with Modernizr or HTML5shiv automatically fixes this issue and adds WAI-ARIA landmarks to enable accessibility of HTML5.
</p>
<h3 id="Shiv-dynamic-html5">Dynamically adding HTML5 markup</h3>
<p>
Additionally it implements the following manipulation methods to allow dynamic creation of HTML5 elements: <code class="i">
.updatePolyfill()</code>
, <code class="i">
.htmlPolyfill()</code>
, <code class="i">
.appendPolyfill()</code>
, <code class="i">
.prependPolyfill()</code>
, <code class="i">
.afterPolyfill()</code>
, <code class="i">
.beforePolyfill()</code>
<code class="i">
.replaceWithPolyfill()</code>
, <code class="i">
.appendPolyfillTo()</code>
, <code class="i">
.prependPolyfillTo()</code>
, <code class="i">
.insertPolyfillAfter()</code>
, <code class="i">
.insertPolyfillBefore()</code>
, <code class="i">
.replacePolyfillAll()</code>
</p>
<pre class="runnable"><code class="language-javascript">
var html = '<section><form action="#">' +
'<input type="text" placeholder="name" name="test" required/>' +
'<input type="date" required="required" name="test2" />' +
'<input type="submit" />' +
'</form></section>';
$('#Shiv-dynamic-html5-test').htmlPolyfill(html);
</code></pre>
<div id="Shiv-dynamic-html5-test">
</div>
</p>
<h3 id="Shiv-updatePolyfill">Using webshims' <code class="i">
updatePolyfill</code> method with Backbone/jQMobile/Knockout</h3>
<p>
If a plugin, script or framework is used, which uses a "normal" JS/jQuery manipulation method instead of the corresponding webshims enhanced manipulation method to generate new HTML5 content (i.e.: <code class="i">
.html()</code>
instead of <code class="i">
.htmlPolyfill()</code>
), the method <code class="i">
.updatePolyfill()</code>
can be used to polyfill the dynamic content:
</p>
<pre><code class="language-javascript">
$('#my-dynamic-container').load('ajax/test.html', function(){
$(this).updatePolyfill();
});
</code></pre>
<h4>jQuery mobile example</h4>
<pre><code class="language-javascript">
//set waitReady to false
webshim.setOptions('waitReady', false);
// call webshim.polyfill() before domready
webshim.polyfill();
// bind to the pageinit event after domready...
$(document).on('pageinit', function(e){
// ...and call updatePolyfill on the changed element container
$(e.target).updatePolyfill();
});
</code></pre>
<p>
For jQuery Mobile see also <a href="demos/webforms/jquery-mobile.html">webshims and jQ mobile</a>
</p>
<h2 id="ES5">ES5</h2>
<p>
The <code class="i">
es5</code>
feature uses the <a href="http://github.com/kriskowal/es5-shim/">ES5 shim</a> by <a href="http://askawizard.blogspot.com/">Kris Kowal</a> (all object methods, which can't be used cross-browser are removed.).
</p>
<p>
The script implements the following methods:
</p>
<ul>
<li>
<strong>Object</strong>: <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys">keys</a>
</li>
<li>
<strong>Array</strong>: <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray">isArray</a>
</li>
<li>
<strong>Array.prototype</strong>: <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map">map</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter">filter</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every">every</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some">some</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/Reduce">reduce</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/ReduceRight">reduceRight</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf">indexOf</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf">lastIndexOf</a>
</li>
<li>
<strong>Date</strong>: <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now">now</a><!--, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/parse">parse</a> -->
</li>
<li>
<strong>Date.prototype</strong>: <a href="http://msdn.microsoft.com/en-us/library/ff925953%28v=vs.94%29.aspx#Y72">toISOString</a>, <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toJSON">toJSON</a>
</li>
<li>
<strong>Function.prototype</strong>: <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind">bind</a>
</li>
<li>
<strong>String.prototype</strong>: <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim">trim</a>
</li>
</ul>
<p>
Note: All methods added to the prototype object are visible inside of a for in loop, while native implementations aren't enumerable. (use hasOwnProperty)
</p>
<pre><code class="language-javascript">
webshim.ready('es5', function(){
[1, 2, 3].forEach(function(){
// do stuff
});
});
</code></pre>
<h3>Abstractions</h3>
<p>
Webshims Lib adds the following methods: <code class="i">
webshim.objectCreate</code>
, <code class="i">
webshim.defineProperty</code>
, <code class="i">
webshim.defineProperties</code>
, <code class="i">
webshim.getOwnPropertyDescriptor</code>
and corresponding support flags: <code class="i">
webshim.support.objectAccessor</code>
(true in all modern Browsers including IE9, getters and setters can be used on all objects) and <code class="i">
webshim.support.advancedObjectProperties</code>
(true in FF4, IE9, Chrome 10..., the full ES5 specification of defineProperty is implemented (including writeable, enumerable and configurable).
</p>
<h4>webshim.objectCreate(proto [, propertiesObject, options ])</h4>
<p>
<code class="i">
webshim.objectCreate</code>
works very similar to <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create">Object.create</a>
</p>
<p>
If <code class="i">
propertiesObject</code>
is defined, the method goes through this object and sets writeable, enumerable and configurable to true, if the corresponding property is undefined.
</p>
<p>
After this, it will pass <code class="i">
proto</code>
and <code class="i">
propertiesObject</code>
to Object.create (if defined) or will use Crockfords <code class="i">
begetObject</code>
-Method on the <code class="i">
proto</code>
-object and then calls <code class="i">
webshim.defineProperties</code>
with the returned object and the <code class="i">
propertiesObject</code>
.
</p>
<p>
If you pass the options parameter and the Object already has a Options-property. The options-property on the object will be deeply extended otherwise an new options-property will be created.
</p>
<p>
If the object has a method called <code class="i">
_create</code>
, it will call this method with options as first argument.
</p>
<p>
After this, the created object will be returned.
</p>
<pre><code class="language-javascript">
var carProto = {
options: {
foo: 'bar',
baz: 'boom'
},
wheels: 4,
drive: function(){
this.isDriving = true;
}
};
var myCar = Object.create(carProto, {
_create: {
value: function(){
this.drive();
}
},
jumps: {
value: function(){
//implements jumping
}
},
{baz: 'jo'}
);
// myCar will look like this:
{
// own property:
options: {
foo: 'bar',
baz: 'jo'
},
// prototype:
wheels: 4,
// prototype
drive: function(){
this.isDriving = true;
},
// own property:
_create: function(){
this.drive();
},
// own property:
jumps: function(){
//implements jumping
},
// own property:
isDriving: true
}
</code></pre>
<h4>webshim.defineProperties (object, props)</h4>
<p>
<code class="i">
webshim.defineProperties</code>
works similar to <a href="https://developer.mozilla.org/en/JavaScript/Reference/global_objects/object/defineproperties">Object.defineProperties</a>
</p>
<p>
It will go through the props properties and will set writeable, enumerable and configurable to true, if they are undefined.
</p>
<p>
After this either Object.defineProperties will be invoked or legacy code is used.
</p>
<h2 id="Forms">Forms</h2>
<p>
The <code class="i">
forms</code>
(constraint validation without number, date etc.) and <code class="i">
forms-ext</code>
(number, date, range etc.) features of the webshim lib are implementing support for the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#the-constraint-validation-api">constraint validation API</a>, some input widgets and the placeholder-attribute.
</p>
<p>
The <code class="i">
forms</code>
feature also implements an easy and cross browser way to control the <a href="demos/forms.html#UI-Settings">validation UI</a> (error message and styling the validation bubble).
</p>
<h3>Implemented/fixed in <code class="i">
forms</code>:</h3>
<ul>
<li>
<strong>elements:</strong> <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-output-element">output</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-datalist-element">datalist<sup>1</sup></a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-progress-element">progress</a>
</li>
<li>
<strong>types</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#e-mail-state-(type=email)">email</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#url-state-(type=url)">url</a>
</li>
<li>
<strong>content attributes and properties (IDL attributes)</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#attr-input-placeholder">placeholder</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#attr-input-list">list</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fe-autofocus">autofocus</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fs-novalidate">novalidate (noValidate)</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#attr-input-required">required</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#attr-input-pattern">pattern</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#attr-textarea-maxlength">maxlength</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fs-formnovalidate">formnovalidate (formNoValidate)</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fs-formaction">formaction (formAction)</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fs-formenctype">formenctype (formEnctype)</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fs-formmethod">formmethod (formMethod)</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#attr-fs-formtarget">formtarget (formTarget)</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#association-of-controls-and-forms">form attribute</a>,
<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#attr-fieldset-disabled">fielset[disabled]</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#the-multiple-attribute">multiple <sup>2</sup></a>
</li>
<li>
<strong>properties/IDLs</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#dom-datalist-options">options<sup>2</sup></a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#dom-progress-position">position</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-cva-willvalidate">willValidate</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-cva-validity">validity</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-cva-validationmessage">validationMessage</a>,
, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-textarea/input-selectionstart">selectionStart/selectionEnd</a>
</li>
<li>
<strong>methods</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-cva-setcustomvalidity">setCustomValidity</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#dom-form-checkvalidity">checkValidity</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-textarea/input-setselectionrange">setSelectionRange</a>
</li>
<li>
<strong>events</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#constraint-validation">invalid</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#event-input-input">input</a>
</li>
<li>
<strong>Selectors</strong>: <a href="http://www.w3.org/TR/css3-ui/#pseudo-invalid">:invalid</a>, <a href="http://www.w3.org/TR/css3-ui/#pseudo-valid">:valid</a>, <a href="http://www.w3.org/TR/css3-ui/#pseudo-required">:required</a>, <a href="http://www.w3.org/TR/selectors4/#user-pseudos">:user-error</a>
(Not for CSS, only for JS, for CSS use selectors .user-sccuess, .user-error or [required] please look into the abstractions section)
</li>
</ul>
<ul class="list">
<li><small>1. You need to wrap the datalist options in a select element (datalist > select > option)!</small></li>
<li><small>2. multiple is only implemented for type=email (also works in conjunction with pattern). Implementation for [type="file"][multiple] or [accept] see <a href="#FileReader">filereader</a>!</small></li>
</ul>
<h3>Implemented/fixed in <code class="i">
forms-ext</code>:</h3>
<ul>
<li>
<strong>types</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#local-date-and-time-state">datetime-local</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#time-state-(type=time)">time</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#date-state-(type=date)">date</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#number-state-(type=number)">number</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#month-state-%28type=month%29">month</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#range-state-(type=range)">range</a>
</li>
<li>
<strong>content attributes and properties (IDL attributes)</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#attr-input-step">step</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#attr-input-max">max</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#attr-input-min">min</a>
</li>
<li>
<strong>properties/IDLs</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#dom-input-valueasnumber">valueAsNumber</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#dom-input-valueasdate">valueAsDate</a>, <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#dom-lfe-labels">labels</a>
</li>
<li>
<strong>methods</strong>: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#dom-input-stepdown">stepUp/stepDown</a>
</li>
</ul>
<h3 id="Forms-forms"><code class="i">
forms</code> Options</h3>
<p>A typical configuration would look like this:</p>
<pre><code class="language-javascript">
webshim.setOptions("forms", {
lazyCustomMessages: true,
replaceValidationUI: true,
customDatalist: "auto",
list: {
"filter": "^"
}
});
webshim.polyfill('forms');
</code></pre>
<ul>
<li>
<strong><a href="demos/forms.html#Locale-customMessages">customMessages</a></strong> <em>boolean</em> If set to true, Webshims will implement a DOM-Property called customValidationMessage, which can be changed through the webshim.validityMessages-Array.
<br>
<em>default: false</em>
</li>
<li>
<strong><a href="demos/forms.html#Locale-customMessages">lazyCustomMessages</a></strong> <em>boolean</em> Similar to <code class="i">
customMessages</code>
, but the data is lazily loaded after window.onload or as soon as the user starts to interact with a form for better performance. The customValidationMessage property is therefore not available on DOM-Ready.
<br>
<em>default: false</em>
</li>
<li>
<strong><a href="demos/forms.html#UI-replaceValidationUI">replaceValidationUI</a></strong> <em>boolean</em> Replaces the browser validation UI with a custom styleable UI.
<br>
<em>default: false</em>
</li>
<li>
<strong><a href="demos/forms.html#UI-ival">iVal</a></strong> <em>mixed object</em> Adds and configures a user friendly form validation UI.
<br>
<em>default: </em>
<pre><code class="language-javascript">
webshim.setOptions("forms", {
iVal: {
"sel": ".ws-validate",
"handleBubble": "hide",
"recheckDelay": 400,
"fieldWrapper": ":not(span):not(label):not(em):not(strong):not(p)",
"events": "focusout change",
"errorClass": "user-error",
"errorWrapperClass": "ws-invalid",
"successWrapperClass": "ws-success",
"errorBoxClass": "ws-errorbox",
"errorMessageClass": "ws-errormessage",
"fx": "slide",
"submitCheck": false
}
});</code></pre>
</li>
<li>
<strong><a href="demos/forms.html#Custom-validity">addValidators</a></strong> <em>boolean</em> Should Webshims implement some new custom validators. <a href="demos/forms.html#Custom-validity">custom validity example</a>
<br>
<em>default: false</em>
</li>
<li>
<strong><a href="demos/forms.html#Datalist">customDatalist</a></strong> <em>boolean</em>|<em>String 'auto'</em> Allows to use custom styleable datalist elements in all browsers. If the string 'auto' is used, input widgets are only replaced in desktop browser or incapable browsers.
<br>
<em>default: false</em>
</li>
<li>
<strong><a href="demos/forms.html#Datalist">list</a></strong> <em>mixed object</em> Options object for the datalist/[list] feature (can be also controlled using data-list markup).
<br>
<em>default:</em>
<pre><code class="language-javascript">
webshim.setOptions("forms", {
list: {
"filter": "*",
"multiple": false,
"focus": false,
"highlight": false,
"valueCompletion": false,
"inlineValue": false,
"noHtmlEscape": false,
"popover": {
"constrainWidth": true
}
}
});</code>
</pre>
</li>
</ul>
<h3 id="Forms-forms-ext"><code class="i">
forms-ext</code> Options</h3>
<ul>
<li>
<strong>replaceUI</strong> <em>boolean</em>|<em>mixed object</em>|<em>String 'auto'</em> If set to true the UI of all input widgets (number, time, month, date, range) are replaced in all browsers (also in browser, which have implemented these types). This is useful, if you want to style the UI in all browsers. If the string 'auto' is used, input widgets are only replaced in desktop browser or incapable browsers.
<br>
<em>default: false</em>
</li>
<li>
<strong>types</strong> <em>string</em> A white space separated string. Possible values are <code class="i">
'datetime-local range date time number month color'</code>
. If one of the listed input types is not supported, Webshim will load the forms-ext API and UI package and implement all types.
<br>
<em>default: date time range number</em>
</li>
<li>
<strong>widgets</strong> <em>object</em> widgets is a general options object for all input widgets. <a href="http://afarkas.github.io/webshim/demos/demos/themes/themes.html">example widgets with different themes</a>, <a href="http://jsfiddle.net/trixta/VNuct/">example widgets with different configurations</a>
<pre><code class="language-javascript">
webshim.setOptions("forms-ext", {
"widgets": {
"startView": 0,
"minView": 0,
"inlinePicker": false,
"size": 1,
"splitInput": false,
"yearSelect": false,
"monthSelect": false,
"daySelect": false,
"noChangeDismiss": false,
"openOnFocus": false,
"buttonOnly": false,
"classes": "",
"popover": {
//popover options
},
"calculateWidth": true,
"animate": true,
"toFixed": 0,
"onlyFixFloat": false
}
});</code>
</pre>
</li>
<li>
<strong>date</strong> <em>object</em> Overrides widgets option object, can be also configured through data-date attribute (<a href="demos/cfgs/input-date.html">datepicker Configurator</a>)
</li>
<li>
<strong>month</strong> <em>object</em> Overrides widgets option object, can be also configured through data-month attribute (<a href="demos/cfgs/input-month.html">monthpicker Configurator</a>)
</li>
<li>
<strong>number</strong> <em>object</em> Overrides widgets option object, can be also configured through data-number attribute (<a href="demos/cfgs/input-number.html">number/spinbutton Configurator</a>)
</li>
<li>
<strong>time</strong> <em>object</em> Overrides widgets option object, can be also configured through data-time attribute (<a href="demos/cfgs/input-time.html">timepicker Configurator</a>)
</li>
<li>
<strong>range</strong> <em>object</em> Overrides widgets option object, can be also configured through data-range attribute (<a href="demos/cfgs/input-range.html">slider/range Configurator</a>)
</li>
<li>
<strong>color</strong> <em>object</em> Overrides widgets option object, can be also configured through data-color attribute (<a href="demos/cfgs/input-color.html">colorpicker Configurator</a>)
</li>
<li>
<strong>datetime-local</strong> <em>object</em> Overrides widgets option object, can be also configured through data-color attribute (<a href="demos/cfgs/input-datetime-local.html">datetimepicker Configurator</a>)
</li>
</ul>
<p>A typical configuration would look like this:</p>
<pre><code class="language-javascript">
//configure forms features
webshim.setOptions("forms", {
lazyCustomMessages: true,
replaceValidationUI: true,
customDatalist: "auto",
list: {
"filter": "^"
}
});
//configure forms-ext features
webshim.setOptions("forms-ext", {
replaceUI: "auto",
types: "date range number",
date: {
startView: 2,
openOnFocus: true,
classes: "show-week"
},
number: {
calculateWidth: false
},
range: {
classes: "show-activevaluetooltip"
}
});
//load forms and forms-ext features
webshim.polyfill('forms forms-ext');
</code></pre>
<h3 id="Forms-extensions">Extensions</h3>
<ul>
<li>
<strong>event: firstinvalid</strong>: <code class="i">
firstinvalid</code>
is a simple, bubbling event, which is triggered on the first invalid form element. Preventing the default of firstinvalid will automatically prevent the default behavior of all current invalid elements.
</li>
<li>
<strong>event: lastinvalid</strong>: <code class="i">
lastinvalid</code>
is an extended, bubbling, (but) uncancelable event, which is triggered on the last invalid form element. The property <code class="i">
invalidlist</code>
is a jQuery-collection of all current invalid elements.
</li>
<li>
<strong>event: changedvalid/changedinvalid</strong>: Event is triggered, if the value of the element was changed and is marked as valid/invalid (see also: .form-ui-valid/.form-ui-invalid).
</li>
<li>
<strong>event: datalistselect</strong>: Event is triggered on each input[list] for each option, in case the callback returns a string this is used to construct the datalist polyfill
</li>
<li>
<strong>event: getoptioncontent</strong>: Event is triggered on the input element, for each option of a datalist. The return value (must be a string) is used to build each list item. Good to enhance list items (For example to add images or more complex HTML)
</li>
<li>
<strong>event: datalistcreated</strong>: Event is triggered on the input element, after the list was created.
</li>
<li>
<strong>selectors for CSS/JS: .ws-validate (.ws-invalid/.ws-success)</strong>: The class 'ws-validate' on a form element will implement UX improved Instant Validation for this form. The classes .ws-invalid (similiar to <a href="http://www.w3.org/TR/selectors4/#user-pseudos">:user-error</a>) and .ws-success will mark either "touched" invalid element wrappers or valid and "filled" element wrappers. <a href="demos/forms.html#UI-ival">example</a>
</li>
<li>
<strong>selectors for CSS/JS: .user-success/.user-error</strong>: which work similar to <a href="https://developer.mozilla.org/en/CSS/%3A-moz-ui-valid">:-moz-ui-valid</a>/<a href="https://developer.mozilla.org/en/CSS/%3A-moz-ui-invalid">:-moz-ui-invalid</a> or <a href="http://www.w3.org/TR/selectors4/#user-pseudos">:user-error</a>
</li>
<li>
<strong>selectors for CSS/JS: .placeholder-visible</strong>: which work similar to <a href="https://developer.mozilla.org/en/CSS/%3A-moz-placeholder">:-moz-placeholder</a>, <a href="http://msdn.microsoft.com/en-us/ie/hh272905#_HTML5FormsVal">:-ms-input-placeholder</a> and <a href="http://css-tricks.com/snippets/css/style-placeholder-text/">::-webkit-input-placeholder</a>
</li>
<li>
<strong>$().getErrorMessage</strong>: very similar to the standard validationMessage, but gives more control over the validationMessage.
</li>
<li>
<strong>attribute: data-errormessage or -x-moz-errormessage</strong>: Attribute with text, which is used be custom validityAlert/customValidationMessage to show a custom error messa