Skip to content

Instantly share code, notes, and snippets.

@hpstuff
Last active December 19, 2015 03:39
Show Gist options
  • Save hpstuff/5892047 to your computer and use it in GitHub Desktop.
Save hpstuff/5892047 to your computer and use it in GitHub Desktop.
var Ajax = (function(){
function Ajax(){
this.xhr = new XMLHttpRequest();
this.handlers();
}
Ajax.prototype.handlers = function(){
var _this = this;
this.xhr.onreadystatechange = function(){
if(_this.xhr.readyState == 4){
if(_this.xhr.status == 200){
_this.successHandler(_this.xhr.response, true);
}else{
_this.errorHandler();
}
}
};
this.onabort = function(){
_this.errorHandler();
};
this.onerror = function(){
_this.errorHandler();
};
};
Ajax.prototype.successHandler = function(response, force){
var data;
try{
data = JSON.parse(response);
}catch (e){
data = response;
}
if(force) localStorage.setItem(this.url, response);
this.dispatchEvent("load", data);
};
Ajax.prototype.errorHandler = function(){
var response = localStorage.getItem(this.url);
if(response){
this.successHandler(response);
}else{
this.dispatchEvent("error", this.xhr.response);
}
};
Ajax.prototype.toQuery = function(data){
var key, q = [], i, value;
for(key in data){
value = data[key];
if(!(value instanceof Array)) value = [value];
for(i = 0; i < value.length; i++){
q.push(key+"="+value[i]);
}
}
return q.join("&");
};
Ajax.prototype.createURL = function(url, data){
return url + (url.indexOf("?") > -1 ? "&" : "?") + this.toQuery(data);
};
Ajax.prototype.open = function(method, url){
this.xhr.open(method, url, true);
};
Ajax.prototype.get = function(url, data){
this.url = data ? this.createURL(data) : url;
this.open("GET", this.url);
this.xhr.send(null);
};
Ajax.prototype.post = function(url, data){
this.open("POST", this.url = url);
if(data) this.xhr.send(JSON.stringify(data));
};
Ajax.prototype.delete = function(url, data){
this.url = data ? this.createURL(data) : url;
this.open("DELETE", this.url);
this.xhr.send(null);
};
Ajax.prototype.put = function(url, data){
this.open("PUT", this.url = url);
if(data) this.xhr.send(JSON.stringify(data));
};
EventDispatcher.implementation(Ajax.prototype);
return Ajax;
})();
NodeList.prototype.forEach = function(callback){
Array.prototype.forEach.call(this, callback);
};
var EventDispatcher = (function(){
function EventDispatcher(){
this._listeners = {};
}
EventDispatcher.prototype.dispatchEvent = function(event, data){
var _this = this;
if(!this._listeners[event]) return;
this._listeners[event].forEach(function(callback){
callback.call(_this, data);
});
};
EventDispatcher.prototype.addEventListener = function(event, listener){
if(!this._listeners) this._listeners = {};
if(!this._listeners[event]) this._listeners[event] = [];
this._listeners[event].push(listener);
};
EventDispatcher.prototype.removeEventListener = function(event, listener){
if(!this._listeners[event]) return;
var index = this._listeners[event].indexOf(listener);
if(index > -1) this._listeners[event].splice(index, 1);
};
EventDispatcher.implementation = function(proto){
var prop;
for(prop in EventDispatcher.prototype){
proto[prop] = EventDispatcher.prototype[prop];
}
};
return EventDispatcher;
})();
var JSONP = (function(){
var counter = 0;
var callbacks = {};
function JSONP(){
this.url = "";
this.response = void 0;
this.script = document.createElement('script');
}
JSONP.prototype.get = function(url){
var _this = this;
//create callback to get data
callbacks[this.counter = counter] = function(data){
_this.response = data;
_this.removeCallback(this.counter);
}.bind(this);
this.addEvents();
//load url in script
this.load(url);
counter++;
};
JSONP.prototype.removeCallback = function(index){
delete callbacks[index];
};
JSONP.prototype.load = function(url){
this.url = url;
this.script.src = url += "JSONP.callbacks["+counter+"]";
document.body.appendChild(this.script);
};
JSONP.prototype.successHandler = function(response, local){
var data;
try{
data = JSON.parse(response);
}catch (e){
data = response;
}
if(!local) {
if(typeof response != 'string') response = JSON.stringify(response);
localStorage.setItem(this.url, response);
}
this.dispatchEvent("load", data);
};
JSONP.prototype.errorHandler = function(){
var response = localStorage.getItem(this.url);
if(response){
this.successHandler(response, true);
}else{
this.dispatchEvent("error");
}
};
JSONP.prototype.addEvents = function(){
var _this = this;
//add events to remove script tag
this.script.addEventListener('load', function(){
_this.successHandler(_this.response);
this.parentElement.removeChild(this);
});
this.script.addEventListener('error', function(){
_this.errorHandler();
this.parentElement.removeChild(this);
});
};
EventDispatcher.implementation(JSONP.prototype);
JSONP.callbacks = callbacks;
return JSONP;
})();
var Layout = (function(){
function Layout(){
}
Layout.prototype = new parent;
Layout.prototype.constructor = Layout;
Layout.prototype.setType = function(orient){
};
return Layout;
})(Element);
var Loader = (function(){
function Loader(){
this.data = {};
this.imagesData = [];
}
Loader.prototype.constructor = Loader;
Loader.prototype.loadImages = function(images){
var _this = this;
this.imageCounter = 0;
(this.imagesData = images).forEach(function(image){
_this.loadImage(image);
});
};
Loader.prototype.loadImage = function(data){
var _this = this, image = new Image();
if(this.imagesData.length === 0) this.imagesData.push(data);
if(this.imageCounter == void 0) this.imageCounter = 0;
image.onload = function(){
_this.data[data.id] = this;
_this.imageCounter++;
if(_this.imageCounter === _this.imagesData.length){
_this.imagesData.length = 0;
_this.imageCounter = void 0;
_this.dispatchEvent("complete")
}
};
image.src = data.src;
};
Loader.prototype.getResult = function(id){
return this.data[id];
};
EventDispatcher.implementation(Loader.prototype);
return Loader;
})();
var Page = (function(parent){
function Page(element, duration){
parent.call(this);
this._active = false;
this.update(element);
}
Page.prototype = new parent;
Page.prototype.update = function(element){
if(element) this.element = element;
};
Page.prototype.constructor = Page;
Page.prototype.hide = function(effect, data){
var _this = this;
if(!this._active) return;
this.dispatchEvent("beforeHide", data);
if(!effect){
this.element.classList.remove("current");
return this._active = false;
}
if(this._animating) return;
this._animating = true;
this.element.addEventListener("webkitAnimationEnd", function fn(){
_this.dispatchEvent("onHide", data);
_this._active = false;
_this._animating = false;
this.classList.remove("current");
this.classList.remove(effect);
_this.element.removeEventListener("webkitAnimationEnd", fn);
});
this.element.classList.add(effect);
};
Page.prototype.show = function(effect, data){
var _this = this;
if(this._active) return;
this.dispatchEvent("beforeShow", data);
if(!effect){
this.element.classList.add("current");
return this._active = true;
}
if(this._animating) return;
this._animating = true;
this.element.addEventListener("webkitAnimationEnd", function fn(){
_this.dispatchEvent("onShow", data);
_this._active = true;
_this._animating = false;
this.classList.remove(effect);
this.removeEventListener("webkitAnimationEnd", fn);
});
this.element.classList.add("current");
this.element.classList.add(effect);
};
return Page;
})(Base);
var debug = true;
/**
* Add events for touches and desktop devices and prevent move page in iphone.
* Create custom Active state and prevent this active state by adding a data-activatable in your
* html or data-preventactive also create a fast click by dispatching a custom event
*/
(function(){
var has = "ontouchstart" in window,
active_tl,
debugTimer = void(0),
_oldItems = [], _oldPrevent = [],
touches = {
start: has ? "touchstart": "mousedown",
touch: has ? "touch": "touch",
move: has ? "touchmove": "mousemove",
end: has ? "touchend": "mouseup",
cancel: has ? "touchcancel": "mouseleave"
},
items, prevent;
/**
* function that dispatch custom event for fast click to item
* @param item {Element}
*/
function dispatchTouch(item){
var event = document.createEvent("Event");
event.initEvent(touches.touch, true, true);
item.dispatchEvent(event);
}
/**
* function that gets the element offset in page context
* @param el {Element}
* @returns {left, top}
*/
function getElementPageOffset(el){
var l = 0, t = 0;
do{
l += el.offsetLeft;
t += el.offsetTop;
}while(el = el.offsetParent);
return {left:l, top:t};
}
/**
* function that return first activatable parent element
* @param item {Element}
* @returns {Element} activatable element
*/
function getParentActivatable(item){
do{
if(item.getAttribute("data-clickable")) return item;
}while(item = item.parentElement);
}
function update(){
items = document.querySelectorAll("[data-clickable]");
prevent = document.querySelectorAll("[data-preventclickable]");
/**
* Add events to all activatable items
*/
Array.prototype.forEach.call(items, function(item){
if(Array.prototype.indexOf.call(_oldItems, item) > -1) return;
item.addEventListener(touches.start, function(){
item.classList.add("active");
});
item.addEventListener(touches.cancel, function(e){
var active = document.querySelector(".active");
if(active) active.classList.remove("active");
});
item.addEventListener(touches.end, function(e){
doEnd(e);
});
});
/**
* Add start event and stopPropagation to prevent active
*/
Array.prototype.forEach.call(prevent, function(item){
if(Array.prototype.indexOf.call(_oldPrevent, item) > -1) return;
item.addEventListener(touches.start, function(e){
e.stopPropagation();
});
});
_oldItems = items;
_oldPrevent = prevent;
}
/**
* Remove custom active state and dispatch fast click event if active item
* is equal to current event item
* @param e
*/
function doEnd(e){
var active = document.querySelector(".active"),
_item = getParentActivatable(e.target);
//get parent activatable item and check if is equal to active element
if(active === _item) dispatchTouch(active);
if(active) {
clearTimeout(active_tl);
active_tl = setTimeout(function(){
active.classList.remove("active");
},300);
}
}
update();
/**
* Prevent default move event to remove page moving on iphone
*/
window.addEventListener(touches.move, function(e){
e.preventDefault();
});
window.addEventListener("DOMNodeInserted", function(){
//update();
});
window.addEventListener("updateClickable", function(){
update();
});
})();
(function(){
var _old_scrolls = [],
scrolls = document.querySelectorAll('[data-scrollable="true"]');
function createScrolls(){
(scrolls || []).forEach(function(el){
if(el.scroll) {
return el.scroll.refresh();
}
el.scroll = new IScroll(el, {
scrollbars: eval(el.dataset['scrollbars']) ? 'custom': false,
fadeScrollbars: eval(el.dataset['scrollbarFade']),
bounce: el.dataset['scrollBaunce'] ? eval(el.dataset['scrollBaunce']) : true,
probeType: 2
});
el.scroll.on("scrollStart", function(){
var el = this.wrapper.querySelector('.active');
if(el) el.classList.remove('active');
});
});
}
function update(){
_old_scrolls = scrolls;
scrolls = document.querySelectorAll('[data-scrollable="true"]');
createScrolls();
}
function refresh(){
(scrolls || []).forEach(function(el){
if(el.scroll) el.scroll.refresh();
});
}
update();
window.addEventListener("updateScrolls", function(){
update();
});
window.addEventListener("refreshScrolls", function(){
refresh();
});
})();
(function(){
if(!debug) return;
window.addEventListener('touchstart', function(e){
if(e.touches.length >= 3) {
window.location.reload(true);
}
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment