_|_|_| _|_|_| _|_|_|_|
_| _| _|
_| _| _|_|_|
_| _| _|
_|_|_| _|_|_| _|_|_|_|
ICE - Lightweight JavaScript library
ICE features:
- Small footprint (65KB uncompressed)
- Mature - used on Todoist.com since 2007
- Unified things that work in all the modern browsers (IE 7+)
- Functional programming
- DOM helpers
- Array helpers
- Element store
- Powerful and easy to use requests
- Deferred abstraction
- Class abstraction
- Effects
- Drag and drop helpers
- and a lot more...
Example of ICE:
// Requests
function loadUsers() {
var req = $requestJSON('/users/get')
req.addCallback(function(users) {
var user_holder = $('user_holder')
$map(users, function(user) {
var li = LI({c: 'user'}, user.name)
$AEV(li, 'click', UserController.click)
$add(user_holder, li)
})
})
req.sendReq({token: TOKEN})
}
// Events
$AEV(window, 'load', loadUsers)
// Effects
$fx.setWidth($('fluffy_4'), {from: 150, to: 400})
// Array helpers
$arrayFlatten([[1, 2, [3, 4]], 5]) == [1, 2, 3, 4, 5]
// DOM abstraction
$add($body(),
DIV({c: 'my_class', s:'padding-top: 10px'}, "Hello"))
// Element store
ElementStore.set(elm, "meaning of life", {42: 42})
A lot of ideas from ICE comes from MochiKit. The effects library is inspired by mootools.
By default ICE exports its public functions to the global name space (window). If you want to disable this set window.ICE_EXPORT_TO_SCOPE = false before sourcing the library. Then use the ICE. prefix to access the API.
- $isWebkit -- Returns true if the browser is webkit
- $isIe -- Returns true if the browser is Internet Explorer
- $isIe8 -- Returns true if the browser is Internet Explorer v8
- $isSafari -- Returns true if the browser is Safari
- $isOpera -- Returns true if the browser is Opera
- $isMozilla -- Returns true if the browser is Mozilla
- $isMac -- Returns true if the browser is a Mac
- $isChrome -- Returns true if the browser is a Chrome
- $queryArgument(var_name) -- Returns the value of var_name from the URL
- $arrayCreate(val) -- Returns val if it's already an array, otherwise [val] is returned. Shortcut $A
- $arrayCompare(arr_a, arr_b) -- Returns true if arr_a and arr_b are equal
- $arrayRemove(array, elm [,eval_fn]) -- Removes elm from array
- $arrayUpdate(array, old_elm, new_elm) -- Updates old_elm to new_elm inside array
- $arrayCopy(array) -- Returns a copy of array
- $arrayDiff(arr1, arr2) -- Returns the diff between arr1 and arr2
- $arrayUnion(arr1, arr2) -- Returns the union between arr1 and arr2
- $arrayForce(args) -- Returns a true array. This functions is useful to force arguments to act as an array instead of an object. Shortcut $AF
- $arrayJoin(delim, array) -- Returns the elements of array as string, separated by the specified delimiter delim
- $isIn(elm, array) -- Returns true if elm is inside array
- $index(elm, array [,eval_fn]) -- Returns the index of elm inside array. -1 is returned if the elm isn't found
- $first(array) -- Returns the first element of array
- $last(array) -- Returns the last element of array
- $random(array) -- Returns an random element of array
- $arrayFlatten(array) -- Returns a flattened array
- $update(obj1, obj2) -- Update obj1 with properties from obj2
$isIn("cow", [1, 2, "cow"]) == true
$getIndex("cow", [1, 2, "cow"]) == 2
$update({a: 1, b: 2}, {c: 3}) == {a: 1, b: 2, c: 3}
$arrayFlatten([[1, 2, [3, 4]], 5]) == [1, 2, 3, 4, 5]
- $map(array, fn, [start_index, end_index]) -- Executes fn on all elements of array. Signature is fn(element, index)
- $rmap(array, fn, [start_index, end_index]) -- Like $map, but in reverse
- $filter(array, fn, [start_index, end_index]) -- Executes fn on all elements of array and returns all the elements of list where fn(elm) equals true
- $partial(fn) -- Return a partially applied function. Shortcut $p
div_with_2 = $filter([1, 5, 8, 4], function(n) {
return (n % 2 == 0)
})
div_with_2 == [8, 4]
adder = function(a, b) {
return a + b
}
add_one = $partial(adder, 1)
add_one(41) == 42
- $(id) -- Returns the DOM element with the id
- $$(selector, [in_children]) -- Returns a list of DOM elements that match the CSS selector
- $nodeName(elm) -- Returns the node name of elm
- $parent(elm, tag_name, [class_name, stop_elm]) -- Look on elm parents and return the first match. The search stops when stop_elm is reached. Shortcut $gp
- $child(elm, tag_name, [class_name, stop_elm]) -- Look on elm children and return the first match. Shortcut $gc
- $prevSibling(elm, tag_name, class_name) -- Look on elm previous siblings and return the first match
- $nextSibling(elm, tag_name, class_name) -- Look on elm next siblings and return the first match
- $body() -- Returns the body DOM element
- $head() -- Returns the head DOM element
- $form(form, name) -- Returns a form element with the specified name. Shortcut $f
- $selectValue(select) -- Returns value of select
-
$all(tag_name, class_name, [parent, first_match]) -- [Deprecated, use $ $ isntead]. Returns a list of DOM elements. To ignore the tag_name or class_name set them to null. The whole document is searched if parent isn't set
// Returns one element with id google_login
$('google_login')
// Returns all of div elements
$$('div')
// Returns div elements with .user class inside #google_list
$$('div.user', $('google_list'))
// Returns the div.facebook_login that's the first sibling of #google_list
$nextSibling($('google_list'), 'div', 'facebook_login')
// Returns the first parent of #google_list that matches div.holder
$parent($('google_list'), 'div', 'holder')
// Returns the first child of #google_list that matches li.user
$child($('google_list'), 'li', 'user')
// Deprecated (use $$): Returns div tags with user class inside #google_list
$all('div', 'user', $('google_list'))
- $documentInsert(elm) -- Write element to the document (using document.write)
- $toDOM(html, [first_child]) -- Transform html to DOM. Returns first child if first_child is true
- $add(elm, elm1, ..., elmN) -- Add elm1,...,elmN to elm
- $addToTop(elm, elm1, ..., elmN) -- Add elm1,...,elmN to the top of elm. Shortcut $ATT
- $replace(elm, elm1, ..., elmN) -- Replace children of elm with elm1,...,elmN
- $addAfter(elm, reference_elm) -- Add elm after reference_elm
- $addBefore(elm, reference_elm) -- Add elm before reference_elm
- $clean(elm) -- Clean data, events, etc. attached to elm
- $swap(dest, src) -- Swap dest with src
- $remove(elm1, ..., elmN) -- Remove elm1,...,elmN
- $create(tag_name, attrs) -- Create a new DOM element with tag_name. attrs should be an object or array
- $setHTML(elm1, ..., elmN, html) -- Set the innerHTML of elm1,...,elmN to html
DOM shortcuts. These elements have shortcuts:
- UL, LI, TD, TR, TH,
- TBODY, TABLE, INPUT, SPAN, B,
- A, DIV, IMG, BUTTON, H1,
- H2, H3, H4, H5, H6, BR, TEXTAREA, FORM,
- P, SELECT, OPTION, OPTGROUP, IFRAME, SCRIPT,
- CENTER, DL, DT, DD, SMALL,
- PRE, I, LABEL, THEAD, HR
// Using $create
$create("p", [{id: "my_p", style: "color: red"}, "Hello world"])
// Using the shortcuts
$add($body(),
DIV({c: 'my_class', s:'padding-top: 10px'}, "Hello"))
// Inserting a DIV elemetn to the body
$insertAfter(DIV("Hello"), $body())
- $setVisibility(elm1, ..., elmN, visibility) -- Update visibility of elm1,...,elmN
- $setOpacity(elm1, ..., elmN, value) -- Update opacity to value of elm1,...,elmN
- $show(elm1, ..., elmN) -- Show elm1,...,elmN
- $hide(elm1, ..., elmN) -- Hide elm1,...,elmN
- $isHidden(elm) -- Returns true if elm is hidden. Otherwise false
- $isShown(elm) -- Returns true if elm is shown. Otherwise false
$show($$('div.user'))
$isHidden($('google_login')) == true
$setVisibility($$('div.user'), false)
$setOpacity($$('div.user'), 0.5)
- $setStyle(elm1, ..., elmN, obj) -- Update elm.style with obj of elm1,...,elmN
- $getStyle(elm, property) -- Return the computed style of elm
- $setWidth(elm1, ..., elmN, width) -- Set width of elm1,...,elmN
- $setHeight(elm1, ..., elmN, height) -- Set height of elm1,...,elmN
- $setLeft(elm1, ..., elmN, left) -- Set left of elm1,...,elmN
- $setRight(elm1, ..., elmN, right) -- Set right of elm1,...,elmN
- $setTop(elm1, ..., elmN, top) -- Set top of elm1,...,elmN
- $setBottom(elm1, ..., elmN, bottom) -- Set bottom of elm1,...,elmN
$setStyle($$('div.user'), {top: 50, left: 40})
$setTop($$('div.user'), 100)
- $setClass(elm1, ..., elmN, class) -- Set class of elm1,...,elmN
- $addClass(elm1, ..., elmN, class) -- Add class to elm1,...,elmN
- $removeClass(elm1, ..., elmN, class) -- Remove class class elm1,...,elmN
- $replaceClass(elm1, ..., elmN, classOld, classNew) -- Replace classOld with classNew in elm1,...,elmN
- $hasClass(elm, class) -- Returns true if elm has class
$setClass($$('div.user', $('google_login')), 'user_deleted')
$addClass($('user_a'), $('user_b'), 'user_loading')
- $mousePos(event) -- Returns the mouse position of event as {x: ..., y: ...}
- $scrollTop(elm) -- Scrolls elm to the top
- $position(elm) -- Returns the absolute position of elm as {x: ..., y: ...}
- $docSize([doc]) -- Returns the document size of doc as {w: ..., h: ...}
- $winSize([doc]) -- Returns the window size as {w: ..., h: ...} by inspecting doc
- $isOverlapping(elm1, elm2) -- Returns true if elm1 is overlapping elm2
$position($('my_elm')) == {x: 100, y: 200}
$isOverlapping($('elm1'), $('elm2')) == true
- $eventElm(event) -- Returns the element that's tied to event
- $addListener(elms, types, handler, [listen_once]) -- Add a handler that handles types. Shortcut $AEV
- $removeListener(elms, types, handler, [listen_once]) -- Remove handler from elms that handles types. Shortcut $REV
- $removeAllListeners(elms, type) -- Remove all handlers that handle type
$AEV($$('div.user'), 'click', function(ev) {
$preventDefault(ev)
var elm = $eventElm(ev)
// ...
})
$AEV([$('input_1'), $('input_2')], 'keypress', function(ev) {
alert(ev.key)
alert(ev.ctrl)
alert(ev.meta)
})
$AEV($('google_btn'), 'click' $b(googleBtnClick, GoogleUser) {
// this points to GoogleUser
});
- $preventDefault(event) -- Prevent the default behavior of an event
- $stopPropagation(event) -- Stop propagation of an event
- $bind(fn, scope, [extra_args]) -- Bind function fn to scope and return it. extra_args is an array of extra parameters that should be sent to fn. Shortcut $b
- $bindMethods(object) -- Force binding all of methods of object to itself. Useful to resolve this
- $request(url, method) -- Perform a request to url and return it in a deferred object. method can be get or post
- $requestJSON(url, method) -- Like $request, but parse the result as JSON
- $httpReq() -- Returns a new XMLHTTPRequest
- $serialize(obj) -- Serialize obj as JSON
- $eval(txt) -- Evaluate txt as JavaScript or JSON (if possible) and return the result
- $evalScript(html) -- Evaluate script tags inside txt
- $encode(data) -- Return the query argument representation of data
d = $request('/feeds/json/amix')
d.addCallback(function(res_txt, req) { alert(res_txt) })
d.addErrback(function(res_txt, req) { alert('Error encountered: ' + res_txt) })
d.sendReq({val: 1})
$serialize({'a': 1, 'b': 2}) == '{"a":1,"b":2}'
$eval('{"a":1,"b":2}') == {'a': 1, 'b': 2}
$encode({name: 'peter', 'age': 29}) == "name=peter&age=29"
A deferred gives the option to chain functions. ICE borrowed this idea from MochiKit that borrowed it from Twisted. ICE implementation is much more simple and limited than MochiKit's or Twisted's.
When you call $request or $requestJSON you get a deferred object. This object has following methods:
- addCallback(fn): Add the function fn to the end of the callback sequence
- addErrback(fn): Add the function fn to the end of the errorback sequence
- addCallbacks(callback, errback)
- sendReq(data): Send the actual request. data should be a JSON object
ICE features a simple way to do OOP in JavaScript. A simple example that demonstrates all of the functionality:
Person = new Class({
init: function(name) {
this.name = name
Person.count++
},
getName: function() {
return this.name
}
})
// Static field
Person.count = 0
UniversityPerson = Person.extend({
init: function(name, school) {
this.parent(name)
this.school = school
},
getSchool: function() {
return this.school
}
})
You can use $fx to create some dazzling effects.
- $fx.highlight(elm, opts) -- Yellow highlight the element
- $fx.fadeIn(elm, opts) -- Fade in the element
- $fx.fadeOut(elm, opts) -- Fade out the element
- $fx.setWidth(elm, opts) -- Animate resize of width
- $fx.setHeight(elm, opts) -- Animate resize of height
- $fx.Style(elm, opts) -- Animates an arbitrary effect
- $fx.Styles(elm, opts) -- Animates an arbitrary effects
$fx.highlight($('fluffy_1'), {duration: 1000})
$fx.setWidth($('fluffy_4'), {from: 150, to: 400})
new $fx.Style($('fluffy_6'), 'width').custom(50, 300)
new $fx.Styles($('fluffy_7')).custom(
{'height': [50, 100], 'width': [150, 300]}
)
$dnd makes it possible to support drag and drop. It provides a bare-bone where browser issues are solved. There is no drop-zones and no sortable lists, but you can implement these things using a few lines code.
Look inside the examples directory for some ideas of how $dnd works.
- $dnd.dragAble(element, opts) -- Make element drag able. The element's style.position should be absolute
- $dnd.removeDragAble(element) -- Remove the drag ability from element
- $dnd.current_root -- When dragging begins this object holds the element that is moved
- $dnd.current_handler -- When dragging begins this object holds the element that drags
The opts to $dnd.dragAble can be following. All of them are optional.
- move_x -- Enable horizontal move. Default true
- move_y -- Enable vertical move. Default true
- scroll_on_overflow -- Scroll the page on overflow. Default true
- on_start -- A callback that is triggered when the drag is started. Signature is on_start()
- on_drag -- A callback that is triggered when a dragable is dragged. Signature is on_drag(new_x, new_y)
- on_end -- A callback that is triggered when the drag is stopped. Signature is on_start()
- move_filter: This function can control the x and y coordinates. Signature is move_filter(x, y) -> [x, y]
var drop_red = $('drop_red')
var drop_blue = $('drop_blue')
var onDrag = function() {
var root = $dnd.current_root
if($isOverlapping(root, drop_red))
$addClass(root, 'color_red')
else if($isOverlapping(root, drop_blue))
$addClass(root, 'color_blue')
else {
$removeClass(root, 'color_blue')
$removeClass(root, 'color_red')
}
}
$dnd.dragAble($('draggy'), {
handler: $('draggy_handler'),
on_drag: onDrag
})
jQuery.data allows you to attach data of any type to DOM elements in a way that is safe from circular references and therefore from memory leaks. ICE a standalone jQuery.data library called ElementStore - - which is also a standalone library github.com/Doist/ElementStore.
- ElementStore.set(elm, key, value)
- ElementStore.get(elm, key)
- ElementStore.remove(elm, key) -- Remove one key
- ElementStore.remove(elm) -- Removes all keys
ElementStore.set(elm, "meaning of life", {42: 42})
ElementStore.get(elm, "meaning of life")
ElementStore.remove(elm, "meaning of life")
ElementStore.remove(elm)
- $keys(object) -- Returns the keys of object
- $values(object) -- Returns the values of object
- $urlencode(str) -- Returns URL encoding of str
- $urldecode(str) -- Returns URL decoding of str
- $defined(obj) -- Returns true if obj is defined (not null or undefined)
- $isArray(obj) -- Returns true if obj is an array
- $isString(obj) -- Returns true if obj is a string
- $isNumber(obj) -- Returns true if obj is a number
- $isObject(obj) -- Returns true if obj is a object
- $isFunction(obj) -- Returns true if obj is a function
- $isBoolean(obj) -- Returns true if obj is a boolean
- $isDict(obj) -- Returns true if obj is a dictionary (e.g. {})
- $log(obj) -- Write obj to the log
- $strip(str) -- Stripe prefix and suffix whitespace from str
- $trim(str, limit, [delim]) -- Trim str with limit length and suffix it with delim if needed. delim is ... by default
- $preload(img_src1, ..., img_srcN) -- Preload images img_src1, ..., img_srcN
$keys({a: 1, b: 2, c: 3}) == ["a", "b", "c"]
$values({a: 1, b: 2, c: 3}) == [1, 2, 3]