├── .meteor ├── .gitignore ├── release ├── platforms ├── .finished-upgraders ├── .id ├── packages └── versions ├── client ├── lib │ └── title.js ├── views │ ├── contacts │ │ ├── _company.js │ │ ├── _search.html │ │ ├── _search.js │ │ ├── index.html │ │ ├── swiper.js │ │ ├── show.scss │ │ └── show.html │ ├── layouts │ │ ├── application.js │ │ ├── application.html │ │ └── application.scss │ └── admin │ │ ├── contacts │ │ ├── new.js │ │ ├── new.html │ │ └── index.html │ │ └── layouts │ │ ├── application.js │ │ └── application.html ├── components │ └── iron-modal │ │ ├── iron-modal.html │ │ └── iron-modal.js └── transitions.js ├── controllers ├── admin │ ├── lib │ │ └── application.js │ └── contacts │ │ └── index.js ├── lib │ └── application.js └── contacts │ ├── show.js │ └── index.js ├── routes.js ├── collections └── contacts.js └── server └── seeds.js /.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.1.0.2 2 | -------------------------------------------------------------------------------- /.meteor/platforms: -------------------------------------------------------------------------------- 1 | browser 2 | ios 3 | server 4 | -------------------------------------------------------------------------------- /client/lib/title.js: -------------------------------------------------------------------------------- 1 | Deps.autorun(function(){ 2 | document.title = Session.get('pageTitle'); 3 | }); 4 | -------------------------------------------------------------------------------- /client/views/contacts/_company.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | $('.slider').slider(); 3 | }); 4 | -------------------------------------------------------------------------------- /client/views/layouts/application.js: -------------------------------------------------------------------------------- 1 | Template.applicationLayout.rendered = function() { 2 | $('ul.tabs').tabs(); 3 | } 4 | -------------------------------------------------------------------------------- /client/views/contacts/_search.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /controllers/admin/lib/application.js: -------------------------------------------------------------------------------- 1 | AdminApplicationController = RouteController.extend({ 2 | layoutTemplate: 'AdminApplicationLayout' 3 | }); 4 | -------------------------------------------------------------------------------- /client/components/iron-modal/iron-modal.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /client/views/admin/contacts/new.js: -------------------------------------------------------------------------------- 1 | AutoForm.hooks({ 2 | newContactForm: { 3 | onSuccess: function(formType, result) { 4 | console.log("You need to close the modal!"); 5 | } 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /routes.js: -------------------------------------------------------------------------------- 1 | Router.route('/', { 2 | name: 'contacts.index' 3 | }); 4 | 5 | Router.route('/contacts/:_id', { 6 | name: 'contacts.show' 7 | }); 8 | 9 | // admin routes 10 | Router.route('/admin', { 11 | name: 'admin.contacts.index' 12 | }); 13 | -------------------------------------------------------------------------------- /.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | -------------------------------------------------------------------------------- /.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | 1rf24z01mvyg6k1yy7qzp 8 | -------------------------------------------------------------------------------- /controllers/lib/application.js: -------------------------------------------------------------------------------- 1 | ApplicationController = RouteController.extend({ 2 | layoutTemplate: 'ApplicationLayout', 3 | notFoundTemplate: 'notFoundLayout', 4 | loadingTemplate: 'loadingLayout', 5 | 6 | onAfterAction: function() { 7 | // trigger looking for matching super-ids in the html 8 | Meteor.transitioner.heroAnimations(); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /client/views/contacts/_search.js: -------------------------------------------------------------------------------- 1 | Template._contactsSearch.events({ 2 | "keyup #searchTerm": function (event) { 3 | var searchTerm = $(event.target).val(); 4 | Session.set('searchTerm', searchTerm); 5 | } 6 | }); 7 | 8 | Template._contactsSearch.rendered = function() { 9 | var searchTerm = Session.get('searchTerm'); 10 | if(searchTerm) { 11 | $('#searchTerm').val(searchTerm); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /controllers/contacts/show.js: -------------------------------------------------------------------------------- 1 | ContactsShowController = ApplicationController.extend({ 2 | data: function() { 3 | var contact = Contacts.findOne({_id: this.params._id}); 4 | 5 | // Apply collection helpers 6 | contact = Contacts._transform(contact); 7 | 8 | Session.set('pageTitle', contact.fullName()); 9 | 10 | return contact; 11 | }, 12 | onAfterAction: function(){ 13 | Meteor.swiper.loadSwiper(); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /client/views/admin/contacts/new.html: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /client/views/admin/layouts/application.js: -------------------------------------------------------------------------------- 1 | Template.adminApplicationLayout.rendered = function() { 2 | // Initialize collapse button 3 | $(".button-collapse").sideNav(); 4 | 5 | var search = Session.get('#search'); 6 | if(search) { 7 | $('#search').val(search); 8 | } 9 | } 10 | 11 | Template.adminApplicationLayout.events({ 12 | "keyup #search": function (event) { 13 | var search = $(event.target).val(); 14 | Session.set('#search', search); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /collections/contacts.js: -------------------------------------------------------------------------------- 1 | Contacts = new Mongo.Collection("contacts"); 2 | 3 | Contacts.attachSchema(new SimpleSchema({ 4 | first_name: { 5 | type: String, 6 | label: "First name" 7 | }, 8 | last_name: { 9 | type: String, 10 | label: "Last Name" 11 | }, 12 | image: { 13 | type: String, 14 | label: "Image URL" 15 | } 16 | })); 17 | 18 | Contacts.helpers({ 19 | fullName: function() { 20 | return this.first_name + ' ' + this.last_name; 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /client/views/admin/contacts/index.html: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-platform 8 | autopublish 9 | insecure 10 | iron:router 11 | materialize:materialize 12 | multiply:iron-router-progress 13 | fourseven:scss 14 | digilord:faker 15 | ccorcos:transitioner 16 | dburles:collection-helpers 17 | underscore 18 | swiper:swiper 19 | aldeed:autoform 20 | aldeed:simple-schema 21 | aldeed:collection2 22 | -------------------------------------------------------------------------------- /controllers/admin/contacts/index.js: -------------------------------------------------------------------------------- 1 | AdminContactsIndexController = AdminApplicationController.extend({ 2 | data: { 3 | contacts: function() { 4 | var search = Session.get('#search'); 5 | 6 | var contacts = Contacts.find({ 7 | $or: [ 8 | { first_name: new RegExp(search, 'i') }, 9 | { last_name: new RegExp(search, 'i') }, 10 | { company_name: new RegExp(search, 'i') } 11 | ] 12 | }, { 13 | sort: { last_name: 1 } 14 | }); 15 | 16 | 17 | Session.set('pageTitle', 'Contacts (' + contacts.count() + ')'); 18 | 19 | return contacts; 20 | } 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /controllers/contacts/index.js: -------------------------------------------------------------------------------- 1 | ContactsIndexController = ApplicationController.extend({ 2 | data: { 3 | contacts: function() { 4 | var searchTerm = Session.get('searchTerm'); 5 | 6 | var contacts = Contacts.find({ 7 | $or: [ 8 | { first_name: new RegExp(searchTerm, 'i') }, 9 | { last_name: new RegExp(searchTerm, 'i') }, 10 | { company_name: new RegExp(searchTerm, 'i') } 11 | ] 12 | }, { 13 | sort: { last_name: 1 } 14 | }); 15 | 16 | Session.set('pageTitle', 'Contacts (' + contacts.count() + ')'); 17 | 18 | return contacts; 19 | } 20 | }, 21 | 22 | action: function() { 23 | this.render('contactsIndex'); 24 | this.render('_contactsSearch', {to: 'header'}); 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /client/views/contacts/index.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /client/views/layouts/application.html: -------------------------------------------------------------------------------- 1 | 2 | Contacts 3 | 4 | 5 | 6 | 7 | 8 | 27 | 28 | 31 | 32 | 35 | -------------------------------------------------------------------------------- /client/views/admin/layouts/application.html: -------------------------------------------------------------------------------- 1 | 2 | Admin 3 | 4 | 5 | 6 | 7 | 8 | 37 | -------------------------------------------------------------------------------- /client/views/contacts/swiper.js: -------------------------------------------------------------------------------- 1 | Meteor.swiper = {} 2 | Meteor.swiper.loading = false; 3 | Meteor.swiper.loadSwiper = function(){ 4 | var interval; 5 | var timeout; 6 | console.log($('.swiper-container')); 7 | if(!Meteor.swiper.loading){ 8 | Meteor.swiper.loading = true; 9 | interval = setInterval(function(){ 10 | if($('.swiper-container').length > 0){ 11 | // hide all but one item in the swiper or else it breaks 12 | // this is a non-abstract hack and should be refactored 13 | // if worst accept an argument to pass nodes so that this function 14 | // can become abstract 15 | $('.company-1, .company-2').hide(); 16 | var mySwiper = new Swiper('.swiper-container', { 17 | speed: 400, 18 | spaceBetween: 0, 19 | width: '100%' 20 | }); 21 | // reshow all the items that were hidden so that they appear on slide 22 | $('.company-1, .company-2').show(); 23 | clearInterval(interval); 24 | clearTimeout(timeout); 25 | Meteor.swiper.loading = false; 26 | } 27 | }, 100); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /client/components/iron-modal/iron-modal.js: -------------------------------------------------------------------------------- 1 | Iron.Router.hooks.ironModal = function () { 2 | var modal = this.params.query.modal; 3 | if (!_.isUndefined(modal)) { 4 | this.render('ironModal', { 5 | to: 'ironModal', 6 | data: function () { return {template: modal} } 7 | }); 8 | } else { 9 | this.render(null, {to: 'ironModal'}); 10 | } 11 | 12 | this.next(); 13 | }; 14 | 15 | Router.onBeforeAction('ironModal'); 16 | 17 | Template.ironModal.rendered = function() { 18 | $(this.firstNode).openModal({ 19 | complete: function() { 20 | var location = Router.current().location.get().path; 21 | var newLocation = removeURLParam(location, 'modal'); 22 | Router.go(newLocation); 23 | } 24 | }); 25 | } 26 | 27 | Template.ironModal.destroyed = function() { 28 | $(this.firstNode).closeModal(); 29 | } 30 | 31 | function removeURLParam (url, param) { 32 | var urlparts = url.split('?'); 33 | if (urlparts.length >= 2) { 34 | var prefix = encodeURIComponent(param) + '='; 35 | var pars = urlparts[1].split(/[&;]/g); 36 | 37 | // reverse iteration as may be destructive 38 | for (var i = pars.length; i-- > 0;) { 39 | // idiom for string.startsWith 40 | if (pars[i].lastIndexOf(prefix, 0) !== -1) { 41 | pars.splice(i, 1); 42 | } 43 | } 44 | 45 | url = urlparts[0]; 46 | if (pars.length > 0) { 47 | url += '?'+pars.join('&'); 48 | } 49 | 50 | return url; 51 | } else { 52 | return url; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.meteor/versions: -------------------------------------------------------------------------------- 1 | aldeed:autoform@5.1.2 2 | aldeed:collection2@2.3.1 3 | aldeed:simple-schema@1.1.0 4 | autopublish@1.0.3 5 | autoupdate@1.2.1 6 | base64@1.0.3 7 | binary-heap@1.0.3 8 | blaze@2.1.2 9 | blaze-tools@1.0.3 10 | boilerplate-generator@1.0.3 11 | callback-hook@1.0.3 12 | ccorcos:transitioner@2.0.1 13 | check@1.0.5 14 | coffeescript@1.0.6 15 | dburles:collection-helpers@1.0.3 16 | ddp@1.1.0 17 | deps@1.0.7 18 | digilord:faker@1.0.6 19 | ejson@1.0.6 20 | fastclick@1.0.3 21 | fourseven:scss@2.1.1 22 | geojson-utils@1.0.3 23 | html-tools@1.0.4 24 | htmljs@1.0.4 25 | http@1.1.0 26 | id-map@1.0.3 27 | insecure@1.0.3 28 | iron:controller@1.0.7 29 | iron:core@1.0.7 30 | iron:dynamic-template@1.0.7 31 | iron:layout@1.0.7 32 | iron:location@1.0.7 33 | iron:middleware-stack@1.0.7 34 | iron:router@1.0.7 35 | iron:url@1.0.7 36 | jquery@1.11.3_2 37 | json@1.0.3 38 | launch-screen@1.0.2 39 | less@1.0.14 40 | livedata@1.0.13 41 | logging@1.0.7 42 | materialize:materialize@0.96.1 43 | meteor@1.1.6 44 | meteor-platform@1.2.2 45 | minifiers@1.1.5 46 | minimongo@1.0.8 47 | mobile-status-bar@1.0.3 48 | momentjs:moment@2.8.4 49 | mongo@1.1.0 50 | multiply:iron-router-progress@1.0.1 51 | observe-sequence@1.0.6 52 | ordered-dict@1.0.3 53 | random@1.0.3 54 | reactive-dict@1.1.0 55 | reactive-var@1.0.5 56 | reload@1.1.3 57 | retry@1.0.3 58 | routepolicy@1.0.5 59 | session@1.1.0 60 | spacebars@1.0.6 61 | spacebars-compiler@1.0.6 62 | swiper:swiper@2.7.5 63 | templating@1.1.1 64 | tracker@1.0.7 65 | ui@1.0.6 66 | underscore@1.0.3 67 | url@1.0.4 68 | velocityjs:velocityjs@1.2.1 69 | webapp@1.2.0 70 | webapp-hashing@1.0.3 71 | -------------------------------------------------------------------------------- /client/views/contacts/show.scss: -------------------------------------------------------------------------------- 1 | $page-bg: #0f1f3d; 2 | $title-bg: #2356bc; 3 | $item-bg: white; 4 | $label-text: #898989; 5 | .contact-header-bg{ 6 | width: 100%; 7 | height: 100%; 8 | padding-top: 15px; 9 | overflow: hidden; 10 | top: 0; 11 | position: fixed; 12 | z-index: 0; 13 | img{ 14 | height: 400px; 15 | position: fixed; 16 | top: 0; 17 | height: 40%; 18 | width: 100%; 19 | } 20 | .bottom-bg{ 21 | background-color: $page-bg; 22 | height: 100%; 23 | width: 100%; 24 | bottom: 0; 25 | z-index: -1; 26 | position: fixed; 27 | } 28 | } 29 | .blur{ 30 | -webkit-filter: blur(20px); 31 | filter: blur(20px); 32 | opacity: 0.5; 33 | } 34 | .contact-wrapper{ 35 | position: absolute; 36 | top: 0; 37 | z-index: 1; 38 | } 39 | .contact-header{ 40 | color: white; 41 | position: relative; 42 | z-index: 2; 43 | padding: 15px; 44 | clear: both; 45 | } 46 | .contact-company-info{ 47 | width: 95%; 48 | margin-left: 2.5%; 49 | overflow: hidden; 50 | border-radius: 5px; 51 | } 52 | .contact-company-info .header{ 53 | position: relative; 54 | z-index: 2; 55 | width: 100%; 56 | color: white; 57 | background-color: $title-bg; 58 | font-size: 2em; 59 | padding: 15px; 60 | } 61 | .profile-name{ 62 | font-size: 2em; 63 | } 64 | .profile-company{ 65 | font-size: 1.8em; 66 | } 67 | .member-since{ 68 | font-size: 1.5em; 69 | } 70 | .contact-company-info .content > div{ 71 | padding: 15px; 72 | background-color: $item-bg; 73 | } 74 | .label-for{ 75 | color: $label-text; 76 | padding-bottom: 5px; 77 | } 78 | .info-for{ 79 | font-size: 1.5em; 80 | } 81 | .company-info-links{ 82 | padding-top: 15px; 83 | width: 150px; 84 | margin: 0 auto; 85 | padding-bottom: 15px; 86 | div{ 87 | width: 40px; 88 | margin-left: 10px; 89 | height: 40px; 90 | border-radius: 50%; 91 | border: 2px solid white; 92 | float: left; 93 | cursor: pointer; 94 | } 95 | } 96 | .selected{ 97 | background-color: white; 98 | } 99 | -------------------------------------------------------------------------------- /client/views/layouts/application.scss: -------------------------------------------------------------------------------- 1 | $blue: #3461AB; 2 | 3 | html, body { 4 | margin:0; 5 | height:100%; 6 | min-height:100%; 7 | } 8 | 9 | body { 10 | margin:0; 11 | display: flex; 12 | flex-direction: column; 13 | overflow-x: hidden; 14 | } 15 | 16 | header { 17 | flex-shrink: 0; 18 | } 19 | 20 | article { 21 | flex-grow: 1; 22 | } 23 | 24 | footer { 25 | flex-shrink: 0; 26 | } 27 | 28 | #iron-router-progress { 29 | background-color: $blue; 30 | box-shadow: 0 0 5px $blue; 31 | } 32 | 33 | #iron-router-progress.spinner:before { 34 | border-color: $blue; 35 | } 36 | 37 | .collection-item{ 38 | a { 39 | color: black; 40 | } 41 | span{ 42 | display: inline-block; 43 | .profile-pic{ 44 | margin-right: 10px; 45 | width: 65px; 46 | } 47 | &.person-info{ 48 | position: relative; 49 | bottom: 19px; 50 | div{ 51 | font-size: 12px; 52 | line-height: 25px; 53 | } 54 | .company { 55 | font-weight: lighter; 56 | } 57 | } 58 | } 59 | } 60 | //Individual Contact 61 | .contact-header{ 62 | text-align: center; 63 | } 64 | // Article on contacts page has no height on safari this is a workaround 65 | // this should be refactored later into a more suitable design layout 66 | // keeps the face in front --- TODO: add a super-primary class to always have the highest z-index 67 | .circle{ 68 | z-index: 5; 69 | } 70 | .transitioner{ 71 | height: 100%; 72 | width: 100%; 73 | overflow: auto; 74 | overflow-y: scroll; 75 | position: absolute; 76 | -webkit-overflow-scrolling: touch; 77 | } 78 | // attempting to fix all layout issues. 79 | .application-header{ 80 | position: relative; 81 | top: 0; 82 | left: 0; 83 | height: 5%; 84 | width: 100%; 85 | } 86 | .application-content{ 87 | position: relative; 88 | left: 0; 89 | height: 90%; 90 | width: 100%; 91 | overflow: auto; 92 | } 93 | .application-footer{ 94 | position: absolute; 95 | bottom: 0; 96 | left: 0; 97 | height: 5%; 98 | width: 100%; 99 | } 100 | -------------------------------------------------------------------------------- /client/views/contacts/show.html: -------------------------------------------------------------------------------- 1 | 57 | -------------------------------------------------------------------------------- /server/seeds.js: -------------------------------------------------------------------------------- 1 | Meteor.startup(function () { 2 | if (Contacts.find().count() === 0) { 3 | for (var i=0; i < 50; i++) { 4 | Contacts.insert({ 5 | first_name: faker.name.firstName(), 6 | last_name: faker.name.lastName(), 7 | companies: [{ 8 | coid: 0, 9 | name: faker.company.companyName(), 10 | email: faker.internet.email(), 11 | phone: faker.phone.phoneNumber(), 12 | address_first: faker.address.streetAddress() + " " + 13 | faker.address.streetName(), 14 | address_second: faker.address.city() + ", " + 15 | faker.address.state() + " " + 16 | faker.address.zipCode(), 17 | website: faker.internet.domainName(), 18 | assistant: { 19 | first_name: faker.name.firstName(), 20 | last_name: faker.name.lastName(), 21 | phone_number: faker.phone.phoneNumberFormat(2), 22 | email: faker.internet.email() 23 | } 24 | }, { 25 | coid: 1, 26 | name: faker.company.companyName(), 27 | email: faker.internet.email(), 28 | phone: faker.phone.phoneNumber(), 29 | address_first: faker.address.streetAddress() + " " + 30 | faker.address.streetName(), 31 | address_second: faker.address.city() + ", " + 32 | faker.address.state() + " " + 33 | faker.address.zipCode(), 34 | website: faker.internet.domainName(), 35 | assistant: { 36 | first_name: faker.name.firstName(), 37 | last_name: faker.name.lastName(), 38 | phone_number: faker.phone.phoneNumberFormat(2), 39 | email: faker.internet.email() 40 | } 41 | }, { 42 | coid: 2, 43 | name: faker.company.companyName(), 44 | email: faker.internet.email(), 45 | phone: faker.phone.phoneNumber(), 46 | address_first: faker.address.streetAddress() + " " + 47 | faker.address.streetName(), 48 | address_second: faker.address.city() + ", " + 49 | faker.address.state() + " " + 50 | faker.address.zipCode(), 51 | website: faker.internet.domainName(), 52 | assistant: { 53 | first_name: faker.name.firstName(), 54 | last_name: faker.name.lastName(), 55 | phone_number: faker.phone.phoneNumberFormat(2), 56 | email: faker.internet.email() 57 | } 58 | }], 59 | image: faker.image.avatar() 60 | }); 61 | } 62 | } 63 | }); 64 | -------------------------------------------------------------------------------- /client/transitions.js: -------------------------------------------------------------------------------- 1 | // Use only one namespace for the entire functionality of transitions 2 | // Due to the restrictions of using anonymous function returns of an Interface 3 | // There can be only ONE interface instance and all internal variables are shared 4 | // by that Instance. Declaring more than one won't work, but there should 5 | // be no need for multiple transitioner instances. 6 | 7 | // Weap the entire code in a check for this global namespace and alert thenuser if one already exists that 8 | // superhero-transitions will not function. A git link to report this issue should be added to the error message 9 | if(!window.Meteor.transitioner){ 10 | Meteor.transitioner = (function(){ 11 | var Interface = {}; 12 | var registeredAnimations = []; 13 | var self = Interface; 14 | var life = 5000; 15 | // boolean to hack around iron router being called twice during transitions 16 | Interface.animated = false; 17 | 18 | // give access to get and set Life which is how long it will poll for super-id pairs 19 | Interface.get = function(name){ 20 | switch(name){ 21 | case 'life': return life; break; 22 | default: console.log(name + 'not recognized as valid get variable for Meteor.transitioner'); return 'error'; 23 | } 24 | } 25 | // set returns the parameter that was set or the string 'error' for testing 26 | Interface.set = function(name, value){ 27 | switch(name){ 28 | case 'life': life = value; return life; 29 | default: console.log(name + 'not recognized as valid set variable for Meteor.transitioner'); return 'error'; 30 | } 31 | } 32 | // TODO: think about how to handle users accidently putting two objects on the same page with the same super-id... these should be unique to templates 33 | // TODO: so a possible console.log error message may communicate this to people who aren't aware. 34 | 35 | Interface.heroAnimations = function(){ 36 | var allHeros = $("[super-id]"); 37 | var found = false; 38 | var interval; 39 | // set a set destruct on the Interval in case the users accidently kicks off this function but there are no matching 40 | // super-id pairs in the two transition templates 41 | setTimeout(function(){ 42 | clearInterval(interval); 43 | }, life) 44 | // start the interval kick-off to detect for a super-id pairs 45 | interval = setInterval(function(){ 46 | allHeros.each(function(){ 47 | var target = $('[super-id=\'' + $(this).attr('super-id') + '\']'); 48 | if(target.length > 1){ 49 | if(!self.isRegistered('hero' + $(this).attr('super-id'))){ 50 | self.registerAnimation('hero' + $(this).attr('super-id')); 51 | self.animateHero(target); 52 | } 53 | found = true; 54 | } 55 | }); 56 | if(found){ 57 | clearInterval(interval); 58 | } 59 | }, 100); 60 | } 61 | Interface.animateHero = function(targets){ 62 | var index = 0; 63 | var animationTarget; 64 | var finalObject; 65 | var startState; 66 | var endState; 67 | targets.each(function(){ 68 | if(index === 0){ 69 | animationTarget = $(this); 70 | startState = { 71 | left: $(this).offset().left, 72 | top: $(this).offset().top, 73 | width: $(this).width(), 74 | height: $(this).height(), 75 | textAlign: $(this).css('text-align'), 76 | borderRadius: $(this).css('borderRadius'), 77 | color: $(this).css('color'), 78 | fontSize: $(this).css('font-size')}; 79 | } 80 | if(index === 1){ 81 | finalObject = $(this); 82 | finalObject.css('visibility', 'hidden'); 83 | var scrollCheck = $(this); 84 | var scrollOff = 0; 85 | while(!scrollCheck.is('body')){ 86 | if(scrollCheck.scrollTop() > 0){ 87 | scrollOff += scrollCheck.scrollTop(); 88 | } 89 | scrollCheck = scrollCheck.parent(); 90 | } 91 | endState = { 92 | left: $(this).offset().left, 93 | top: $(this).offset().top + scrollOff, 94 | width: $(this).width(), 95 | height: $(this).height(), 96 | textAlign: $(this).css('text-align'), 97 | borderRadius: $(this).css('borderRadius'), 98 | color: $(this).css('color'), 99 | fontSize: $(this).css('font-size')}; 100 | } 101 | $('body').append(animationTarget); 102 | index++; 103 | }); 104 | animationTarget.css({ 105 | fontSize: endState.fontSize, 106 | color: endState.color, 107 | top: startState.top, 108 | left: startState.left, 109 | width: startState.width, 110 | height: startState.height, 111 | borderRadius: startState.borderRadius, 112 | position: 'absolute'}); 113 | 114 | if(finalObject.css('textAlign') === 'center'){ 115 | animationTarget.css('textAlign', endState.textAlign); 116 | } 117 | else if(startState.textAlign === 'center'){ 118 | animationTarget.css('textAlign', 'center'); 119 | } 120 | var temp = endState.top-$('.transitioner').offset().top; 121 | var eStop = $('.transitioner').offset().top + finalObject.parent().css('padding-top'); 122 | if(temp < $(window).height()){ 123 | $('.transitioner').scrollTop(0); 124 | eStop = endState.top; 125 | } 126 | else{ 127 | console.log('hey'); 128 | $('.transitioner').animate({ 129 | scrollTop: temp 130 | }, 1000); 131 | } 132 | animationTarget.velocity({ 133 | top: eStop, 134 | left: endState.left, 135 | width: endState.width, 136 | height: endState.height, 137 | borderRadius: endState.borderRadius 138 | }, { 139 | complete: function(){ 140 | animationTarget.remove(); 141 | finalObject.css('visibility', 'visible'); 142 | }, 143 | duration: 1000, 144 | step: function(){ 145 | } 146 | }); 147 | startState = {}; 148 | endState = {}; 149 | setTimeout(function(){ 150 | self.unRegisterAnimation('hero' + animationTarget.attr('super-id')); 151 | }, 1000); 152 | } 153 | Interface.isRegistered = function(animation){ 154 | if(registeredAnimations.indexOf(animation) > -1){ 155 | return true; 156 | } 157 | else{ 158 | return false; 159 | } 160 | } 161 | Interface.registerAnimation = function(animation){ 162 | if(!self.isRegistered(animation)){ 163 | registeredAnimations[registeredAnimations.length] = animation; 164 | } 165 | } 166 | Interface.unRegisterAnimation = function(animation){ 167 | if(self.isRegistered(animation)){ 168 | registeredAnimations.splice(registeredAnimations.indexOf(animation), 1); 169 | } 170 | } 171 | return Interface; 172 | })(); 173 | } 174 | else{ 175 | console.log('Meteor.transitioner already exists. SuperHero Transitions will not be exectued. As a result either report this error at the github' + 176 | 'that you cloned this addon from or navigate to transitioner.js and change Meteor.transitioner to a different namespace: EX: Meteor.myPage.transitioner'); 177 | } 178 | Transitioner.default({ 179 | in: 'transition.fadeIn', 180 | out: 'transition.fadeOut', 181 | duration: 1000 182 | }) 183 | 184 | --------------------------------------------------------------------------------