view index.html @ 14:c156c147c741

Added ligatures.
author Atul Varma <avarma@mozilla.com>
date Mon, 03 May 2010 11:23:39 -0700
parents e34413f21290
children d7761afdae70
line wrap: on
line source

<html>
<head>
<style type="text/css">
body {
  -webkit-user-select: none;
  font-family: Palatino;
  margin: 0;
}

div.letter {
  -webkit-transition-property: -webkit-transform, color;
  -webkit-transition-duration: 0.1s, 0.2s;
  -webkit-transition-timing-function: linear;
  position: absolute;
  cursor: pointer;
  font-size: 144pt;
}

div.letter .info {
  font-family: Futura, Helvetica;
  white-space: pre;
  font-size: 9pt;
}

div.letter.active {
  color: red;
}

div.palette {
  float: right;
  width: 1em;
  overflow: hidden;
  font-size: 144pt;
}

div.palette-container {
  -webkit-transition-property: -webkit-transform;
  -webkit-transition-duration: 0.5s;
  -webkit-transition-timing-function: ease-out;
  -webkit-backface-visibility: hidden;
}

.letter-prototype {
  cursor: pointer;
  color: gray;
  padding: 1px;
  border-bottom: 1px solid gray;
}
</style>
</head>
<body>
<div id="letters" class="palette">
  <div class="palette-container">
  </div>
</div>
<script>
if (typeof Array.isArray !== 'function') {
  Array.isArray = function (value) {
    return Object.prototype.toString.call(value) === '[object Array]';
  };
}

function $(selector) {
  return new $.fn.init(selector);
}

$.fn = $.prototype = {
  _qsa: function qsa(selector, element) {
    if (element === undefined)
      element = document;
    var nodeList = element.querySelectorAll(selector);
    var array = [];
    for (var i = 0; i < nodeList.length; i++) {
      array.push(nodeList[i]);
    }
    return array;
  },
  length: 0,
  init: function init(selector) {
    if (typeof(selector) == "string") {
      this.elems = this._qsa(selector);
    } else {
      if (Array.isArray(selector)) {
        this.elems = selector;
      } else
        this.elems = [selector];
    }
    this.length = this.elems.length;
  },
  get: function(i) {
    if (i !== undefined)
      return this.elems[i];
    return this.elems;
  },
  bind: function(name, handler) {
    this.elems.forEach(function(elem) {
     elem.addEventListener(name, handler, false);
    });
  },
  css: function(options) {
    this.elems.forEach(function(elem) {
      for (name in options)
        elem.style.setProperty(name, options[name], null);
    });
  },
  removeClass: function(name) {
    this.elems.forEach(function(elem) {
      var classes = elem.className.split(" ");
      var index = classes.indexOf(name);
      if (index != -1) {
        classes.splice(index, 1);
        elem.className = classes.join(" ");
      }
    });    
  },
  addClass: function(name) {
    this.elems.forEach(function(elem) {
      var classes = elem.className.split(" ");
      var index = classes.indexOf(name);
      if (index == -1) {
        classes.push(name);
        elem.className = classes.join(" ");
      }
    });
  },
  toggleClass: function(name) {
    this.elems.forEach(function(elem) {
      var classes = elem.className.split(" ");
      var index = classes.indexOf(name);
      if (index == -1)
        classes.push(name);
      else
        classes.splice(index, 1);
      elem.className = classes.join(" ");
    });
  },
  text: function(text) {
    if (text === undefined)
      return this.elems[0].textContent;
    this.elems.forEach(function(elem) {
      elem.textContent = text;
    });
  },
  find: function(selector) {
    var self = this;
    var array = [];
    this.elems.forEach(function(elem) {
      array = array.concat(self._qsa(selector, elem));
    });
    return new this.init(array);
  },
  each: function(cb) {
    this.elems.forEach(function(elem) { cb.call(elem); });
  }
};

$.fn.init.prototype = $.fn;

