Skip to content

Commit

Permalink
generalize polymer's fuoc prevention strategy; fixes: #276
Browse files Browse the repository at this point in the history
 - styling is now expressed via 'polymer-veiled' and 'polymer-unveil' classes which are now user customizable.
 - to veil (initially hide) an element either include the class 'polymer-veiled' or add to the array: Polymer.veiledElements. This list includes 'body' by default but that can be removed to prevent body from getting de-fuoc'd.
 - note: Polymer automatically unveils elements at WebComponentsReady time, but elements can be dynamically unveiled by (1) adding the polymer-veiled class to them to hide them and then (2) when they are ready, calling Polymer.unveilElements().
  • Loading branch information
sorvell committed Sep 30, 2013
1 parent 3f3fd2d commit 24b3b3b
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 10 deletions.
76 changes: 66 additions & 10 deletions src/boot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,71 @@

(function(scope) {

// FOUC prevention tactic
var style = document.createElement('style');
style.textContent = 'body {opacity: 0;}';
var head = document.querySelector('head');
head.insertBefore(style, head.firstChild);

window.addEventListener('WebComponentsReady', function() {
document.body.style.webkitTransition = 'opacity 0.3s';
document.body.style.opacity = 1;
});
// FOUC prevention tactic
// default list of veiled elements
scope.veiledElements = ['body'];
// add polymer styles
var VEILED_CLASS = 'polymer-veiled';
var UNVEIL_CLASS = 'polymer-unveil';
var TRANSITION_TIME = 0.3;
var style = document.createElement('style');
style.textContent = '.' + VEILED_CLASS + ' { ' +
'visibility: hidden; opacity: 0; } \n' +
'.' + UNVEIL_CLASS + '{ ' +
'-webkit-transition: opacity ' + TRANSITION_TIME + 's; ' +
'transition: opacity ' + TRANSITION_TIME +'s; }\n';
var head = document.querySelector('head');
head.insertBefore(style, head.firstChild);

// apply veiled class
function veilElements() {
var veiled = Polymer.veiledElements;
if (veiled) {
for (var i=0, l=veiled.length, u; (i<l) && (u=veiled[i]); i++) {
veilElementsBySelector(u);
}
}
}

function veilElementsBySelector(selector) {
var nodes = document.querySelectorAll(selector);
for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
n.classList.add(VEILED_CLASS);
}
}

// apply unveil class
function unveilElements() {
requestAnimationFrame(function() {
var nodes = document.querySelectorAll('.' + VEILED_CLASS);
for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
n.classList.add(UNVEIL_CLASS);
n.classList.remove(VEILED_CLASS);
}
// NOTE: depends on transition end event to remove 'unveil' class.
if (nodes.length) {
var removeUnveiled = function() {
for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
n.classList.remove(UNVEIL_CLASS);
}
document.body.removeEventListener(endEvent, removeUnveiled, false);
}
document.body.addEventListener(endEvent, removeUnveiled, false);
};
});
}

// determine transition end event
var endEvent = (document.documentElement.style.webkitTransition !== undefined) ?
'webkitTransitionEnd' : 'transitionend';

// hookup auto-unveiling
document.addEventListener('DOMContentLoaded', veilElements);
window.addEventListener('WebComponentsReady', unveilElements);

// exports
// can dynamically unveil elements by adding the veiled class and then
// calling Polymer.unveilElements
scope.unveilElements = unveilElements;

})(Polymer);
84 changes: 84 additions & 0 deletions test/html/styling/unveil.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<!--
Copyright 2013 The Polymer Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->
<html>
<head>
<title>unveil</title>
<script src="../../../polymer.js"></script>
<script src="../../../../tools/test/htmltest.js"></script>
<script src="../../../../tools/test/chai/chai.js"></script>
<style>
.polymer-unveil {
background: red;
}
</style>
<script>
Polymer.veiledElements = ['body', '#veiled'];
</script>
</head>
<body>
<x-test id="veiled"></x-test>
<x-test class="polymer-veiled"></x-test>

<polymer-element name="x-test">
<template>
<style>
:host { dispay: block};

This comment has been minimized.

Copy link
@ebidel

ebidel Sep 30, 2013

Contributor

dispay -> display

This comment has been minimized.

Copy link
@sorvell

sorvell Sep 30, 2013

Author Contributor

Thanks, removed that in a6a8675

</style>
x-test
</template>
<script>
Polymer('x-test', {
enteredView: function() {
chai.assert.isTrue(getComputedStyle(this).visibility == 'hidden',
'veiled elements are visible');
}
});
</script>
</polymer-element>

<script>
document.addEventListener('WebComponentsReady', function() {
chai.assert.isTrue(getComputedStyle(document.body).visibility == 'hidden',
'veiled elements are visible');
// test during transition
requestAnimationFrame(function() {
requestAnimationFrame(function() {
chai.assert.equal(document.querySelectorAll('.polymer-veiled').length, 0,
'element veiled class is removed when unveiling');
chai.assert.equal(document.querySelectorAll('.polymer-unveil').length, 3,
'element unveil class is applied when unveiling');
var nodes = document.querySelectorAll('.polymer-unveil')
for (var i=0; i<nodes.length; i++) {
chai.assert.equal(getComputedStyle(nodes[i]).backgroundColor,
'rgb(255, 0, 0)', 'user unveil style is applied');
}

});
});
var endEvent = (document.documentElement.style.webkitTransition !== undefined) ?
'webkitTransitionEnd' : 'transitionend';
document.body.addEventListener(endEvent, function(e) {
if (e.target != this) {
return;
}
requestAnimationFrame(function() {
for (var i=0, l=Polymer.veiledElements.length, elt; i<l; i++) {
elt = document.querySelector(Polymer.veiledElements[i]);
chai.assert.isTrue(getComputedStyle(elt).visibility == 'visible',
'unveiled elements are visible');
}
chai.assert.equal(document.querySelectorAll('.polymer-veiled').length, 0,
'element classes are cleared after unveiling');
chai.assert.equal(document.querySelectorAll('.polymer-unveil').length, 0,
'element classes are cleared after unveiling');
done();
});
}, false);
});
</script>
</body>
</html>
1 change: 1 addition & 0 deletions test/js/styling.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ htmlSuite('styling', function() {
htmlTest('html/styling/sheet-scope.html');
htmlTest('html/styling/sheet-main-doc.html');
htmlTest('html/styling/apply-reset-styles.html');
htmlTest('html/styling/unveil.html');
});

0 comments on commit 24b3b3b

Please sign in to comment.