mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-06 22:29:44 +08:00
Cleanup
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
.DS_Store
|
||||
*.sw[mnpcod]
|
||||
example/cordova/iOS/www/js/framework
|
||||
|
||||
example/cordova/iOS/www/js/framework
|
||||
.sass-cache/
|
||||
|
||||
2
Makefile
2
Makefile
@ -6,6 +6,6 @@ release:
|
||||
@sass -I scss/ scss/framework.scss:dist/framework.css
|
||||
|
||||
cordova:
|
||||
@cp js/framework/*.js example/cordova/iOS/www/js
|
||||
@cp -R js/ example/cordova/iOS/www/js
|
||||
@cp dist/framework.css example/cordova/iOS/www/css
|
||||
|
||||
|
||||
Binary file not shown.
@ -221,26 +221,36 @@ a.list-item {
|
||||
margin-bottom: 0;
|
||||
line-height: 1.3; }
|
||||
|
||||
/* the container of panel content to show */
|
||||
.panel-content {
|
||||
display: block;
|
||||
width: 17em;
|
||||
[data-panel] {
|
||||
display: none;
|
||||
min-height: 100%;
|
||||
max-height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 0; }
|
||||
|
||||
.panel-active {
|
||||
display: block;
|
||||
width: 270px; }
|
||||
|
||||
header, main, footer {
|
||||
z-index: 100;
|
||||
left: 0;
|
||||
right: 0;
|
||||
-webkit-transition: -webkit-transform 200ms ease;
|
||||
-moz-transition: -moz-transform 200ms ease;
|
||||
transition: transform 200ms ease;
|
||||
-webkit-transition: -webkit-transform 300ms ease;
|
||||
-moz-transition: -moz-transform 300ms ease;
|
||||
transition: transform 300ms ease;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
-moz-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0); }
|
||||
|
||||
.panel-opened > section > header,
|
||||
.panel-opened > section > main,
|
||||
.panel-opened > section > footer {
|
||||
-webkit-transform: translate3d(270px, 0, 0);
|
||||
-moz-transform: translate3d(270px, 0, 0);
|
||||
transform: translate3d(270px, 0, 0); }
|
||||
|
||||
.ptr-capable {
|
||||
-webkit-user-drag: element; }
|
||||
|
||||
@ -524,7 +534,7 @@ main {
|
||||
a.list-item {
|
||||
color: #333333; }
|
||||
|
||||
.panel-content {
|
||||
[data-panel] {
|
||||
background: #eeeeee;
|
||||
border-right: 1px solid #bbbbbb; }
|
||||
|
||||
|
||||
@ -7,12 +7,21 @@
|
||||
<link rel="stylesheet" href="css/framework.css">
|
||||
<script src="js/angular-1.2.0rc1.min.js"></script>
|
||||
<script src="js/angular-touch.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
|
||||
<script src="js/framework/framework-panel.js"></script>
|
||||
<script src="js/framework/glue/angular-touch.js"></script>
|
||||
</head>
|
||||
<body ng-app="Chat">
|
||||
<section class="panel-page-container">
|
||||
|
||||
<section id="this-panel" class="panel-content" ng-class="{'panel-open': isPanelShowing}" ng-controller="MenuCtrl">
|
||||
</section>
|
||||
<panel id="this-panel" class="panel-content" ng-class="{'panel-open': isPanelShowing}" ng-controller="MenuCtrl">
|
||||
<ul class="list">
|
||||
<li class="list-item">
|
||||
Max Lynch
|
||||
</li>
|
||||
</ul>
|
||||
</panel>
|
||||
|
||||
<section ng-controller="RoomsCtrl">
|
||||
|
||||
@ -31,14 +40,6 @@
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<script src="js/app.js"></script>
|
||||
<!--
|
||||
<script src="js/framework-gestures.js"></script>
|
||||
<script src="js/framework-events.js"></script>
|
||||
-->
|
||||
<script src="js/framework-panel.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
536
example/cordova/iOS/www/js/angular-touch.js
vendored
Normal file
536
example/cordova/iOS/www/js/angular-touch.js
vendored
Normal file
@ -0,0 +1,536 @@
|
||||
/**
|
||||
* @license AngularJS v1.2.0rc1
|
||||
* (c) 2010-2012 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, angular, undefined) {'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name ngTouch
|
||||
* @description
|
||||
* Touch events and other mobile helpers.
|
||||
* Based on jQuery Mobile touch event handling (jquerymobile.com)
|
||||
*/
|
||||
|
||||
// define ngTouch module
|
||||
var ngTouch = angular.module('ngTouch', []);
|
||||
|
||||
/**
|
||||
* @ngdoc object
|
||||
* @name ngTouch.$swipe
|
||||
*
|
||||
* @description
|
||||
* The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe
|
||||
* behavior, to make implementing swipe-related directives more convenient.
|
||||
*
|
||||
* It is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`, and by
|
||||
* `ngCarousel` in a separate component.
|
||||
*
|
||||
* # Usage
|
||||
* The `$swipe` service is an object with a single method: `bind`. `bind` takes an element
|
||||
* which is to be watched for swipes, and an object with four handler functions. See the
|
||||
* documentation for `bind` below.
|
||||
*/
|
||||
|
||||
ngTouch.factory('$swipe', [function() {
|
||||
// The total distance in any direction before we make the call on swipe vs. scroll.
|
||||
var MOVE_BUFFER_RADIUS = 10;
|
||||
|
||||
function getCoordinates(event) {
|
||||
var touches = event.touches && event.touches.length ? event.touches : [event];
|
||||
var e = (event.changedTouches && event.changedTouches[0]) ||
|
||||
(event.originalEvent && event.originalEvent.changedTouches &&
|
||||
event.originalEvent.changedTouches[0]) ||
|
||||
touches[0].originalEvent || touches[0];
|
||||
|
||||
return {
|
||||
x: e.clientX,
|
||||
y: e.clientY
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name ngTouch.$swipe#bind
|
||||
* @methodOf ngTouch.$swipe
|
||||
*
|
||||
* @description
|
||||
* The main method of `$swipe`. It takes an element to be watched for swipe motions, and an
|
||||
* object containing event handlers.
|
||||
*
|
||||
* The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
|
||||
* receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }`.
|
||||
*
|
||||
* `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
|
||||
* watching for `touchmove` or `mousemove` events. These events are ignored until the total
|
||||
* distance moved in either dimension exceeds a small threshold.
|
||||
*
|
||||
* Once this threshold is exceeded, either the horizontal or vertical delta is greater.
|
||||
* - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow.
|
||||
* - If the vertical distance is greater, this is a scroll, and we let the browser take over.
|
||||
* A `cancel` event is sent.
|
||||
*
|
||||
* `move` is called on `mousemove` and `touchmove` after the above logic has determined that
|
||||
* a swipe is in progress.
|
||||
*
|
||||
* `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`.
|
||||
*
|
||||
* `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling
|
||||
* as described above.
|
||||
*
|
||||
*/
|
||||
bind: function(element, eventHandlers) {
|
||||
// Absolute total movement, used to control swipe vs. scroll.
|
||||
var totalX, totalY;
|
||||
// Coordinates of the start position.
|
||||
var startCoords;
|
||||
// Last event's position.
|
||||
var lastPos;
|
||||
// Whether a swipe is active.
|
||||
var active = false;
|
||||
|
||||
element.on('touchstart mousedown', function(event) {
|
||||
startCoords = getCoordinates(event);
|
||||
active = true;
|
||||
totalX = 0;
|
||||
totalY = 0;
|
||||
lastPos = startCoords;
|
||||
eventHandlers['start'] && eventHandlers['start'](startCoords);
|
||||
});
|
||||
|
||||
element.on('touchcancel', function(event) {
|
||||
active = false;
|
||||
eventHandlers['cancel'] && eventHandlers['cancel']();
|
||||
});
|
||||
|
||||
element.on('touchmove mousemove', function(event) {
|
||||
if (!active) return;
|
||||
|
||||
// Android will send a touchcancel if it thinks we're starting to scroll.
|
||||
// So when the total distance (+ or - or both) exceeds 10px in either direction,
|
||||
// we either:
|
||||
// - On totalX > totalY, we send preventDefault() and treat this as a swipe.
|
||||
// - On totalY > totalX, we let the browser handle it as a scroll.
|
||||
|
||||
if (!startCoords) return;
|
||||
var coords = getCoordinates(event);
|
||||
|
||||
totalX += Math.abs(coords.x - lastPos.x);
|
||||
totalY += Math.abs(coords.y - lastPos.y);
|
||||
|
||||
lastPos = coords;
|
||||
|
||||
if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll.
|
||||
if (totalY > totalX) {
|
||||
// Allow native scrolling to take over.
|
||||
active = false;
|
||||
eventHandlers['cancel'] && eventHandlers['cancel']();
|
||||
return;
|
||||
} else {
|
||||
// Prevent the browser from scrolling.
|
||||
event.preventDefault();
|
||||
|
||||
eventHandlers['move'] && eventHandlers['move'](coords);
|
||||
}
|
||||
});
|
||||
|
||||
element.on('touchend mouseup', function(event) {
|
||||
if (!active) return;
|
||||
active = false;
|
||||
eventHandlers['end'] && eventHandlers['end'](getCoordinates(event));
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngTouch.directive:ngClick
|
||||
*
|
||||
* @description
|
||||
* A more powerful replacement for the default ngClick designed to be used on touchscreen
|
||||
* devices. Most mobile browsers wait about 300ms after a tap-and-release before sending
|
||||
* the click event. This version handles them immediately, and then prevents the
|
||||
* following click event from propagating.
|
||||
*
|
||||
* This directive can fall back to using an ordinary click event, and so works on desktop
|
||||
* browsers as well as mobile.
|
||||
*
|
||||
* This directive also sets the CSS class `ng-click-active` while the element is being held
|
||||
* down (by a mouse click or touch) so you can restyle the depressed element if you wish.
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} ngClick {@link guide/expression Expression} to evaluate
|
||||
* upon tap. (Event object is available as `$event`)
|
||||
*
|
||||
* @example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<button ng-click="count = count + 1" ng-init="count=0">
|
||||
Increment
|
||||
</button>
|
||||
count: {{ count }}
|
||||
</doc:source>
|
||||
</doc:example>
|
||||
*/
|
||||
|
||||
ngTouch.config(['$provide', function($provide) {
|
||||
$provide.decorator('ngClickDirective', ['$delegate', function($delegate) {
|
||||
// drop the default ngClick directive
|
||||
$delegate.shift();
|
||||
return $delegate;
|
||||
}]);
|
||||
}]);
|
||||
|
||||
ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
|
||||
function($parse, $timeout, $rootElement) {
|
||||
var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag.
|
||||
var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.
|
||||
var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click
|
||||
var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.
|
||||
|
||||
var ACTIVE_CLASS_NAME = 'ng-click-active';
|
||||
var lastPreventedTime;
|
||||
var touchCoordinates;
|
||||
|
||||
|
||||
// TAP EVENTS AND GHOST CLICKS
|
||||
//
|
||||
// Why tap events?
|
||||
// Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're
|
||||
// double-tapping, and then fire a click event.
|
||||
//
|
||||
// This delay sucks and makes mobile apps feel unresponsive.
|
||||
// So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when
|
||||
// the user has tapped on something.
|
||||
//
|
||||
// What happens when the browser then generates a click event?
|
||||
// The browser, of course, also detects the tap and fires a click after a delay. This results in
|
||||
// tapping/clicking twice. So we do "clickbusting" to prevent it.
|
||||
//
|
||||
// How does it work?
|
||||
// We attach global touchstart and click handlers, that run during the capture (early) phase.
|
||||
// So the sequence for a tap is:
|
||||
// - global touchstart: Sets an "allowable region" at the point touched.
|
||||
// - element's touchstart: Starts a touch
|
||||
// (- touchmove or touchcancel ends the touch, no click follows)
|
||||
// - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
|
||||
// too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
|
||||
// - preventGhostClick() removes the allowable region the global touchstart created.
|
||||
// - The browser generates a click event.
|
||||
// - The global click handler catches the click, and checks whether it was in an allowable region.
|
||||
// - If preventGhostClick was called, the region will have been removed, the click is busted.
|
||||
// - If the region is still there, the click proceeds normally. Therefore clicks on links and
|
||||
// other elements without ngTap on them work normally.
|
||||
//
|
||||
// This is an ugly, terrible hack!
|
||||
// Yeah, tell me about it. The alternatives are using the slow click events, or making our users
|
||||
// deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular
|
||||
// encapsulates this ugly logic away from the user.
|
||||
//
|
||||
// Why not just put click handlers on the element?
|
||||
// We do that too, just to be sure. The problem is that the tap event might have caused the DOM
|
||||
// to change, so that the click fires in the same position but something else is there now. So
|
||||
// the handlers are global and care only about coordinates and not elements.
|
||||
|
||||
// Checks if the coordinates are close enough to be within the region.
|
||||
function hit(x1, y1, x2, y2) {
|
||||
return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD;
|
||||
}
|
||||
|
||||
// Checks a list of allowable regions against a click location.
|
||||
// Returns true if the click should be allowed.
|
||||
// Splices out the allowable region from the list after it has been used.
|
||||
function checkAllowableRegions(touchCoordinates, x, y) {
|
||||
for (var i = 0; i < touchCoordinates.length; i += 2) {
|
||||
if (hit(touchCoordinates[i], touchCoordinates[i+1], x, y)) {
|
||||
touchCoordinates.splice(i, i + 2);
|
||||
return true; // allowable region
|
||||
}
|
||||
}
|
||||
return false; // No allowable region; bust it.
|
||||
}
|
||||
|
||||
// Global click handler that prevents the click if it's in a bustable zone and preventGhostClick
|
||||
// was called recently.
|
||||
function onClick(event) {
|
||||
if (Date.now() - lastPreventedTime > PREVENT_DURATION) {
|
||||
return; // Too old.
|
||||
}
|
||||
|
||||
var touches = event.touches && event.touches.length ? event.touches : [event];
|
||||
var x = touches[0].clientX;
|
||||
var y = touches[0].clientY;
|
||||
// Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label
|
||||
// and on the input element). Depending on the exact browser, this second click we don't want
|
||||
// to bust has either (0,0) or negative coordinates.
|
||||
if (x < 1 && y < 1) {
|
||||
return; // offscreen
|
||||
}
|
||||
|
||||
// Look for an allowable region containing this click.
|
||||
// If we find one, that means it was created by touchstart and not removed by
|
||||
// preventGhostClick, so we don't bust it.
|
||||
if (checkAllowableRegions(touchCoordinates, x, y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we didn't find an allowable region, bust the click.
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
// Blur focused form elements
|
||||
event.target && event.target.blur();
|
||||
}
|
||||
|
||||
|
||||
// Global touchstart handler that creates an allowable region for a click event.
|
||||
// This allowable region can be removed by preventGhostClick if we want to bust it.
|
||||
function onTouchStart(event) {
|
||||
var touches = event.touches && event.touches.length ? event.touches : [event];
|
||||
var x = touches[0].clientX;
|
||||
var y = touches[0].clientY;
|
||||
touchCoordinates.push(x, y);
|
||||
|
||||
$timeout(function() {
|
||||
// Remove the allowable region.
|
||||
for (var i = 0; i < touchCoordinates.length; i += 2) {
|
||||
if (touchCoordinates[i] == x && touchCoordinates[i+1] == y) {
|
||||
touchCoordinates.splice(i, i + 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}, PREVENT_DURATION, false);
|
||||
}
|
||||
|
||||
// On the first call, attaches some event handlers. Then whenever it gets called, it creates a
|
||||
// zone around the touchstart where clicks will get busted.
|
||||
function preventGhostClick(x, y) {
|
||||
if (!touchCoordinates) {
|
||||
$rootElement[0].addEventListener('click', onClick, true);
|
||||
$rootElement[0].addEventListener('touchstart', onTouchStart, true);
|
||||
touchCoordinates = [];
|
||||
}
|
||||
|
||||
lastPreventedTime = Date.now();
|
||||
|
||||
checkAllowableRegions(touchCoordinates, x, y);
|
||||
}
|
||||
|
||||
// Actual linking function.
|
||||
return function(scope, element, attr) {
|
||||
var clickHandler = $parse(attr.ngClick),
|
||||
tapping = false,
|
||||
tapElement, // Used to blur the element after a tap.
|
||||
startTime, // Used to check if the tap was held too long.
|
||||
touchStartX,
|
||||
touchStartY;
|
||||
|
||||
function resetState() {
|
||||
tapping = false;
|
||||
element.removeClass(ACTIVE_CLASS_NAME);
|
||||
}
|
||||
|
||||
element.on('touchstart', function(event) {
|
||||
tapping = true;
|
||||
tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement.
|
||||
// Hack for Safari, which can target text nodes instead of containers.
|
||||
if(tapElement.nodeType == 3) {
|
||||
tapElement = tapElement.parentNode;
|
||||
}
|
||||
|
||||
element.addClass(ACTIVE_CLASS_NAME);
|
||||
|
||||
startTime = Date.now();
|
||||
|
||||
var touches = event.touches && event.touches.length ? event.touches : [event];
|
||||
var e = touches[0].originalEvent || touches[0];
|
||||
touchStartX = e.clientX;
|
||||
touchStartY = e.clientY;
|
||||
});
|
||||
|
||||
element.on('touchmove', function(event) {
|
||||
resetState();
|
||||
});
|
||||
|
||||
element.on('touchcancel', function(event) {
|
||||
resetState();
|
||||
});
|
||||
|
||||
element.on('touchend', function(event) {
|
||||
var diff = Date.now() - startTime;
|
||||
|
||||
var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches :
|
||||
((event.touches && event.touches.length) ? event.touches : [event]);
|
||||
var e = touches[0].originalEvent || touches[0];
|
||||
var x = e.clientX;
|
||||
var y = e.clientY;
|
||||
var dist = Math.sqrt( Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2) );
|
||||
|
||||
if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
|
||||
// Call preventGhostClick so the clickbuster will catch the corresponding click.
|
||||
preventGhostClick(x, y);
|
||||
|
||||
// Blur the focused element (the button, probably) before firing the callback.
|
||||
// This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
|
||||
// I couldn't get anything to work reliably on Android Chrome.
|
||||
if (tapElement) {
|
||||
tapElement.blur();
|
||||
}
|
||||
|
||||
if (!angular.isDefined(attr.disabled) || attr.disabled === false) {
|
||||
element.triggerHandler('click', event);
|
||||
}
|
||||
}
|
||||
|
||||
resetState();
|
||||
});
|
||||
|
||||
// Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
|
||||
// something else nearby.
|
||||
element.onclick = function(event) { };
|
||||
|
||||
// Actual click handler.
|
||||
// There are three different kinds of clicks, only two of which reach this point.
|
||||
// - On desktop browsers without touch events, their clicks will always come here.
|
||||
// - On mobile browsers, the simulated "fast" click will call this.
|
||||
// - But the browser's follow-up slow click will be "busted" before it reaches this handler.
|
||||
// Therefore it's safe to use this directive on both mobile and desktop.
|
||||
element.on('click', function(event) {
|
||||
scope.$apply(function() {
|
||||
clickHandler(scope, {$event: event});
|
||||
});
|
||||
});
|
||||
|
||||
element.on('mousedown', function(event) {
|
||||
element.addClass(ACTIVE_CLASS_NAME);
|
||||
});
|
||||
|
||||
element.on('mousemove mouseup', function(event) {
|
||||
element.removeClass(ACTIVE_CLASS_NAME);
|
||||
});
|
||||
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngTouch.directive:ngSwipeLeft
|
||||
*
|
||||
* @description
|
||||
* Specify custom behavior when an element is swiped to the left on a touchscreen device.
|
||||
* A leftward swipe is a quick, right-to-left slide of the finger.
|
||||
* Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag too.
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate
|
||||
* upon left swipe. (Event object is available as `$event`)
|
||||
*
|
||||
* @example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng-show="!showActions" ng-swipe-left="showActions = true">
|
||||
Some list content, like an email in the inbox
|
||||
</div>
|
||||
<div ng-show="showActions" ng-swipe-right="showActions = false">
|
||||
<button ng-click="reply()">Reply</button>
|
||||
<button ng-click="delete()">Delete</button>
|
||||
</div>
|
||||
</doc:source>
|
||||
</doc:example>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngTouch.directive:ngSwipeRight
|
||||
*
|
||||
* @description
|
||||
* Specify custom behavior when an element is swiped to the right on a touchscreen device.
|
||||
* A rightward swipe is a quick, left-to-right slide of the finger.
|
||||
* Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag too.
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate
|
||||
* upon right swipe. (Event object is available as `$event`)
|
||||
*
|
||||
* @example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng-show="!showActions" ng-swipe-left="showActions = true">
|
||||
Some list content, like an email in the inbox
|
||||
</div>
|
||||
<div ng-show="showActions" ng-swipe-right="showActions = false">
|
||||
<button ng-click="reply()">Reply</button>
|
||||
<button ng-click="delete()">Delete</button>
|
||||
</div>
|
||||
</doc:source>
|
||||
</doc:example>
|
||||
*/
|
||||
|
||||
function makeSwipeDirective(directiveName, direction, eventName) {
|
||||
ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) {
|
||||
// The maximum vertical delta for a swipe should be less than 75px.
|
||||
var MAX_VERTICAL_DISTANCE = 75;
|
||||
// Vertical distance should not be more than a fraction of the horizontal distance.
|
||||
var MAX_VERTICAL_RATIO = 0.3;
|
||||
// At least a 30px lateral motion is necessary for a swipe.
|
||||
var MIN_HORIZONTAL_DISTANCE = 30;
|
||||
|
||||
return function(scope, element, attr) {
|
||||
var swipeHandler = $parse(attr[directiveName]);
|
||||
|
||||
var startCoords, valid;
|
||||
|
||||
function validSwipe(coords) {
|
||||
// Check that it's within the coordinates.
|
||||
// Absolute vertical distance must be within tolerances.
|
||||
// Horizontal distance, we take the current X - the starting X.
|
||||
// This is negative for leftward swipes and positive for rightward swipes.
|
||||
// After multiplying by the direction (-1 for left, +1 for right), legal swipes
|
||||
// (ie. same direction as the directive wants) will have a positive delta and
|
||||
// illegal ones a negative delta.
|
||||
// Therefore this delta must be positive, and larger than the minimum.
|
||||
if (!startCoords) return false;
|
||||
var deltaY = Math.abs(coords.y - startCoords.y);
|
||||
var deltaX = (coords.x - startCoords.x) * direction;
|
||||
return valid && // Short circuit for already-invalidated swipes.
|
||||
deltaY < MAX_VERTICAL_DISTANCE &&
|
||||
deltaX > 0 &&
|
||||
deltaX > MIN_HORIZONTAL_DISTANCE &&
|
||||
deltaY / deltaX < MAX_VERTICAL_RATIO;
|
||||
}
|
||||
|
||||
$swipe.bind(element, {
|
||||
'start': function(coords) {
|
||||
startCoords = coords;
|
||||
valid = true;
|
||||
},
|
||||
'cancel': function() {
|
||||
valid = false;
|
||||
},
|
||||
'end': function(coords) {
|
||||
if (validSwipe(coords)) {
|
||||
scope.$apply(function() {
|
||||
element.triggerHandler(eventName);
|
||||
swipeHandler(scope);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}]);
|
||||
}
|
||||
|
||||
// Left is negative X-coordinate, right is positive.
|
||||
makeSwipeDirective('ngSwipeLeft', -1, 'swipeleft');
|
||||
makeSwipeDirective('ngSwipeRight', 1, 'swiperight');
|
||||
|
||||
|
||||
|
||||
})(window, window.angular);
|
||||
14847
example/cordova/iOS/www/js/angular/angular.js
vendored
Normal file
14847
example/cordova/iOS/www/js/angular/angular.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
example/cordova/iOS/www/js/app.js
vendored
13
example/cordova/iOS/www/js/app.js
vendored
@ -1,16 +1,23 @@
|
||||
var chat = angular.module('Chat', ['ngTouch']);
|
||||
|
||||
chat.controller('MenuCtrl', function($scope) {
|
||||
chat.service('MenuService', function() {
|
||||
this.openPanel = function() {
|
||||
console.log('Opening panel');
|
||||
}
|
||||
});
|
||||
|
||||
chat.controller('RoomsCtrl', function($scope) {
|
||||
chat.controller('MenuCtrl', function($scope) {
|
||||
$scope.isPanelShowing = false;
|
||||
});
|
||||
|
||||
chat.controller('RoomsCtrl', function($scope, MenuService) {
|
||||
$scope.rooms = [
|
||||
{ name: 'All', key: 'all' },
|
||||
{ name: 'Marketing', key: 'marketing' }
|
||||
];
|
||||
|
||||
$scope.openPanel = function() {
|
||||
$scope.isPanelShowing = true;
|
||||
MenuService.openPanel();
|
||||
};
|
||||
|
||||
$scope.showAlert = function() {
|
||||
|
||||
29
example/cordova/iOS/www/js/framework-buttons.js
vendored
29
example/cordova/iOS/www/js/framework-buttons.js
vendored
@ -1,29 +0,0 @@
|
||||
(function(window, document, framework) {
|
||||
framework.Button = function() {}
|
||||
|
||||
// Process an the touchstart event and if this is a button,
|
||||
// add the .active class so Android will show depressed
|
||||
// button states.
|
||||
framework.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.
|
||||
framework.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', framework.Button.prototype._onTouchStart);
|
||||
document.addEventListener('touchend', framework.Button.prototype._onTouchEnd);
|
||||
document.addEventListener('touchcancel', framework.Button.prototype._onTouchEnd);
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
98
example/cordova/iOS/www/js/framework-events.js
vendored
98
example/cordova/iOS/www/js/framework-events.js
vendored
@ -1,98 +0,0 @@
|
||||
/**
|
||||
* framework-events.js
|
||||
*
|
||||
* Author: Max Lynch <max@drifty.com>
|
||||
*
|
||||
* Framework events handles various mobile browser events, and
|
||||
* detects special events like tap/swipe/etc. and emits them
|
||||
* as custom events that can be used in an app.
|
||||
*
|
||||
* Portions lovingly adapted from github.com/maker/ratchet and github.com/alexgibson/tap.js - thanks guys!
|
||||
*/
|
||||
|
||||
(function(window, document, framework) {
|
||||
framework.EventController = {
|
||||
|
||||
// Trigger a new event
|
||||
trigger: function(eventType, data) {
|
||||
// TODO: Do we need to use the old-school createEvent stuff?
|
||||
var event = new CustomEvent(eventType, data);
|
||||
|
||||
// Make sure to trigger the event on the given target, or dispatch it from
|
||||
// the window if we don't have an event target
|
||||
data.target && data.target.dispatchEvent(event) || window.dispatchEvent(event);
|
||||
},
|
||||
|
||||
// Bind an event
|
||||
on: function(type, callback, element) {
|
||||
var e = element || window;
|
||||
e.addEventListener(type, callback);
|
||||
},
|
||||
|
||||
off: function(type, callback, element) {
|
||||
element.removeEventListener(type, callback);
|
||||
},
|
||||
|
||||
// Register for a new gesture event on the given element
|
||||
onGesture: function(type, callback, element) {
|
||||
var gesture = new framework.Gesture(element);
|
||||
gesture.on(type, callback);
|
||||
return gesture;
|
||||
},
|
||||
|
||||
// Unregister a previous gesture event
|
||||
offGesture: function(gesture, type, callback) {
|
||||
gesture.off(type, callback);
|
||||
},
|
||||
|
||||
// With a click event, we need to check the target
|
||||
// and if it's an internal target that doesn't want
|
||||
// a click, cancel it
|
||||
handleClick: function(e) {
|
||||
var target = e.target;
|
||||
|
||||
if(framework.Gestures.HAS_TOUCHEVENTS) {
|
||||
// We don't allow any clicks on mobile
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
! target
|
||||
|| e.which > 1
|
||||
|| e.metaKey
|
||||
|| e.ctrlKey
|
||||
//|| isScrolling
|
||||
|| location.protocol !== target.protocol
|
||||
|| location.host !== target.host
|
||||
// Not sure abotu this one
|
||||
//|| !target.hash && /#/.test(target.href)
|
||||
|| target.hash && target.href.replace(target.hash, '') === location.href.replace(location.hash, '')
|
||||
//|| target.getAttribute('data-ignore') == 'push'
|
||||
) {
|
||||
// Allow it
|
||||
return;
|
||||
}
|
||||
// We need to cancel this one
|
||||
e.preventDefault();
|
||||
|
||||
},
|
||||
|
||||
handlePopState: function(event) {
|
||||
console.log("EVENT: popstate", event);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
// Map some convenient top-level functions for event handling
|
||||
framework.on = framework.EventController.on;
|
||||
framework.off = framework.EventController.off;
|
||||
framework.trigger = framework.EventController.trigger;
|
||||
framework.onGesture = framework.EventController.onGesture;
|
||||
framework.offGesture = framework.EventController.offGesture;
|
||||
|
||||
// Set up various listeners
|
||||
window.addEventListener('click', framework.EventController.handleClick);
|
||||
//window.addEventListener('popstate', framework.EventController.handlePopState);
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
1420
example/cordova/iOS/www/js/framework-gestures.js
vendored
1420
example/cordova/iOS/www/js/framework-gestures.js
vendored
File diff suppressed because it is too large
Load Diff
28
example/cordova/iOS/www/js/framework-init.js
vendored
28
example/cordova/iOS/www/js/framework-init.js
vendored
@ -1,28 +0,0 @@
|
||||
(function(window, document, framework) {
|
||||
|
||||
function initalize() {
|
||||
// remove the ready listeners
|
||||
document.removeEventListener( "DOMContentLoaded", initalize, false );
|
||||
window.removeEventListener( "load", initalize, false );
|
||||
|
||||
// trigger that the DOM is ready
|
||||
framework.trigger("ready");
|
||||
|
||||
// trigger that the start page is in view
|
||||
framework.trigger("pageview");
|
||||
|
||||
// trigger that the webapp has been initalized
|
||||
framework.trigger("initalized");
|
||||
}
|
||||
|
||||
// When the DOM is ready, initalize the webapp
|
||||
if ( document.readyState === "complete" ) {
|
||||
// DOM is already ready
|
||||
setTimeout( initalize );
|
||||
} else {
|
||||
// DOM isn't ready yet, add event listeners
|
||||
document.addEventListener( "DOMContentLoaded", initalize, false );
|
||||
window.addEventListener( "load", initalize, false );
|
||||
}
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
23
example/cordova/iOS/www/js/framework-list.js
vendored
23
example/cordova/iOS/www/js/framework-list.js
vendored
@ -1,23 +0,0 @@
|
||||
(function(window, document, framework) {
|
||||
framework.List = function() {}
|
||||
|
||||
framework.List.prototype._TAB_ITEM_CLASS = 'tab-item';
|
||||
|
||||
framework.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');
|
||||
}
|
||||
};
|
||||
framework.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', framework.List.prototype._onTouchStart);
|
||||
document.addEventListener('touchstart', framework.List.prototype._onTouchStart);
|
||||
document.addEventListener('touchend', framework.List.prototype._onTouchEnd);
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
154
example/cordova/iOS/www/js/framework-navigation.js
vendored
154
example/cordova/iOS/www/js/framework-navigation.js
vendored
@ -1,154 +0,0 @@
|
||||
(function(window, document, location, framework) {
|
||||
|
||||
var
|
||||
x,
|
||||
el;
|
||||
|
||||
// Add listeners to each link in the document
|
||||
function click(e) {
|
||||
// an element has been clicked. If its a link its good to go
|
||||
// if its not a link then jump up its parents until you find
|
||||
// its wrapping link. If you never find a link do nothing.
|
||||
if(e.target) {
|
||||
el = e.target;
|
||||
if(el.tagName === "A") {
|
||||
return linkClick(e, el);
|
||||
}
|
||||
while(el.parentElement) {
|
||||
el = el.parentElement;
|
||||
if(el.tagName === "A") {
|
||||
return linkClick(e, el);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A link has been clicked
|
||||
function linkClick(e, el) {
|
||||
|
||||
// if they clicked a link while scrolling don't nav to it
|
||||
if(framework.isScrolling) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// data-history-go="-1"
|
||||
// shortcut if they just want to use window.history.go()
|
||||
if(el.dataset.historyGo) {
|
||||
window.history.go( parseInt(el.dataset.historyGo, 10) );
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// only intercept the nav click if they're going to the same domain or page
|
||||
if (location.protocol === el.protocol && location.host === el.host) {
|
||||
|
||||
// trigger the event that a new page should be shown
|
||||
framework.trigger("pageinit", el.href);
|
||||
|
||||
// decide how to handle this click depending on the href
|
||||
if(el.getAttribute("href").indexOf("#") === 0) {
|
||||
// this click is going to another element within this same page
|
||||
|
||||
|
||||
} else {
|
||||
// this click is going to another page in the same domain
|
||||
requestData({
|
||||
url: el.href,
|
||||
success: successPageLoad,
|
||||
fail: failedPageLoad
|
||||
});
|
||||
}
|
||||
|
||||
// stop the browser itself from continuing on with this click
|
||||
// the above code will take care of the navigation
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function locationChange(e) {
|
||||
if(!this._initPopstate) {
|
||||
this._initPopstate = true;
|
||||
return;
|
||||
}
|
||||
|
||||
requestData({
|
||||
url: location.href,
|
||||
success: successPageLoad,
|
||||
fail: failedPageLoad
|
||||
});
|
||||
}
|
||||
|
||||
function requestData(options) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', options.url, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
if(xhr.status === 200) {
|
||||
options.success(xhr, options);
|
||||
} else {
|
||||
options.fail(xhr, options);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function successPageLoad(xhr, options) {
|
||||
var data = parseXHR(xhr, options);
|
||||
framework.trigger("pageloaded", {
|
||||
data: data
|
||||
});
|
||||
history.pushState({}, data.title, data.url);
|
||||
document.title = data.title;
|
||||
}
|
||||
|
||||
function failedPageLoad(xhr, options) {
|
||||
framework.trigger("pageinitfailed", {
|
||||
responseText: xhr.responseText,
|
||||
responseStatus: xhr.status
|
||||
});
|
||||
}
|
||||
|
||||
function parseXHR(xhr, options) {
|
||||
var
|
||||
container,
|
||||
tmp,
|
||||
data = {};
|
||||
|
||||
data.url = options.url;
|
||||
|
||||
if (!xhr.responseText) return data;
|
||||
|
||||
container = document.createElement('div');
|
||||
container.innerHTML = xhr.responseText;
|
||||
|
||||
// get the title of the page
|
||||
tmp = container.querySelector("title");
|
||||
if(tmp) {
|
||||
data.title = tmp.innerText;
|
||||
} else {
|
||||
data.title = data.url;
|
||||
}
|
||||
|
||||
// get the main content of the page
|
||||
tmp = container.querySelector("main");
|
||||
if(tmp) {
|
||||
data.main = tmp.innerHTML;
|
||||
} else {
|
||||
// something is wrong with the data, trigger that the page init failed
|
||||
framework.trigger("pageinitfailed");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// listen to every click
|
||||
document.addEventListener("click", click, false);
|
||||
|
||||
// listen to when the location changes
|
||||
framework.on("popstate", locationChange);
|
||||
|
||||
|
||||
})(this, document, location, FM = this.FM || {});
|
||||
56
example/cordova/iOS/www/js/framework-panel.js
vendored
56
example/cordova/iOS/www/js/framework-panel.js
vendored
@ -1,56 +0,0 @@
|
||||
(function(window, document, framework) {
|
||||
|
||||
var
|
||||
el,
|
||||
styleElement,
|
||||
isPanelOpen;
|
||||
|
||||
function onTap(e) {
|
||||
var el = e.target;
|
||||
return togglePanel(e, el, el.dataset.togglePanel);
|
||||
|
||||
if(e.target) {
|
||||
if(el.dataset.togglePanel) {
|
||||
}
|
||||
while(el.parentElement) {
|
||||
el = el.parentElement;
|
||||
if(el.dataset.togglePanel) {
|
||||
return togglePanel(e, el, el.dataset.togglePanel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function togglePanel(e, el, panelName) {
|
||||
var styles = "";
|
||||
|
||||
if(isPanelOpen) {
|
||||
// there is a panel already open, so close it
|
||||
isPanelOpen = false;
|
||||
} else {
|
||||
// open the panel
|
||||
styles = "section .panel-content ~ * { width:" + document.width + "px !important; \
|
||||
-webkit-transform: translate3d(17em,0,0); \
|
||||
-moz-transform: translate3d(17em,0,0); \
|
||||
transform: translate3d(17em,0,0); }";
|
||||
isPanelOpen = true;
|
||||
}
|
||||
|
||||
setStyles(styles);
|
||||
}
|
||||
|
||||
function setStyles(styles) {
|
||||
// get the <style> from the head that will be used by the panel
|
||||
if(!styleElement) {
|
||||
styleElement = document.createElement("style");
|
||||
styleElement.id = "panel-styles";
|
||||
styleElement.innerHTML = styles;
|
||||
document.head.appendChild(styleElement);
|
||||
} else {
|
||||
styleElement.innerHTML = styles;
|
||||
}
|
||||
}
|
||||
|
||||
//framework.onGesture("tap", onTap, document.getElementById('open-panel'));
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
25
example/cordova/iOS/www/js/framework-tabs.js
vendored
25
example/cordova/iOS/www/js/framework-tabs.js
vendored
@ -1,25 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
(function(window, document, framework) {
|
||||
framework.Tabs = function() {}
|
||||
|
||||
framework.Tabs.prototype._TAB_ITEM_CLASS = 'tab-item';
|
||||
|
||||
framework.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');
|
||||
}
|
||||
};
|
||||
framework.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', framework.Tabs.prototype._onTouchStart);
|
||||
document.addEventListener('touchstart', framework.Tabs.prototype._onTouchStart);
|
||||
document.addEventListener('touchend', framework.Tabs.prototype._onTouchEnd);
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
68
example/cordova/iOS/www/js/framework-template.js
vendored
68
example/cordova/iOS/www/js/framework-template.js
vendored
@ -1,68 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
(function(window, document, framework) {
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
framework.on("ready", initTemplates);
|
||||
framework.on("pagecreate", initTemplates);
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
@ -1,41 +0,0 @@
|
||||
(function(window, document, framework) {
|
||||
|
||||
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);
|
||||
framework.trigger("pagecreate", {
|
||||
url: data.url,
|
||||
title: data.title
|
||||
});
|
||||
framework.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
|
||||
}
|
||||
|
||||
framework.on("pageloaded", initTransitions);
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
22
example/cordova/iOS/www/js/framework-utils.js
vendored
22
example/cordova/iOS/www/js/framework-utils.js
vendored
@ -1,22 +0,0 @@
|
||||
(function(window, document, framework) {
|
||||
|
||||
framework.Utils = {
|
||||
/**
|
||||
* extend method,
|
||||
* also used for cloning when dest is an empty object
|
||||
* @param {Object} dest
|
||||
* @param {Object} src
|
||||
* @parm {Boolean} merge do a merge
|
||||
* @returns {Object} dest
|
||||
*/
|
||||
extend: function extend(dest, src, merge) {
|
||||
for (var key in src) {
|
||||
if(dest[key] !== undefined && merge) {
|
||||
continue;
|
||||
}
|
||||
dest[key] = src[key];
|
||||
}
|
||||
return dest;
|
||||
},
|
||||
}
|
||||
})(this, document, FM = this.FM || {});
|
||||
12
example/cordova/iOS/www/js/glue/angular-glue.js
vendored
Normal file
12
example/cordova/iOS/www/js/glue/angular-glue.js
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/* used to tie angular.js with the framework */
|
||||
/* nowhere should the framework reference angular.js */
|
||||
/* nowhere in angular.js should it reference the framework */
|
||||
|
||||
var ionic = angular.module('ionic', ['ngTouch']);
|
||||
|
||||
ionic.directive('panel', ['$parse', '$timeout', '$rootElement',
|
||||
function($parse, $timeout, $rootElement) {
|
||||
return function(scope, element, attrs) {
|
||||
};
|
||||
}
|
||||
]);
|
||||
9789
example/cordova/iOS/www/js/jquery/jquery-1.10.2.js
vendored
Normal file
9789
example/cordova/iOS/www/js/jquery/jquery-1.10.2.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
741
example/cordova/iOS/www/js/ratchet/ratchet.js
vendored
Normal file
741
example/cordova/iOS/www/js/ratchet/ratchet.js
vendored
Normal file
@ -0,0 +1,741 @@
|
||||
/**
|
||||
* ==================================
|
||||
* Ratchet v1.0.0
|
||||
* Licensed under The MIT License
|
||||
* http://opensource.org/licenses/MIT
|
||||
* ==================================
|
||||
*/
|
||||
|
||||
/* ----------------------------------
|
||||
* POPOVER v1.0.0
|
||||
* Licensed under The MIT License
|
||||
* http://opensource.org/licenses/MIT
|
||||
* ---------------------------------- */
|
||||
|
||||
!function () {
|
||||
|
||||
var popover;
|
||||
|
||||
var findPopovers = function (target) {
|
||||
var i, popovers = document.querySelectorAll('a');
|
||||
for (; target && target !== document; target = target.parentNode) {
|
||||
for (i = popovers.length; i--;) { if (popovers[i] === target) return target; }
|
||||
}
|
||||
};
|
||||
|
||||
var onPopoverHidden = function () {
|
||||
document.body.removeChild(backdrop);
|
||||
popover.style.display = 'none';
|
||||
popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
|
||||
}
|
||||
|
||||
var backdrop = function () {
|
||||
var element = document.createElement('div');
|
||||
|
||||
element.classList.add('backdrop');
|
||||
|
||||
element.addEventListener('touchend', function () {
|
||||
popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
|
||||
popover.classList.remove('visible');
|
||||
});
|
||||
|
||||
return element;
|
||||
}();
|
||||
|
||||
var getPopover = function (e) {
|
||||
var anchor = findPopovers(e.target);
|
||||
|
||||
if (!anchor || !anchor.hash) return;
|
||||
|
||||
popover = document.querySelector(anchor.hash);
|
||||
|
||||
if (!popover || !popover.classList.contains('popover')) return;
|
||||
|
||||
return popover;
|
||||
}
|
||||
|
||||
window.addEventListener('touchend', function (e) {
|
||||
var popover = getPopover(e);
|
||||
|
||||
if (!popover) return;
|
||||
|
||||
popover.style.display = 'block';
|
||||
popover.offsetHeight;
|
||||
popover.classList.add('visible');
|
||||
|
||||
popover.parentNode.appendChild(backdrop);
|
||||
});
|
||||
|
||||
window.addEventListener('click', function (e) { if (getPopover(e)) e.preventDefault(); });
|
||||
|
||||
}();
|
||||
/* ----------------------------------
|
||||
* PUSH v1.0.0
|
||||
* Licensed under The MIT License
|
||||
* inspired by chris's jquery.pjax.js
|
||||
* http://opensource.org/licenses/MIT
|
||||
* ---------------------------------- */
|
||||
|
||||
!function () {
|
||||
|
||||
var noop = function () {};
|
||||
|
||||
|
||||
// Pushstate cacheing
|
||||
// ==================
|
||||
|
||||
var isScrolling;
|
||||
var maxCacheLength = 20;
|
||||
var cacheMapping = sessionStorage;
|
||||
var domCache = {};
|
||||
var transitionMap = {
|
||||
'slide-in' : 'slide-out',
|
||||
'slide-out' : 'slide-in',
|
||||
'fade' : 'fade'
|
||||
};
|
||||
var bars = {
|
||||
bartab : '.bar-tab',
|
||||
bartitle : '.bar-title',
|
||||
barfooter : '.bar-footer',
|
||||
barheadersecondary : '.bar-header-secondary'
|
||||
}
|
||||
|
||||
var cacheReplace = function (data, updates) {
|
||||
PUSH.id = data.id;
|
||||
if (updates) data = getCached(data.id);
|
||||
cacheMapping[data.id] = JSON.stringify(data);
|
||||
window.history.replaceState(data.id, data.title, data.url);
|
||||
domCache[data.id] = document.body.cloneNode(true);
|
||||
};
|
||||
|
||||
var cachePush = function () {
|
||||
var id = PUSH.id;
|
||||
|
||||
var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
|
||||
var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
|
||||
|
||||
cacheBackStack.push(id);
|
||||
|
||||
while (cacheForwardStack.length) delete cacheMapping[cacheForwardStack.shift()];
|
||||
while (cacheBackStack.length > maxCacheLength) delete cacheMapping[cacheBackStack.shift()];
|
||||
|
||||
window.history.pushState(null, '', cacheMapping[PUSH.id].url);
|
||||
|
||||
cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
|
||||
cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
|
||||
};
|
||||
|
||||
var cachePop = function (id, direction) {
|
||||
var forward = direction == 'forward';
|
||||
var cacheForwardStack = JSON.parse(cacheMapping.cacheForwardStack || '[]');
|
||||
var cacheBackStack = JSON.parse(cacheMapping.cacheBackStack || '[]');
|
||||
var pushStack = forward ? cacheBackStack : cacheForwardStack;
|
||||
var popStack = forward ? cacheForwardStack : cacheBackStack;
|
||||
|
||||
if (PUSH.id) pushStack.push(PUSH.id);
|
||||
popStack.pop();
|
||||
|
||||
cacheMapping.cacheForwardStack = JSON.stringify(cacheForwardStack);
|
||||
cacheMapping.cacheBackStack = JSON.stringify(cacheBackStack);
|
||||
};
|
||||
|
||||
var getCached = function (id) {
|
||||
return JSON.parse(cacheMapping[id] || null) || {};
|
||||
};
|
||||
|
||||
var getTarget = function (e) {
|
||||
var target = findTarget(e.target);
|
||||
|
||||
if (
|
||||
! target
|
||||
|| e.which > 1
|
||||
|| e.metaKey
|
||||
|| e.ctrlKey
|
||||
|| isScrolling
|
||||
|| location.protocol !== target.protocol
|
||||
|| location.host !== target.host
|
||||
|| !target.hash && /#/.test(target.href)
|
||||
|| target.hash && target.href.replace(target.hash, '') === location.href.replace(location.hash, '')
|
||||
|| target.getAttribute('data-ignore') == 'push'
|
||||
) return;
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
|
||||
// Main event handlers (touchend, popstate)
|
||||
// ==========================================
|
||||
|
||||
var touchend = function (e) {
|
||||
var target = getTarget(e);
|
||||
|
||||
if (!target) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
PUSH({
|
||||
url : target.href,
|
||||
hash : target.hash,
|
||||
timeout : target.getAttribute('data-timeout'),
|
||||
transition : target.getAttribute('data-transition')
|
||||
});
|
||||
};
|
||||
|
||||
var popstate = function (e) {
|
||||
var key;
|
||||
var barElement;
|
||||
var activeObj;
|
||||
var activeDom;
|
||||
var direction;
|
||||
var transition;
|
||||
var transitionFrom;
|
||||
var transitionFromObj;
|
||||
var id = e.state;
|
||||
|
||||
if (!id || !cacheMapping[id]) return;
|
||||
|
||||
direction = PUSH.id < id ? 'forward' : 'back';
|
||||
|
||||
cachePop(id, direction);
|
||||
|
||||
activeObj = getCached(id);
|
||||
activeDom = domCache[id];
|
||||
|
||||
if (activeObj.title) document.title = activeObj.title;
|
||||
|
||||
if (direction == 'back') {
|
||||
transitionFrom = JSON.parse(direction == 'back' ? cacheMapping.cacheForwardStack : cacheMapping.cacheBackStack);
|
||||
transitionFromObj = getCached(transitionFrom[transitionFrom.length - 1]);
|
||||
} else {
|
||||
transitionFromObj = activeObj;
|
||||
}
|
||||
|
||||
if (direction == 'back' && !transitionFromObj.id) return PUSH.id = id;
|
||||
|
||||
transition = direction == 'back' ? transitionMap[transitionFromObj.transition] : transitionFromObj.transition;
|
||||
|
||||
if (!activeDom) {
|
||||
return PUSH({
|
||||
id : activeObj.id,
|
||||
url : activeObj.url,
|
||||
title : activeObj.title,
|
||||
timeout : activeObj.timeout,
|
||||
transition : transition,
|
||||
ignorePush : true
|
||||
});
|
||||
}
|
||||
|
||||
if (transitionFromObj.transition) {
|
||||
activeObj = extendWithDom(activeObj, '.content', activeDom.cloneNode(true));
|
||||
for (key in bars) {
|
||||
barElement = document.querySelector(bars[key])
|
||||
if (activeObj[key]) swapContent(activeObj[key], barElement);
|
||||
else if (barElement) barElement.parentNode.removeChild(barElement);
|
||||
}
|
||||
}
|
||||
|
||||
swapContent(
|
||||
(activeObj.contents || activeDom).cloneNode(true),
|
||||
document.querySelector('.content'),
|
||||
transition
|
||||
);
|
||||
|
||||
PUSH.id = id;
|
||||
|
||||
document.body.offsetHeight; // force reflow to prevent scroll
|
||||
};
|
||||
|
||||
|
||||
// Core PUSH functionality
|
||||
// =======================
|
||||
|
||||
var PUSH = function (options) {
|
||||
var key;
|
||||
var data = {};
|
||||
var xhr = PUSH.xhr;
|
||||
|
||||
options.container = options.container || options.transition ? document.querySelector('.content') : document.body;
|
||||
|
||||
for (key in bars) {
|
||||
options[key] = options[key] || document.querySelector(bars[key]);
|
||||
}
|
||||
|
||||
if (xhr && xhr.readyState < 4) {
|
||||
xhr.onreadystatechange = noop;
|
||||
xhr.abort()
|
||||
}
|
||||
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', options.url, true);
|
||||
xhr.setRequestHeader('X-PUSH', 'true');
|
||||
|
||||
xhr.onreadystatechange = function () {
|
||||
if (options._timeout) clearTimeout(options._timeout);
|
||||
if (xhr.readyState == 4) xhr.status == 200 ? success(xhr, options) : failure(options.url);
|
||||
};
|
||||
|
||||
if (!PUSH.id) {
|
||||
cacheReplace({
|
||||
id : +new Date,
|
||||
url : window.location.href,
|
||||
title : document.title,
|
||||
timeout : options.timeout,
|
||||
transition : null
|
||||
});
|
||||
}
|
||||
|
||||
if (options.timeout) {
|
||||
options._timeout = setTimeout(function () { xhr.abort('timeout'); }, options.timeout);
|
||||
}
|
||||
|
||||
xhr.send();
|
||||
|
||||
if (xhr.readyState && !options.ignorePush) cachePush();
|
||||
};
|
||||
|
||||
|
||||
// Main XHR handlers
|
||||
// =================
|
||||
|
||||
var success = function (xhr, options) {
|
||||
var key;
|
||||
var barElement;
|
||||
var data = parseXHR(xhr, options);
|
||||
|
||||
if (!data.contents) return locationReplace(options.url);
|
||||
|
||||
if (data.title) document.title = data.title;
|
||||
|
||||
if (options.transition) {
|
||||
for (key in bars) {
|
||||
barElement = document.querySelector(bars[key])
|
||||
if (data[key]) swapContent(data[key], barElement);
|
||||
else if (barElement) barElement.parentNode.removeChild(barElement);
|
||||
}
|
||||
}
|
||||
|
||||
swapContent(data.contents, options.container, options.transition, function () {
|
||||
cacheReplace({
|
||||
id : options.id || +new Date,
|
||||
url : data.url,
|
||||
title : data.title,
|
||||
timeout : options.timeout,
|
||||
transition : options.transition
|
||||
}, options.id);
|
||||
triggerStateChange();
|
||||
});
|
||||
|
||||
if (!options.ignorePush && window._gaq) _gaq.push(['_trackPageview']) // google analytics
|
||||
if (!options.hash) return;
|
||||
};
|
||||
|
||||
var failure = function (url) {
|
||||
throw new Error('Could not get: ' + url)
|
||||
};
|
||||
|
||||
|
||||
// PUSH helpers
|
||||
// ============
|
||||
|
||||
var swapContent = function (swap, container, transition, complete) {
|
||||
var enter;
|
||||
var containerDirection;
|
||||
var swapDirection;
|
||||
|
||||
if (!transition) {
|
||||
if (container) container.innerHTML = swap.innerHTML;
|
||||
else if (swap.classList.contains('content')) document.body.appendChild(swap);
|
||||
else document.body.insertBefore(swap, document.querySelector('.content'));
|
||||
} else {
|
||||
enter = /in$/.test(transition);
|
||||
|
||||
if (transition == 'fade') {
|
||||
container.classList.add('in');
|
||||
container.classList.add('fade');
|
||||
swap.classList.add('fade');
|
||||
}
|
||||
|
||||
if (/slide/.test(transition)) {
|
||||
swap.classList.add(enter ? 'right' : 'left');
|
||||
swap.classList.add('slide');
|
||||
container.classList.add('slide');
|
||||
}
|
||||
|
||||
container.parentNode.insertBefore(swap, container);
|
||||
}
|
||||
|
||||
if (!transition) complete && complete();
|
||||
|
||||
if (transition == 'fade') {
|
||||
container.offsetWidth; // force reflow
|
||||
container.classList.remove('in');
|
||||
container.addEventListener('webkitTransitionEnd', fadeContainerEnd);
|
||||
|
||||
function fadeContainerEnd() {
|
||||
container.removeEventListener('webkitTransitionEnd', fadeContainerEnd);
|
||||
swap.classList.add('in');
|
||||
swap.addEventListener('webkitTransitionEnd', fadeSwapEnd);
|
||||
}
|
||||
function fadeSwapEnd () {
|
||||
swap.removeEventListener('webkitTransitionEnd', fadeSwapEnd);
|
||||
container.parentNode.removeChild(container);
|
||||
swap.classList.remove('fade');
|
||||
swap.classList.remove('in');
|
||||
complete && complete();
|
||||
}
|
||||
}
|
||||
|
||||
if (/slide/.test(transition)) {
|
||||
container.offsetWidth; // force reflow
|
||||
swapDirection = enter ? 'right' : 'left'
|
||||
containerDirection = enter ? 'left' : 'right'
|
||||
container.classList.add(containerDirection);
|
||||
swap.classList.remove(swapDirection);
|
||||
swap.addEventListener('webkitTransitionEnd', slideEnd);
|
||||
|
||||
function slideEnd() {
|
||||
swap.removeEventListener('webkitTransitionEnd', slideEnd);
|
||||
swap.classList.remove('slide');
|
||||
swap.classList.remove(swapDirection);
|
||||
container.parentNode.removeChild(container);
|
||||
complete && complete();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var triggerStateChange = function () {
|
||||
var e = new CustomEvent('push', {
|
||||
detail: { state: getCached(PUSH.id) },
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
|
||||
window.dispatchEvent(e);
|
||||
};
|
||||
|
||||
var findTarget = function (target) {
|
||||
var i, toggles = document.querySelectorAll('a');
|
||||
for (; target && target !== document; target = target.parentNode) {
|
||||
for (i = toggles.length; i--;) { if (toggles[i] === target) return target; }
|
||||
}
|
||||
};
|
||||
|
||||
var locationReplace = function (url) {
|
||||
window.history.replaceState(null, '', '#');
|
||||
window.location.replace(url);
|
||||
};
|
||||
|
||||
var parseURL = function (url) {
|
||||
var a = document.createElement('a'); a.href = url; return a;
|
||||
};
|
||||
|
||||
var extendWithDom = function (obj, fragment, dom) {
|
||||
var i;
|
||||
var result = {};
|
||||
|
||||
for (i in obj) result[i] = obj[i];
|
||||
|
||||
Object.keys(bars).forEach(function (key) {
|
||||
var el = dom.querySelector(bars[key]);
|
||||
if (el) el.parentNode.removeChild(el);
|
||||
result[key] = el;
|
||||
});
|
||||
|
||||
result.contents = dom.querySelector(fragment);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var parseXHR = function (xhr, options) {
|
||||
var head;
|
||||
var body;
|
||||
var data = {};
|
||||
var responseText = xhr.responseText;
|
||||
|
||||
data.url = options.url;
|
||||
|
||||
if (!responseText) return data;
|
||||
|
||||
if (/<html/i.test(responseText)) {
|
||||
head = document.createElement('div');
|
||||
body = document.createElement('div');
|
||||
head.innerHTML = responseText.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]
|
||||
body.innerHTML = responseText.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]
|
||||
} else {
|
||||
head = body = document.createElement('div');
|
||||
head.innerHTML = responseText;
|
||||
}
|
||||
|
||||
data.title = head.querySelector('title');
|
||||
data.title = data.title && data.title.innerText.trim();
|
||||
|
||||
if (options.transition) data = extendWithDom(data, '.content', body);
|
||||
else data.contents = body;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
// Attach PUSH event handlers
|
||||
// ==========================
|
||||
|
||||
window.addEventListener('touchstart', function () { isScrolling = false; });
|
||||
window.addEventListener('touchmove', function () { isScrolling = true; })
|
||||
window.addEventListener('touchend', touchend);
|
||||
window.addEventListener('click', function (e) { if (getTarget(e)) e.preventDefault(); });
|
||||
window.addEventListener('popstate', popstate);
|
||||
|
||||
}();/* ----------------------------------
|
||||
* TABS v1.0.0
|
||||
* Licensed under The MIT License
|
||||
* http://opensource.org/licenses/MIT
|
||||
* ---------------------------------- */
|
||||
|
||||
!function () {
|
||||
var getTarget = function (target) {
|
||||
var i, popovers = document.querySelectorAll('.segmented-controller li a');
|
||||
for (; target && target !== document; target = target.parentNode) {
|
||||
for (i = popovers.length; i--;) { if (popovers[i] === target) return target; }
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("touchend", function (e) {
|
||||
var activeTab;
|
||||
var activeBody;
|
||||
var targetBody;
|
||||
var targetTab;
|
||||
var className = 'active';
|
||||
var classSelector = '.' + className;
|
||||
var targetAnchor = getTarget(e.target);
|
||||
|
||||
if (!targetAnchor) return;
|
||||
|
||||
targetTab = targetAnchor.parentNode;
|
||||
activeTab = targetTab.parentNode.querySelector(classSelector);
|
||||
|
||||
if (activeTab) activeTab.classList.remove(className);
|
||||
|
||||
targetTab.classList.add(className);
|
||||
|
||||
if (!targetAnchor.hash) return;
|
||||
|
||||
targetBody = document.querySelector(targetAnchor.hash);
|
||||
|
||||
if (!targetBody) return;
|
||||
|
||||
activeBody = targetBody.parentNode.querySelector(classSelector);
|
||||
|
||||
if (activeBody) activeBody.classList.remove(className);
|
||||
|
||||
targetBody.classList.add(className)
|
||||
});
|
||||
|
||||
window.addEventListener('click', function (e) { if (getTarget(e.target)) e.preventDefault(); });
|
||||
}();/* ----------------------------------
|
||||
* SLIDER v1.0.0
|
||||
* Licensed under The MIT License
|
||||
* Adapted from Brad Birdsall's swipe
|
||||
* http://opensource.org/licenses/MIT
|
||||
* ---------------------------------- */
|
||||
|
||||
!function () {
|
||||
|
||||
var pageX;
|
||||
var pageY;
|
||||
var slider;
|
||||
var deltaX;
|
||||
var deltaY;
|
||||
var offsetX;
|
||||
var lastSlide;
|
||||
var startTime;
|
||||
var resistance;
|
||||
var sliderWidth;
|
||||
var slideNumber;
|
||||
var isScrolling;
|
||||
var scrollableArea;
|
||||
|
||||
var getSlider = function (target) {
|
||||
var i, sliders = document.querySelectorAll('.slider ul');
|
||||
for (; target && target !== document; target = target.parentNode) {
|
||||
for (i = sliders.length; i--;) { if (sliders[i] === target) return target; }
|
||||
}
|
||||
}
|
||||
|
||||
var getScroll = function () {
|
||||
var translate3d = slider.style.webkitTransform.match(/translate3d\(([^,]*)/);
|
||||
return parseInt(translate3d ? translate3d[1] : 0)
|
||||
};
|
||||
|
||||
var setSlideNumber = function (offset) {
|
||||
var round = offset ? (deltaX < 0 ? 'ceil' : 'floor') : 'round';
|
||||
slideNumber = Math[round](getScroll() / ( scrollableArea / slider.children.length) );
|
||||
slideNumber += offset;
|
||||
slideNumber = Math.min(slideNumber, 0);
|
||||
slideNumber = Math.max(-(slider.children.length - 1), slideNumber);
|
||||
}
|
||||
|
||||
var onTouchStart = function (e) {
|
||||
slider = getSlider(e.target);
|
||||
|
||||
if (!slider) return;
|
||||
|
||||
var firstItem = slider.querySelector('li');
|
||||
|
||||
scrollableArea = firstItem.offsetWidth * slider.children.length;
|
||||
isScrolling = undefined;
|
||||
sliderWidth = slider.offsetWidth;
|
||||
resistance = 1;
|
||||
lastSlide = -(slider.children.length - 1);
|
||||
startTime = +new Date;
|
||||
pageX = e.touches[0].pageX;
|
||||
pageY = e.touches[0].pageY;
|
||||
|
||||
setSlideNumber(0);
|
||||
|
||||
slider.style['-webkit-transition-duration'] = 0;
|
||||
};
|
||||
|
||||
var onTouchMove = function (e) {
|
||||
if (e.touches.length > 1 || !slider) return; // Exit if a pinch || no slider
|
||||
|
||||
deltaX = e.touches[0].pageX - pageX;
|
||||
deltaY = e.touches[0].pageY - pageY;
|
||||
pageX = e.touches[0].pageX;
|
||||
pageY = e.touches[0].pageY;
|
||||
|
||||
if (typeof isScrolling == 'undefined') {
|
||||
isScrolling = Math.abs(deltaY) > Math.abs(deltaX);
|
||||
}
|
||||
|
||||
if (isScrolling) return;
|
||||
|
||||
offsetX = (deltaX / resistance) + getScroll();
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
resistance = slideNumber == 0 && deltaX > 0 ? (pageX / sliderWidth) + 1.25 :
|
||||
slideNumber == lastSlide && deltaX < 0 ? (Math.abs(pageX) / sliderWidth) + 1.25 : 1;
|
||||
|
||||
slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
|
||||
};
|
||||
|
||||
var onTouchEnd = function (e) {
|
||||
if (!slider || isScrolling) return;
|
||||
|
||||
setSlideNumber(
|
||||
(+new Date) - startTime < 1000 && Math.abs(deltaX) > 15 ? (deltaX < 0 ? -1 : 1) : 0
|
||||
);
|
||||
|
||||
offsetX = slideNumber * sliderWidth;
|
||||
|
||||
slider.style['-webkit-transition-duration'] = '.2s';
|
||||
slider.style.webkitTransform = 'translate3d(' + offsetX + 'px,0,0)';
|
||||
|
||||
e = new CustomEvent('slide', {
|
||||
detail: { slideNumber: Math.abs(slideNumber) },
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
|
||||
slider.parentNode.dispatchEvent(e);
|
||||
};
|
||||
|
||||
window.addEventListener('touchstart', onTouchStart);
|
||||
window.addEventListener('touchmove', onTouchMove);
|
||||
window.addEventListener('touchend', onTouchEnd);
|
||||
|
||||
}();
|
||||
/* ----------------------------------
|
||||
* TOGGLE v1.0.0
|
||||
* Licensed under The MIT License
|
||||
* http://opensource.org/licenses/MIT
|
||||
* ---------------------------------- */
|
||||
|
||||
!function () {
|
||||
|
||||
var start = {};
|
||||
var touchMove = false;
|
||||
var distanceX = false;
|
||||
var toggle = false;
|
||||
|
||||
var findToggle = function (target) {
|
||||
var i, toggles = document.querySelectorAll('.toggle');
|
||||
for (; target && target !== document; target = target.parentNode) {
|
||||
for (i = toggles.length; i--;) { if (toggles[i] === target) return target; }
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('touchstart', function (e) {
|
||||
e = e.originalEvent || e;
|
||||
|
||||
toggle = findToggle(e.target);
|
||||
|
||||
if (!toggle) return;
|
||||
|
||||
var handle = toggle.querySelector('.toggle-handle');
|
||||
var toggleWidth = toggle.offsetWidth;
|
||||
var handleWidth = handle.offsetWidth;
|
||||
var offset = toggle.classList.contains('active') ? toggleWidth - handleWidth : 0;
|
||||
|
||||
start = { pageX : e.touches[0].pageX - offset, pageY : e.touches[0].pageY };
|
||||
touchMove = false;
|
||||
|
||||
// todo: probably should be moved to the css
|
||||
toggle.style['-webkit-transition-duration'] = 0;
|
||||
});
|
||||
|
||||
window.addEventListener('touchmove', function (e) {
|
||||
e = e.originalEvent || e;
|
||||
|
||||
if (e.touches.length > 1) return; // Exit if a pinch
|
||||
|
||||
if (!toggle) return;
|
||||
|
||||
var handle = toggle.querySelector('.toggle-handle');
|
||||
var current = e.touches[0];
|
||||
var toggleWidth = toggle.offsetWidth;
|
||||
var handleWidth = handle.offsetWidth;
|
||||
var offset = toggleWidth - handleWidth;
|
||||
|
||||
touchMove = true;
|
||||
distanceX = current.pageX - start.pageX;
|
||||
|
||||
if (Math.abs(distanceX) < Math.abs(current.pageY - start.pageY)) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if (distanceX < 0) return handle.style.webkitTransform = 'translate3d(0,0,0)';
|
||||
if (distanceX > offset) return handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)';
|
||||
|
||||
handle.style.webkitTransform = 'translate3d(' + distanceX + 'px,0,0)';
|
||||
|
||||
toggle.classList[(distanceX > (toggleWidth/2 - handleWidth/2)) ? 'add' : 'remove']('active');
|
||||
});
|
||||
|
||||
window.addEventListener('touchend', function (e) {
|
||||
if (!toggle) return;
|
||||
|
||||
var handle = toggle.querySelector('.toggle-handle');
|
||||
var toggleWidth = toggle.offsetWidth;
|
||||
var handleWidth = handle.offsetWidth;
|
||||
var offset = toggleWidth - handleWidth;
|
||||
var slideOn = (!touchMove && !toggle.classList.contains('active')) || (touchMove && (distanceX > (toggleWidth/2 - handleWidth/2)));
|
||||
|
||||
if (slideOn) handle.style.webkitTransform = 'translate3d(' + offset + 'px,0,0)';
|
||||
else handle.style.webkitTransform = 'translate3d(0,0,0)';
|
||||
|
||||
toggle.classList[slideOn ? 'add' : 'remove']('active');
|
||||
|
||||
e = new CustomEvent('toggle', {
|
||||
detail: { isActive: slideOn },
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
|
||||
toggle.dispatchEvent(e);
|
||||
|
||||
touchMove = false;
|
||||
toggle = false;
|
||||
});
|
||||
|
||||
}();
|
||||
42
example/cordova/iOS/www/js/test/event-listeners.js
vendored
Normal file
42
example/cordova/iOS/www/js/test/event-listeners.js
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
(function(window, document, framework) {
|
||||
|
||||
// this file should not be apart of the build
|
||||
// its just just for testing that the correct
|
||||
// events are being triggered and at the correct
|
||||
// times, and so we don't have to hardcode/remove
|
||||
// console calls throughout the code
|
||||
|
||||
framework.on('ready', function(){
|
||||
console.log('ready');
|
||||
});
|
||||
|
||||
framework.on('initalized', function(){
|
||||
console.log('initalized');
|
||||
});
|
||||
|
||||
framework.on('pageinit', function(e){
|
||||
console.log('pageinit:', e.detail);
|
||||
});
|
||||
|
||||
framework.on('pageinitfailed', function(){
|
||||
console.log('pageinitfailed');
|
||||
});
|
||||
|
||||
framework.on('pageloaded', function(e){
|
||||
console.log('pageloaded,', e.detail.data.url, ", Title:", e.detail.data.title);
|
||||
});
|
||||
|
||||
framework.on('pagecreate', function(e){
|
||||
console.log('pagecreate,', e.detail.url);
|
||||
});
|
||||
|
||||
framework.on('pageview', function(){
|
||||
console.log('pageview');
|
||||
});
|
||||
|
||||
framework.on('pageremove', function(){
|
||||
console.log('pageremove');
|
||||
});
|
||||
|
||||
|
||||
})(this, document, FM = this.FM || {});
|
||||
11
js/framework/glue/angular-glue.js
vendored
11
js/framework/glue/angular-glue.js
vendored
@ -1,3 +1,12 @@
|
||||
/* used to tie angular.js with the framework */
|
||||
/* nowhere should the framework reference angular.js */
|
||||
/* nowhere in angular.js should it reference the framework */
|
||||
/* nowhere in angular.js should it reference the framework */
|
||||
|
||||
var ionic = angular.module('ionic', ['ngTouch']);
|
||||
|
||||
ionic.directive('panel', ['$parse', '$timeout', '$rootElement',
|
||||
function($parse, $timeout, $rootElement) {
|
||||
return function(scope, element, attrs) {
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user