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
Deroy |
Sergio |
alt="{diagram}"
and the like.Last month, just before I left on vacation, I posted three sets of data to help implementors of the HTML5 parser specification optimise their code. There are several implementations coming along, for example those that are part of the html5lib project and the one behind Validator.nu.
The three sets of data that I posted are all derived from parsing several billion documents from Google's Web search index using a parser I wrote in Sawzall.
The first set of data gives the relative aggregate distribution of invocations of the "in head", "in body", and "in table" insertion modes, for each of the insertion modes. This allows implementors to determine, for instance, that invoking the "in body" code while in a cell must be very efficient, while invoking the "in body" code from the "after frameset" code need not be as efficient, in case the implementor has a strategy that optimises one at the cost of another. See: documentation, data.
The second set of data gives the relative aggregate distribution of tokens for each phase/insertion mode pair. This can help implementors that are using a cascade of if
statements decide on the right order for their statements. For instance, the most common token type seen in the "in body" insertion mode is character data, and the second most token is the start tag token for an a
element, but the isindex
start tag was almost never seen. This tells implementors that they should check for characters and a
start tags long before checking for isindex
tags. See: documentation, data.
The last set of data examines the number of attributes per element. It allows implementors to decide on the optimum memory allocation strategy for attributes. For example, since most elements have 9 or fewer attributes, the data structure that stores attributes can be optimised for simply having 9 attributes, using little memory, and if an element has more than this number of attributes, the implementation can switch to a separate implementation that is more memory-heaving but is optimised for large numbers of attributes. See: data.
I hope this data is useful!
2013, By: Seo Masterfunction 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
drawImage()
method allows us to draw only a certain part of a tileset or animation sheet to the screen. In Impact, however, you don't have to deal with any of the Canvas API methods directly. Instead, you specify your tilemaps and animation sheets and let the engine handle the details.// Each animation frame is 16x16 pixelsSimilarly, here's the code needed to create and draw a background layer:
var sheet = new ig.AnimationSheet( 'player.png', 16, 16 );
// This creates the "run" animation: it has 6 frames (the 2nd row
// in the image), with each one being shown for 0.07 seconds
var run = new ig.Animation( sheet, 0.07, [6,7,8,9,10,11] );
// Create a 2D tilemapYou don't have to create these tilemaps by hand. Impact comes with a powerful level editor called Weltmeister, which makes it easy to draw background layers and position your entities (non-static objects in the game world) in your levels.
var map = [
[5, 3, 4],
[2, 7, 1],
[6, 0, 3]
];
// Specify a layer with a tilesize of 16px and our tilemap
var layer = new ig.BackgroundMap( 16, map, 'tileset.png' );
layer.draw();
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!