Wednesday, July 4, 2012

animateObjectFromTo

This method will animate an object from a given left, top to another left, top over a specified number of milliseconds at a specified frame rate. This is an example of how it might be called:
  var myDiv = document.getElementById('myDiv),
      currentPosition = window.getComputedStyle(myDiv,null),
      currentLeft     = parseFloat(currentPosition["left"]),
      currentTop      = parseFloat(currentPosition["top"]);
  animateObjectFromTo( 
    myDiv, 
    { top:currentTop, left:currentLeft }, 
    { top:0, left:currentLeft }, 
    250 
  );
    /////////////////////////////////////////////////////////////////////////////////////////
// animateObjectFromTo([object|string] oHTMLElement, json From, json To, int totalTimeInMilliseconds, OPTIONAL int framesPerSecond)
    //   Sets up an animation that interpolates frame animation from a beginning top, left coordinate
    //   to an ending top, left coordinate over a number of milliseconds at a specified frame rate
    //      totalTimeInMilliseconds - default is 1 second
    //      framesPerSecond - default is 30
    /////////////////////////////////////////////////////////////////////////////////////////
    animateObjectFromTo : function(oHTMLElement, from, to, totalTimeInMilliseconds, framesPerSecond) {
      if (typeof(oHTMLElement)=="string")  {  oHTMLElement = document.getElementById(oHTMLElement); }
      totalTimeInMilliseconds = totalTimeInMilliseconds || 1000;
      framesPerSecond = framesPerSecond || 30;
      var currentFrame      = 0,
          numberOfFrames    = parseInt(totalTimeInMilliseconds / framesPerSecond),
          deltaTimePerFrame = totalTimeInMilliseconds/numberOfFrames,
          deltaXPerFrame    = (to.left - from.left)/numberOfFrames || 0,
          deltaYPerFrame    = (to.top - from.top)/numberOfFrames || 0;
      
      animate();

      function animate() {
        if (currentFrame<numberOfFrames) {
          var oCurrentStyle = document.defaultView.getComputedStyle(oHTMLElement, null);
          oHTMLElement.style.left = parseFloat(oCurrentStyle["left"]) + deltaXPerFrame + "px";
          oHTMLElement.style.top  = parseFloat(oCurrentStyle["top"]) + deltaYPerFrame + "px";
          currentFrame += 1;
          console.log('top is now: ' + parseFloat(oCurrentStyle["top"]) + deltaYPerFrame + "px")
          setTimeout( function() { animate(); }, deltaTimePerFrame );
        }
      }

Friday, June 22, 2012

Javascript String Length

Javascript does not provide way to get at the pixel width of a string. There is, of course, the getComputedStyle method, but I wanted another way. This method uses <CANVAS>'s measureText method and accounts for current fontFamily and fontSize:
////////////////////////////////////////////////////////////////////////////////
//
// String.width(OPTIONAL string fontSize, OPTIONAL string fontFamily)
// ==================================================================
// Measures the length of a string, in pixels, using CANVAS's measureText method
// By passing in fontSize and FontFamily, you will get accurate measurements
// eg: x.width('22px','HelveticaNeueLTStdTh')
////////////////////////////////////////////////////////////////////////////////
String.prototype.width = function(fontSize, fontFamily) {
  var ctx = document.createElement('canvas').getContext('2d'),
      retVal = 0,
      theString = this.toString();
  fontSize    = (typeof fontSize==="undefined") ? "12pt" : fontSize;
  fontFamily  = (typeof fontFamily==="undefined") ? "Arial" : fontFamily;
  ctx.font = fontSize + " " + fontFamily;
  return (ctx.measureText(theString).width);
}
Shannon Norrell

Thursday, August 18, 2011

Javascript Reliable Detect Internet Connection

I was told that the new HTML5 "navigator.isOnline" property is somewhat buggy.
Here is an alternative I wrote that seems to work flawlessly.


<script type="text/javascript">
var bIsOnline = false;
(function() {
var anImage = document.createElement("img");
anImage.onerror = function() { bIsOnline=false; }
anImage.onload = function() { bIsOnline=true; }
anImage.src="http://www.quirksmode.org/pix/logo_quirksmode.gif?" + (Math.random()*100000 << 0); })(); function test() { alert("You " + ((bIsOnline) ? "ARE" : "ARE NOT") + " online") } </script> <body onload="test();"></body>


Shannon Norrell

Thursday, March 3, 2011

CSS3 Tooltip Trick using CSS3 :before psuedo element, content attribute and custom data attributes

I was looking for a way to make an HTMLElement's title appear faster in a WebKit application.

Turns out there is a way to capture the "title" attribute of an element using the :before pseudo element and content property, store that value in a div that only appears onhover over the original element. The problem with this technique was that the actual "title" attribute would eventually display.


Therefore, I made use of another CSS3 feature called "custom data attributes" and, rather than storing the title of the element in the "title" attribute, I used "data-title" instead.

Here is a quick example:
<!DOCTYPE html>
<head>
  <style type="text/css">
    .sprocket { position:relative;width:50px;height:50px;background-color:red; }
    .sprocket:before { content:attr(data-title); display:none; }
    .sprocket:hover::before{ width:160px; display:block; border-radius:3px; background-color:#fffdc7; padding:5px; color:black; margin-top:40px; margin-left:20px; -webkit-box-shadow: 3px 3px 3px rgba(193,193,193,.5);}
    .sprocket:hover{ z-index:10; position:absolute; }
  </style>
</head>
<body>
  <div class="sprocket" data-title="Fancy Title Text">
</body>
</html>
Click here for an Example

Shannon Norrell

Saturday, January 1, 2011

Array.remove method (also Array,indexOf

I kept finding myself needing to remove items from an array, so developed a quick helper (prototype) method attached to the Array Object to help.


////////////////////////////////////////////////////////////////////////////////
//
// Array.remove( object|string item) - removes an item from an array
// Example x = ["abc","xyz",1,4] x.remove("xyz") returns ["abc",1,4]
//
////////////////////////////////////////////////////////////////////////////////
if (Array.prototype.remove===undefined) { // Presumably this will eventually be added to Javascript
Array.prototype.remove = function( item ) {
var itemLocation = this.indexOf(item);
if (itemLocation > -1) {
this.splice(itemLocation,1);
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Array.indexOf() - returns integer index where valueToSearchFor is in an Array
// (believe it or not, not all browsers have this yet ... and it's 2010!
////////////////////////////////////////////////////////////////////////////////
if (Array.prototype.indexOf===undefined) {
Array.prototype.indexOf = function( valueToSearchFor ) {
var iEnd = this.length;
var retVal = -1;
for (var i=0;i<iEnd; i++) {
if (this[i] == valueToSearchFor) {
retVal = i;
break;
}
}
return retVal;
};
}


Shannon Norrell

Wednesday, October 6, 2010

Javascript Array Detection

Turns out the most reliable way to detect an Array is not to use the old return (typeof foo === 'object' && foo.constructor === Array) but rather to do this:


function isArray(anArray) {
return Object.prototype.toString.apply(anArray) === "[object Array]";
}

Wednesday, September 8, 2010

Flatten Array

This quick function takes a an array, whose elements may or may not be other arrays, and flattens it into a single array.

Extremely simple solution, but kind of fun because it's a chance to use recursion:
<script type=text/javascript>
var a = [1,2,[5,6,7], 8, [9,10,[11,12],13], 14];

function flatten( oArray ) {
var retVal = [];
for (var i=0;i<oArray.length;i++) {
if (!isArray( oArray[i]) ) {
retVal.push( oArray[i] );
} else {
var tempFlatt = flatten(oArray[i]);
for (var j=0;j<tempFlatt.length;j++) {
retVal.push( tempFlatt[j] );
}
}
}
return retVal;
}

function isArray( anElement ) {
return (typeof anElement=="object" && anElement.constructor == Array);
}

alert(flatten(a));
</script>