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



HTML5Rocks


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.


Precision Touch for Precise Gestures

A change landed in the implementation of Chrome's TouchEvents as of M37 (stable in 08/2014), which alters the reported co-ordinates to floats instead of integers.

Before After
clientX: 167
clientY: 196
pageX:   167
pageY:   196
radiusX: 26
radiusY: 26
screenX: 167
screenY: 277
clientX: 167.33299255371094
clientY: 195.66700744628906
pageX:   167.33299255371094
pageY:   195.66700744628906
radiusX: 25.843116760253906
radiusY: 25.843116760253906
screenX: 167.33334350585938
screenY: 276.66668701171875

The result of this change means you have a smoother response to the users gestures as it gives you higher accuracy of the fingers position.

Using Rick Byers' demo, you can see what a huge difference this can make when slowly drawing a swirl.

Differences in Touch Events

This will only make affect screens which have a pixel density greater than 1. To understand why, let's step through an example.

Imagine you have a 3x3 grid of CSS pixels and the screen density is 3, meaning we have a grid of 9x9 physical pixels and the user gestures from the top left to the bottom right.

CSS Pixel and Screen Pixel Grid

Originally, we were rounding the touches position to the nearest CSS pixel, which meant in this gesture you would end up with the following steps.

CSS Pixel Precision During Gesture

We miss out on drawing any of the intermediate steps that the physical pixels could show as the user moves their finger.

Now that we've switched to floats, our gesture can look like this.

Float Precision During Gesture

In most cases, this won't require any changes in your code, but does mean any animations or movements you do as a result of TouchEvents, will be smoother, especially for slow gestures.

There is also plan to bring this improvement to mobile Safari as well: https://bugs.webkit.org/show_bug.cgi?id=133180.


Built-in Browser Support for Responsive Images

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


Collecting and Iterating, the ES6 Way

The ECMAScript 6 specification, while still in draft form, brings the promise of many exciting new tools to add to the JavaScript programmer?s belt. New classes such as Set and Map offer native solutions to working with specific types of collections, and the for...of statement provides an elegant alternative to traditional ways of iterating over data.

Sets offer a way of keeping track of a collection of items in which each item can appear at most once. Maps offer more functionality than was previously possible by using Objects to associate keys with values?with a Map, your keys don?t have to be strings, and you don?t have to worry about accidentally choosing a key name that clashes with an Object?s method names. Lookup operations on native Maps and Sets are done in constant time, which offers efficiency gains over what?s possible with simulated implementations.

The following sample demonstrates constructing a Set, and using for...of to iterate over its elements:

<pre id="log"></pre>

<script>
  function log() {
    document.querySelector('#log').textContent += Array.prototype.join.call(arguments, '') + '\n';
  }

  log('Creating, using, and iterating over a Set:');
  var randomIntegers = new Set();
  // Generate a random integer in the range [1..10] five times,
  // and use a Set to keep track of the distinct integers that were generated.
  for (var i = 0; i < 5; i++) {
    randomIntegers.add(Math.floor(Math.random() * 10) + 1);
  }
  log(randomIntegers.size, ' distinct integers were generated.');
  log('The number 10 was ', randomIntegers.has(10) ? '' : 'not ', 'one of them.');
  log('Here\'s all of them:');
  // Use for...of to iterate over the items in the Set.
  // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-iteration-statements
  // The Set iterator yields a single value corresponding to each entry in the Set.
  for (var item of randomIntegers) {
    log(item);
  }
</script>

Here?s a corresponding sample that illustrates using and iterating over a Map:

<script>
  log('\nCreating and iterating over a Map:');
  // Maps can be initialized by passing in an iterable value (https://people.mozilla.org/~jorendorff/es6-draft.html#sec-map-iterable)
  // Here, we use an Array of Arrays to initialize. The first value in each sub-Array is the new
  // Map entry's key, and the second is the item's value.
  var typesOfKeys = new Map([
    ['one', 'My key is a string.'],
    ['1', 'My key is also a string'],
    [1, 'My key is a number'],
    [document.querySelector('#log'), 'My key is an object']
  ]);
  // You can also call set() to add new keys/values to an existing Map.
  typesOfKeys.set('!!!!', 'My key is excited!');

  // Use for...of to iterate over the items in the Map.
  // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-iteration-statements
  // There are several types of Map iterators available.
  // typesOfKeys.keys() can be used to iterate over just the keys:
  log('Just the keys:');
  for (var key of typesOfKeys.keys()) {
    log('  key: ', key);
  }

  // typesOfKeys.values() can be used to iterate over just the values:
  log('Just the values:');
  for (var value of typesOfKeys.values()) {
    log('  value: ', value);
  }

  // The default Map iterator yields an Array with two items; the first is the Map entry's key and the
  // second is the Map entry's value. This default iterator is equivalent to typesOfKeys.entries().
  log('Keys and values:');
  // Alternative, ES6-idiomatic syntax currently supported in Safari & Firefox:
  // for (var [key, value] of typesOfKeys) { ? } 
  for (var item of typesOfKeys) {
    log('  ', item[0], ' -> ', item[1]);
  }
