Computer Coding
Home |  ColdFusion |  IBM |  Java |  JavaScript |  Spring |  Misc |  Sign in



HTML5Rocks


DevTools Timeline: Now Providing the Full Story

The DevTools Timeline panel has always been the best first stop on the path to performance optimization. This centralized overview of your app?s activity helps you analyze where time is spent on loading, scripting, rendering, and painting. Recently, we?ve upgraded the Timeline with more instrumentation so that you can see a more in-depth view of your app?s performance.

We?ve added the following features:

Note that using the Paint capture options described in this article do incur some performance overhead, so flip them on only when you want ?em.

Integrated JavaScript Profiler

If you?ve ever poked around in Profiles panel, you?re probably familiar with the JavaScript CPU profiler. This tool measures where execution time is spent in your JavaScript functions. By viewing JavaScript profiles with the Flame Chart, you can visualize your JavaScript processing over time.

Now, you can get this granular breakdown of your JavaScript execution in the Timeline panel. By selecting the JS Profiler capture option, you can see your JavaScript call stacks in the Timeline along with other browser events. Adding this feature to the Timeline helps streamline your debugging workflow. But more than that, it allows you to view your JavaScript in context and identify the parts of your code that affect page load time and rendering.

In addition to the JavaScript profiler, we also integrated a Flame Chart view into the Timeline panel. You can now view your app?s activity either as the classic waterfall of events or as a Flame Chart. The Flame Chart icon allows you to toggle between these two views.

JavaScript Profiler on Timeline Using the JS Profiler capture option and Flame Chart view to investigate call stacks in the Timeline.

Tip: Use WASD to zoom and pan through the Flame Chart. Shift-drag to draw a selection box.

Frame Viewer

The art of layer compositing is another aspect of the browser that has been mostly hidden from developers. When used sparingly and with care, layers can help avoid costly re-paints and yield huge performance boosts. But it?s often not obvious to predict how the browser will composite your content. Using the Timeline?s new Paint capture option, you can visualize composited layers at each frame of a recording.

When you select a gray frame bar above the Main Thread, its Layers panel provides a visual model of the layers that compose your app.

Tip: Play back animations by clicking through frame bars on a Timeline recording.

You can zoom, rotate, and drag the layers model to explore its contents. Hovering over a layer reveals its current position on the page. Right-clicking on a layer lets you jump to the corresponding node in the Elements panel. These features show you what was promoted to a layer. If you select a layer, you can also see why it was promoted in the row labeled Compositing Reasons.

Compositing Reasons Inspecting a layer from Codrops' Scattered Polaroids Gallery to reveal the browser?s reasons for compositing.

Paint Profiler

Last but not least, we?ve added the paint profiler to help you identify jank caused by expensive paints. This feature enriches the Timeline with more details about the work Chrome does during paint events.

For starters, it?s now easier to identify the visual content corresponding to each paint event. When you select a green paint event in the Timeline, the Details pane shows you a preview of the actual pixels that were painted.

Paint capture option Previewing pixels that the browser painted using the Paint capture option.

If you really want to dive in, switch over to the Paint Profiler pane. This profiler shows you the exact draw commands that the browser executed for the selected paint. To help you connect these native commands with actual content in your app, you can right-click on a draw* call and jump straight to the corresponding node in the Elements panel.

Paint capture option Relating native browser draw* calls to DOM elements using the Paint Profiler.

The mini-timeline across the top of the pane lets you play back the painting process and get a sense of which operations are expensive for the browser to perform. Drawing operations are color-coded as follows: pink (shapes), blue (bitmap), green (text), purple (misc.). Bar height indicates call duration, so investigating tall bars can help you understand what about a particular paint was costly.

Profile and profit!

When it comes to performance optimization, knowledge of the browser can be incredibly powerful. By giving you a peek under the hood, these Timeline updates help clarify the relationship between your code and Chrome?s rendering processes. Try out these new options in the Timeline and see what Chrome DevTools can do to enhance your jank-hunting workflow!


Permissions API for the Web

If you?ve worked with the Geolocation API before, chances are you?ve wanted to check if you had permission to use Geolocation without causing a prompt. This simply wasn?t possible. You had to request the current position and this would indicate the permission state or cause a prompt to be shown to the user.

Not all APIs work this way. The Notifications API has its own way of allowing you to check the current permission state via Notification.permission.

As the web platform grows in API?s, there needs to be a single, standard way for developers to check the status of a permission rather than having to remember how each and every API works. The Permission API, available in Chrome version 43, is intended to be this single, standard way to check the permission status of an API.

permissions.query()

Check the status of a permission using the permissions.query() method. This will return a status of granted (you have permission), denied (you are blocked from accessing the API) or prompt (user needs to be prompted). For example:

// Check for Geolocation API permissions  
navigator.permissions.query({name:'geolocation'}).then(function(permissionStatus) 
{  
  console.log('geolocation permission status is ', permissionStatus.status);  
  permissionStatus.onchange = function() {  
    console.log('geolocation permission status has changed to ', this.status);  
  };
});

The query method takes a PermissionDescriptor object, where you define the permission?s name. The response is a Promise resolving to a PermissionStatus object. From this object, you can check the status with permissionStatus.status for ?granted?, ?denied? or ?prompt?. You can also also implement an event handler for permissionStatus.onchange and handle changes to the permission status of an API.

Supported PermissionDescriptors

In the above example, we highlight how to query the permission state for geolocation with the following permission descriptor: {name:'geolocation'}.

The Notification permission descriptor is similar in that it only requires a name attribute: {name:'notifications'}.

Push and midi each have an additional parameter that is specific to that API.

For the push permission, you can supply a userVisible parameter. This indicates whether you wish to show a notification for every push message or be able to send silent push notifications (At the moment Chrome only supports push messages with notifications). You?d use it like so:

navigator.permissions.query({name:'push', userVisible:true})

Midi allows a sysex parameter. This indicates whether you need to and/or receive system exclusive messages. For midi this would be:

navigator.permissions.query({name:'midi', sysex:true})

Requesting Permissions

Requesting permission from the user depends on the specific API. For example, geolocation would show a permission prompt when you call getCurrentPosition().

navigator.geolocation.getCurrentPosition(function(position) {  
  console.log('Geolocation permissions granted');  
  console.log('Latitude:' + position.coords.latitude);  
  console.log('Longitude:' + position.coords.longitude);  
});

Whereas notifications would prompt the user when you call requestPermission().

Notification.requestPermission(function(result) {  
  if (result === 'denied') {  
    console.log('Permission wasn\'t granted. Allow a retry.');  
    return;  
  } else if (result === 'default') {  
    console.log('The permission request was dismissed.');  
    return;  
  }  
  console.log('Permission was granted for notifications');  
});

The point here is that the Permission API allows a consistent way to monitor the status of permissions while being able to support the range of APIs currently on the web.

The big advantage of this is that it allows you to build better experiences for your users, only prompting when it?s obvious to the user why you need extra privileges and taking full advantage of these APIs when you know you have been granted permission.

You can find a full set of examples here.

Browser Support

Chrome is the first browser to implement this, Mozilla are planning on shipping this, and Microsoft have shown interest in the API.

Known Issues

  • Geolocation will not re-show a prompt if the user dismisses the permission request. The permission status however remains ?prompt?. [crbug.com/476509]

Cut and Copy Commands

IE10 and above added support for the ?cut? and ?copy? commands through the Document.execCommand() method. As of Chrome version 43, these commands are also supported in Chrome.

Any text selected in the browser when one of these commands is executed will be cut or copied to the user?s clipboard. This lets you offer the user a simple way to select a portion of text and copy it to the clipboard.

This becomes extremely useful when you combine it with the Selection API to programmatically select text to determine what is copied to the clipboard, which we?ll be looking at in more detail later on in this article.

Simple Example

For example?s sake, let?s add a button which copies an email address to the user?s clipboard.

We add the email address in our HTML with a button to initiate the copying when it?s clicked:

<p>Email me at <a class="js-emaillink" href="mailto:matt@example.co.uk">matt@example.co.uk</a></p>

<p><button class="js-emailcopybtn"><img src="./images/copy-icon.png" /></button></p>

Then in our JavaScript, we want to add a click event handler to our button in which we select the email address text from the js-emaillink anchor, execute a copy command so that the email address is in the user?s clipboard and then we deselect the email address so the user doesn?t see the selection occur.

var copyEmailBtn = document.querySelector('.js-emailcopybtn');  
copyEmailBtn.addEventListener('click', function(event) {  
  // Select the email link anchor text  
  var emailLink = document.querySelector('.js-emaillink');  
  var range = document.createRange();  
  range.selectNode(emailLink);  
  window.getSelection().addRange(range);  
    
  try {  
    // Now that we've selected the anchor text, execute the copy command  
    var successful = document.execCommand('copy');  
    var msg = successful ? 'successful' : 'unsuccessful';  
    console.log('Copy email command was ' + msg);  
  } catch(err) {  
    console.log('Oops, unable to copy');  
  }  
    
  // Remove the selections - NOTE: Should use   
  // removeRange(range) when it is supported  
  window.getSelection().removeAllRanges();  
});

What we are doing here is using a method of the Selection API, window.getSelection() to programmatically set the ?selection? of text to the anchor, which is the text we want to copy to the user?s clipboard. After calling document.execCommand() we can remove the selection by calling window.getSelection().removeAllRanges().
If you wanted to confirm everything worked as expected you can examine the response of document.execCommand(); it returns false if the command is not supported or enabled. We wrap execCommand() in a try and catch since the ?cut? and ?copy? commands can throw an error in a few scenarios.

The ?cut? command can be used for text fields where you want to remove the text content and make it accessible via the clipboard.

Using a textarea and a button in our HTML:

<p><textarea class="js-cuttextarea">Hello I'm some text</textarea></p>
  
<p><button class="js-textareacutbtn" disable>Cut Textarea</button></p>

We can do the following to cut the content:

var cutTextareaBtn = document.querySelector('.js-textareacutbtn');

cutTextareaBtn.addEventListener('click', function(event) {  
  var cutTextarea = document.querySelector('.js-cuttextarea');  
  cutTextarea.select();

  try {  
    var successful = document.execCommand('cut');  
    var msg = successful ? 'successful' : 'unsuccessful';  
    console.log('Cutting text command was ' + msg);  
  } catch(err) {  
    console.log('Oops, unable to cut');  
  }  
});

queryCommandSupported and queryCommandEnabled

Ahead of calling document.execCommand(), you should ensure that this API is supported using the document.queryCommandSupported() method. In our example above we could set the button disabled state based on support like so:

copyEmailBtn.disabled = !document.queryCommandSupported('copy');

The difference between document.queryCommandSupported() and document.queryCommandEnabled() is that cut and copy could be supported by a browser, but if no text is currently selected, they won?t be enabled. This is useful in scenarios where you aren?t setting the selection of text programmatically and want to ensure the command will do as expected, otherwise present a message to the user.

Browser Support

IE 10+, Chrome 43+, and Opera 29+ support these commands.

Firefox supports this but requires a preference change (See cut and copy commands here). Without this Firefox throws an error.

Safari does not support these commands.

Known Bugs


DOM Attributes now on the prototype chain

The Chrome team recently announced that we are moving DOM properties to the prototype chain. This change, implemented in Chrome 43 - (Beta as of mid April 2015) - brings Chrome more in line with the Web IDL Spec and other browsers? implementations, such as IE and Firefox. Edit: clarified   Older WebKit based browsers, are currently not compatible with the spec, however Safari now is.

