mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-07 06:57:02 +08:00
Moved hacking controllers and views
They are now official files.
This commit is contained in:
105
js/controllers/navController.js
Normal file
105
js/controllers/navController.js
Normal file
@ -0,0 +1,105 @@
|
||||
(function(window, document, ionic) {
|
||||
NavController = function(opts) {
|
||||
var _this = this;
|
||||
|
||||
this.navBar = opts.navBar;
|
||||
this.content = opts.content;
|
||||
this.controllers = opts.controllers || [];
|
||||
|
||||
this._updateNavBar();
|
||||
|
||||
// TODO: Is this the best way?
|
||||
this.navBar.shouldGoBack = function() {
|
||||
_this.pop();
|
||||
}
|
||||
};
|
||||
|
||||
NavController.prototype = {
|
||||
getControllers: function() {
|
||||
return this.controllers;
|
||||
},
|
||||
getTopController: function() {
|
||||
return this.controllers[this.controllers.length-1];
|
||||
},
|
||||
push: function(controller) {
|
||||
var last = this.controllers[this.controllers.length - 1];
|
||||
|
||||
this.controllers.push(controller);
|
||||
|
||||
// Indicate we are switching controllers
|
||||
var shouldSwitch = this.switchingController && this.switchingController(controller) || true;
|
||||
|
||||
// Return if navigation cancelled
|
||||
if(shouldSwitch === false)
|
||||
return;
|
||||
|
||||
// Actually switch the active controllers
|
||||
|
||||
// Remove the old one
|
||||
//last && last.detach();
|
||||
if(last) {
|
||||
last.isVisible = false;
|
||||
last.visibilityChanged && last.visibilityChanged();
|
||||
}
|
||||
|
||||
// Grab the top controller on the stack
|
||||
var next = this.controllers[this.controllers.length - 1];
|
||||
|
||||
// TODO: No DOM stuff here
|
||||
//this.content.el.appendChild(next.el);
|
||||
next.isVisible = true;
|
||||
next.visibilityChanged && next.visibilityChanged();
|
||||
|
||||
this._updateNavBar();
|
||||
|
||||
return controller;
|
||||
},
|
||||
|
||||
pop: function() {
|
||||
var next, last;
|
||||
|
||||
// Make sure we keep one on the stack at all times
|
||||
if(this.controllers.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab the controller behind the top one on the stack
|
||||
last = this.controllers.pop();
|
||||
if(last) {
|
||||
last.isVisible = false;
|
||||
last.visibilityChanged && last.visibilityChanged();
|
||||
}
|
||||
|
||||
// Remove the old one
|
||||
//last && last.detach();
|
||||
|
||||
next = this.controllers[this.controllers.length - 1];
|
||||
|
||||
// TODO: No DOM stuff here
|
||||
//this.content.el.appendChild(next.el);
|
||||
next.isVisible = true;
|
||||
next.visibilityChanged && next.visibilityChanged();
|
||||
|
||||
// Switch to it (TODO: Animate or such things here)
|
||||
|
||||
this._updateNavBar();
|
||||
|
||||
return last;
|
||||
},
|
||||
|
||||
_updateNavBar: function() {
|
||||
if(!this.getTopController()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.navBar.setTitle(this.getTopController().title);
|
||||
|
||||
if(this.controllers.length > 1) {
|
||||
this.navBar.showBackButton(true);
|
||||
} else {
|
||||
this.navBar.showBackButton(false);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
})(this, document, this.ionic || {});
|
||||
191
js/controllers/sideMenuController.js
Normal file
191
js/controllers/sideMenuController.js
Normal file
@ -0,0 +1,191 @@
|
||||
(function(window, document, ionic) {
|
||||
|
||||
SideMenuController = function(options) {
|
||||
var _this = this;
|
||||
|
||||
|
||||
this.left = options.left;
|
||||
this.right = options.right;
|
||||
this.content = options.content;
|
||||
|
||||
this._rightShowing = false;
|
||||
this._leftShowing = false;
|
||||
|
||||
this.content.onDrag = function(e) {
|
||||
_this._handleDrag(e);
|
||||
};
|
||||
|
||||
this.content.endDrag = function(e) {
|
||||
_this._endDrag(e);
|
||||
};
|
||||
|
||||
/*
|
||||
// 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);
|
||||
*/
|
||||
};
|
||||
|
||||
SideMenuController.prototype = {
|
||||
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() {
|
||||
return this.content.getTranslateX() || 0;
|
||||
},
|
||||
getOpenRatio: function() {
|
||||
var amount = this.getOpenAmount();
|
||||
if(amount >= 0) {
|
||||
return amount / this.left.width;
|
||||
}
|
||||
return amount / this.right.width;
|
||||
},
|
||||
getOpenPercentage: function() {
|
||||
return this.getOpenRatio() * 100;
|
||||
},
|
||||
openPercentage: function(percentage) {
|
||||
var p = percentage / 100;
|
||||
var maxLeft = this.left.width;
|
||||
var maxRight = this.right.width;
|
||||
if(percentage >= 0) {
|
||||
this.openAmount(maxLeft * p);
|
||||
} else {
|
||||
this.openAmount(maxRight * p);
|
||||
}
|
||||
},
|
||||
openAmount: function(amount) {
|
||||
var maxLeft = this.left.width;
|
||||
var maxRight = this.right.width;
|
||||
|
||||
// Check if we can move to that side, depending if the left/right panel is enabled
|
||||
if((!this.left.isEnabled && amount > 0) || (!this.right.isEnabled && amount < 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if((this._leftShowing && amount > maxLeft) || (this._rightShowing && amount < -maxRight)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.content.setTranslateX(amount);
|
||||
|
||||
if(amount >= 0) {
|
||||
this._leftShowing = true;
|
||||
this._rightShowing = false;
|
||||
|
||||
// Push the z-index of the right menu down
|
||||
this.right.pushDown();
|
||||
// Bring the z-index of the left menu up
|
||||
this.left.bringUp();
|
||||
} else {
|
||||
this._rightShowing = true;
|
||||
this._leftShowing = false;
|
||||
|
||||
// Bring the z-index of the right menu up
|
||||
this.right.bringUp();
|
||||
// Push the z-index of the left menu down
|
||||
this.left.pushDown();
|
||||
}
|
||||
},
|
||||
snapToRest: function(e) {
|
||||
// We want to animate at the end of this
|
||||
this.content.enableAnimation();
|
||||
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.content.disableAnimation();
|
||||
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.ionic || {});
|
||||
@ -1,3 +0,0 @@
|
||||
(function(window, document, ion) {
|
||||
|
||||
});
|
||||
43
js/views/navBar.js
Normal file
43
js/views/navBar.js
Normal file
@ -0,0 +1,43 @@
|
||||
(function(window, document, ionic) {
|
||||
|
||||
NavBar = function(opts) {
|
||||
this.el = opts.el;
|
||||
|
||||
this._titleEl = this.el.querySelector('.title');
|
||||
};
|
||||
|
||||
NavBar.prototype = {
|
||||
shouldGoBack: function() {},
|
||||
|
||||
setTitle: function(title) {
|
||||
if(!this._titleEl) {
|
||||
return;
|
||||
}
|
||||
this._titleEl.innerHTML = title;
|
||||
},
|
||||
|
||||
showBackButton: function(shouldShow) {
|
||||
var _this = this;
|
||||
|
||||
if(!this._currentBackButton) {
|
||||
var back = document.createElement('a');
|
||||
back.className = 'button back';
|
||||
back.innerHTML = 'Back';
|
||||
|
||||
this._currentBackButton = back;
|
||||
this._currentBackButton.onclick = function(event) {
|
||||
_this.shouldGoBack && _this.shouldGoBack();
|
||||
}
|
||||
}
|
||||
|
||||
if(shouldShow && !this._currentBackButton.parentNode) {
|
||||
// Prepend the back button
|
||||
this.el.insertBefore(this._currentBackButton, this.el.firstChild);
|
||||
} else if(!shouldShow && this._currentBackButton.parentNode) {
|
||||
// Remove the back button if it's there
|
||||
this._currentBackButton.parentNode.removeChild(this._currentBackButton);
|
||||
}
|
||||
}
|
||||
};
|
||||
})(this, document, ion = this.ionic || {});
|
||||
|
||||
22
js/views/sideMenu.js
Normal file
22
js/views/sideMenu.js
Normal file
@ -0,0 +1,22 @@
|
||||
(function(window, document, ionic) {
|
||||
SideMenu = function(opts) {
|
||||
this.el = opts.el;
|
||||
this.width = opts.width;
|
||||
this.isEnabled = opts.isEnabled || true;
|
||||
};
|
||||
|
||||
SideMenu.prototype = {
|
||||
getFullWidth: function() {
|
||||
return this.width;
|
||||
},
|
||||
setIsEnabled: function(isEnabled) {
|
||||
this.isEnabled = isEnabled;
|
||||
},
|
||||
bringUp: function() {
|
||||
this.el.style.zIndex = 0;
|
||||
},
|
||||
pushDown: function() {
|
||||
this.el.style.zIndex = -1;
|
||||
}
|
||||
};
|
||||
})(this, document, ion = this.ionic || {});
|
||||
201
js/views/tabBar.js
Normal file
201
js/views/tabBar.js
Normal file
@ -0,0 +1,201 @@
|
||||
(function(window, document, ionic) {
|
||||
|
||||
TabBarItem = function(el) {
|
||||
this.el = el;
|
||||
|
||||
this._buildItem();
|
||||
};
|
||||
TabBarItem.prototype = {
|
||||
// Factory for creating an item from a given javascript object
|
||||
create: function(itemData) {
|
||||
var item = document.createElement('a');
|
||||
item.className = 'tab-item';
|
||||
|
||||
// If there is an icon, add the icon element
|
||||
if(itemData.icon) {
|
||||
var icon = document.createElement('i');
|
||||
icon.className = itemData.icon;
|
||||
item.appendChild(icon);
|
||||
}
|
||||
item.appendChild(document.createTextNode(itemData.title));
|
||||
|
||||
return new TabBarItem(item);
|
||||
},
|
||||
|
||||
|
||||
_buildItem: function() {
|
||||
var _this = this, child, children = Array.prototype.slice.call(this.el.children);
|
||||
|
||||
for(var i = 0, j = children.length; i < j; i++) {
|
||||
child = children[i];
|
||||
|
||||
// Test if this is a "i" tag with icon in the class name
|
||||
// TODO: This heuristic might not be sufficient
|
||||
if(child.tagName.toLowerCase() == 'i' && /icon/.test(child.className)) {
|
||||
this.icon = child.className;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Set the title to the text content of the tab.
|
||||
this.title = this.el.innerText.trim();
|
||||
|
||||
this._tapHandler = function(e) {
|
||||
_this.onTap && _this.onTap(e);
|
||||
};
|
||||
|
||||
ionic.on('tap', this._tapHandler, this.el);
|
||||
},
|
||||
onTap: function(e) {
|
||||
console.log('On tap');
|
||||
},
|
||||
|
||||
// Remove the event listeners from this object
|
||||
destroy: function() {
|
||||
ionic.off('tap', this._tapHandler, this.el);
|
||||
},
|
||||
|
||||
getIcon: function() {
|
||||
return this.icon;
|
||||
},
|
||||
|
||||
getTitle: function() {
|
||||
return this.title;
|
||||
},
|
||||
|
||||
setSelected: function(isSelected) {
|
||||
this.isSelected = isSelected;
|
||||
if(isSelected) {
|
||||
this.el.classList.add('active');
|
||||
} else {
|
||||
this.el.classList.remove('active');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TabBar = function(opts) {
|
||||
this.el = opts.el;
|
||||
|
||||
this.items = [];
|
||||
|
||||
this._buildItems();
|
||||
};
|
||||
|
||||
TabBar.prototype = {
|
||||
// get all the items for the TabBar
|
||||
getItems: function() {
|
||||
return this.items;
|
||||
},
|
||||
|
||||
// Add an item to the tab bar
|
||||
addItem: function(item) {
|
||||
// Create a new TabItem
|
||||
var tabItem = TabBarItem.prototype.create(item);
|
||||
|
||||
this.appendItemElement(tabItem);
|
||||
|
||||
this.items.push(tabItem);
|
||||
this._bindEventsOnItem(tabItem);
|
||||
},
|
||||
|
||||
appendItemElement: function(item) {
|
||||
if(!this.el) {
|
||||
return;
|
||||
}
|
||||
this.el.appendChild(item.el);
|
||||
},
|
||||
|
||||
// Remove an item from the tab bar
|
||||
removeItem: function(index) {
|
||||
var item = this.items[index];
|
||||
if(!item) {
|
||||
return;
|
||||
}
|
||||
item.onTap = undefined;
|
||||
item.destroy();
|
||||
},
|
||||
|
||||
_bindEventsOnItem: function(item) {
|
||||
var _this = this;
|
||||
|
||||
if(!this._itemTapHandler) {
|
||||
this._itemTapHandler = function(e) {
|
||||
//_this.selectItem(this);
|
||||
_this.trySelectItem(this);
|
||||
};
|
||||
}
|
||||
item.onTap = this._itemTapHandler;
|
||||
},
|
||||
|
||||
// Get the currently selected item
|
||||
getSelectedItem: function() {
|
||||
return this.selectedItem;
|
||||
},
|
||||
|
||||
// Set the currently selected item by index
|
||||
setSelectedItem: function(index) {
|
||||
this.selectedItem = this.items[index];
|
||||
|
||||
// Deselect all
|
||||
for(var i = 0, j = this.items.length; i < j; i += 1) {
|
||||
this.items[i].setSelected(false);
|
||||
}
|
||||
|
||||
// Select the new item
|
||||
if(this.selectedItem) {
|
||||
this.selectedItem.setSelected(true);
|
||||
//this.onTabSelected && this.onTabSelected(this.selectedItem, index);
|
||||
}
|
||||
},
|
||||
|
||||
// Select the given item assuming we can find it in our
|
||||
// item list.
|
||||
selectItem: function(item) {
|
||||
for(var i = 0, j = this.items.length; i < j; i += 1) {
|
||||
if(this.items[i] == item) {
|
||||
this.setSelectedItem(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Try to select a given item. This triggers an event such
|
||||
// that the view controller managing this tab bar can decide
|
||||
// whether to select the item or cancel it.
|
||||
trySelectItem: function(item) {
|
||||
for(var i = 0, j = this.items.length; i < j; i += 1) {
|
||||
if(this.items[i] == item) {
|
||||
this.tryTabSelect && this.tryTabSelect(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Build the initial items list from the given DOM node.
|
||||
_buildItems: function() {
|
||||
|
||||
var item, items = Array.prototype.slice.call(this.el.children);
|
||||
|
||||
for(var i = 0, j = items.length; i < j; i += 1) {
|
||||
item = new TabBarItem(items[i]);
|
||||
this.items[i] = item;
|
||||
this._bindEventsOnItem(item);
|
||||
}
|
||||
|
||||
if(this.items.length > 0) {
|
||||
this.selectedItem = this.items[0];
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// Destroy this tab bar
|
||||
destroy: function() {
|
||||
for(var i = 0, j = this.items.length; i < j; i += 1) {
|
||||
this.items[i].destroy();
|
||||
}
|
||||
this.items.length = 0;
|
||||
}
|
||||
};
|
||||
|
||||
})(this, document, this.ionic || {});
|
||||
Reference in New Issue
Block a user