Cleaning House (JS)

This commit is contained in:
Max Lynch
2013-09-22 22:55:56 -05:00
parent 509b3c345c
commit 0aeb90bed5
8 changed files with 0 additions and 485 deletions

View File

@ -1,208 +0,0 @@
/**
* The LeftRightMenuViewController makes it easy to have an interface
* with two hidden menus: one on the left, and one on the right.
*
* The main content supports dragging to show either panel, or the panel can be
* show/hidden through buttons elsewhere in the app.
*
* Either panel can be disabled based on the context in the app.
*/
(function(window, document, ion) {
ion.controllers = ion.controllers || {};
ion.controllers.LeftRightMenuViewController = function(options) {
var _this = this;
this.animateClass = options.animateClass;
this.left = options.left;
this.leftWidth = options.leftWidth;
this.right = options.right;
this.rightWidth = options.rightWidth;
this.center = options.center;
this.isLeftEnabled = options.isLeftEnabled == undefined ? true : options.isLeftEnabled;
this.isRightEnabled = options.isRightEnabled == undefined ? true : options.isRightEnabled;
this._rightShowing = false;
this._leftShowing = false;
// Bind release and drag listeners
window.ion.onGesture('release', function(e) {
_this._endDrag(e);
}, this.center);
window.ion.onGesture('drag', function(e) {
_this._handleDrag(e);
}, this.center);
};
ion.controllers.LeftRightMenuViewController.prototype = {
setIsLeftEnabled: function(isLeftEnabled) {
this.isLeftEnabled = isLeftEnabled;
},
setIsRightEnabled: function(isRightEnabled) {
this.isRightEnabled = isRightEnabled;
},
toggleLeft: function() {
var openAmount = this.getOpenAmount();
if(openAmount > 0) {
this.openPercentage(0);
} else {
this.openPercentage(100);
}
},
toggleRight: function() {
var openAmount = this.getOpenAmount();
if(openAmount < 0) {
this.openPercentage(0);
} else {
this.openPercentage(-100);
}
},
getOpenAmount: function() {
var r = /translate3d\((-?\d+)px/;
var d = r.exec(this.center.style.webkitTransform);
if(d && d.length > 0) {
return parseInt(d[1]);
}
return 0;
},
getOpenRatio: function() {
var amount = this.getOpenAmount();
if(amount >= 0) {
return amount / this.leftWidth;
}
return amount / this.rightWidth;
},
openPercentage: function(percentage) {
var p = percentage / 100;
var maxLeft = this.leftWidth;
var maxRight = this.rightWidth;
if(percentage >= 0) {
this.openAmount(maxLeft * p);
} else {
this.openAmount(maxRight * p);
}
},
openAmount: function(amount) {
var maxLeft = this.leftWidth;
var maxRight = this.rightWidth;
// Check if we can move to that side, depending if the left/right panel is enabled
if((!this.isLeftEnabled && amount > 0) || (!this.isRightEnabled && amount < 0)) {
return;
}
if((this._leftShowing && amount > maxLeft) || (this._rightShowing && amount < -maxRight)) {
return;
}
this.center.style.webkitTransform = 'translate3d(' + amount + 'px, 0, 0)';
if(amount >= 0) {
this._leftShowing = true;
this._rightShowing = false;
if(this.isRightEnabled) {
this.right.style.zIndex = -1;
}
if(this.isLeftEnabled) {
this.left.style.zIndex = 0;
}
} else {
this._rightShowing = true;
this._leftShowing = false;
if(this.isRightEnabled) {
this.right.style.zIndex = 0;
}
if(this.isLeftEnabled) {
this.left.style.zIndex = -1;
}
}
},
snapToRest: function(e) {
// We want to animate at the end of this
this.center.classList.add(this.animateClass);
this._isDragging = false;
// Check how much the panel is open after the drag, and
// what the drag velocity is
var ratio = this.getOpenRatio();
if(ratio == 0)
return;
var velocityThreshold = 0.3;
var velocityX = e.gesture.velocityX
var direction = e.gesture.direction;
// Less than half, going left
//if(ratio > 0 && ratio < 0.5 && direction == 'left' && velocityX < velocityThreshold) {
//this.openPercentage(0);
//}
// Going right, less than half, too slow (snap back)
if(ratio > 0 && ratio < 0.5 && direction == 'right' && velocityX < velocityThreshold) {
this.openPercentage(0);
}
// Going left, more than half, too slow (snap back)
else if(ratio > 0.5 && direction == 'left' && velocityX < velocityThreshold) {
this.openPercentage(100);
}
// Going left, less than half, too slow (snap back)
else if(ratio < 0 && ratio > -0.5 && direction == 'left' && velocityX < velocityThreshold) {
this.openPercentage(0);
}
// Going right, more than half, too slow (snap back)
else if(ratio < 0.5 && direction == 'right' && velocityX < velocityThreshold) {
this.openPercentage(-100);
}
// Going right, more than half, or quickly (snap open)
else if(direction == 'right' && ratio >= 0 && (ratio >= 0.5 || velocityX > velocityThreshold)) {
this.openPercentage(100);
}
// Going left, more than half, or quickly (span open)
else if(direction == 'left' && ratio <= 0 && (ratio <= -0.5 || velocityX > velocityThreshold)) {
this.openPercentage(-100);
}
// Snap back for safety
else {
this.openPercentage(0);
}
},
_endDrag: function(e) {
this.snapToRest(e);
},
_initDrag: function(e) {
this.center.classList.remove(this.animateClass);
this._isDragging = true;
this._startX = 0;
this._offsetX = 0;
this._lastX = 0;
},
_handleDrag: function(e) {
if(!this._isDragging) {
this._initDrag(e);
this._startX = e.gesture.touches[0].pageX;
this._lastX = this._startX;
this._offsetX = this.getOpenAmount();
}
//console.log('Dragging page', this._startX, this._lastX, this._offsetX, e);
var newX = this._offsetX + (this._lastX - this._startX);
this.openAmount(newX);
this._lastX = e.gesture.touches[0].pageX;
}
};
})(this, document, ion = this.ion || {});

View File

@ -1,19 +0,0 @@
(function(window, document, ion) {
ion.controllers = ion.controllers || {};
ion.controllers.TabController = function(options) {
this.viewControllers = [];
this.selectedViewController = null;
var tabChildren = options.tab.querySelectorAll('.tab-item');
console.log("Building from", tabChildren.length, "tab items");
for(var i = 0; i < tabChildren.length; i++) {
}
};
ion.controllers.TabController.prototype = {
};
})(this, document, ion = this.ion || {});

View File

@ -1,29 +0,0 @@
(function(window, document, ion) {
ion.Button = function() {}
// Process an the touchstart event and if this is a button,
// add the .active class so Android will show depressed
// button states.
ion.Button.prototype._onTouchStart = function(event) {
console.log('Touch start!', event);
if(event.target && event.target.classList.contains('button')) {
event.target.classList.add('active');
}
};
// Remove any active state on touch end/cancel/etc.
ion.Button.prototype._onTouchEnd = function(event) {
console.log('Touch end!', event);
if(event.target && event.target.classList.contains('button')) {
event.target.classList.remove('active');
}
// TODO: Process the click? Set flag to not process other click events
};
document.addEventListener('touchstart', ion.Button.prototype._onTouchStart);
document.addEventListener('touchend', ion.Button.prototype._onTouchEnd);
document.addEventListener('touchcancel', ion.Button.prototype._onTouchEnd);
})(this, document, ion = this.ion || {});

View File

@ -1,23 +0,0 @@
(function(window, document, ion) {
ion.List = function() {}
ion.List.prototype._TAB_ITEM_CLASS = 'tab-item';
ion.List.prototype._onTouchStart = function(event) {
console.log('Touch start!', event);
if(event.target && event.target.parentNode.classList.contains(this._TAB_ITEM_CLASS)) {
event.target.classList.add('active');
}
};
ion.List.prototype._onTouchEnd = function(event) {
console.log('Touch end!', event);
if(event.target && event.target.parentNode.classList.contains(this._TAB_ITEM_CLASS)) {
event.target.classList.remove('active');
}
};
document.addEventListener('mousedown', ion.List.prototype._onTouchStart);
document.addEventListener('touchstart', ion.List.prototype._onTouchStart);
document.addEventListener('touchend', ion.List.prototype._onTouchEnd);
})(this, document, ion = this.ion || {});

View File

@ -1,72 +0,0 @@
(function(window, document, ion) {
var
x,
isPanelOpen,
PANEL_ACTIVE = "ion-panel-active",
PANEL_ACTIVE_LEFT = "ion-panel-active-left",
PANEL_ACTIVE_RIGHT = "ion-panel-active-right",
PANEL_OPEN_LEFT = "ion-panel-left",
PANEL_OPEN_RIGHT = "ion-panel-right";
ion.Panel = {
toggle: function(panelId, options) {
if(isPanelOpen) {
this.close();
} else {
this.open(panelId, options);
}
},
open: function(panelId, options) {
// see if there is an element with this id
var panel = document.getElementById(panelId);
if(panel) {
// this element is a panel, open it!
// remember that a panel is currently open
isPanelOpen = true;
// find all the panels that are or were once active
var panelsActive = document.getElementsByClassName(PANEL_ACTIVE);
// remove the panel-active css classes from each of the previously active panels
for(x=0; x<panelsActive.length; x++) {
panelsActive[x].classList.remove(PANEL_ACTIVE);
}
// activate the panel we want open by adding the panel-active css classes
panel.classList.add(PANEL_ACTIVE);
// add to <body> that there is a panel open
if(options && options.direction === "right") {
panel.classList.add(PANEL_ACTIVE_RIGHT);
document.body.classList.add(PANEL_OPEN_RIGHT);
} else {
// left is the default
panel.classList.add(PANEL_ACTIVE_LEFT);
document.body.classList.add(PANEL_OPEN_LEFT);
}
}
},
close: function() {
if(isPanelOpen) {
// there is a panel already open, so close it
isPanelOpen = false;
// remove from <body> so that no panels should be open
var className = document.body.className;
className = className.replace(PANEL_OPEN_LEFT, "").replace(PANEL_OPEN_RIGHT, "").trim();
document.body.className = className;
}
}
};
window.addEventListener("popstate", ion.Panel.close, false);
})(this, document, ion = this.ion || {});

View File

@ -1,25 +0,0 @@
'use strict';
(function(window, document, ion) {
ion.Tabs = function() {}
ion.Tabs.prototype._TAB_ITEM_CLASS = 'tab-item';
ion.Tabs.prototype._onTouchStart = function(event) {
console.log('Touch start!', event);
if(event.target && event.target.parentNode.classList.contains(this._TAB_ITEM_CLASS)) {
event.target.classList.add('active');
}
};
ion.Tabs.prototype._onTouchEnd = function(event) {
console.log('Touch end!', event);
if(event.target && event.target.parentNode.classList.contains(this._TAB_ITEM_CLASS)) {
event.target.classList.remove('active');
}
};
document.addEventListener('mousedown', ion.Tabs.prototype._onTouchStart);
document.addEventListener('touchstart', ion.Tabs.prototype._onTouchStart);
document.addEventListener('touchend', ion.Tabs.prototype._onTouchEnd);
})(this, document, ion = this.ion || {});

View File

@ -1,68 +0,0 @@
'use strict';
(function(window, document, ion) {
// Loop through each element in the DOM and collect up all
// the templates it has. A template either has data to supply
// to others, or it needs data from another template
function initTemplates() {
var
x,
el,
tmp,
emptyTemplates = [],
container,
templateElements;
// collect up all the templates currently in the DOM
templateElements = document.body.querySelectorAll("[data-template]");
for(x=0; x<templateElements.length; x++) {
el = templateElements[x];
if(el.dataset.template && !el.tSet) {
// this element is either supplying template
// data or it needs to be filled with template data
if(el.innerHTML == "") {
// this element is requesting to have its innerHTML
// built from a template already set
emptyTemplates.push(el);
} else {
// this element contains innerHTML which should be used
// as a template for other elements. Save this template
// data for future use.
// Save only in sessionStorage, which maintains a storage area that's
// available for the duration of the page session. A page session
// lasts for as long as the browser is open and survives over page
// reloads and restores. Opening a page in a new tab or window will
// cause a new session to be initiated.
sessionStorage.setItem("t:" + el.dataset.template, el.outerHTML);
}
// remember that this is set so we don't bother doing all this
// code again for the same element in the future
el.tSet = true;
}
}
// go through each empty template and build it up with existing template data
for(x=0; x<emptyTemplates.length; x++) {
el = emptyTemplates[x];
tmp = sessionStorage.getItem("t:" + el.dataset.template);
if(tmp) {
// we've got template data, plug it into this element's innerHTML
container = document.createElement("div");
container.innerHTML = tmp;
el.parentNode.replaceChild(container.children[0].cloneNode(true), el);
}
}
}
ion.on("ready", initTemplates);
ion.on("pagecreate", initTemplates);
})(this, document, ion = this.ion || {});

View File

@ -1,41 +0,0 @@
(function(window, document, ion) {
function initTransitions(e) {
var data = e.detail.data;
// build a new main element to hold the new html
var newMainElement = document.createElement("main");
newMainElement.innerHTML = data.main;
// get the old main element, which will be the first one
var oldMainElement = document.querySelector("main");
// decide how to do the page transition
if(data.transition === "slide-from-left") {
slideStart(newMainElement, oldMainElement, "left");
} else {
// No animation. Nothing fancy here
noTransition(newMainElement, oldMainElement, data);
}
}
function noTransition(newMainElement, oldMainElement, data) {
// entirely replace the old element, no transition
oldMainElement.parentNode.replaceChild(newMainElement, oldMainElement);
ion.trigger("pagecreate", {
url: data.url,
title: data.title
});
ion.trigger("pageview");
}
function slideStart(newMainElement, oldMainElement, fromDirection) {
// copy what the main element currently looks like into a document fragment
// make all the changes to the document fragment, then replace the
// old main with the two new ones. Both the old and new main will be
// in the DOM, but their CSS classes will do the transitioning for us
}
ion.on("pageloaded", initTransitions);
})(this, document, ion = this.ion || {});