Création des Logiciels de gestion d'Entreprise, Création et référencement des sites web, Réseaux et Maintenance, Conception
Création des Logiciels de gestion d'Entreprise, Création et référencement des sites web, Réseaux et Maintenance, Conception
.CSS_FLOATY_BAR {
...
top: -50px; /* start off the screen, so it slides in nicely */
-webkit-transition: top 0.2s ease-out;
...
}
In JavaScript:// Constructor for the floaty bar
gmail.FloatyBar = function() {
this.menuDiv = document.createElement('div');
this.menuDiv.className = CSS_FLOATY_BAR;
...
};
// Called when it's time for the floaty bar to move
gmail.FloatyBar.prototype.setTop = function() {
this.menuDiv.style.top = window.scrollY + 'px';
};
// Called when the floaty bar menu is dismissed
gmail.FloatyBar.prototype.hideOffScreen = function() {
this.menuDiv.style.top = '-50px';
};
gmail.floatyBar = new gmail.FloatyBar();
// Listen for scroll events on the top level window
window.onscroll = function() {
...
gmail.floatyBar.setTop();
...
};
The essence here is that when the viewport scrolls, the floaty bar 'top' is set to the new viewport offset. The -webkit-transition rule specifies the animation parameters. (The 'top' property is to be animated, over 0.2s, using the ease-out timing function.) This is the animation behavior we had at launch, and it works just fine on Android and mobile Safari browsers..CSS_FLOATY_BAR {
...
top: -50px; /* start off the screen, so it slides in nicely */
-webkit-transition: -webkit-transform 0.2s ease-out;
...
}
In JavaScript:// Called when it's time for the floaty bar to move
gmail.FloatyBar.prototype.setTop = function() {
var translate = window.scrollY - (-50);
this.menuDiv.style['-webkit-transform'] = 'translateY(' + translate + 'px)';
};
// Called when the floaty bar menu is dismissed
gmail.FloatyBar.prototype.hideOffScreen = function() {
this.menuDiv.style['-webkit-transform'] = 'translateY(0px)';
};
Upon every scroll event, the floaty bar is translated vertically to the new viewport offset (modulo the offscreen offset which is important to the floaty bar's initial appearance). And, why exactly is this such an improvement? Even though the logic is equivalent, iPhone OS's implementation of CSS transforms is "performance enhanced", whilst our first iteration (animating the 'top' property) is performed by the OS in software. That's why the experience was unfortunately somewhat chunky at times, depending on the speed of the iPhone hardware.-webkit-transition-property
-webkit-transition-duration
-webkit-transition-timing-function
-webkit-transition-delay
-webkit-transition-property
property identifies the CSS properties where changes to the property will trigger a transition between the old value of the property and the new value. The -webkit-transition-duration
property specifies, in milliseconds, the length of time over which the transition should take place. The -webkit-transition-timing-function
property describes the speed at which the transition progresses over the duration of the transition. For example, -webkit-transition-timing-function: ease-in-out
describes a transition that will proceed slowly at the beginning and the end of the transition, but that will proceed quickly during the middle of the transition. You can also provide a custom, cubic-bezier function for a higher degree of control over the timing. The -webkit-transition-delay property specifies a delay, measured in milliseconds, before the transition begins. -webkit-transition
property, by simply specifying them in the above order. Once the transitions properties are set and up to the point where the value of -webkit-transition-property
is changed, all modifications of the specified CSS properties will trigger transitions.-webkit-transform
CSS property with the desired list of transforms. Each transform takes the form of a transformation function, such as translate3d
or rotate
, and a list of parameters enclosed in brackets. For example, to move an object to the right by 100 pixels and rotate it by 45 degrees you can use the -webkit-transform
property:-webkit-transform: translate(100px, 0) rotate(45deg);
-webkit-transform
as the transition property when moving an element is advantageous relative to using the standard top
and left
properties because transitions using -webkit-transform
are hardware-accelerated in Safari. An exception here is that it seems that 2D translations are not hardware-accelerated. But, since any 2D translation is equivalent to a corresponding 3D translation with the same translations in the x and y and no translation in the z axis, it is easy to use a hardware accelerated translate3d(x, y, 0) transform instead of a non-hardware accelerated translate(x, y)
transform.card.style.WebkitTransform =
‘translate3d(-700px, 0, 0) rotate(5deg)’;
window.setTimeout(function() {
card.style.WebkitTransition =
‘-webkit-transform 300ms ease-in-out’;
card.style.WebkitTransform =
‘translate3d(0, 0, 0) rotate(5deg)’;
}, 0);
element.addEventListener(‘webkitTransitionEnd’, listener, false);
card.style.WebkitTransform =
‘translate3d(-700px, 0, 0) rotate(5deg)’;
translated3d(-350px, 0, 0) rotate(5deg).
The final value will be translate3d(-700px, 0, 0) rotate(5deg).
The full duration of the transition will still apply, so the card will move about half as quickly as it usually does. It is possible to determine the current transform applied to an HTML element using the WebKitCSSMatrix and to use this to recalculate more appropriate transition parameters, but this is outside the scope of this post. function grow() {
var textarea = document.getElementById('growingTextarea');
var newHeight = textarea.scrollHeight;
var currentHeight = textarea.clientHeight;
…
}
One limitation of using scrollHeight and clientHeight is that we aren't able to shrink the textarea when content is deleted. When all the content of a textarea is visible, the scrollHeight is equal to the clientHeight. Therefore we aren't able to detect that our textarea is actually larger than the minimum size required to fit all the content (please do leave a comment if you think of a solution that doesn't require re-rendering the page).if (newHeight > currentHeight) {
textarea.style.height = newHeight + 5 * TEXTAREA_LINE_HEIGHT + 'px';
}
Notice how we only change the height if newHeight > currentHeight. Depending on the browser, changing the height (even if it's to the same value) will cause the page to re-render. On a mobile device, we want to try our best to minimize the number of operations.<script>
// Value of the line-height CSS property for the textarea.
var TEXTAREA_LINE_HEIGHT = 13;
function grow() {
var textarea = document.getElementById('growingTextarea');
var newHeight = textarea.scrollHeight;
var currentHeight = textarea.clientHeight;
if (newHeight > currentHeight) {
textarea.style.height = newHeight + 5 * TEXTAREA_LINE_HEIGHT + 'px';
}
}
</script>
<textarea id="growingTextarea"
onkeyup="grow();">
</textarea>
SELECT Author, COUNT(*) as NumArticles
FROM Magazines
GROUP BY Author
ORDER BY NumArticles;
SELECT Author, COUNT(*) as NumBooks
FROM Books
GROUP BY Author
ORDER BY NumBooks;
SELECT Author, NumPublications, PubType
FROM (
SELECT Author, COUNT(*) as NumPublications, 'Magazine' as PubType, 0 as SortIndex
FROM Magazines
GROUP BY Author
UNION
SELECT Author, COUNT(*) as NumPublications, 'Book' as PubType, 1 as SortIndex
FROM Books
GROUP BY Author
)
ORDER BY SortIndex, NumPublications;
CREATE TRIGGER IF NOT EXISTS RemoveAuthor
AFTER DELETE ON Books
BEGIN
DELETE FROM Authors
WHERE Author NOT IN
(SELECT Author
FROM Books);
END;
We'll get into more detail on triggers and how to use them in another performance post to come.google.wspl.Statement
- A parametrizable SQL statement classgoogle.wspl.Transaction
- Used to execute one or more Statements with ACID propertiesgoogle.wspl.ResultSet
- Arrays of JavaScript hash objects, where the hash key is the table column namegoogle.wspl.Database
- A connection to the backing database, also provides transaction supportgoogle.wspl.DatabaseFactory
- Creates the appropriate HTML5 or Gears database implementationvar database = google.wspl.DatabaseFactory.createDatabase('db name', 'http://yourdomain/dbworker.js');
var statement = google.wspl.Statement('SELECT col from test_table;');
database.createTransaction(function(tx) {
tx.executeAll([statement], {onSuccess: function(tx, resultSet) {
// Statement succeeded.
for(; resultSet.isValidRow(); resultSet.next()) {
window.console.info(resultSet.getRow()['col']);
}
}, onFailure: function(error) {
// Statement failed.
}});
}, {onSuccess: function() {
// After transaction commits, before any other starts.
}, onFailure: function(error) {
// After transaction fails, before any other starts.
}});
I've found that using the Gears database asynchronously will nicely split up the JavaScript execution, allowing event handlers and other code to execute between the callbacks. This can improve the responsiveness of your application if you're using long transactions. You can also use SQL triggers to avoid the read-modify-write pattern that causes "ping ponging" between threads -- either the main thread and Gears worker or the main thread and the HTML5 SQL thread.~/Library/Application Support/iPhone Simulator/User/Library/Caches/com.apple.WebAppCache/ApplicationCache.db
$ sqlite3 ApplicationCache.db
SQLite version 3.4.0
Enter ".help" for instructions
sqlite> .mode column
sqlite> .headers on
sqlite> .tables
CacheEntries CacheResourceData CacheWhitelistURLs FallbackURLs
CacheGroups CacheResources Caches SchemaVersion
sqlite> select * from CacheGroups;
id manifestHostHash manifestURL newestCache
---------- ---------------- ------------------------------------------------- -----------
1 906983082 http://mail.google.com/mail/s/?v=ma&name=sm 1
sqlite> select * from Caches;
id cacheGroup
---------- ----------
1 1
sqlite> select * from CacheEntries limit 1;
cache type resource
---------- ---------- ----------
1 2 1
sqlite> select * from CacheResources where id=1;
id url statusCode responseURL
---------- ------------------------------------------- ---------- -----------------------
1 http://mail.google.com/mail/s/?v=ma&name=sm 200 http://mail.google.c...
mimeType textEncodingName headers data
------------------- ---------------- --------------
text/cache-manifest utf-8
sqlite> select type,url,mimeType,statusCode from CacheEntries,CacheResources where resource=id;
type url mimeType statusCode
---------- ---------------------------------------------- ------------------- ----------
2 http://mail.google.com/mail/s/?v=ma&name=sm text/cache-manifest 200
4 http://mail.google.com/mail/images/xls.gif image/gif 200
4 http://mail.google.com/mail/images/pdf.gif image/gif 200
4 http://mail.google.com/mail/images/ppt.gif image/gif 200
4 http://mail.google.com/mail/images/sound.gif image/gif 200
4 http://mail.google.com/mail/images/doc.gif image/gif 200
4 http://mail.google.com/mail/images/graphic.gif image/gif 200
1 http://mail.google.com/mail/s text/html 200
4 http://mail.google.com/mail/images/generic.gif image/gif 200
4 http://mail.google.com/mail/images/zip.gif image/gif 200
4 http://mail.google.com/mail/images/html2.gif image/gif 200
4 http://mail.google.com/mail/images/txt.gif image/gif 200
CACHE MANIFEST
# version: 3f1b9s84
jsfile1.js
... other URLs ...
CACHE MANIFEST
jsfile1.js
NETWORK:
/images/
FALLBACK:
/thumbnails/ images/missing_thumb.jpg
if (window.applicationCache.status == 0) {
// Page was loaded from the Network.
} else {
// Page was loaded from AppCache
}
CACHE MANIFEST
jsfile1.js
jsfile2.js
styles.css
/images/image1.png
/images/image2.png
It is important to note that it is not necessary to list the URL of the main webpage in the manifest because it is treated as an implicit entry. However, if you have more than one top level URL that you want to be available offline, they must all be listed in the manifest. In addition, they must all set a manifest attribute on the HTML tag that points to the manifest. For example, if the manifest URL was "/sitemanifest", then each page in the site would have an HTML tag that looked like this:<html manifest="/sitemanifest">
Finally, the manifest must be served using the content type "text/cache-manifest". And that's it!