</script>

Some browsers, like Chrome, Internet Explorer, and Firefox have already added support for Sets and Maps. Native support complemented by polyfill libraries like es6-collections or es6-shim means that JavaScript developers can start building with these new collection types today. There are no polyfills available for the for...of statement (though it is possible to transpile support via Traceur), but native support is available today in Chrome and Firefox.

Update, September 2014: Linked to an additional polyfill option, es6-shim


Easier ArrayBuffer <-> String conversion with the Encoding API

Over two years ago, Renato Mangini described a method for converting between raw ArrayBuffers and the corresponding string representation of that data. At the end of the post, Renato mentioned that an official standardized API to handle the conversion was in the process of being drafted. The specification has now matured, and both Firefox and Google Chrome have added native support for the TextDecoder and TextEncoder interfaces.

As demonstrated by this live sample, excerpted below, the Encoding API makes it simple to translate between raw bytes and native JavaScript strings, regardless of which of the many standard encodings you need to work with.

<pre id="results"></pre>

<script>
  if ('TextDecoder' in window) {
    // The local files to be fetched, mapped to the encoding that they're using.
    var filesToEncoding = {
      'utf8.bin': 'utf-8',
      'utf16le.bin': 'utf-16le',
      'macintosh.bin': 'macintosh'
    };

    Object.keys(filesToEncoding).forEach(function(file) {
      fetchAndDecode(file, filesToEncoding[file]);
    });
  } else {
    document.querySelector('#results').textContent = 'Your browser does not support the Encoding API.'
  }

  // Use XHR to fetch `file` and interpret its contents as being encoded with `encoding`.
  function fetchAndDecode(file, encoding) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', file);
    // Using 'arraybuffer' as the responseType ensures that the raw data is returned,
    // rather than letting XMLHttpRequest decode the data first.
    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {
      if (this.status == 200) {
        // The decode() method takes a DataView as a parameter, which is a wrapper on top of the ArrayBuffer.
        var dataView = new DataView(this.response);
        // The TextDecoder interface is documented at http://encoding.spec.whatwg.org/#interface-textdecoder
        var decoder = new TextDecoder(encoding);
        var decodedString = decoder.decode(dataView);
        // Add the decoded file's text to the <pre> element on the page.
        document.querySelector('#results').textContent += decodedString + '\n';
      } else {
        console.error('Error while requesting', file, this);
      }
    };
    xhr.send();
  }
</script>

The sample above uses feature detection to determine whether the required TextDecoder interface is available in the current browser, and displays an error message if it?s not. In a real application, you would normally want to fall back on an alternative implementation if native support isn?t available. Fortunately, the text-encoding library that Renato mentioned in his original article is still a good choice. The library uses the native methods on browsers that support them, and offers polyfills for the Encoding API on browsers that haven?t yet added support.

Update, September 2014: Modified the sample to illustrate checking whether the Encoding API is available in the current browser.


Web Audio Changes in m36

Web Audio changes

At Google, we love standards. We?re on a mission to build out the standards-defined Web platform. One of the small warts on that for some time has been the webkit- prefixed implementation of the Web Audio API (notably the webkitAudioContext object), and some of the deprecated bits of Web Audio that we?ve continued to support.

It was originally planned that m36 would remove support for the prefixed webkitAudioContext, since we had begun supporting the unprefixed AudioContext object. This turned out to be more troublesome than expected, so m36 supports both unprefixed and prefixed - however, even in the reintroduced webkitAudioContext, several legacy methods and attributes like createGainNode and createJavaScriptNode have been removed. In short, in m36 webkitAudioContext and AudioContext are aliases of each other; there is no difference in functionality between the two.

We will remove the support for the prefix completely after m36, likely in a couple of releases. We'll make an announcement here when the change is imminent, and we are continuing to reach out to authors to fix their Web Audio applications.

Why have we done this, rather than reverting to the previous implementation? Well, in part, we?ve been reticent to move too far backwards; we?ve already removed those APIs, and as a nice side-effect to this aliasing, applications can then work nicely on Firefox, which has never supported a prefixed AudioContext object (and quite right, too!) in their Web Audio support initially released last fall.

The rest of this update provides a guide to fixing things that may be broken in your code due to this change. The great thing about fixing these problems is that your code is then quite likely to just work in Firefox, too! (I?d thought for a long time that my Vocoder application was broken due to Firefox?s implementation, but it turned out to be one of these problems!)

If you just want to get up and running, you may want to take a look at a monkey-patch library I wrote for applications that were written to the old Web Audio code - this can help you get up and running in a minimum amount of time, as it will alias the objects and methods appropriately. Indeed, the patches the library lists is a good guide to the things that have changed.