Clarification: The use of the word Attribute and Property are used interchangeably in this post, the ECMA Script spec defines ?Properties? that have ?Attributes?. A JS property is a ?WebIDL Attribute?. An Attribute in this article is not an HTML Attribute such as class on an image element.

The new behavior is positive in many ways. It:

  • Improves compatibility across the web (IE and Firefox do this already) via compliance with the spec.
  • Allows you to consistently and efficiently create getters/setters on every DOM Object.
  • Increases the hackability of DOM programming. For example, it will enable you to implement polyfills that allow you to efficiently emulate functionality missing in some browsers and JavaScript libraries that override default DOM attribute behaviors.

For example, a hypothetical W3C specification includes some new functionality called isSuperContentEditable and the Chrome Browser doesn?t implement it, but it is possible to ?polyfill? or emulate the feature with a library. As the library developer, you would naturally want to use the prototype as follows to create an efficient polyfill:

Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
  get: function() { return true; },
  set: function() { /* some logic to set it up */ },
});

Prior to this change ? for consistency with other DOM properties in Chrome ? you would have had to create the new property on every instance, which for every HTMLDivElement on the page would be very inefficient.

These changes are important for consistency, performance and standardization of the web platform, yet they can cause some issues for developers. If you were relying on this behavior because of legacy compatibility between Chrome and WebKit we encourage you to check your site and see the summary of changes below.

Summary of changes

Using hasOwnProperty on a DOM Object instance will now return false

Sometimes developers will use hasOwnProperty to check for presence of an property on an object. This will no longer work as per the spec because DOM attributes are now part of the prototype chain and hasOwnProperty only inspects the current objects to see if it is defined on it.

Prior to and including Chrome 42 the following would return true.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

true

In Chrome 43 onwards it will return false.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

false

This now means if you want to check that isContentEditable is available on the element you will to have check the prototype on the HTMLElement object. For example HTMLDivElement inherits from HTMLElement which defines the isContentEditable property.

> HTMLElement.prototype.hasOwnProperty("isContentEditable");

true

You are not locked in to using hasOwnProperty. We recommend to use the much simpler in operand as this will check property on the entire prototype chain.

if("isContentEditable" in div) {
  // We have support!!
}

Object.getOwnPropertyDescriptor on DOM Object Instance will no longer return a property descriptor for Attributes.

If your site needs to get the property descriptor for an attribute on a DOM Object, you will now need to follow the prototype chain.

If you wanted to get the property description in Chrome 42 and earlier you would have done:

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

Object {value: "", writable: true, enumerable: true, configurable: true}

Chrome 43 onwards will return undefined in this scenario.

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

undefined

Which means to now get the property descriptor for the ?isContentEditable? property you will need to follow the prototype chain as follows:

> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");

Object {get: function, set: function, enumerable: false, configurable: false}

JSON.stringify will no longer serialize DOM Attributes

JSON.stringify doesn?t serialize DOM properties that are on the prototype. For example, this can affect your site if you are trying to serialize an object such as Push Notification?s PushSubscription.

Chrome 42 and earlier the following would have worked:

> JSON.stringify(subscription);

{
  "endpoint": "https://something",
  "subscriptionId": "SomeID"
}

Chrome 43 onwards will not serialize the properties that are on defined on the protoype and you will be returned an empty object.

> JSON.stringify(subscription);

{}

You will have to provide your own serialization method, for example you could do the following:

function stringifyDOMObject(object)
{
    function deepCopy(src) {
        if (typeof src != "object")
            return src;
        var dst = Array.isArray(src) ? [] : {};
        for (var property in src) {
            dst[property] = deepCopy(src[property]);
        }
        return dst;
    }
    return JSON.stringify(deepCopy(object));
}
var s = stringifyDOMObject(domObject);

Writing to read-only properties in strict mode will throw an error

Writing to read-only properties is supposed to throw an exception when you are using strict mode. For example, take the following:

function foo() {
  "use strict";
  var d = document.createElement("div");
  console.log(d.isContentEditable);
  d.isContentEditable = 1;
  console.log(d.isContentEditable);
}

Chrome 42 and earlier the function would have continued and silently carried on executing the function, although isContentEditable would have not been changed.

// Chrome 42 and earlier behavior
> foo();

false // isContentEditable
false // isContentEditable (after writing to read-only property)

Now in Chrome 43 and onwards there will be an exception thrown.

// Chrome 43 and onwards behavior
> foo();

false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter

I have a problem, what should I do?

Follow the guidance, or leave a comment below and let?s talk.

I have seen a site with a problem, what should I do?

Great question. Most issues with sites will be based on the fact a site has chosen to do Attribute presence detection with the getOwnProperty method, this is mostly done when a site owner has only targeted older WebKit browsers. There are a couple of things that a developer can do:

  • File an issue about the affected site on our (Chrome?s) issue tracker
  • File an issue on WebKit radar and reference https://bugs.webkit.org/show_bug.cgi?id=49739

I am generally interested in following this change


Simplified Concepts in Web Animations Naming

Native support for Web Animations first shipped in Chrome 36, and was updated with playback control in Chrome 39. The Element.animate() method can be used to trigger imperative animations directly from JavaScript, and its returned object can be leveraged to control the playback of these animations. These methods are detailed in the current draft of the Web Animations W3C spec.

There?s a shipped polyfill under active development that tracks all Web Animations features implemented natively, and which is supported in all modern browsers. These core methods are ready for use right now, and deserve to be part of your toolbox for building rich experiences that benefit from animations (such as for the Google I/O 2015 web app).

Constructor and groups changes

The Web Animations spec also describes groups and sequences, and constructors for animations and players. These have been available in the web-animations-next polyfill, which has been designed to showcase features still undergoing discussion and yet to be implemented natively. In response to developer feedback, the team developing Web Animations are renaming these features to be more self-explanatory.

The FXTF recently met in Sydney, Australia, and discussed naming, as a number of developers raised valid points about some of the naming being confusing. As a result, the following naming changes were agreed on:

  • Animation becomes KeyframeEffect
  • AnimationSequence becomes SequenceEffect
  • AnimationGroup becomes GroupEffect
  • AnimationPlayer becomes Animation

Remember that while animations and their players are available natively in Chrome and as part of the polyfill, they are currently created directly via the Element.animate() method. Existing code that uses the Element.animate() method will require no changes.

The new names more accurately represent the behavior provided by each object. KeyframeEffect, for instance, describes keyframe-based effects that can target HTML elements. In contrast, the new Animation object represents an animation in one of many states (such as playing, paused etc).

SourceCodeEffect

If you?re using parts of the draft spec via the web-animations-next polyfill, you?ll have to update your code within the deprecation period to reflect these new names. As per the polyfill changes policy, we aim to support an old version for three months and provide console warning statements if your site use deprecated features or names.

If you?re keen to try out these features, then watch out for the v2 release of the polyfill to take advantage of these new names. Finally, be sure to subscribe to the web-animations-changes group to hear about any other changes.


Introduction to Service Worker: How to use Service Worker

Service Worker will revolutionize the way we build for the web. Learn about what it is, why it is important and how to use it.


The Hobbit Experience 2014: Adding WebRTC gameplay to the Hobbit Experience

Learn how North Kingdom built an immersive multimedia experience optimized for modern mobile browsers using Web RTC


Getting Started with CSS Shapes: Wrapping content around custom paths

Using CSS Shapes we can create experiences that we have never been able to create on the web before.


Built-in Browser Support for Responsive Images

Take advantage of the new element and new features of in your next responsive website.


DevTools Digest - Chrome 35: Updates to the Developer Tools in Chrome 35

Updates to the Chrome Developer Tools: CSS property quick search, memory stats for heap snapshots, CodeMirror upgrade and more.



@2014 CompCoding.com