Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/magnetikonline/picoh
Yet another JavaScript frontend micro framework - minified and gzipped to around 2.3KB.
https://github.com/magnetikonline/picoh
css-animations css-transitions dom frontend-framework xmlhttp
Last synced: 13 days ago
JSON representation
Yet another JavaScript frontend micro framework - minified and gzipped to around 2.3KB.
- Host: GitHub
- URL: https://github.com/magnetikonline/picoh
- Owner: magnetikonline
- License: mit
- Created: 2013-06-21T08:32:35.000Z (over 11 years ago)
- Default Branch: main
- Last Pushed: 2022-01-31T00:46:29.000Z (almost 3 years ago)
- Last Synced: 2024-11-12T14:07:56.038Z (2 months ago)
- Topics: css-animations, css-transitions, dom, frontend-framework, xmlhttp
- Language: JavaScript
- Homepage:
- Size: 62.5 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Picoh
Picoh is my take on the JavaScript frontend micro framework, providing event handling, DOM querying/manipulation, XMLHTTP requests and a handful of utility methods.The focus is on a lean code footprint - minified and gzipped everything weighs in around **2.3KB**.
All methods are namespaced under `window.$` / `window.$$` with no modification of *any* object prototypes.
## What's supported?
- Picoh takes advantage of core methods available in more modern browsers (such as `document.querySelectorAll()`) avoiding heavy polyfills to keep the code footprint small.
- Designed for and tested against the usual suspects of Google Chrome, Firefox and OSX Safari. On the Microsoft front **IE9 and above** is supported.
- The final revision supporting IE8 is [tagged here](https://github.com/magnetikonline/picoh/tree/ie8-final).
- Expects:
- A `!DOCTYPE` that puts your pages into *standards mode*, with the [HTML5 doctype](https://w3c.github.io/html/syntax.html#the-doctype) a good selection. More a requirement for full IE compatibility (historically an IE8 gripe), where some core methods used by Picoh [won't make themselves available](https://caniuse.com/#feat=json) in 'quirks mode'. You *can* work around such edge cases, but the result is increased code footprint - exactly what I'm trying to avoid here.
- Picoh loaded ideally from page `` and executed asynchronously (e.g. ``).
- Removal of both `margin` and `padding` from the `` element to help cross browser consistency with some DOM methods, such as calculating [viewport](#domgetviewportsize) and [document](#domgetdocumentsize) sizes.## Methods
- [General](#general)
- [$(id)](#id)
- [$.debounce(handler,delay)](#debouncehandlerdelay)
- [$.each(collection,handler)](#eachcollectionhandler)
- [$.nextTick(handler)](#nexttickhandler)
- [$.reqAnimFrame(handler)](#reqanimframehandler)
- [Events](#events)
- [$.Event.add(object,type,handler)](#eventaddobjecttypehandler)
- [$.Event.remove(object,type,handler)](#eventremoveobjecttypehandler)
- [$.Event.getTarget(event)](#eventgettargetevent)
- [$.Event.isMouseEnterLeave(event,element)](#eventismouseenterleaveeventelement)
- [$.Event.getMousePosition(event)](#eventgetmousepositionevent)
- [DOM](#dom)
- [$$(query) / $$(element,query)](#query--elementquery)
- [$.DOM.ready(handler)](#domreadyhandler)
- [$.DOM.create(name[,attributeList][,childElementList])](#domcreatenameattributelistchildelementlist)
- [$.DOM.insertBefore(element,referenceElement)](#dominsertbeforeelementreferenceelement)
- [$.DOM.insertAfter(element,referenceElement)](#dominsertafterelementreferenceelement)
- [$.DOM.replace(element,oldElement)](#domreplaceelementoldelement)
- [$.DOM.remove(element)](#domremoveelement)
- [$.DOM.removeChildAll(element)](#domremovechildallelement)
- [$.DOM.hasClass(element,name)](#domhasclasselementname)
- [$.DOM.addClass(element,name)](#domaddclasselementname)
- [$.DOM.removeClass(element,name)](#domremoveclasselementname)
- [$.DOM.setStyle(element,styleList)](#domsetstyleelementstylelist)
- [$.DOM.getData(element,key)](#domgetdataelementkey)
- [$.DOM.getOffset(element[,toParent])](#domgetoffsetelementtoparent)
- [$.DOM.getPageScroll()](#domgetpagescroll)
- [$.DOM.getViewportSize()](#domgetviewportsize)
- [$.DOM.getDocumentSize()](#domgetdocumentsize)
- [Animation/transition end DOM events](#animationtransition-end-dom-events)
- [$.DOM.Anim.onAnimationEnd(element,handler[,data])](#domanimonanimationendelementhandlerdata)
- [$.DOM.Anim.cancelAnimationEnd(element)](#domanimcancelanimationendelement)
- [$.DOM.Anim.onTransitionEnd(element,handler[,data])](#domanimontransitionendelementhandlerdata)
- [$.DOM.Anim.cancelTransitionEnd(element)](#domanimcanceltransitionendelement)
- [XMLHTTP](#xmlhttp)
- [$.request(url[,method][,handler][,parameterCollection])](#requesturlmethodhandlerparametercollection)
- [Miscellaneous](#miscellaneous)
- [*Has JavaScript?* CSS class hook](#has-javascript-css-class-hook)
- [Attachment of Picoh to alternative object](#attachment-of-picoh-to-alternative-object)### General
#### $(id)
Returns a single DOM element from the `id` given. Just a wrapper around `document.getElementByID()` we all know and love.#### $.debounce(handler,delay)
- Wraps the given `handler` in a debounce routine that will be called only after `delay` milliseconds have elapsed since last call to the routine was made.
- A `clear()` method allows for the reset of the current debounce timeout in progress.Example:
```js
function callMe() {console.log('Called');
}var debounceMe = $.debounce(callMe,500);
// log message will only display once, though debounceMe() is called three times
debounceMe();
debounceMe();
debounceMe();// to clear a current debounce timeout
//debounceMe.clear();
```#### $.each(collection,handler)
- Iterate over the given `collection`, calling `handler` for each item.
- Collection can be of type `array`, `HtmlCollection`, `NodeList` or `object`.
- `handler` passed arguments of `value` and `index` for types `array`, `HtmlCollection` and `NodeList`.
- `handler` passed arguments of `value`, `key` name and `iteration` count for type `object`.
- Returning `false` from `handler` will halt the iteration immediately.Example:
```js
function handlerArray(value,index) {console.log([value,index].join(' - '));
}$.each(
[1,2,3,4],
handlerArray
);function handlerObject(value,key,iteration) {
console.log([value,key,iteration].join(' - '));
if (key == 'key3') {
// exit right away
return false;
}
}$.each(
{ key1: 'value1',key2: 'value2',key3: 'value3',key4: 'value4' },
handlerObject
);
```**Note:** For evaluating `HTMLCollection`/`NodeList` types, `$.each()` uses [Duck typing](https://en.wikipedia.org/wiki/Duck_typing), looking for `item` and `length` properties.
#### $.nextTick(handler)
- Emulation of Node.js [`process.nextTick()`](https://nodejs.org/api/process.html#process_process_nexttick_callback_args) method.
- Produces a faster and [more efficient](https://dbaron.org/log/20100309-faster-timeouts) callback on the next event loop vs. `window.setTimeout(function() {},0)`.
- Implemented using `window.postMessage()` under the hood.#### $.reqAnimFrame(handler)
- Wrapper for `window.requestAnimationFrame`, a more efficient method of processing animation frames versus traditional `window.setTimeout()` use.
- Handles cross browser API prefixing between browser vendors.
- A fallback `window.setTimeout()` polyfill is provided for unsupported browsers which will be called approximately once every 16ms to give a *close to* 60fps fire rate.### Events
#### $.Event.add(object,type,handler)
- Attach an event `handler` to the given `object` of the given `type`.
- Event `type` can be given as a space separated list for attaching multiple events to a single `object`.Example:
```js
function clickTouchHandler(event) {console.log('Clicked or touched!');
console.log(this);
console.log(event);
}$.Event.add($('domelement'),'click touchstart',clickTouchHandler);
```#### $.Event.remove(object,type,handler)
- Remove an event `handler` from the given `object` of the given `type`.
- Event `type` can be given as a space separated list for removing multiple events from a single `object`.#### $.Event.getTarget(event)
- Returns the DOM element that the given `event` was dispatched on.
- Handles the edge case with older versions of Safari where a [text node would be incorrectly returned](https://bugs.jquery.com/ticket/5539).#### $.Event.isMouseEnterLeave(event,element)
Emulates behavior of the mighty handy and IE only (**note:** Chrome 30+ and Firefox 10+ also natively support) event types of [mouseenter](https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter) and [mouseleave](https://developer.mozilla.org/en-US/docs/Web/Events/mouseleave).Example:
```html
Child element
Another child element
``````js
function mouseEnterHandler(event) {if ($.Event.isMouseEnterLeave(event,this)) {
console.log('mouseenter!');
}
}function mouseLeaveHandler(event) {
if ($.Event.isMouseEnterLeave(event,this)) {
console.log('mouseleave!');
}
}var watchMeEl = $('watchme');
$.Event.add(watchMeEl,'mouseover',mouseEnterHandler);
$.Event.add(watchMeEl,'mouseout',mouseLeaveHandler);
```With above example messages will only log messages when mouse pointer *enters* or *leaves* `
`, ignoring all mouseover/mouseout child events fired from `` elements.#### $.Event.getMousePosition(event)
- Returns the current mouse x/y pixel coordinates from the given `event`.
- Data will be returned as an object with the structure of `{ x: 123,y: 456 }`.
- **Note:** At time of writing IE10 (and possibly other browser vendors going forward) can/will return mouse coordinates with a sub-pixel resolution, `getMousePosition()` will round down to whole pixel units.### DOM
#### $$(query) / $$(element,query)
- A wrapper for [`querySelectorAll()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll), returning DOM elements for the given CSS `query`.
- In the first form the query will be based from `document` (entire page), otherwise in the second form from the given `element`.
- In the instance `query` is matching elements containing one or more classes _only_ (e.g. `.apple.orange.banana`) the function will use [`getElementsByClassName()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName) in place of `querySelectorAll()` for query speed advantage.
- Returned DOM elements will be provided as an array, rather than a `NodeList`.
- **Note:** `querySelectorAll()` will only support queries based upon the browsers CSS implementation and it's capabilities.#### $.DOM.ready(handler)
- Will call the given `handler` upon firing of the `document.DOMContentLoaded` event.
- Can be called with multiple `handler` functions, each of which be called in turn at the point of DOM load completion.
- If called *after* DOM has already loaded, the given `handler` will execute immediately via [$.nextTick(handler)](#nexttickhandler).#### $.DOM.create(name[,attributeList][,childElementList])
- Creates a new DOM element with the given node `name`.
- Optional attributes given as a key/value object `attributeList`.
- Keys are to be given as DOM element properties (e.g. `class="myclass"` as `{ className: 'myclass' }`.
- Optional child DOM elements automatically appended given as an array `childElementList`.
- Child elements of type `string` will be appended as a new `TextNode`.Example:
```js
var myCreatedDOMEl = $.DOM.create(
'div',{ className: 'myclass' },
[
$.DOM.create('span',false,['My span text']),
$.DOM.create('a',{ href: '/link/to/item' },['Click me']),
'Another line of text'
]
);// append the following tag structure to end of the document
/*
*/document.documentElement.appendChild(myCreatedDOMEl);
```#### $.DOM.insertBefore(element,referenceElement)
Insert the given `element` before `referenceElement` within the current document.#### $.DOM.insertAfter(element,referenceElement)
Insert the given `element` after `referenceElement` within the current document.#### $.DOM.replace(element,oldElement)
Replace the given `oldElement` within the current document with `element`. Returns `oldElement`.#### $.DOM.remove(element)
Remove the given `element` from the DOM, returning `element`.#### $.DOM.removeChildAll(element)
Remove all child DOM elements from the given `element`, returning an array of removed elements.#### $.DOM.hasClass(element,name)
Returns `true` if `element` has the given CSS class `name` assigned, otherwise return `false`.#### $.DOM.addClass(element,name)
- Add one or more CSS classes of the given `name` to `element` - providing multiple CSS class names space separated.
- CSS classes already present on `element` will be silently ignored.#### $.DOM.removeClass(element,name)
- Remove one or more CSS classes of the given `name` from `element`.
- Provide multiple CSS class names for removal space separated.#### $.DOM.setStyle(element,styleList)
- Set the given inline CSS `styleList` (as a key/value object) to `element`. Essentially an easier way to set multiple inline element style attributes at once.
- Internally uses a simplistic `element.style.[styleKey] = value` assignment, therefore `styleList` key(s) must be given using camel cased style names (e.g. `backgroundColor`).Example:
```js
var myCreatedDOMEl = $.DOM.create('div',false,['Content']);
$.DOM.setStyle(
myCreatedDOMEl,
{
backgroundColor: '#f00',
left: '10px',
position: 'absolute',
top: '40px'
}
);// myCreatedDOMEl contains
/*
Content
*/
```#### $.DOM.getData(element,key)
- Returns the value of the [HTML5 data attribute](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes) `key` associated to `element`.
- If the given `key` does not exist returns `null`.#### $.DOM.getOffset(element[,toParent])
- Returns the left/top pixel offset of the given `element` to either the top left corner of the document, or if `toParent` is `true` - to the element's parent.
- Data will be returned as an object with the structure of `{ left: 123,top: 456 }`.#### $.DOM.getPageScroll()
- Returns the x/y pixel scroll offset from the top left corner of the document.
- Data will be returned as an object with the structure of `{ x: 123,y: 456 }`.#### $.DOM.getViewportSize()
- Returns the pixel width and height of the browser viewport.
- Data will be returned as an object with the structure of `{ width: 123,height: 456 }`.#### $.DOM.getDocumentSize()
- Returns the pixel width and height of the document.
- Data will be returned as an object with the structure of `{ width: 123,height: 456 }`.
- Uses the techniques suggested by [Ryan Van Etten](https://ryanve.com/lab/dimensions/#document).### Animation/transition end DOM events
For the background behind these methods and their use, refer to the [cssanimevent](https://github.com/magnetikonline/cssanimevent) library. The following methods have been integrated here.#### $.DOM.Anim.onAnimationEnd(element,handler[,data])
- Calls the given `handler` upon completion of a [CSS3 animation](https://developer.mozilla.org/en/docs/Web/CSS/animation) applied to `element`. Lifetime of the handler is *one* animation end event.
- For browsers that do not support CSS3 animations, `handler` will be called instantaneously.
- Handler will be passed arguments of `element` and optional `data`.#### $.DOM.Anim.cancelAnimationEnd(element)
Cancel a pending handler assigned to `element` by a previous call to `$.DOM.Anim.onAnimationEnd()`.#### $.DOM.Anim.onTransitionEnd(element,handler[,data])
Identical in functionality to `$.DOM.Anim.onAnimationEnd()`, but for [CSS3 transitions](https://developer.mozilla.org/en/docs/Web/CSS/transition).#### $.DOM.Anim.cancelTransitionEnd(element)
Identical in functionality to `$.DOM.Anim.cancelAnimationEnd()`, but for CSS3 transitions.### XMLHTTP
#### $.request(url[,method][,handler][,parameterCollection])
- Execute a `XMLHttpRequest()` call to the given `url`, returning `true` if the call was successful made by the browser (e.g. supports `XMLHttpRequest()`).
- The `method` can be one of `GET` or `POST`, with `false`/`undefined` defaulting to `GET`.
- Optional `handler` will be executed at completion of the URL call (success or fail). Handler will be passed a single parameter of the return status/response as an object with the following keys:
- `ok:` Set `true` if the call returned successfully, otherwise `false`.
- `status:` Numeric HTTP status code returned.
- `text:` The response body as a string upon success, otherwise empty string.
- `JSON:` If response body is JSON data and could be successfully parsed, will contain a JavaScript object of this data, otherwise an empty object.
- Optional `parameterCollection` given as key/value pairs with be passed either:
- On the query string with HTTP `GET`.
- Form data of content type `application/x-www-form-urlencoded` with HTTP `POST`.Example:
```js
function myHandler(data) {if (data.ok) {
console.log('HTTP status: ' + data.status);
console.log('Response text: ' + data.text);
console.dir(data.JSON);} else {
// handle error
}
}// make a POST request to /xmlhttp/endpoint with parameters "key1=value,key2=value"
$.request(
'/xmlhttp/endpoint',
'POST',
myHandler,
{
key1: 'value',
key2: 'value'
}
);
```### Miscellaneous
#### *Has JavaScript?* CSS class hook
- Placing a class attribute of `` on a document's `` element will be automatically replaced with `` upon load of Picoh.
- Used as a CSS styling hook for no/has JavaScript scenarios.#### Attachment of Picoh to alternative object
- By default Picoh is attached to the global `window` object, providing access to it's methods via `window.$` and `window.$$()` respectively, or simply `$` and `$$()`.
- Alternatively, Picoh can be attached to an isolated object to avoid namespace clashes, by modification of the library's [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) arguments.Example:
```js
var attachHere = {};// start of Picoh
(function(win,doc,picohAttach,undefined) {// SNIP
})(window,document,attachHere);
```Picoh will be accessible at `attachHere.$`/`attachHere.$$()`.