function makeDraggable(node, matrix) {
  var startX = 0;
  var startY = 0;
  var currX = 0;
  var currY = 0;

  function updateInfo() {
    var msg = "";
    if (isMouseDown)
      msg = "x: " + matrix.e + "\ny: " + matrix.f;
    $(node).find(".info").text(msg);
  }

  function move() {
    matrix = matrix.translate(currX - startX, currY - startY);
    node.style.webkitTransform = matrix;
  }

  updateInfo();

  if (!isTouchSupported) {
    var isMouseDown;

    function onMouseDown(event) {
      event.preventDefault();
      startX = event.clientX;
      startY = event.clientY;
      isMouseDown = true;
      $(node).addClass("active");
      updateInfo();
    }

    onMouseDown(event);

    $(node).bind("mousedown", onMouseDown);

    $(node.ownerDocument).bind("mousemove", function(event) {
     if (isMouseDown) {
        currX = event.clientX;
        currY = event.clientY;
        move(this);
        startX = currX;
        startY = currY;
        updateInfo();
      }
    });

    $(node.ownerDocument).bind("mouseup", function(event) {
      if (isMouseDown) {
        event.preventDefault();
        isMouseDown = false;
        $(node).removeClass("active");
        updateInfo();
      }
    });
  } else {
    $(node).bind("touchstart", function(event) {
      event.preventDefault();
      startX = event.targetTouches[0].pageX;
      startY = event.targetTouches[0].pageY;
      updateInfo();
      $(this).addClass("active");
    });

    $(node).bind("touchmove", function(event) {
      event.preventDefault();
      currX = event.targetTouches[0].pageX;
      currY = event.targetTouches[0].pageY;
      move(this);
      startX = currX;
      startY = currY;
      updateInfo();
    });

    $(node).bind("touchend", function(event) {
      event.preventDefault();
      $(this).removeClass("active");
    });

    $(node).bind("touchcancel", function(event) {
      event.preventDefault();
      $(this).removeClass("active");
    });
  }
}

function makeScrollable() {
  var node = this;
  var startY = 0;
  var floatScrollTop = 0;
  var touchMoved = false;
  var matrix = new WebKitCSSMatrix();

  function accelerate(delta) {
    var maxHeight = node.parentNode.scrollHeight -
                    node.parentNode.clientHeight;

    matrix = matrix.translate(0, delta);
    if (matrix.f > 0)
      matrix.f = 0;
    else if (matrix.f < -maxHeight)
      matrix.f = -maxHeight;
    node.style.webkitTransform = matrix;
  }

  if (!isTouchSupported) {
    $(node).bind("mousewheel", function(event) {
      accelerate(event.wheelDelta);
    });

    $(node).find(".letter-prototype").bind("mousedown", makeLetter);
  } else {
    $(node).bind("touchstart", function(event) {
      event.preventDefault();
      startY = event.targetTouches[0].pageY;
      touchMoved = false;
    });

    $(node).bind("touchmove", function(event) {
      event.preventDefault();
      var currY = event.targetTouches[0].pageY;
      accelerate((currY - startY) * 2);
      startY = currY;
      touchMoved = true;
    });

    $(node).bind("touchend", function(event) {
      event.preventDefault();
      if (!touchMoved) {
        var target = event.changedTouches[0].target;
        if (target.nodeType == target.TEXT_NODE)
          target = target.parentNode;
        makeLetter.call(target);
      }
    });
  }
}

function makeLetter(event) {
  if (event)
    event.preventDefault();

  var node = this;
  var doc = this.ownerDocument;

  var letter = doc.createElement("div");
  var char = doc.createTextNode(this.textContent);
  var info = doc.createElement("div");

  letter.className = "letter";
  info.className = "info";
  letter.appendChild(char);
  letter.appendChild(info);

  // TODO: This assumes things about the DOM structure that
  // we don't want to have to assume.
  var parentMatrix = new WebKitCSSMatrix();
  var matrix = new WebKitCSSMatrix();

  parentMatrix.setMatrixValue(this.parentNode.style.webkitTransform);
  matrix = matrix.translate(
    this.offsetLeft,
    this.offsetTop + parentMatrix.f
  );

  letter.style.webkitTransform = matrix;
  doc.body.appendChild(letter);

  // Apply a new transform to make the letter animate.
  if (isTouchSupported) {
    matrix = matrix.translate(-this.offsetWidth, 0);
    letter.style.webkitTransform = matrix;
  }

  makeDraggable(letter, matrix);
}

function addLetters() {
  var node = this;

  const LIGATURES = "\u0026\u00DF\u00C6\u00E6\u0152\u0153" +
                    "\u0132\u0133\u1D6B\uFB00\uFB01\uFB02" +
                    "\uFB03\uFB04\uFB05\uFB06";
  const ALPHABET = "abcdefghijklmnopqrstuvwxyz" +
                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  var letters = ALPHABET + LIGATURES;

  for (var i = 0; i < letters.length; i++) {
    var div = document.createElement("div");
    div.textContent = letters[i];
    div.className = "letter-prototype";
    node.appendChild(div);
  }
}

var isTouchSupported = (function isTouchSupported() {
  try {
    document.createEvent("TouchEvent");
    return true;
  } catch (e) {
    if (e.code != e.NOT_SUPPORTED_ERR)
      throw e;
    return false;
  }
})();

function resize() {
  $("#letters").css({"max-height": document.body.clientHeight});
}

$(window).bind("resize", resize);

$(window).bind("DOMContentLoaded", function() {
  resize();
  $("#letters .palette-container").each(addLetters);
  $(".palette-container").each(makeScrollable);
});
</script>
</body>
</html>