First and foremost:

Any references to window.webkitAudioContext should be made to window.AudioContext instead. Frequently, this has been fixed with a simple:

window.AudioContext = window.AudioContext || window.webkitAudioContext;

If your app is responding with something like ?Unfortunately, your browser does not support Web Audio. Please use Chrome or Safari.? - it?s quite likely explicitly looking for webkitAudioContext. Bad developer! You could have been supporting Firefox for months!

But there are a few other, more subtle code removals, some of which can be less obvious.

  • The BiquadFilter enumerated type constants for the .type attribute (which is now a string) no longer appear on the BiquadFilterNode object, and we do not support them on the .type attribute. So you don?t use .LOWPASS (or 0) anymore - you set it to ?lowpass?.
  • Also, the Oscillator.type attribute is similarly now a string enumerated type - no more .SAWTOOTH.
  • PannerNode.type is also now a string enumerated type.
  • PannerNode.distanceModel is also now a string enumerated type.
  • createGainNode was renamed to createGain
  • createDelayNode was renamed to createDelay
  • createJavaScriptNode was renamed to createScriptProcessor
  • AudioBufferSourceNode.noteOn() is now replaced by start()
  • AudioBufferSourceNode.noteGrainOn() is also now replaced by start()
  • AudioBufferSourceNode.noteOff() is renamed to stop()
  • OscillatorNode.noteOn() is renamed to start()
  • OscillatorNode.noteOff() is renamed to stop()
  • AudioParam.setTargetValueAtTime() is renamed to setTargetAtTime()
  • `AudioContext.createWaveTable()andOscillatorNode.setWaveTable()are now renamedcreatePeriodicWave() and setPeriodicWave().
  • AudioBufferSourceNode.looping was removed, in favor of .loop
  • AudioContext.createBuffer(ArrayBuffer, boolean) to synchronously decode a blob of encoded audio data has been removed. Synchronous calls that take a long time to complete are poor coding practice; use the asynchronous decodeAudioData call instead. This is one of the more challenging changes - you need to actually change logic flow - but a far better practice. Mozilla's Ehsan Angkari wrote a nice example of how to do this in their post on converting to standard Web Audio.

Many of these (like the renaming of createGainNode, and the removal of the synchronous decoding in createBuffer) will obviously show up in the developer tools console as an error - however, some others, like this usage:

myFilterNode.type = myFilterNode.BANDPASS;

will not show up at all, and silently fail (myFilterNode.BANDPASS will now resolve to undefined, and the attempt to set .type to undefined will simply fail to produce any effect. This, by the way, was what was causing the vocoder to fail.) Likewise, just assigning the filter.type to a number used to work:

myFilterNode.type = 2;

But now, you need to use the string enumeration:

myFilterNode.type = ?bandpass?;

So, you may wish to grep your code for the following terms:

  • webkitAudioContext
  • .LOWPASS
  • .HIGHPASS
  • .BANDPASS
  • .LOWSHELF
  • .HIGHSHELF
  • .PEAKING
  • .NOTCH
  • .ALLPASS
  • .SINE
  • .SQUARE
  • .SAWTOOTH
  • .TRIANGLE
  • .noteOn
  • .noteGrainOn
  • .noteOff
  • .setWaveTable
  • .createWaveTable
  • .looping
  • .EQUALPOWER
  • .HRTF
  • .LINEAR
  • .INVERSE
  • .EXPONENTIAL
  • createGainNode
  • createDelayNode
  • .type (yes, this will have lots of false positives - but it?s the only way to catch the last example above!)

Once more, if you're in a hurry and want to get up and running, just grab a copy of my monkeypatch webkitAudioContext library and include it in your application. Happy Audio Hacking!


dialog element: shipped in Chrome 37 Beta

Chrome Beta has landed its native support for <dialog> element without needing "Enable experimental Web Platform features." flag turned on.

<dialog>
  <p>This is da dialog!</p>
  <button id="close">Close</button>
</dialog>
<button id="show">Open Dialog!</button>
<script>
  var dialog = document.querySelector('dialog');
  document.querySelector('#show').onclick = function() {
    dialog.show();
  };
  document.querySelector('#close').onclick = function() {
    dialog.close();
  };
</script>

Check out more sample codes and how it works in detail with a live demo.

There are a few changes applied to the implementation since the last announcement but notable one is:

  • Non-modal <dialog> is no longer vertically centered in the viewport. It has no special positioning behavior beyond its default CSS styling.

If you are curious about further details on the spec update, check out diffs here and here.


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.


Data-binding Revolutions with Object.observe()

Learn about Object.observe() - a new feature giving JavaScript the power to directly observe changes to objects.


Debugging Asynchronous JavaScript with Chrome DevTools

Up your JavaScript debugging kung fu with asynchronous call stack traces in the Chrome DevTools.



@2014 CompCoding.com