mirror of
https://github.com/lukevella/rallly.git
synced 2025-05-11 07:56:47 +02:00
Added custom confirm modal dialog box
This commit is contained in:
parent
0320185ce5
commit
6ad493a079
31 changed files with 909 additions and 41 deletions
|
@ -14,10 +14,7 @@ var EventSchema = new Schema({
|
|||
type : Date,
|
||||
default : Date.now
|
||||
},
|
||||
updated : {
|
||||
type : Date,
|
||||
default : Date.now
|
||||
},
|
||||
updated : Date,
|
||||
title : String,
|
||||
dates : [Date],
|
||||
emails : [String],
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"bootstrap-datepicker": "~1.3.0",
|
||||
"angular-ui-router": "~0.2.13",
|
||||
"angular-resource": "~1.3.6",
|
||||
"ngFx": "~1.0.5"
|
||||
"ngFx": "~1.0.5",
|
||||
"angular-modal": "~0.4.0"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
angular.module('rallly')
|
||||
.controller('EditEventCtrl', function($scope, $http, $state, $timeout, Event){
|
||||
.controller('EditEventCtrl', function($scope, $http, $state, $timeout, Event, ConfirmModal){
|
||||
var id = $state.params.id
|
||||
$scope.event = Event.get({id:id}, function(data){
|
||||
var dates = [];
|
||||
|
@ -20,16 +20,23 @@ angular.module('rallly')
|
|||
$scope.submit = function(){
|
||||
if ($scope.didChange()){
|
||||
if ($scope.didChangeDates() ){
|
||||
if (confirm("Changing the dates will reset all entries by the participants. Are you sure you want to proceed?")){
|
||||
update();
|
||||
}
|
||||
var modal = new ConfirmModal({
|
||||
title : 'Hold up!',
|
||||
message : 'Changing the dates will reset all entries by the participants. Are you sure you want to do that?',
|
||||
confirmText : 'Yes, I\'m sure',
|
||||
isDestructive : true,
|
||||
confirm : function(){
|
||||
update();
|
||||
}
|
||||
});
|
||||
modal.show();
|
||||
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
var update = function(){
|
||||
$scope.event.participants = [];
|
||||
Event.update({
|
||||
id : id
|
||||
}, $scope.event,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
angular.module('rallly')
|
||||
.controller('EventCtrl', function($scope, $http, $state, Event, Participant){
|
||||
.controller('EventCtrl', function($scope, $http, $state, Event, Participant, ConfirmModal){
|
||||
$(".nav-link").removeClass('active');
|
||||
var id = $state.params.id;
|
||||
$scope.participant = {};
|
||||
|
@ -13,12 +13,21 @@ angular.module('rallly')
|
|||
$state.go('notfound');
|
||||
});
|
||||
$scope.delete = function(participant){
|
||||
if (confirm("Are you sure you want to remove "+participant.name+"?")){
|
||||
Participant.remove({ id : id , pid : participant._id }, function(event){
|
||||
$scope.event = event;
|
||||
});
|
||||
}
|
||||
var modal = new ConfirmModal({
|
||||
title : 'Delete "'+participant.name+'"?',
|
||||
message : 'Are you sure you want to remove '+participant.name+' from the poll?',
|
||||
confirmText : 'Yes - delete',
|
||||
cancelText : 'No - nevermind',
|
||||
isDestructive : true,
|
||||
confirm : function(){
|
||||
Participant.remove({ id : id , pid : participant._id }, function(event){
|
||||
$scope.event = event;
|
||||
});
|
||||
}
|
||||
});
|
||||
modal.show();
|
||||
}
|
||||
|
||||
$scope.defaults = [];
|
||||
|
||||
$scope.editEvent = function(){
|
||||
|
@ -46,4 +55,6 @@ angular.module('rallly')
|
|||
$scope.participant = {};
|
||||
});
|
||||
}
|
||||
}).controller('DeleteModalCtrl', function(){
|
||||
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ angular.module('rallly')
|
|||
restrict : 'A',
|
||||
require : 'ngModel',
|
||||
link : function(scope, el, attrs, ngModel){
|
||||
$(el).datepicker({
|
||||
angular.element(el).datepicker({
|
||||
multidate : true,
|
||||
todayHighlight: true,
|
||||
format : 'dd/mm/yyyy'
|
||||
|
@ -40,10 +40,10 @@ angular.module('rallly')
|
|||
});
|
||||
|
||||
scope.clearDates = function(){
|
||||
$(el).datepicker('setDate', null)
|
||||
angular.element(el).datepicker('setDate', null)
|
||||
};
|
||||
scope.unsetDate = function(date){
|
||||
$(el).datepicker('setDates', scope.event.dates.filter(function(el){
|
||||
angular.element(el).datepicker('setDates', scope.event.dates.filter(function(el){
|
||||
return el != date;
|
||||
}));
|
||||
};
|
||||
|
|
28
public/js/filters/elapsed.filter.js
Normal file
28
public/js/filters/elapsed.filter.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
angular.module('rallly')
|
||||
.filter('elapsed', function(){
|
||||
return function(date){
|
||||
if (!date) return;
|
||||
var time = Date.parse(date),
|
||||
timeNow = new Date().getTime(),
|
||||
difference = timeNow - time,
|
||||
seconds = Math.floor(difference / 1000),
|
||||
minutes = Math.floor(seconds / 60),
|
||||
hours = Math.floor(minutes / 60),
|
||||
days = Math.floor(hours / 24);
|
||||
if (days > 1) {
|
||||
return days + " days ago";
|
||||
} else if (days == 1) {
|
||||
return "1 day ago"
|
||||
} else if (hours > 1) {
|
||||
return hours + " hours ago";
|
||||
} else if (hours == 1) {
|
||||
return "an hour ago";
|
||||
} else if (minutes > 1) {
|
||||
return minutes + " minutes ago";
|
||||
} else if (minutes == 1){
|
||||
return "a minute ago";
|
||||
} else {
|
||||
return "a few seconds ago";
|
||||
}
|
||||
}
|
||||
})
|
|
@ -1,4 +1,4 @@
|
|||
angular.module('rallly', ['ui.router','ngResource','ngFx'])
|
||||
angular.module('rallly', ['ui.router','ngResource','ngFx','btford.modal'])
|
||||
.config(function($stateProvider, $urlRouterProvider, $locationProvider){
|
||||
$locationProvider.html5Mode(true);
|
||||
$urlRouterProvider.otherwise("/notfound")
|
||||
|
|
29
public/js/services/modal.service.js
Normal file
29
public/js/services/modal.service.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
angular.module('rallly')
|
||||
.factory('ConfirmModal', function(btfModal){
|
||||
|
||||
return function(config){
|
||||
var modal;
|
||||
modal = btfModal({
|
||||
templateUrl : 'templates/confirmmodal.html',
|
||||
controllerAs : 'modal',
|
||||
controller : function(){
|
||||
this.title = config.title
|
||||
this.message = config.message;
|
||||
this.confirm = function(){
|
||||
if (config.confirm) config.confirm();
|
||||
modal.deactivate();
|
||||
}
|
||||
this.cancel = modal.deactivate;
|
||||
this.confirmText = config.confirmText || 'Confirm';
|
||||
this.cancelText = config.cancelText || 'Cancel';
|
||||
this.isDestructive = config.isDestructive;
|
||||
}
|
||||
});
|
||||
this.show = function(){
|
||||
modal.activate();
|
||||
}
|
||||
this.destroy = function(){
|
||||
modal.deactivate();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -15,7 +15,7 @@
|
|||
font-weight:600;
|
||||
color: $dark-gray-clr;
|
||||
text-decoration:none;
|
||||
padding: em(8px) em(20px);
|
||||
padding: em(8px) em(15px);
|
||||
&.disabled {
|
||||
cursor:default;
|
||||
opacity: 0.5;
|
||||
|
|
42
public/scss/partials/_modal.scss
Normal file
42
public/scss/partials/_modal.scss
Normal file
|
@ -0,0 +1,42 @@
|
|||
.rl-modal {
|
||||
background:white;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
box-shadow: 0 0 5px rgba(black, 0.5);
|
||||
left: 50%;
|
||||
width: 50%;
|
||||
max-width: 400px;
|
||||
display:inline-block;
|
||||
min-width: 200px;
|
||||
height: auto;
|
||||
z-index: 2000;
|
||||
overflow:hidden;
|
||||
border-radius: 5px;
|
||||
@include transform(translateX(-50%) translateY(-50%));
|
||||
.rl-modal-message {
|
||||
padding: 0 20px 20px 20px;
|
||||
font-size: em(12px);
|
||||
color: $body-clr;
|
||||
}
|
||||
.rl-modal-title {
|
||||
padding:20px 20px 5px 20px;
|
||||
font-size: em(18px);
|
||||
}
|
||||
.rl-modal-actions {
|
||||
border-top:1px solid #ddd;
|
||||
background: #F9FAFA;
|
||||
text-align:right;
|
||||
padding: em(10px) em(20px);
|
||||
}
|
||||
}
|
||||
|
||||
.rl-modal-overlay {
|
||||
position:fixed;
|
||||
z-index: 1000;
|
||||
top:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
background:transparent;
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@ body {
|
|||
@import "partials/buttons";
|
||||
@import "partials/type";
|
||||
@import "partials/form";
|
||||
@import "partials/modal";
|
||||
@import "partials/datepicker";
|
||||
@import "partials/event";
|
||||
@import "partials/newevent";
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<div style="max-width:500px">
|
||||
<div style="max-width:600px">
|
||||
<h1>What is Rallly?</h1>
|
||||
<h2>Rallly is a collaborative scheduling service that makes deciding on a date fast and easy.</h2>
|
||||
<div class="rl-page-desc">Rallly is a collaborative scheduling service that makes deciding on a date fast and easy.</div>
|
||||
<h2>Hi, I'm Luke!</h2>
|
||||
<p>
|
||||
Hi, my name is Luke and I created Rallly as side project to help me learn some new technologies. I decided to publish it because I thought other people might find it useful. Rallly is a completely free service. In fact it is even open source. You can look at the latest source code on Github.
|
||||
I created Rallly as side project to help me learn some new technologies. I decided to publish it because I thought other people might find it useful. Rallly is a completely free service. In fact it is even open source. You can look at the latest source code on Github.
|
||||
</p>
|
||||
</div>
|
||||
|
|
12
public/templates/confirmmodal.html
Normal file
12
public/templates/confirmmodal.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="rl-modal-overlay" ng-click="modal.cancel()"></div>
|
||||
|
||||
<div class="rl-modal">
|
||||
<div class="rl-modal-title">{{modal.title}}</div>
|
||||
<div class="rl-modal-message">
|
||||
{{modal.message}}
|
||||
</div>
|
||||
<div class="rl-modal-actions">
|
||||
<button ng-click="modal.confirm()" class="btn-primary" ng-class="{danger : modal.isDestructive}">{{modal.confirmText}}</button>
|
||||
<button ng-click="modal.cancel()" class="btn-primary">{{modal.cancelText}}</button>
|
||||
</div>
|
||||
</div>
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
<h1>Editing: {{event.title}}</h1>
|
||||
<h1>Edit Event</h1>
|
||||
<div class="rl-page-desc">
|
||||
You can makes changes to your existing event by changing the fields in the form below. When you're ready click save.
|
||||
</div>
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<h1 class="fx-rotate-clock">{{event.title}}</h1>
|
||||
<ul class="event-detail-list">
|
||||
<li class="event-created-by">
|
||||
Created by <a href="{{event.creator.email}}">{{event.creator.name}}</a> on {{event.created | date : 'medium'}}
|
||||
Created by <a href="{{event.creator.email}}">{{event.creator.name}}</a> - {{event.created | elapsed}}
|
||||
</li>
|
||||
<li>
|
||||
Last updated {{event.updated | date : 'medium'}}
|
||||
<li ng-show="event.updated">
|
||||
Updated {{event.updated | elapsed}}
|
||||
</li>
|
||||
<li ng-show="event.location" class="event-location">
|
||||
{{event.location}}
|
||||
|
@ -24,7 +24,7 @@
|
|||
<th class="event-poll-participants">
|
||||
{{event.participants.length}} participants
|
||||
</th>
|
||||
<th class="center" ng-repeat="date in event.dates">
|
||||
<th width="70" class="center" ng-repeat="date in event.dates">
|
||||
<div class="daticon">
|
||||
<div class="dow">
|
||||
{{date | date: 'EEE'}}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<h1>Good Job!</h1>
|
||||
<p>
|
||||
Your event has been created. An email has been sent to all the participants with a link to the event page. Make sure you visit the page and vote on the dates yourself.
|
||||
</p>
|
||||
<h2>Here's the link</h2>
|
||||
<h1>{{eventUrl}}</h1>
|
||||
<a class="btn-primary" href="{{eventUrl}}">Go to Event Page</a>
|
30
public/vendor/angular-modal/.bower.json
vendored
Normal file
30
public/vendor/angular-modal/.bower.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "angular-modal",
|
||||
"version": "0.4.0",
|
||||
"main": "modal.js",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"components",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"angular": "~1.2.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "~1.2.13"
|
||||
},
|
||||
"homepage": "https://github.com/btford/angular-modal",
|
||||
"_release": "0.4.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v0.4.0",
|
||||
"commit": "ecbdc657bfe0c4ad6281aee0c1432278f10c5026"
|
||||
},
|
||||
"_source": "git://github.com/btford/angular-modal.git",
|
||||
"_target": "~0.4.0",
|
||||
"_originalSource": "angular-modal",
|
||||
"_direct": true
|
||||
}
|
211
public/vendor/angular-modal/README.md
vendored
Normal file
211
public/vendor/angular-modal/README.md
vendored
Normal file
|
@ -0,0 +1,211 @@
|
|||
# angular-modal [](https://travis-ci.org/btford/angular-modal)
|
||||
|
||||
A modal factory service for AngularJS that makes it easy to add modals to your app.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
bower install angular-modal
|
||||
```
|
||||
|
||||
## Usage
|
||||
1. Include the `modal.js` script provided by this component into your app.
|
||||
2. *Optional:* Include the `modal.css` style provided by this component into your html.
|
||||
3. Add `btford.modal` as a module dependency to your app.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
[Plunker demo](http://plnkr.co/edit/lJDNqafSCKdpMI8AjR0B?p=preview)
|
||||
|
||||
### Typical Use
|
||||
|
||||
> app.js
|
||||
|
||||
```javascript
|
||||
angular.module('myApp', ['btford.modal']).
|
||||
|
||||
// let's make a modal called `myModal`
|
||||
factory('myModal', function (btfModal) {
|
||||
return btfModal({
|
||||
controller: 'MyModalCtrl',
|
||||
controllerAs: 'modal',
|
||||
templateUrl: 'my-modal.html'
|
||||
});
|
||||
}).
|
||||
|
||||
// typically you'll inject the modal service into its own
|
||||
// controller so that the modal can close itself
|
||||
controller('MyModalCtrl', function (myModal) {
|
||||
this.closeMe = myModal.deactivate;
|
||||
}).
|
||||
|
||||
controller('MyCtrl', function (myModal) {
|
||||
this.showModal = myModal.activate;
|
||||
});
|
||||
```
|
||||
|
||||
> my-modal.html
|
||||
|
||||
```html
|
||||
<div class="btf-modal">
|
||||
<h3>Hello {{name}}</h3>
|
||||
<p><a href ng-click="modal.closeMe()">Close Me</a></p>
|
||||
</div>
|
||||
```
|
||||
|
||||
> index.html
|
||||
|
||||
```html
|
||||
<div ng-app="myApp" ng-controller="MyCtrl as ctrl">
|
||||
<a href ng-click="ctrl.showModal()">Show the modal</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Cleaning up
|
||||
|
||||
If you add any listeners within the modal's controller that are **outside the modal's `scope`**,
|
||||
you should remove them with `$scope.$on('$destroy', fn () { ... })` to avoid creating a memory leak.
|
||||
|
||||
Building on the example above:
|
||||
|
||||
> app.js
|
||||
|
||||
```javascript
|
||||
// ...
|
||||
controller('MyModalCtrl', function (myModal, $timeout) {
|
||||
|
||||
var ctrl = this,
|
||||
timeoutId;
|
||||
|
||||
ctrl.tickCount = 5;
|
||||
|
||||
ctrl.closeMe = function () {
|
||||
cancelTick();
|
||||
myModal.deactivate();
|
||||
};
|
||||
|
||||
function tick() {
|
||||
timeoutId = $timeout(function() {
|
||||
ctrl.tickCount -= 1;
|
||||
if (ctrl.tickCount <= 0) {
|
||||
ctrl.closeMe();
|
||||
} else {
|
||||
tick();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function cancelTick() {
|
||||
$timeout.cancel(timeoutId);
|
||||
}
|
||||
|
||||
$scope.$on('$destroy', cancelTick);
|
||||
|
||||
tick();
|
||||
}).
|
||||
// ...
|
||||
```
|
||||
|
||||
|
||||
### Inline Options
|
||||
|
||||
**Note:** The best practice is to use a separate file for the template and a separate declaration for
|
||||
the controller, but inlining these options might be more pragmatic for cases where the template or
|
||||
controller is just a couple lines.
|
||||
|
||||
```javascript
|
||||
angular.module('myApp', []).
|
||||
|
||||
// let's make a modal called myModal
|
||||
factory('myModal', function (btfModal) {
|
||||
return btfModal({
|
||||
controller: function () {
|
||||
this.name = 'World';
|
||||
},
|
||||
controllerAs: 'ctrl',
|
||||
template: '<div class="btf-modal">Hello {{ctrl.name}}</div>'
|
||||
});
|
||||
}).
|
||||
|
||||
controller('MyCtrl', function (myModal) {
|
||||
this.showModal = myModal.activate;
|
||||
});
|
||||
```
|
||||
|
||||
```html
|
||||
<div ng-app="myApp" ng-controller="MyCtrl">
|
||||
<a href ng-click="ctrl.showModal()">Show the modal</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### `btfModal`
|
||||
|
||||
The modal `factory`. Takes a configuration object as a parameter:
|
||||
|
||||
```javascript
|
||||
var modalService = btfModal({
|
||||
/* options */
|
||||
})
|
||||
```
|
||||
|
||||
And returns a `modalService` object that you can use to show/hide the modal (described below).
|
||||
|
||||
The config object **must** either have a `template` or a `templateUrl` option.
|
||||
|
||||
These options work just like the [route configuration in Angular's
|
||||
`$routeProvider`](http://docs.angularjs.org/api/ngRoute.$routeProvider#methods_when).
|
||||
|
||||
|
||||
#### `config.template`
|
||||
**string:** HTML string of the template to be used for this modal.
|
||||
Unless the template is very simple, you should probably use `config.templateUrl` instead.
|
||||
|
||||
#### `config.templateUrl`
|
||||
**string (recommended):** URL to the HTML template to be used for this modal.
|
||||
|
||||
#### `config.controller`
|
||||
**string|function (optional):** The name of a controller or a controller function.
|
||||
|
||||
#### `config.controllerAs`
|
||||
**string (optional, recommended):** Makes the controller available on the scope of the modal as the given name.
|
||||
|
||||
#### `config.container`
|
||||
**DOM Node (optional):** DOM node to prepend . Defaults to `document.body`.
|
||||
|
||||
|
||||
### `modalService`
|
||||
|
||||
A `modalService` has just two methods: `activate` and `deactivate`.
|
||||
|
||||
#### `modalService.activate`
|
||||
|
||||
Takes a hash of objects to add to the scope of the modal as locals.
|
||||
Adds the modal to the DOM by prepending it to the `<body>`.
|
||||
Returns a promise that resolves once the modal is active.
|
||||
|
||||
#### `modalService.deactivate`
|
||||
|
||||
Removes the modal (DOM and scope) from the DOM.
|
||||
Returns a promise that resolves once the modal is removed.
|
||||
|
||||
#### `modalService.active`
|
||||
|
||||
Returns whether or not the modal is currently activated.
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
You can run the tests with [`karma`](http://karma-runner.github.io/0.10/index.html):
|
||||
|
||||
```shell
|
||||
karma start karma.conf.js
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
MIT
|
19
public/vendor/angular-modal/bower.json
vendored
Normal file
19
public/vendor/angular-modal/bower.json
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "angular-modal",
|
||||
"version": "0.4.0",
|
||||
"main": "modal.js",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"components",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"angular": "~1.2.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "~1.2.13"
|
||||
}
|
||||
}
|
20
public/vendor/angular-modal/gulpfile.js
vendored
Normal file
20
public/vendor/angular-modal/gulpfile.js
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
var gulp = require('gulp'),
|
||||
gutil = require('gulp-util'),
|
||||
uglify = require('gulp-uglify'),
|
||||
rename = require("gulp-rename"),
|
||||
ngmin = require('gulp-ngmin');
|
||||
|
||||
gulp.task('scripts', function() {
|
||||
return gulp.src('modal.js').
|
||||
pipe(rename('modal.min.js')).
|
||||
pipe(ngmin()).
|
||||
pipe(uglify({
|
||||
preserveComments: 'some',
|
||||
outSourceMap: true
|
||||
})).
|
||||
pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('default', function() {
|
||||
gulp.start('scripts');
|
||||
});
|
30
public/vendor/angular-modal/karma.conf.js
vendored
Normal file
30
public/vendor/angular-modal/karma.conf.js
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
module.exports = function(config){
|
||||
config.set({
|
||||
basePath : './',
|
||||
|
||||
files : [
|
||||
'bower_components/angular/angular.js',
|
||||
'bower_components/angular-mocks/angular-mocks.js',
|
||||
'modal.js',
|
||||
'modal.spec.js'
|
||||
],
|
||||
|
||||
autoWatch : true,
|
||||
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
browsers : ['Chrome'],
|
||||
|
||||
plugins : [
|
||||
'karma-junit-reporter',
|
||||
'karma-chrome-launcher',
|
||||
'karma-firefox-launcher',
|
||||
'karma-jasmine'
|
||||
],
|
||||
|
||||
junitReporter : {
|
||||
outputFile: 'test_out/unit.xml',
|
||||
suite: 'unit'
|
||||
}
|
||||
|
||||
})}
|
20
public/vendor/angular-modal/modal.css
vendored
Normal file
20
public/vendor/angular-modal/modal.css
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* angular-modal v0.1.0
|
||||
* (c) 2013 Brian Ford http://briantford.com
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
.btf-modal {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 50%;
|
||||
max-width: 550px;
|
||||
min-width: 330px;
|
||||
height: auto;
|
||||
z-index: 2000;
|
||||
-webkit-transform: translateX(-50%) translateY(-50%);
|
||||
-moz-transform: translateX(-50%) translateY(-50%);
|
||||
-ms-transform: translateX(-50%) translateY(-50%);
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
}
|
89
public/vendor/angular-modal/modal.js
vendored
Normal file
89
public/vendor/angular-modal/modal.js
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* @license
|
||||
* angular-modal v0.4.0
|
||||
* (c) 2013 Brian Ford http://briantford.com
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('btford.modal', []).
|
||||
factory('btfModal', function ($animate, $compile, $rootScope, $controller, $q, $http, $templateCache) {
|
||||
return function modalFactory (config) {
|
||||
if (!(!config.template ^ !config.templateUrl)) {
|
||||
throw new Error('Expected modal to have exacly one of either `template` or `templateUrl`');
|
||||
}
|
||||
|
||||
var template = config.template,
|
||||
controller = config.controller || angular.noop,
|
||||
controllerAs = config.controllerAs,
|
||||
container = angular.element(config.container || document.body),
|
||||
element = null,
|
||||
html,
|
||||
scope;
|
||||
|
||||
if (config.template) {
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve(config.template);
|
||||
html = deferred.promise;
|
||||
} else {
|
||||
html = $http.get(config.templateUrl, {
|
||||
cache: $templateCache
|
||||
}).
|
||||
then(function (response) {
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
function activate (locals) {
|
||||
return html.then(function (html) {
|
||||
if (!element) {
|
||||
attach(html, locals);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function attach (html, locals) {
|
||||
element = angular.element(html);
|
||||
if (element.length === 0) {
|
||||
throw new Error('The template contains no elements; you need to wrap text nodes')
|
||||
}
|
||||
$animate.enter(element, container);
|
||||
scope = $rootScope.$new();
|
||||
if (locals) {
|
||||
for (var prop in locals) {
|
||||
scope[prop] = locals[prop];
|
||||
}
|
||||
}
|
||||
var ctrl = $controller(controller, { $scope: scope });
|
||||
if (controllerAs) {
|
||||
scope[controllerAs] = ctrl;
|
||||
}
|
||||
$compile(element)(scope);
|
||||
}
|
||||
|
||||
function deactivate () {
|
||||
var deferred = $q.defer();
|
||||
if (element) {
|
||||
$animate.leave(element, function () {
|
||||
scope.$destroy();
|
||||
element = null;
|
||||
deferred.resolve();
|
||||
});
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function active () {
|
||||
return !!element;
|
||||
}
|
||||
|
||||
return {
|
||||
activate: activate,
|
||||
deactivate: deactivate,
|
||||
active: active
|
||||
};
|
||||
};
|
||||
});
|
7
public/vendor/angular-modal/modal.min.js
vendored
Normal file
7
public/vendor/angular-modal/modal.min.js
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* @license
|
||||
* angular-modal v0.4.0
|
||||
* (c) 2013 Brian Ford http://briantford.com
|
||||
* License: MIT
|
||||
*/
|
||||
"use strict";angular.module("btford.modal",[]).factory("btfModal",["$animate","$compile","$rootScope","$controller","$q","$http","$templateCache",function(e,t,r,n,o,a,l){return function(c){function i(e){return p.then(function(t){$||u(t,e)})}function u(o,a){if($=angular.element(o),0===$.length)throw new Error("The template contains no elements; you need to wrap text nodes");if(e.enter($,h),d=r.$new(),a)for(var l in a)d[l]=a[l];var c=n(s,{$scope:d});v&&(d[v]=c),t($)(d)}function m(){var t=o.defer();return $?e.leave($,function(){d.$destroy(),$=null,t.resolve()}):t.resolve(),t.promise}function f(){return!!$}if(!(!c.template^!c.templateUrl))throw new Error("Expected modal to have exacly one of either `template` or `templateUrl`");var p,d,s=(c.template,c.controller||angular.noop),v=c.controllerAs,h=angular.element(c.container||document.body),$=null;if(c.template){var g=o.defer();g.resolve(c.template),p=g.promise}else p=a.get(c.templateUrl,{cache:l}).then(function(e){return e.data});return{activate:i,deactivate:m,active:f}}}]);
|
1
public/vendor/angular-modal/modal.min.js.map
vendored
Normal file
1
public/vendor/angular-modal/modal.min.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"modal.min.js.map","sources":["modal.min.js"],"names":["angular","module","factory","$animate","$compile","$rootScope","$controller","$q","$http","$templateCache","config","activate","locals","html","then","element","attach","length","Error","enter","container","scope","$new","prop","ctrl","controller","$scope","controllerAs","deactivate","deferred","defer","leave","$destroy","resolve","promise","active","template","templateUrl","noop","document","body","get","cache","response","data"],"mappings":";;;;;;AAMA,YACAA,SAAQC,OAAO,mBAAoBC,QAAQ,YACzC,WACA,WACA,aACA,cACA,KACA,QACA,iBACA,SAAUC,EAAUC,EAAUC,EAAYC,EAAaC,EAAIC,EAAOC,GAChE,MAAO,UAAsBC,GAc3B,QAASC,GAASC,GAChB,MAAOC,GAAKC,KAAK,SAAUD,GACpBE,GACHC,EAAOH,EAAMD,KAInB,QAASI,GAAOH,EAAMD,GAEpB,GADAG,EAAUf,QAAQe,QAAQF,GACH,IAAnBE,EAAQE,OACV,KAAM,IAAIC,OAAM,iEAIlB,IAFAf,EAASgB,MAAMJ,EAASK,GACxBC,EAAQhB,EAAWiB,OACfV,EACF,IAAK,GAAIW,KAAQX,GACfS,EAAME,GAAQX,EAAOW,EAGzB,IAAIC,GAAOlB,EAAYmB,GAAcC,OAAQL,GACzCM,KACFN,EAAMM,GAAgBH,GAExBpB,EAASW,GAASM,GAEpB,QAASO,KACP,GAAIC,GAAWtB,EAAGuB,OAUlB,OATIf,GACFZ,EAAS4B,MAAMhB,EAAS,WACtBM,EAAMW,WACNjB,EAAU,KACVc,EAASI,YAGXJ,EAASI,UAEJJ,EAASK,QAElB,QAASC,KACP,QAASpB,EApDX,MAAOL,EAAO0B,UAAY1B,EAAO2B,aAC/B,KAAM,IAAInB,OAAM,0EAElB,IAAoML,GAAMQ,EAA1KI,GAAjBf,EAAO0B,SAAuB1B,EAAOe,YAAczB,QAAQsC,MAAMX,EAAejB,EAAOiB,aAAcP,EAAYpB,QAAQe,QAAQL,EAAOU,WAAamB,SAASC,MAAOzB,EAAU,IAC9L,IAAIL,EAAO0B,SAAU,CACnB,GAAIP,GAAWtB,EAAGuB,OAClBD,GAASI,QAAQvB,EAAO0B,UACxBvB,EAAOgB,EAASK,YAEhBrB,GAAOL,EAAMiC,IAAI/B,EAAO2B,aAAeK,MAAOjC,IAAkBK,KAAK,SAAU6B,GAC7E,MAAOA,GAASC,MA4CpB,QACEjC,SAAUA,EACViB,WAAYA,EACZO,OAAQA"}
|
286
public/vendor/angular-modal/modal.spec.js
vendored
Normal file
286
public/vendor/angular-modal/modal.spec.js
vendored
Normal file
|
@ -0,0 +1,286 @@
|
|||
'use strict';
|
||||
|
||||
describe('btfModal', function() {
|
||||
var container,
|
||||
btfModal,
|
||||
$rootScope;
|
||||
|
||||
beforeEach(module('btford.modal'));
|
||||
|
||||
beforeEach(function () {
|
||||
container = angular.element('<div></div>');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container = null;
|
||||
});
|
||||
|
||||
describe('without animations', function () {
|
||||
beforeEach(inject(function(_btfModal_, _$rootScope_, $templateCache) {
|
||||
btfModal = _btfModal_;
|
||||
$rootScope = _$rootScope_;
|
||||
$rootScope.greeting = 'こんばんは';
|
||||
|
||||
$templateCache.put('test.html', [200, '<div>{{greeting}}</div>', {}]);
|
||||
}));
|
||||
|
||||
it('should not show a modal initially', function() {
|
||||
var modal = btfModal({
|
||||
templateUrl: 'test.html',
|
||||
container: container
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('');
|
||||
});
|
||||
|
||||
|
||||
it('should throw if called without a `template` or `templateUrl` option', function() {
|
||||
expect(function () { btfModal({}); }).toThrow();
|
||||
});
|
||||
|
||||
it('should throw if called with a text node', function() {
|
||||
var modal = btfModal({
|
||||
template: 'hey'
|
||||
});
|
||||
expect(function () {
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it('should throw if called with both `template` and `templateUrl` options', function() {
|
||||
expect(function () {
|
||||
btfModal({
|
||||
template: 'foo',
|
||||
templateUrl: 'foo.html'
|
||||
});
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
describe('#activate', function () {
|
||||
it('should show a modal when activated with `templateUrl`', function() {
|
||||
var modal = btfModal({
|
||||
templateUrl: 'test.html',
|
||||
container: container
|
||||
});
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('こんばんは');
|
||||
});
|
||||
|
||||
it('should show a modal when activated with `template`', function() {
|
||||
var modal = btfModal({
|
||||
template: '<span>{{greeting}}</span>',
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('こんばんは');
|
||||
});
|
||||
|
||||
it('should instantiate a controller via the `controller` option', function() {
|
||||
var modal = btfModal({
|
||||
template: '<span>{{greeting}}</span>',
|
||||
controller: function ($scope) {
|
||||
$scope.greeting = 'goodnight'
|
||||
},
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('goodnight');
|
||||
});
|
||||
|
||||
it('should expose a controller to the scope via the `controllerAs` option', function() {
|
||||
var modal = btfModal({
|
||||
template: '<span>{{ctrl.greeting}}</span>',
|
||||
controller: function () {
|
||||
this.greeting = 'boa noite'
|
||||
},
|
||||
controllerAs: 'ctrl',
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('boa noite');
|
||||
});
|
||||
|
||||
it('should pass locals to the modal scope', function() {
|
||||
var modal = btfModal({
|
||||
template: '<span>{{greeting}}</span>',
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate({
|
||||
greeting: 'bon soir'
|
||||
});
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('bon soir');
|
||||
});
|
||||
|
||||
it('should not activate multiple times', function() {
|
||||
var modal = btfModal({
|
||||
template: '<span>x</span>',
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('x');
|
||||
});
|
||||
|
||||
it('should resolve a promise after activating', function() {
|
||||
var spy = jasmine.createSpy('activated');
|
||||
|
||||
var modal = btfModal({
|
||||
template: '<span>x</span>',
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate().then(spy);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
|
||||
$rootScope.$digest();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#deactivate', function () {
|
||||
it('should remove a modal when deactivated', function() {
|
||||
|
||||
var modal = btfModal({
|
||||
template: '<span>{{greeting}}</span>',
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
modal.deactivate();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(container.text()).toBe('');
|
||||
});
|
||||
|
||||
it('should destroy the scope when deactivated', inject(function($$asyncCallback) {
|
||||
var destroySpy = jasmine.createSpy('onDestroy');
|
||||
|
||||
var modal = btfModal({
|
||||
template: '<span>{{greeting}}</span>',
|
||||
container: container,
|
||||
controller: function ($scope) {
|
||||
$scope.$on('$destroy', destroySpy);
|
||||
}
|
||||
});
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(destroySpy).not.toHaveBeenCalled();
|
||||
|
||||
modal.deactivate();
|
||||
$rootScope.$digest();
|
||||
$$asyncCallback.flush();
|
||||
|
||||
expect(destroySpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should resolve a promise after deactivating', inject(function($$asyncCallback) {
|
||||
var spy = jasmine.createSpy('deactivated');
|
||||
|
||||
var modal = btfModal({
|
||||
template: '<span>x</span>',
|
||||
container: container
|
||||
});
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
modal.deactivate().then(spy);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
|
||||
$$asyncCallback.flush();
|
||||
$rootScope.$digest();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('#active', function () {
|
||||
it('should return the state of the modal', inject(function($$asyncCallback) {
|
||||
|
||||
var modal = btfModal({
|
||||
template: '<span>{{greeting}}</span>',
|
||||
container: container
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
expect(modal.active()).toBe(false);
|
||||
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
expect(modal.active()).toBe(true);
|
||||
|
||||
modal.deactivate();
|
||||
$rootScope.$digest();
|
||||
$$asyncCallback.flush();
|
||||
|
||||
expect(modal.active()).toBe(false);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('with animations', function () {
|
||||
var $animate,
|
||||
modal;
|
||||
|
||||
beforeEach(module('ngAnimateMock'));
|
||||
|
||||
beforeEach(inject(function(btfModal, _$rootScope_, _$animate_) {
|
||||
$rootScope = _$rootScope_;
|
||||
$animate = _$animate_;
|
||||
|
||||
modal = btfModal({
|
||||
template: '<span>animations!</span>',
|
||||
container: container
|
||||
});
|
||||
}));
|
||||
|
||||
it('should trigger an enter animation when activated', function () {
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
|
||||
var item = $animate.queue.shift();
|
||||
expect(item.event).toBe('enter');
|
||||
});
|
||||
|
||||
it('should trigger a leave animation when deactivated', function () {
|
||||
modal.activate();
|
||||
$rootScope.$digest();
|
||||
$animate.queue.shift();
|
||||
|
||||
modal.deactivate();
|
||||
$rootScope.$digest();
|
||||
|
||||
var item = $animate.queue.shift();
|
||||
expect(item.event).toBe('leave');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
33
public/vendor/angular-modal/package.json
vendored
Normal file
33
public/vendor/angular-modal/package.json
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "angular-modal",
|
||||
"version": "0.4.0",
|
||||
"description": "easily add a modal to your angular app",
|
||||
"main": "modal.js",
|
||||
"scripts": {
|
||||
"test": "./node_modules/.bin/bower install && ./node_modules/.bin/karma start karma.conf.js --browsers Firefox --single-run"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/btford/angular-modal.git"
|
||||
},
|
||||
"keywords": [
|
||||
"angular",
|
||||
"angularjs",
|
||||
"modal"
|
||||
],
|
||||
"author": "Brian Ford",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/btford/angular-modal/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"karma": "~0.10",
|
||||
"karma-junit-reporter": "~0.1.0",
|
||||
"bower": "~1.2.7",
|
||||
"gulp": "~3.5.5",
|
||||
"gulp-util": "~2.2.14",
|
||||
"gulp-uglify": "~0.2.1",
|
||||
"gulp-rename": "~1.2.0",
|
||||
"gulp-ngmin": "~0.1.2"
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
<script type="text/javascript" src="/vendor/angular-resource/angular-resource.min.js"></script>
|
||||
<script type="text/javascript" src="/vendor/angular-ui-router/release/angular-ui-router.min.js"></script>
|
||||
<script type="text/javascript" src="/vendor/ngFx/dist/ngFx.min.js"></script>
|
||||
<script type="text/javascript" src="/vendor/angular-modal/modal.min.js"></script>
|
||||
<script type="text/javascript" src="/build/app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue