Prototype JS in a nutshell. Part 2.

Welcome to the second part of the Prototype JS course. Today we will focus on the elements of the document and performing operations on them.

Prototype JS — further steps

In this part of the course we will work with the DOM, but using Prototype JS approach. So let’s move ahead to discuss further elements of this library.

The Template object

This allows us to get some kind of interpolation; in JavaScript is a handy tool for the presentation of data, e.g. data received from the network and processed.

Example — use of the Template object:

var cart = new Object();
cart.items = [];
cart.items.push({ product: 'Book', price: 24.50, quantity: 1 });

cart.items.push({ product: 'Pencils', price: 5.44, quantity: 3 });

var itemFormat = new Template (
    'You are ordering #{quantity} units ' +
    'of #{product} at $#{price} each' );

var formatted = '';

for (var i = 0; i < cart.items.length; i++) {
    var cartItem = cart.items[i];
    formatted += itemFormat.evaluate(cartItem) + '<br/>\n';
}

Nice possibilities, isn’t it? We simply define a format of data display (itemFormat variable), and then iterate on the data (items collection) to extract the data, that will be substituted in the appropriate places.

Example #2 — using the Template to build URL elements:

var hx = new Template('show.php?lang=#{lang}&cat=#{mycat}&x=#{x}');
var selection = { my_cat: 'books' , lang: 'en' };
hx.evaluate(selection); // 'show.php?lang=en&cat=books&x='

The object “selection” the key “x” is missing. It’s not a problem — simply will be skipped during processing of the template.

Arrays — the different way

We already know how to work with arrays in “pure” JavaScript. Prototype JS gives us additional capabilities for working with arrays, or simplifies standard methods.

Let’s start with iterations.

Implementation of the iterator pattern is used to transition by the next elements of set, array or object.

Example — iteration using each():

var myArray = new Array('A', 'B', 'C', 'D');

myArray.each(function(item) {
    // code that works on a particular (current) element …
    alert(item);
});

// case 2 - iteration on the HTML elements:
//var elements = $$('.menu-item');

//elements.each(function(element) {
  // …
//});

Prototype JS methods related with arrays

– clear() – deletes the contents of the array

– clone() – cloning an array

var two = mytab.clone(); // 'mytab' will be cloned in 'two'

– compact() – returns a new version of the table, without null / undefined “values”

– each() – iterator

– first() – returns the first element of an array

– flatten() – transformation into 1-D array, e.g.:

['al', ['bob', 'lisa']].flatten(); // ['al', 'bob', 'lisa']

– from() – method $A() alias

– indexOf() – index of an element

– inspect() – returns debug-oriented string

– last() – the last element, the reverse of first()

– reverse() – reversal

– size() – size, just as native X.length

– toArray() – conversion to an array, for example:

var str = 'a, b, c';
alert(string.toArray());

alert($R(1, 5).toArray()); // [1, 2, 3, 4, 5]

– toJSON() – conversion to JSON, for example:

['a', {b: null}].toJSON(); // '["a", {"b": null}]'

– uniq() – removes duplicates from an array

– without() – returns an array with omitting certain values​​, such as:

[5, 6, 1, 20].without(20, 6) // -> [5, 1]

Class and object oriented programming (OOP) with Prototype JS

We discussed already OOP in JavaScript, however Prototype JS gives us more options.

Operations on the “classes” can be performed according to the scheme as in the following example:

var theClass = {}; // …

// add methods
theClass.addMethods({
    speak: function() {
        // alert(this.name);
        alert('Hello!');
    }
});

To create a “class” (at the Prototype JS level) there is the create() method:

create([superclass][, methods…]);

The superclass parameter It specifies the class of the parent, and to the parent we refer through $super. Thanks to this we can easily get the possibility to implement inheritance.

Example — use of Class.create():

var Animal = Class.create({
    initialize: function(name, sound) {
        this.name  = name;
        this.sound = sound;
    },

    speak: function() {
        alert(this.name + " says: " + this.sound + "!");
    }
});

// "derive" an animal from the Animal class:
var Snake = Class.create(Animal, {
    initialize: function($super, name) {
        $super(name, 'hissssssssss');
    }
});

var ms = new Snake("Python");
ms.speak(); // "Python says: hissssssssss!"

var snake2 = new Snake("Boa");
snake2.speak(); // "Boa says: hissssssssss!"

// let's embed also Enumerable
var AnimalPen = Class.create(Enumerable, {
    initialize: function() {
    var args = $A(arguments);
        if (!args.all(function(arg) {
            return arg instanceof Animal
        }))
        throw "Only animals in here!"

        this.animals = args;
    },

    // implementation of _each to use the methods of Enumerable
    _each: function(iterator) {
        return this.animals._each(iterator);
    }
});

var snakePen = new AnimalPen(ms, snake2);
snakePen.invoke('speak'); // invoke - call the method
// alert: "Python says: hissssssssss!"
// alert: "Boa says: hissssssssss!"

I personally like OOP approach offered by Prototype JS framework.

And now let’s consider work with the elements of the document and related tools available in Prototype JS.

The Element object — a deeper look

In the first part of the course we mentioned about the objects of the Element type. Now we will develop this topic.

At start: the element as a constructor.

Example:

var a = new Element('a', { 'class': 'foo', href: '/file.htm' })
        .update("Next page");

Link will be created, based on specified parameters.

A step further: Element, Prototype JS and extending DOM through the extend() method.

Example — dynamic creation of element:

var my_div = document.createElement('div');
Element.extend(my_div);
my_div.addClassName('pending').hide();
document.body.appendChild(my_div);

Tip: older browsers:

$('someElement').parentNode.hide(); // error in IE
$($('someElement').parentNode).hide(); // cross-browser way

The methods

Below we listed method for the objects of Element type.

– absolutize() – sets absolute position

– addClassName() – adding a class, e.g.:

$('mydiv').addClassName('myclass');

– addMethods() – addMethods([methods]) or addMethods(tagName, methods), for example:

var MyUtils = {
    truncate: function(element, len) {
        element = $(element);
        return element.update(element.innerHTML.truncate(len));
    },
    updateAndMark: function(element, html) {
        return $(element).update(html).addClassName('updated');
    }
}
Element.addMethods(MyUtils);

// try it:
$('explanation').truncate(100);

– ancestors() – get ancestors for the element, e.g.:

<div id="father"><div id="kid"></div></div>
$('kid').ancestors();
// result: [div#father, body, html]

– childElements() – child elements, depth = 1

– classNames() – returns an array with classes set for the element, e.g.:

$('mydiv').classNames(); // ['apple', 'fruit', 'food']

– cleanWhitespace() – cleans up whitespace

– clonePosition() – clonePosition(element, source[, options]), returns new HTMLElement with position

– cumulativeOffset() – the cumulative value of the element offset — x, y

– cumulativeScrollOffset() – offset for the scrolling (nested elements)

– descendantOf() – checks whether the element is a descendant of the ancestor, e.g.:

$('div1').descendantOf('div-foobar'); // true

– descendants() – returns an array of descendants

– down() – the next element down, for example:

$(element).down(1).next('li', 2).hide();

– empty() – checks if the element is empty, true in case of whitespace only

– extend() – extend(element) — will expand the element by the methods of Element.Methods and Element.Methods.Simulated

– fire() – creates a custom event with the specified name, and then runs it on a given element

– firstDescendant() – so-called “the first child”, for example:

<div id="australopithecus">
  <div id="homo-erectus"><!-- This is cool -->
    <div id="homo-neanderthalensis"></div>
    <div id="homo-sapiens"></div>
  </div>
</div>
$('australopithecus').firstDescendant();
// div#homo-erectus

$('homo-erectus').firstChild;
// comment node "This is cool"

$('homo-erectus').firstDescendant();
// div#homo-neanderthalensis

– getDimensions() – sizes — the width, height, eg:

$('rectangle').getDimensions(); // {width: 200, height: 100}

– getElementsByClassName() – gets elements with selected class name:

$('div1').getElementsByClassName('myclass');

– getElementsBySelector() – gets items by the selector, e.g. by the title:

