Estelle Weyl
www.standardista.com
@estellevw
@standardista
![HTML5 and CSS3 for the Real World](http://akamaicovers.oreilly.com/images/9780980846904/cat.gif)
![HTML5: The Definitive Guide](http://akamaicovers.oreilly.com/images/0636920018063/cat.gif)
![MObile HTML5](http://akamaicovers.oreilly.com/images/0636920021711/cat.gif)
![Web Performance Daybook](http://akamaicovers.oreilly.com/images/0636920025955/cat.gif)
All statements are those of my employer, and not necessarily those of the speaker
Estelle Weyl | @estellevw | Github | Press → to advance, 2 for comments, 4 to read/write notes.
http://estelle.github.com/fluentconf/
All statements are those of my employer, and not necessarily those of the speaker
var isDHTML, isID, isAll, isLayers; if (document.getElementById) { isID = 1; isDHTML = 1; } else { if (document.all) { isAll = 1; isDHTML = 1; } else { browserVersion = parseInt(navigator.appVersion); if ((navigator.appName.indexOf('Netscape') != -1) && (browserVersion == 4)) { isLayers = 1; isDHTML = 1; } } } function findDOM(objectID,withStyle) { if (withStyle == 1) { if (isID) { return (document.getElementById(objectID).style) ; } else { if (isAll) { return (document.all[objectID].style); } else { if (isLayers) { return (document.layers[objectID]); } }; } } else { if (isID) { return (document.getElementById(objectID)); } else { if (isAll) { return (document.all[objectID]); } else { if (isLayers) { return (document.layers[objectID]); } }; } } } function setClass(objectID,newClass) { var dom =findDOM(objectID, 0); dom.className = newClass; }
Normalize browser features / code once, works everywhere
if (el.addEventListener) { // W3C el.addEventListener("click", func, false); } // IE5+, Opera else if (el.attachEvent) { el.attachEvent ("click", func); } else { // Netscape 4, IE5Mac el.onclick = func; }
addEventListener supported in IE9 & Opera 7
Faster, optimized, readable code
Function chaining & implicit iteration behavior
Less code. Faster to code.
Faster learning curve. No need to know JS?!?!
<script src="jquery.js"></script> <script type="text/javascript"> $('li:first').addClass('first'); </script>
With jQuery
$("a[href^='http']").each(function() { $(this).css({ background-image: "url(http://g.etfv.co/" + this.href + ")"}); });
with Vanilla.js
var links = document.querySelectorAll("a[href^='http']"), i; for (i=0; i<links.length; i++){ links[i].style.backgroundImage = "url(http://g.etfv.co/" + links[i].getAttribute('href') +")"; }
jquery.min.js
from: ajax.googleapis.com/ajax/libs/jquery/1.7.2
96.2KB + HTTP request + 4J + DNS lookup
Don't Add Frameworks in the 3rd party widgets you create!!
"Eight Simple Rules for Running Your JavaScript on My Page" by Kent Brewster
<script></script>
If possible, make home pages work BEFORE the library needs to be downloaded. - SurveyMonkey
While you many not support non-JavaScript users, your users are basically non-JS while they're downloading, parsing and executing your JS files
Get and maintain mad JS skillz.
<script src="jquery.js"></script> <script type="text/javascript"> $('li:first').addClass('first'); </script>
Global Variables for presentation:
var d = document, i, el, EBCN, QSA;
vanilla js
d.querySelector('li').classList.add('first');
or simply
li:first-of-type { /* .first declarations */ }
Hit 4 for taking notes
var tr = d.getElementsByTagName('tr'); for(i=0; i < tr.length; i+=2) { tr[i].setAttribute('class','odd'); }
thead tr { background-color: #999; color: #fff; } tbody tr:nth-of-type(odd) { background-color: #fff; } tbody tr:nth-of-type(even) { background-color: #ccc; }
First | Last | |
---|---|---|
Estelle | Weyl | @estellevw |
Nicole | Sullivan | @stubbornella |
Amy | Hoy | @amyhoy |
Sarah | Mei | @sarahmei |
Rebecca | Murphey | @rmurphey |
Garann | Means | @garannm |
Tomomi | Imura | girlie_mac |
Pamela | Fox | @pamelafox |
Stacie | Hibino | @staciehibino |
Sharon | Minsuk | @sharonminsuk |
Sarah | Allen | @ultrasaurus |
Avni | Khatri | @avni321 |
Shelley | Powers | @shelleypowers |
nav > ul > li { display: inline-block; position:relative; } nav ul ul { transform: scale(1,0); transform-origin: top center; transition: 0.2s linear 50ms; position: absolute; top: 100%; } nav li:hover ul { transform: scale(1,1); }
nav > ul > li { display: inline; zoom: 1; display: inline-block; position:relative; } nav ul ul { -webkit-transform: scale(1,0); -moz-transform: scale(1,0); -ms-transform: scale(1,0); -o-transform: scale(1,0); transform: scale(1,0); -webkit-transform-origin: top center; -moz-transform-origin: top center; -ms-transform-origin: top center; -o-transform-origin: top center; transform-origin: top center; -webkit-transition: transform 0.2s linear 50ms; -moz-transition: transform 0.2s linear 50ms; -ms-transition: transform 0.2s linear 50ms; -o-transition: transform 0.2s linear 50ms; transition: transform 0.2s linear 50ms; position: absolute; top: 100%; display: none; }
nav li:hover ul { -webkit-transform: scale(1,1); -moz-transform: scale(1,1); -ms-transform: scale(1,1); -o-transform: scale(1,1); transform: scale(1,1); display: block; }
Supported since IE9
on the document
d.getElementsByClassName('foo');
on a DOM node
el = document.getElementById('bar'); el.getElementsByClassName('foo');
jQuery Equivalent
el = $('.bar');
Try the following code in the console
var container = document.getElementById('slides'); var slides = container.getElementsByClassName('slide'); console.log('1.' + slides.length); var foo = document.createElement('div'); foo.classList.add('slide'); container.appendChild(foo); console.log('2.' + slides.length);
var emptyList = document.getElementsByClassName('zxcv'); if(emptyList) {alert('returned true')};
The getElementsByClassName(classNames) method takes a string that contains an unordered set of unique space-separated tokens representing classes. When called, the method must return a live NodeList object containing all the elements in the document, in tree order, that have all the classes specified in that argument, having obtained the classes by splitting a string on spaces. If there are no tokens specified in the argument, then the method must return an empty NodeList. If the document is in quirks mode, then the comparisons for the classes must be done in an ASCII case-insensitive manner, otherwise, the comparisons must be done in a case-sensitive manner.
-- Specification.
Supported since IE8
var chil = $('#bar .foo');
Natively
var el = document.querySelector('#bar'); var chil = el.querySelectorAll('.foo');
or
chil = d.querySelectorAll('#bar .foo');
Access DOM elements with standard CSS selectors.
elem.querySelector(selector); elem.querySelectorAll(selector);
Examples
d.querySelector('#id, li, #slides'); d.querySelectorAll('li:nth-of-type(odd)');
QSA = d.querySelectorAll('#slides .slide')
if you increase # of slides, EBCN increases, QSA does not.
var EBCN = d.getElementsByClassName('slide'); var QSA = d.querySelectorAll('.slide');
var newSlide = d.createElement('div'); newSlide.classList.add('slide'); d.getElementById('slides').appendChild(newSlide); console.log('Current EBCN: ' + EBCN.length); console.log('Current QSA: ' + QSA.length);
jQuery
$('#slides .slide').addClass('current');
Vanilla.js
var slides = d.querySelectorAll('#slides .slide'); for(var i=0; i < slides.length; i++){ slides[i].classList.add('current'); }
No Internet Explorer love :(
$('#foo').addClass('bar'); $('#foo').removeClass('bar'); $('#foo').toggle('bar'); $('#foo').hasClass('bar');
d.querySelector('#foo').classList.add('bar'); d.querySelector('#foo').classList.remove('bar'); d.querySelector('#foo').classList.toggle('bar');
fooCL = d.querySelector('#foo').classList; fooCL.add('bar'); fooCL.remove('bar'); fooCL.toggle('bar'); fooCL.contains('bar'); // true or false
cl = d.querySelector('#foo').classList; cl.add('zap'); cl.remove('bar'); cl.toggle('bar'); cl.contains('bar')); // true or false var classes = el.toString();
jQuery
$('.foo').addClass('bar');
Native
var foos = d.querySelectorAll('.foo'); for(var i = 0; i < foos.length; i++){ foos[i].classList.add('bar'); }
All Browsers love getAttribute()
Dataset supported since IE10
Attribute Abuse
<span class="link externallink" evt="5" omnit="RFAW Review" rel="www~trekaroo~com|activities|arizona-museum-of-natural-history-mesa-arizona" target="_blank"> Trekaroo </span>
Add attributes to elements in the form of data-name and access these through the DOM using dataset[name] on the element in question.
<p data-foo-bar="test">
That's an author defined attribute
</p>
dataset property returns a DOMStringMap object of element's data- attributes
el.dataset['fooBar']
Valid code
<span class="link" data-usage="externallink" data-evt="5" data-omnit="RFAW Review" data-link="www.trekaroo.com/activities/arizona-museum-of-natural-history-mesa-arizona" data-target="_blank"> Trekaroo </span>
links=d.querySelectorAll('[data-usage]'); for (var i=0; i<links.length; i++) { switch(links[i].dataset.dataUsage){ case "externallink": uptake.createExternalLink(links[i]); break; case "internallink": uptake.createInternalLink(links[i]); break; case "downloadlink": uptake.createDownloadLink(links[i]); break; } }
dataset is a convenience feature for handling the data-* attributes, which are exposed as camel-cased properties.
e.dataset.fooBar = 'test' e.dataset.usage = 'externallink'
sets the data-foo-bar or data-usage attribute on e.
d.body.dataset.aBC = 'frog'; alert(d.body.getAttribute('data-a-b-c')); alert(d.body.dataset['aBC']); alert(d.body.dataset.aBC);
Define your own DOM manipulable data attributes
<b class="card" data-value="10" data-suite="3" data-row="3" data-col="2"></b>
var cards = document.querySelectorAll('.card'), cardinfo; deck=[]; for(var i=0; i < cards.length; i++){ cardinfo = []; for (var key in cards[i].dataset) { cardinfo.push(key,': ',cards[i].dataset[key],','); } var currentCard = cardinfo.join(''); deck.push(currentCard); }
currentCard == 'value: 10, suite: 3, row: 3, col: 2'
var cardID = info.getAttribute('data-value'); //10
All browsers support "data-*", but full support of 'dataset started with IE10, FF6, Safari 5.1, Chrome 7, Opera 11.1. Supported in iOS and Android. Polly fill