<li id="golden-delicious" title="yummy!">Golden Delicious<li>
$('apples').getElementsBySelector('[title="yummy!"]');

– getHeight() – gets height of the element

– getOffsetParent() – element of the nearest ancestor

– getStyle() – gets current style of the element:

$(element).getStyle('font-size');

– getWidth() – gets width of the element

– hasClassName() – checks if the element has a selected class, for example:

$('div1').hasClassName('lol');

– hide() – hide element

– identify() – returns the ID attribute of the element (if it exists)

– immediateDescendants() – direct descendants

– insert() – adding new element; insert(element, { position: content })
or insert(element, content)

– inspect() – debug-oriented string (more detailed information)

– makeClipping() – performs element framing, e.g. div with a picture:

$('photo').makeClipping().setStyle({
    width: '100px', height: '100px'
});

– makePositioned() – sets relative position

– match() – check matching, e.g. match(element, selector):

<ul id="fruits">
  <li id="apples">
  <ul>
    <li id="golden-delicious">Golden Delicious</li>
    <li id="mcintosh">McIntosh</li>
  </ul>
  </li>
</ul>
$('fruits').match('ul'); // true

$('macintosh').match('li#macintosh.yummy');
$('fruits').match('p');

– next() – next node sibling

– nextSiblings() – next nodes (siblings)

– observe() – observation of the object / item, related with handling events, for example:

$(element).observe('click', function(event) {
    alert(Event.element(event).innerHTML);
});

– positionedOffset() – offsetLeft and offsetTop

– previous() – previous node (siblings)

– previousSiblings() – as above, but with all previous nodes

– readAttribute() – read the attribute, for example:

$('mylink').readAttribute('href'); // '/tags/prototype'

– recursivelyCollect(property) — recursive collecting items, e.g.:

$('my-ul-li-element').recursivelyCollect('firstChild');

– relativize() – makes a relatively-positioned element

– remove() – removing element, e.g.:

// removes an element from the document (and optionally returns it)
var x = $('div1').remove();

– removeClassName() – removes a CSS class, for example:

$('div1').removeClassName('myclass');

– replace() – replacing elements
replace(element[, html]); // html parameter defines the new content, which may be added

– scrollTo() – scrolls to the element, e.g.:

$(element).scrollTo();

– select() – selects the item

– setOpacity() – manipulation of transparency

// 50% transparency - sets 50% of transparency
$(element).setOpacity(0.5);

– setStyle() – dynamic style setting, for example:

$(element).setStyle({
    backgroundColor: '#900',
    fontSize: '12px'
});

– show() – show the element (if hidden), see also: hide()

– siblings() – an array of neighbors, for example: $(‘div1’).siblings();

– stopObserving() – stop watching / handling the event, see also: observe()

Example:

$(element).stopObserving('click', coolAction);
// unregister coolAction

– toggle() – changing the visibility of the element, calls the show() method when hidden, hide() when visible:

$('el').toggle();

– toggleClassName() – as above: adds / removes the class, e.g. if we have a class = “foo bar”;

elem.toggleClassName("foo"); // class="bar";

– undoClipping() – the inverse operation to makeClipping()

– undoPositioned() – restores the previous position of the element

– up() – returns the first ancestor of element

– update() – updates the contents of the element

– viewportOffset() – returns the coordinates x, y

– visible() – checks whether the element is visible

$('visible').visible(); // true or false

– wrap() – adds a wrapper to the element; encapsulates it with another element, for example:

var div = new Element('div', { 'class': 'table-wrapper' });
$('elem').wrap(div);

Summary

And after this list of methods, we are finishing 2nd part of the Prototype JS course. In the 3rd part we will summarize learning of Prototype JS basics.

Thank you.


2 Responses to “Prototype JS in a nutshell. Part 2.”

  1. Mark Moreto says:

    This is a great post! Very helpful. Hopefully on your next tutorials, you can walk through a demo project combing all stuffs you are teaching.

    • DirectCode says:

      Thank you!
      I worked a lot with Prototype JS in the past.
      Currently I try to publish next articles and tutorials, I hope there are / will be useful; but they’re mainly related with jQuery, which I use mostly.

      Best!