diff --git a/.meteor/packages b/.meteor/packages index db57c6c..d50e8a2 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -3,35 +3,41 @@ # 'meteor add' and 'meteor remove' will edit this file for you, # but you can also edit it by hand. +raix:handlebar-helpers +cmather:handlebars-server +natestrauser:font-awesome +gadicohen:sitemaps +dburles:collection-helpers +matb33:collection-hooks +chuangbo:marked@0.3.3 +meteorhacks:fast-render +xorax:multiple-callbacks +gadicohen:robots-txt +arunoda:streams +iron:router +joshowens:shareit +meteor +patrickleet:tags +service-configuration underscore accounts-google less spiderable jquery email -standard-app-packages -chatroom -collection-hooks -font-awesome -handlebar-helpers -handlebars-server -iron-router -marked -mongo-counter -npm -presence -robots-txt -roles -sitemaps -streams -fast-render -bootstrap-3 -service-configuration accounts-ui-unstyled -collection-helpers -reactive-path -multiple-callbacks -shareit -kadira -publish-composite -tags +alanning:roles +meteorhacks:npm + + +npm-container +check +reywood:publish-composite +mongo +random +meteor-platform +twbs:bootstrap +coderstv:reactive-path +tmeasday:presence +coderstv:chat +meteorhacks:kadira diff --git a/.meteor/platforms b/.meteor/platforms new file mode 100644 index 0000000..efeba1b --- /dev/null +++ b/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/.meteor/release b/.meteor/release index ee94dd8..74a74cb 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -0.8.3 +METEOR@1.0.3.2 diff --git a/.meteor/versions b/.meteor/versions new file mode 100644 index 0000000..9be2561 --- /dev/null +++ b/.meteor/versions @@ -0,0 +1,101 @@ +accounts-base@1.1.3 +accounts-google@1.0.3 +accounts-oauth@1.1.3 +accounts-ui-unstyled@1.1.6 +alanning:roles@1.2.13 +application-configuration@1.0.4 +arunoda:streams@0.1.17 +autoupdate@1.1.5 +base64@1.0.2 +binary-heap@1.0.2 +blaze@2.0.4 +blaze-tools@1.0.2 +boilerplate-generator@1.0.2 +callback-hook@1.0.2 +check@1.0.4 +chuangbo:cookie@1.1.0 +chuangbo:marked@0.3.5 +cmather:handlebars-server@2.0.0 +coderstv:chat@0.2.0 +coderstv:reactive-path@0.2.1 +coffeescript@1.0.5 +dburles:collection-helpers@1.0.2 +ddp@1.0.14 +deps@1.0.6 +ejson@1.0.5 +email@1.0.5 +fastclick@1.0.2 +follower-livedata@1.0.3 +gadicohen:robots-txt@0.0.9 +gadicohen:sitemaps@0.0.20 +geojson-utils@1.0.2 +google@1.1.4 +handlebars@1.0.2 +html-tools@1.0.3 +htmljs@1.0.3 +http@1.0.10 +id-map@1.0.2 +iron:controller@1.0.7 +iron:core@1.0.7 +iron:dynamic-template@1.0.7 +iron:layout@1.0.7 +iron:location@1.0.7 +iron:middleware-stack@1.0.7 +iron:router@1.0.7 +iron:url@1.0.7 +joshowens:shareit@0.3.1 +jquery@1.11.3 +json@1.0.2 +launch-screen@1.0.1 +lepozepo:streams@0.2.0 +less@1.0.12 +livedata@1.0.12 +localstorage@1.0.2 +logging@1.0.6 +matb33:collection-hooks@0.7.11 +meteor@1.1.4 +meteor-platform@1.2.1 +meteorhacks:async@1.0.0 +meteorhacks:fast-render@2.3.1 +meteorhacks:inject-data@1.2.2 +meteorhacks:kadira@2.19.6 +meteorhacks:meteorx@1.3.1 +meteorhacks:npm@1.2.2 +meteorhacks:picker@1.0.1 +minifiers@1.1.3 +minimongo@1.0.6 +mobile-status-bar@1.0.2 +mongo@1.0.11 +mongo-livedata@1.0.7 +natestrauser:font-awesome@4.3.0 +npm-container@1.0.0 +oauth@1.1.3 +oauth2@1.1.2 +observe-sequence@1.0.4 +ordered-dict@1.0.2 +patrickleet:tags@1.1.3 +raix:handlebar-helpers@0.2.4 +random@1.0.2 +reactive-dict@1.0.5 +reactive-var@1.0.4 +reload@1.1.2 +retry@1.0.2 +reywood:publish-composite@1.3.5 +routepolicy@1.0.4 +service-configuration@1.0.3 +session@1.0.5 +spacebars@1.0.5 +spacebars-compiler@1.0.4 +spiderable@1.0.6 +standard-app-packages@1.0.4 +startup@1.0.2 +templating@1.0.11 +tmeasday:presence@1.0.3 +tracker@1.0.5 +twbs:bootstrap@3.3.2 +ui@1.0.5 +underscore@1.0.2 +url@1.0.3 +webapp@1.1.6 +webapp-hashing@1.0.2 +xorax:multiple-callbacks@0.1.4 diff --git a/client/lib/controllers/channel.js b/client/lib/controllers/channel.js index 3041034..ae23b2c 100644 --- a/client/lib/controllers/channel.js +++ b/client/lib/controllers/channel.js @@ -11,6 +11,8 @@ CoderController = RouteController.extend({ var coder = Meteor.users.findOneFromCoderId(this.params.coderId); if (! _.isEmpty(coder)) { Session.set('coder', coder); + Session.set('chatHost', coder._id); + Session.set('currentCoder', coder._id); Meteor.subscribe( 'userPresenceWithProfile', coder.profile.username, @@ -19,7 +21,6 @@ CoderController = RouteController.extend({ Session.set('chatSubsReady', true); } ); - Session.set('currentCoder', coder._id); } } }); diff --git a/client/lib/routes.js b/client/lib/routes.js index b46f74d..bb3e3cb 100644 --- a/client/lib/routes.js +++ b/client/lib/routes.js @@ -27,7 +27,7 @@ Router.onBeforeAction(function setTitle () { }); Router.onBeforeAction(function headerActiveLi () { - var href = Router.current().path; + var href = Router.current().location.get().path; $('li.active').removeClass('active'); $('.navbar li').find('a[href="'+href+'"]').parent().addClass('active'); @@ -37,7 +37,7 @@ Router.onAfterAction(function setPath () { var current = Router.current(); if (! current) return; - Path.set(current.path); + Path.set(current.location.get().path); }); Deps.autorun(function () { @@ -68,7 +68,7 @@ Router.onRun(function reactiveTrackPageview () { return; } - var path = current.path; + var path = current.location.get().path; trackPageview(path); }); diff --git a/dev b/dev index dfce700..a8c066f 100755 --- a/dev +++ b/dev @@ -18,7 +18,7 @@ APP_DIR=/home/meteor ROOT_URL=http://$APP_HOST MONGO_URL=mongodb://localhost:27017/$APP_NAME -METEOR_CMD=mrt +METEOR_CMD=meteor METEOR_OPTIONS='' if [ -z "$EC2_PEM_FILE" ]; then @@ -61,17 +61,15 @@ sudo git clone $GIT_URL $APP_NAME; DEPLOY=" cd $APP_DIR; cd $APP_NAME; -sudo npm -g update meteorite; sudo git fetch --all; sudo git reset --hard origin/$GIT_BRANCH; sudo git checkout $GIT_BRANCH; -sudo rm -rf ../dev-bundle; -sudo rm -rf ../dev-bundle.tgz; -sudo $METEOR_CMD update --force; -sudo $METEOR_CMD bundle --debug ../dev-bundle.tgz; -cd ..; -mkdir -p dev-bundle; -sudo tar -zxvf dev-bundle.tgz; +sudo git clean -f -d; +sudo rm -rf ../bundle; +sudo $METEOR_CMD build ../ --debug --directory; +cd ../bundle/programs/server; +npm install; +cd ../../..; pm2 delete dev; mongo $APP_NAME $APP_DIR/$APP_NAME/mongo.config; METEOR_SETTINGS=\$(cat ${APP_DIR}/${APP_NAME}/dev.json) DEBUG=ct:* PORT=80 ROOT_URL=$ROOT_URL MONGO_URL=$MONGO_URL pm2 start bundle/main.js -x --name 'dev'; diff --git a/dev.config b/dev.config index ccc7581..49c737c 100644 --- a/dev.config +++ b/dev.config @@ -8,10 +8,10 @@ APP_HOST=dev.coderstv.com GIT_URL=git@github.com:CodersTV/site.git # Does your project use meteorite, or plain meteor? -METEORITE=true +METEORITE=false # What's your app name? APP_NAME=dev-coderstv # Git branch -GIT_BRANCH=master +GIT_BRANCH=update-1.0 diff --git a/lib/both/collections/channels.js b/lib/both/collections/channels.js index 9136851..dfdb6c2 100644 --- a/lib/both/collections/channels.js +++ b/lib/both/collections/channels.js @@ -52,7 +52,6 @@ Channel = (function () { function set (doc) { _validate(doc); - Language.incVideos(doc.language); return Channels.insert(doc); } @@ -71,7 +70,6 @@ Channel = (function () { function removeByURL (URL) { var channel = Channels.findOne({URL: URL}); if (channel) { - Language.incVideos(channel.language, -1); Channels.remove(channel._id); return true; } diff --git a/packages/.gitignore b/packages/.gitignore deleted file mode 100644 index a9244ec..0000000 --- a/packages/.gitignore +++ /dev/null @@ -1,73 +0,0 @@ -mini-pages -simple-i18n -presence -pagination -paginated-subscription -superchat -HTML5-History-API -page-js-ie-support -underscore-string -marked -observatory -observatory-apollo -handlebar-helpers -npm -font-awesome -phantomjs -collection-hooks -bootstrap-3 -mongo-counter -roles -Mesosphere -underscore-string-latest -supercalendar -superchat-streams -streams -handlebars-server -sitemaps -robots-txt -iron-router -/handlebar-helpers -/npm -/presence -/collection-hooks -/handlebars-server -/roles -/houston -/paginated-subscription -/spin -/reactive-path -reactive-path -fast-render -/fast-render -apm -server-eval -/apm -/sitemaps -/iron-router -/bootstrap-3 -/accounts-ui-bootstrap-3 -/marked -/blaze-layout -/font-awesome -/mongo-counter -/robots-txt -/streams -/tokbox -/collection-helpers -/timesync -/sharejs -/typeahead -/publish-counts -/meteor-editable -/multiple-callbacks -/iron-layout -/iron-core -/iron-dynamic-template -/bootstrap-daterangepicker -/bootstrap3-datetimepicker -/phantomjs -/kadira -/meteorx -/publish-composite -/tags diff --git a/packages/chatroom/.gitignore b/packages/chatroom/.gitignore deleted file mode 100644 index 9317be9..0000000 --- a/packages/chatroom/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.project -.pydevproject -tags -.build* diff --git a/packages/chatroom/README.md b/packages/chatroom/README.md deleted file mode 100644 index a98044f..0000000 --- a/packages/chatroom/README.md +++ /dev/null @@ -1,152 +0,0 @@ -Meteor SuperChat with Meteor Streams -================ - -Smart package for SuperChat Streams. It is a chat that includes Social Login and Github Flavored Markdown and do not use MongoDB for persistence, but uses Meteor Streams for direct messaging between clients. - -Works with Meteor release 0.6.4.1 and below only. - -If you want persistence see -[SuperChat](https://github.com/gabrielhpugliese/meteor_superchat) instead. - -## Demo - -http://superchat-streams.meteor.com - -### Mantained by CodersTV - -This package is used and mantained by [CodersTV](http://coderstv.com) - -## Install - -To install in a new project: -```bash -> mrt add superchat-streams -``` - -To update an existing project: -```bash -> mrt update superchat-streams -``` - -## Quick Start - -You need to configure at least one kind of account. Supported social plataforms now are: -* Facebook -* Google -* ~~Twitter~~ (Twitter API v1.1 requires OAuth authenticated requests to - get profile picture) - -For example, with Google: - -```bash -meteor add accounts-google -``` - -```html - - {{> chatroom}} - {{loginButtons}} - -``` - -## Configuration - -If you don't want to have a global chat for entire website, you can set a Path so you can have a different chat box for each Path you set. -What's needed to do on javascript part is set a Path. Path is a reactive source of current page path (like window.location.pathname). -So, whenever it changes, it must be updated calling ```Path.set(path)``` - -I've removed loginButtons from it and the popover that shows up to tell -people to login, because loginButtons frag has an id on its div. And if -you have another button on your site, it blows up your code. **So add them -to your site!** - -### Example with iron-router -```javascript -Router.map(function () { - this.route('index', { - path: '/', - before: function () { - Path.set(Router.current().path); - } - }); -}); -``` - -### Example with mini-pages -```javascript -Meteor.pages({ - '/': {to: 'index', before: setPath} -}); - -function setPath () { - Path.set(Meteor.router.path()); -} -``` - -### Example with router -```javascript -Meteor.Router.add({ - '/': { to: 'index', and: setPath} -}); - -function setPath () { - Path.set(Meteor.Router.page()); -} -``` - -### Making height responsive -``` -Template.parentTemplate.rendered = function() { - $(window).resize(function () { - var height = $(this).height(); // you can set a value you want here - $('#chat-wrapper').height(height); - }); - $(window).resize(); // trigger the resize -} -``` - -### Tracking users online - -You will have to set up the Meteor-presence publication and -subscription: - -```javascript -/* On Server */ -Meteor.publish('superChatUserPresence', function (whereAt) { - var filter = whereAt ? {'state.whereAt': whereAt} : {}; - - return Meteor.presences.find(filter, {fields: {state: true, userId: true}}); -}); - -/* On Client */ -Meteor.Presence.state = function() { - return { - online: true, - whereAt: Path() - }; -} - -Deps.autorun(function () { - Meteor.subscribe('superChatUserPresence', Path()); -}); -``` - -### Number of messages on chat area - -Just put on the client, on startup (if you override the default object, -make sure you put all those params): - -```javascript -Superchat = { - messageLimitOnScreen: 50, - defaultProfilePicture: 'http://i.imgur.com/HKSh9X9.png' -}; -``` - -## Dependencies - -Thanks @arunoda for his great Meteor project called [Meteor -Streams](https://github.com/arunoda/meteor-streams). - -Thanks @tmeasday for this awesome package [Meteor -Presence](https://github.com/tmeasday/meteor-presence) diff --git a/packages/chatroom/client/compatibility/jquery.nicescroll.min.js b/packages/chatroom/client/compatibility/jquery.nicescroll.min.js deleted file mode 100644 index 0ba5510..0000000 --- a/packages/chatroom/client/compatibility/jquery.nicescroll.min.js +++ /dev/null @@ -1,111 +0,0 @@ -/* jquery.nicescroll 3.4.1 InuYaksa*2013 MIT http://areaaperta.com/nicescroll */(function(e){var D=!1,G=!1,N=5E3,O=2E3,C=0,J,u=document.getElementsByTagName("script"),u=u[u.length-1].src.split("?")[0];J=0e){if(b.getScrollTop()>=b.page.maxh)return!0}else if(0>=b.getScrollTop())return!0;b.scrollmom&&b.scrollmom.stop();b.lastdeltay+= -e;b.debounced("mousewheely",function(){var c=b.lastdeltay;b.lastdeltay=0;b.rail.drag||b.doScrollBy(c)},120)}c.stopImmediatePropagation();return c.preventDefault()}var b=this;this.version="3.4.0";this.name="nicescroll";this.me=d;this.opt={doc:e("body"),win:!1};e.extend(this.opt,K);this.opt.snapbackspeed=80;if(j)for(var m in b.opt)"undefined"!=typeof j[m]&&(b.opt[m]=j[m]);this.iddoc=(this.doc=b.opt.doc)&&this.doc[0]?this.doc[0].id||"":"";this.ispage=/BODY|HTML/.test(b.opt.win?b.opt.win[0].nodeName: -this.doc[0].nodeName);this.haswrapper=!1!==b.opt.win;this.win=b.opt.win||(this.ispage?e(window):this.doc);this.docscroll=this.ispage&&!this.haswrapper?e(window):this.win;this.body=e("body");this.iframe=this.isfixed=this.viewport=!1;this.isiframe="IFRAME"==this.doc[0].nodeName&&"IFRAME"==this.win[0].nodeName;this.istextarea="TEXTAREA"==this.win[0].nodeName;this.forcescreen=!1;this.canshowonmouseevent="scroll"!=b.opt.autohidemode;this.page=this.view=this.onzoomout=this.onzoomin=this.onscrollcancel= -this.onscrollend=this.onscrollstart=this.onclick=this.ongesturezoom=this.onkeypress=this.onmousewheel=this.onmousemove=this.onmouseup=this.onmousedown=!1;this.scroll={x:0,y:0};this.scrollratio={x:0,y:0};this.cursorheight=20;this.scrollvaluemax=0;this.observerremover=this.observer=this.scrollmom=this.scrollrunning=this.checkrtlmode=!1;do this.id="ascrail"+O++;while(document.getElementById(this.id));this.hasmousefocus=this.hasfocus=this.zoomactive=this.zoom=this.selectiondrag=this.cursorfreezed=this.cursor= -this.rail=!1;this.visibility=!0;this.hidden=this.locked=!1;this.cursoractive=!0;this.overflowx=b.opt.overflowx;this.overflowy=b.opt.overflowy;this.nativescrollingarea=!1;this.checkarea=0;this.events=[];this.saved={};this.delaylist={};this.synclist={};this.lastdeltay=this.lastdeltax=0;if(H)m=H;else{m=document.createElement("DIV");var h={haspointerlock:"pointerLockElement"in document||"mozPointerLockElement"in document||"webkitPointerLockElement"in document};h.isopera="opera"in window;h.isopera12=h.isopera&& -"getUserMedia"in navigator;h.isie="all"in document&&"attachEvent"in m&&!h.isopera;h.isieold=h.isie&&!("msInterpolationMode"in m.style);h.isie7=h.isie&&!h.isieold&&(!("documentMode"in document)||7==document.documentMode);h.isie8=h.isie&&"documentMode"in document&&8==document.documentMode;h.isie9=h.isie&&"performance"in window&&9<=document.documentMode;h.isie10=h.isie&&"performance"in window&&10<=document.documentMode;h.isie9mobile=/iemobile.9/i.test(navigator.userAgent);h.isie9mobile&&(h.isie9=!1); -h.isie7mobile=!h.isie9mobile&&h.isie7&&/iemobile/i.test(navigator.userAgent);h.ismozilla="MozAppearance"in m.style;h.iswebkit="WebkitAppearance"in m.style;h.ischrome="chrome"in window;h.ischrome22=h.ischrome&&h.haspointerlock;h.ischrome26=h.ischrome&&"transition"in m.style;h.cantouch="ontouchstart"in document.documentElement||"ontouchstart"in window;h.hasmstouch=window.navigator.msPointerEnabled||!1;h.ismac=/^mac$/i.test(navigator.platform);h.isios=h.cantouch&&/iphone|ipad|ipod/i.test(navigator.platform); -h.isios4=h.isios&&!("seal"in Object);h.isandroid=/android/i.test(navigator.userAgent);h.trstyle=!1;h.hastransform=!1;h.hastranslate3d=!1;h.transitionstyle=!1;h.hastransition=!1;h.transitionend=!1;for(var q=["transform","msTransform","webkitTransform","MozTransform","OTransform"],r=0;rh&&!e.tt)b.delaylist[c]={last:h+d,tt:setTimeout(function(){b.delaylist[c].tt=0;g.call()},d)};else if(!e||!e.tt)b.delaylist[c]= -{last:h,tt:0},setTimeout(function(){g.call()},0)};this.debounced=function(c,g,d){var e=b.delaylist[c];(new Date).getTime();b.delaylist[c]=g;e||setTimeout(function(){var g=b.delaylist[c];b.delaylist[c]=!1;g.call()},d)};this.synched=function(c,g){b.synclist[c]=g;b.onsync||(w(function(){b.onsync=!1;for(c in b.synclist){var g=b.synclist[c];g&&g.call(b);b.synclist[c]=!1}}),b.onsync=!0);return c};this.unsynched=function(c){b.synclist[c]&&(b.synclist[c]=!1)};this.css=function(c,g){for(var d in g)b.saved.css.push([c, -d,c.css(d)]),c.css(d,g[d])};this.scrollTop=function(c){return"undefined"==typeof c?b.getScrollTop():b.setScrollTop(c)};this.scrollLeft=function(c){return"undefined"==typeof c?b.getScrollLeft():b.setScrollLeft(c)};BezierClass=function(b,g,d,e,f,h,k){this.st=b;this.ed=g;this.spd=d;this.p1=e||0;this.p2=f||1;this.p3=h||0;this.p4=k||1;this.ts=(new Date).getTime();this.df=this.ed-this.st};BezierClass.prototype={B2:function(b){return 3*b*b*(1-b)},B3:function(b){return 3*b*(1-b)*(1-b)},B4:function(b){return(1- -b)*(1-b)*(1-b)},getNow:function(){var b=1-((new Date).getTime()-this.ts)/this.spd,g=this.B2(b)+this.B3(b)+this.B4(b);return 0>b?this.ed:this.st+Math.round(this.df*g)},update:function(b,g){this.st=this.getNow();this.ed=b;this.spd=g;this.ts=(new Date).getTime();this.df=this.ed-this.st;return this}};if(this.ishwscroll){this.doc.translate={x:0,y:0,tx:"0px",ty:"0px"};f.hastranslate3d&&f.isios&&this.doc.css("-webkit-backface-visibility","hidden");var z=function(){var c=b.doc.css(f.trstyle);return c&&"matrix"== -c.substr(0,6)?c.replace(/^.*\((.*)\)$/g,"$1").replace(/px/g,"").split(/, +/):!1};this.getScrollTop=function(c){if(!c){if(c=z())return 16==c.length?-c[13]:-c[5];if(b.timerscroll&&b.timerscroll.bz)return b.timerscroll.bz.getNow()}return b.doc.translate.y};this.getScrollLeft=function(c){if(!c){if(c=z())return 16==c.length?-c[12]:-c[4];if(b.timerscroll&&b.timerscroll.bh)return b.timerscroll.bh.getNow()}return b.doc.translate.x};this.notifyScrollEvent=document.createEvent?function(b){var g=document.createEvent("UIEvents"); -g.initUIEvent("scroll",!1,!0,window,1);b.dispatchEvent(g)}:document.fireEvent?function(b){var g=document.createEventObject();b.fireEvent("onscroll");g.cancelBubble=!0}:function(){};f.hastranslate3d&&b.opt.enabletranslate3d?(this.setScrollTop=function(c,g){b.doc.translate.y=c;b.doc.translate.ty=-1*c+"px";b.doc.css(f.trstyle,"translate3d("+b.doc.translate.tx+","+b.doc.translate.ty+",0px)");g||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(c,g){b.doc.translate.x=c;b.doc.translate.tx=-1*c+ -"px";b.doc.css(f.trstyle,"translate3d("+b.doc.translate.tx+","+b.doc.translate.ty+",0px)");g||b.notifyScrollEvent(b.win[0])}):(this.setScrollTop=function(c,g){b.doc.translate.y=c;b.doc.translate.ty=-1*c+"px";b.doc.css(f.trstyle,"translate("+b.doc.translate.tx+","+b.doc.translate.ty+")");g||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(c,g){b.doc.translate.x=c;b.doc.translate.tx=-1*c+"px";b.doc.css(f.trstyle,"translate("+b.doc.translate.tx+","+b.doc.translate.ty+")");g||b.notifyScrollEvent(b.win[0])})}else this.getScrollTop= -function(){return b.docscroll.scrollTop()},this.setScrollTop=function(c){return b.docscroll.scrollTop(c)},this.getScrollLeft=function(){return b.docscroll.scrollLeft()},this.setScrollLeft=function(c){return b.docscroll.scrollLeft(c)};this.getTarget=function(b){return!b?!1:b.target?b.target:b.srcElement?b.srcElement:!1};this.hasParent=function(b,g){if(!b)return!1;for(var d=b.target||b.srcElement||b||!1;d&&d.id!=g;)d=d.parentNode||!1;return!1!==d};var B={thin:1,medium:3,thick:5};this.getOffset=function(){if(b.isfixed)return{top:parseFloat(b.win.css("top")), -left:parseFloat(b.win.css("left"))};if(!b.viewport)return b.win.offset();var c=b.win.offset(),g=b.viewport.offset();return{top:c.top-g.top+b.viewport.scrollTop(),left:c.left-g.left+b.viewport.scrollLeft()}};this.updateScrollBar=function(c){if(b.ishwscroll)b.rail.css({height:b.win.innerHeight()}),b.railh&&b.railh.css({width:b.win.innerWidth()});else{var g=b.getOffset(),d=g.top,e=g.left,d=d+s(b.win,"border-top-width",!0);b.win.outerWidth();b.win.innerWidth();var e=e+(b.rail.align?b.win.outerWidth()- -s(b.win,"border-right-width")-b.rail.width:s(b.win,"border-left-width")),f=b.opt.railoffset;f&&(f.top&&(d+=f.top),b.rail.align&&f.left&&(e+=f.left));b.locked||b.rail.css({top:d,left:e,height:c?c.h:b.win.innerHeight()});b.zoom&&b.zoom.css({top:d+1,left:1==b.rail.align?e-20:e+b.rail.width+4});b.railh&&!b.locked&&(d=g.top,e=g.left,c=b.railh.align?d+s(b.win,"border-top-width",!0)+b.win.innerHeight()-b.railh.height:d+s(b.win,"border-top-width",!0),e+=s(b.win,"border-left-width"),b.railh.css({top:c,left:e, -width:b.railh.width}))}};this.doRailClick=function(c,g,d){var e;b.locked||(b.cancelEvent(c),g?(g=d?b.doScrollLeft:b.doScrollTop,e=d?(c.pageX-b.railh.offset().left-b.cursorwidth/2)*b.scrollratio.x:(c.pageY-b.rail.offset().top-b.cursorheight/2)*b.scrollratio.y,g(e)):(g=d?b.doScrollLeftBy:b.doScrollBy,e=d?b.scroll.x:b.scroll.y,c=d?c.pageX-b.railh.offset().left:c.pageY-b.rail.offset().top,d=d?b.view.w:b.view.h,e>=c?g(d):g(-d)))};b.hasanimationframe=w;b.hascancelanimationframe=x;b.hasanimationframe?b.hascancelanimationframe|| -(x=function(){b.cancelAnimationFrame=!0}):(w=function(b){return setTimeout(b,15-Math.floor(+new Date/1E3)%16)},x=clearInterval);this.init=function(){b.saved.css=[];if(f.isie7mobile)return!0;f.hasmstouch&&b.css(b.ispage?e("html"):b.win,{"-ms-touch-action":"none"});b.zindex="auto";b.zindex=!b.ispage&&"auto"==b.opt.zindex?k()||"auto":b.opt.zindex;!b.ispage&&"auto"!=b.zindex&&b.zindex>C&&(C=b.zindex);b.isie&&(0==b.zindex&&"auto"==b.opt.zindex)&&(b.zindex="auto");if(!b.ispage||!f.cantouch&&!f.isieold&& -!f.isie9mobile){var c=b.docscroll;b.ispage&&(c=b.haswrapper?b.win:b.doc);f.isie9mobile||b.css(c,{"overflow-y":"hidden"});b.ispage&&f.isie7&&("BODY"==b.doc[0].nodeName?b.css(e("html"),{"overflow-y":"hidden"}):"HTML"==b.doc[0].nodeName&&b.css(e("body"),{"overflow-y":"hidden"}));f.isios&&(!b.ispage&&!b.haswrapper)&&b.css(e("body"),{"-webkit-overflow-scrolling":"touch"});var g=e(document.createElement("div"));g.css({position:"relative",top:0,"float":"right",width:b.opt.cursorwidth,height:"0px","background-color":b.opt.cursorcolor, -border:b.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":b.opt.cursorborderradius,"-moz-border-radius":b.opt.cursorborderradius,"border-radius":b.opt.cursorborderradius});g.hborder=parseFloat(g.outerHeight()-g.innerHeight());b.cursor=g;var d=e(document.createElement("div"));d.attr("id",b.id);d.addClass("nicescroll-rails");var h,j,y=["left","right"],s;for(s in y)j=y[s],(h=b.opt.railpadding[j])?d.css("padding-"+j,h+"px"):b.opt.railpadding[j]=0;d.append(g);d.width=Math.max(parseFloat(b.opt.cursorwidth), -g.outerWidth())+b.opt.railpadding.left+b.opt.railpadding.right;d.css({width:d.width+"px",zIndex:b.zindex,background:b.opt.background,cursor:"default"});d.visibility=!0;d.scrollable=!0;d.align="left"==b.opt.railalign?0:1;b.rail=d;g=b.rail.drag=!1;b.opt.boxzoom&&(!b.ispage&&!f.isieold)&&(g=document.createElement("div"),b.bind(g,"click",b.doZoom),b.zoom=e(g),b.zoom.css({cursor:"pointer","z-index":b.zindex,backgroundImage:"url("+J+"zoomico.png)",height:18,width:18,backgroundPosition:"0px 0px"}),b.opt.dblclickzoom&& -b.bind(b.win,"dblclick",b.doZoom),f.cantouch&&b.opt.gesturezoom&&(b.ongesturezoom=function(c){1.5c.scale&&b.doZoomOut(c);return b.cancelEvent(c)},b.bind(b.win,"gestureend",b.ongesturezoom)));b.railh=!1;if(b.opt.horizrailenabled){b.css(c,{"overflow-x":"hidden"});g=e(document.createElement("div"));g.css({position:"relative",top:0,height:b.opt.cursorwidth,width:"0px","background-color":b.opt.cursorcolor,border:b.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":b.opt.cursorborderradius, -"-moz-border-radius":b.opt.cursorborderradius,"border-radius":b.opt.cursorborderradius});g.wborder=parseFloat(g.outerWidth()-g.innerWidth());b.cursorh=g;var l=e(document.createElement("div"));l.attr("id",b.id+"-hr");l.addClass("nicescroll-rails");l.height=Math.max(parseFloat(b.opt.cursorwidth),g.outerHeight());l.css({height:l.height+"px",zIndex:b.zindex,background:b.opt.background});l.append(g);l.visibility=!0;l.scrollable=!0;l.align="top"==b.opt.railvalign?0:1;b.railh=l;b.railh.drag=!1}b.ispage? -(d.css({position:"fixed",top:"0px",height:"100%"}),d.align?d.css({right:"0px"}):d.css({left:"0px"}),b.body.append(d),b.railh&&(l.css({position:"fixed",left:"0px",width:"100%"}),l.align?l.css({bottom:"0px"}):l.css({top:"0px"}),b.body.append(l))):(b.ishwscroll?("static"==b.win.css("position")&&b.css(b.win,{position:"relative"}),c="HTML"==b.win[0].nodeName?b.body:b.win,b.zoom&&(b.zoom.css({position:"absolute",top:1,right:0,"margin-right":d.width+4}),c.append(b.zoom)),d.css({position:"absolute",top:0}), -d.align?d.css({right:0}):d.css({left:0}),c.append(d),l&&(l.css({position:"absolute",left:0,bottom:0}),l.align?l.css({bottom:0}):l.css({top:0}),c.append(l))):(b.isfixed="fixed"==b.win.css("position"),c=b.isfixed?"fixed":"absolute",b.isfixed||(b.viewport=b.getViewport(b.win[0])),b.viewport&&(b.body=b.viewport,!1==/relative|absolute/.test(b.viewport.css("position"))&&b.css(b.viewport,{position:"relative"})),d.css({position:c}),b.zoom&&b.zoom.css({position:c}),b.updateScrollBar(),b.body.append(d),b.zoom&& -b.body.append(b.zoom),b.railh&&(l.css({position:c}),b.body.append(l))),f.isios&&b.css(b.win,{"-webkit-tap-highlight-color":"rgba(0,0,0,0)","-webkit-touch-callout":"none"}),f.isie&&b.opt.disableoutline&&b.win.attr("hideFocus","true"),f.iswebkit&&b.opt.disableoutline&&b.win.css({outline:"none"}));!1===b.opt.autohidemode?(b.autohidedom=!1,b.rail.css({opacity:b.opt.cursoropacitymax}),b.railh&&b.railh.css({opacity:b.opt.cursoropacitymax})):!0===b.opt.autohidemode?(b.autohidedom=e().add(b.rail),f.isie8&& -(b.autohidedom=b.autohidedom.add(b.cursor)),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh)),b.railh&&f.isie8&&(b.autohidedom=b.autohidedom.add(b.cursorh))):"scroll"==b.opt.autohidemode?(b.autohidedom=e().add(b.rail),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh))):"cursor"==b.opt.autohidemode?(b.autohidedom=e().add(b.cursor),b.railh&&(b.autohidedom=b.autohidedom.add(b.cursorh))):"hidden"==b.opt.autohidemode&&(b.autohidedom=!1,b.hide(),b.locked=!1);if(f.isie9mobile)b.scrollmom=new L(b),b.onmangotouch= -function(){var c=b.getScrollTop(),d=b.getScrollLeft();if(c==b.scrollmom.lastscrolly&&d==b.scrollmom.lastscrollx)return!0;var g=c-b.mangotouch.sy,e=d-b.mangotouch.sx;if(0!=Math.round(Math.sqrt(Math.pow(e,2)+Math.pow(g,2)))){var f=0>g?-1:1,p=0>e?-1:1,h=+new Date;b.mangotouch.lazy&&clearTimeout(b.mangotouch.lazy);80t?t=Math.round(t/2):t>b.page.maxh&&(t=b.page.maxh+Math.round((t-b.page.maxh)/2)):(0>t&&(h=t=0),t>b.page.maxh&&(t=b.page.maxh,h=0));if(b.railh&&b.railh.scrollable){var l=b.rail.drag.sl-j;b.ishwscroll&&b.opt.bouncescroll?0>l?l=Math.round(l/2):l>b.page.maxw&&(l=b.page.maxw+ -Math.round((l-b.page.maxw)/2)):(0>l&&(k=l=0),l>b.page.maxw&&(l=b.page.maxw,k=0))}g=!1;if(b.rail.drag.dl)g=!0,"v"==b.rail.drag.dl?l=b.rail.drag.sl:"h"==b.rail.drag.dl&&(t=b.rail.drag.st);else{var p=Math.abs(p),j=Math.abs(j),y=b.opt.directionlockdeadzone;if("v"==b.rail.drag.ck){if(p>y&&j<=0.3*p)return b.rail.drag=!1,!0;j>y&&(b.rail.drag.dl="f",e("body").scrollTop(e("body").scrollTop()))}else if("h"==b.rail.drag.ck){if(j>y&&p<=0.3*az)return b.rail.drag=!1,!0;p>y&&(b.rail.drag.dl="f",e("body").scrollLeft(e("body").scrollLeft()))}}b.synched("touchmove", -function(){b.rail.drag&&2==b.rail.drag.pt&&(b.prepareTransition&&b.prepareTransition(0),b.rail.scrollable&&b.setScrollTop(t),b.scrollmom.update(k,h),b.railh&&b.railh.scrollable?(b.setScrollLeft(l),b.showCursor(t,l)):b.showCursor(t),f.isie10&&document.selection.clear())});f.ischrome&&b.istouchcapable&&(g=!1);if(g)return b.cancelEvent(c)}}}b.onmousedown=function(c,d){if(!(b.rail.drag&&1!=b.rail.drag.pt)){if(b.locked)return b.cancelEvent(c);b.cancelScroll();b.rail.drag={x:c.clientX,y:c.clientY,sx:b.scroll.x, -sy:b.scroll.y,pt:1,hr:!!d};var g=b.getTarget(c);!b.ispage&&f.hasmousecapture&&g.setCapture();b.isiframe&&!f.hasmousecapture&&(b.saved.csspointerevents=b.doc.css("pointer-events"),b.css(b.doc,{"pointer-events":"none"}));return b.cancelEvent(c)}};b.onmouseup=function(c){if(b.rail.drag&&(f.hasmousecapture&&document.releaseCapture(),b.isiframe&&!f.hasmousecapture&&b.doc.css("pointer-events",b.saved.csspointerevents),1==b.rail.drag.pt))return b.rail.drag=!1,b.cancelEvent(c)};b.onmousemove=function(c){if(b.rail.drag&& -1==b.rail.drag.pt){if(f.ischrome&&0==c.which)return b.onmouseup(c);b.cursorfreezed=!0;if(b.rail.drag.hr){b.scroll.x=b.rail.drag.sx+(c.clientX-b.rail.drag.x);0>b.scroll.x&&(b.scroll.x=0);var d=b.scrollvaluemaxw;b.scroll.x>d&&(b.scroll.x=d)}else b.scroll.y=b.rail.drag.sy+(c.clientY-b.rail.drag.y),0>b.scroll.y&&(b.scroll.y=0),d=b.scrollvaluemax,b.scroll.y>d&&(b.scroll.y=d);b.synched("mousemove",function(){b.rail.drag&&1==b.rail.drag.pt&&(b.showCursor(),b.rail.drag.hr?b.doScrollLeft(Math.round(b.scroll.x* -b.scrollratio.x),b.opt.cursordragspeed):b.doScrollTop(Math.round(b.scroll.y*b.scrollratio.y),b.opt.cursordragspeed))});return b.cancelEvent(c)}};if(f.cantouch||b.opt.touchbehavior)b.onpreventclick=function(c){if(b.preventclick)return b.preventclick.tg.onclick=b.preventclick.click,b.preventclick=!1,b.cancelEvent(c)},b.bind(b.win,"mousedown",b.ontouchstart),b.onclick=f.isios?!1:function(c){return b.lastmouseup?(b.lastmouseup=!1,b.cancelEvent(c)):!0},b.opt.grabcursorenabled&&f.cursorgrabvalue&&(b.css(b.ispage? -b.doc:b.win,{cursor:f.cursorgrabvalue}),b.css(b.rail,{cursor:f.cursorgrabvalue}));else{var m=function(c){if(b.selectiondrag){if(c){var d=b.win.outerHeight();c=c.pageY-b.selectiondrag.top;0=d&&(c-=d);b.selectiondrag.df=c}0!=b.selectiondrag.df&&(b.doScrollBy(2*-Math.floor(b.selectiondrag.df/6)),b.debounced("doselectionscroll",function(){m()},50))}};b.hasTextSelected="getSelection"in document?function(){return 0b.page.maxh?b.doScrollTop(b.page.maxh):(b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y)), -b.scroll.x=Math.round(b.getScrollLeft()*(1/b.scrollratio.x)),b.cursoractive&&b.noticeCursor());b.scroll.y&&0==b.getScrollTop()&&b.doScrollTo(Math.floor(b.scroll.y*b.scrollratio.y));return b};this.resize=b.onResize;this.lazyResize=function(c){c=isNaN(c)?30:c;b.delayed("resize",b.resize,c);return b};this._bind=function(c,d,e,f){b.events.push({e:c,n:d,f:e,b:f,q:!1});c.addEventListener?c.addEventListener(d,e,f||!1):c.attachEvent?c.attachEvent("on"+d,e):c["on"+d]=e};this.jqbind=function(c,d,f){b.events.push({e:c, -n:d,f:f,q:!0});e(c).bind(d,f)};this.bind=function(c,d,e,h){var k="jquery"in c?c[0]:c;"mousewheel"==d?"onwheel"in b.win?b._bind(k,"wheel",e,h||!1):(c="undefined"!=typeof document.onmousewheel?"mousewheel":"DOMMouseScroll",n(k,c,e,h||!1),"DOMMouseScroll"==c&&n(k,"MozMousePixelScroll",e,h||!1)):k.addEventListener?(f.cantouch&&/mouseup|mousedown|mousemove/.test(d)&&b._bind(k,"mousedown"==d?"touchstart":"mouseup"==d?"touchend":"touchmove",function(b){if(b.touches){if(2>b.touches.length){var c=b.touches.length? -b.touches[0]:b;c.original=b;e.call(this,c)}}else b.changedTouches&&(c=b.changedTouches[0],c.original=b,e.call(this,c))},h||!1),b._bind(k,d,e,h||!1),f.cantouch&&"mouseup"==d&&b._bind(k,"touchcancel",e,h||!1)):b._bind(k,d,function(c){if((c=c||window.event||!1)&&c.srcElement)c.target=c.srcElement;"pageY"in c||(c.pageX=c.clientX+document.documentElement.scrollLeft,c.pageY=c.clientY+document.documentElement.scrollTop);return!1===e.call(k,c)||!1===h?b.cancelEvent(c):!0})};this._unbind=function(b,d,e,f){b.removeEventListener? -b.removeEventListener(d,e,f):b.detachEvent?b.detachEvent("on"+d,e):b["on"+d]=!1};this.unbindAll=function(){for(var c=0;c(b.newscrolly-h)*(d-h)||0>(b.newscrollx-k)* -(c-k))&&b.cancelScroll();!1==b.opt.bouncescroll&&(0>d?d=0:d>b.page.maxh&&(d=b.page.maxh),0>c?c=0:c>b.page.maxw&&(c=b.page.maxw));if(b.scrollrunning&&c==b.newscrollx&&d==b.newscrolly)return!1;b.newscrolly=d;b.newscrollx=c;b.newscrollspeed=e||!1;if(b.timer)return!1;b.timer=setTimeout(function(){var e=b.getScrollTop(),h=b.getScrollLeft(),k,p;k=c-h;p=d-e;k=Math.round(Math.sqrt(Math.pow(k,2)+Math.pow(p,2)));k=b.newscrollspeed&&1=b.newscrollspeed&&(k*=b.newscrollspeed);b.prepareTransition(k,!0);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm);0c?c=0:c>b.page.maxh&&(c=b.page.maxh);0>d?d=0:d>b.page.maxw&&(d=b.page.maxw);if(c!=b.newscrolly||d!=b.newscrollx)return b.doScrollPos(d,c,b.opt.snapbackspeed);b.onscrollend&&b.scrollrunning&&b.onscrollend.call(b,{type:"scrollend",current:{x:d,y:c},end:{x:b.newscrollx,y:b.newscrolly}});b.scrollrunning= -!1}):(this.doScrollLeft=function(c,d){var e=b.scrollrunning?b.newscrolly:b.getScrollTop();b.doScrollPos(c,e,d)},this.doScrollTop=function(c,d){var e=b.scrollrunning?b.newscrollx:b.getScrollLeft();b.doScrollPos(e,c,d)},this.doScrollPos=function(c,d,e){function f(){if(b.cancelAnimationFrame)return!0;b.scrollrunning=!0;if(n=1-n)return b.timer=w(f)||1;var c=0,d=sy=b.getScrollTop();if(b.dst.ay){var d=b.bzscroll?b.dst.py+b.bzscroll.getNow()*b.dst.ay:b.newscrolly,e=d-sy;if(0>e&&db.newscrolly)d= -b.newscrolly;b.setScrollTop(d);d==b.newscrolly&&(c=1)}else c=1;var g=sx=b.getScrollLeft();if(b.dst.ax){g=b.bzscroll?b.dst.px+b.bzscroll.getNow()*b.dst.ax:b.newscrollx;e=g-sx;if(0>e&&gb.newscrollx)g=b.newscrollx;b.setScrollLeft(g);g==b.newscrollx&&(c+=1)}else c+=1;2==c?(b.timer=0,b.cursorfreezed=!1,b.bzscroll=!1,b.scrollrunning=!1,0>d?d=0:d>b.page.maxh&&(d=b.page.maxh),0>g?g=0:g>b.page.maxw&&(g=b.page.maxw),g!=b.newscrollx||d!=b.newscrolly?b.doScrollPos(g,d):b.onscrollend&&b.onscrollend.call(b, -{type:"scrollend",current:{x:sx,y:sy},end:{x:b.newscrollx,y:b.newscrolly}})):b.timer=w(f)||1}d="undefined"==typeof d||!1===d?b.getScrollTop(!0):d;if(b.timer&&b.newscrolly==d&&b.newscrollx==c)return!0;b.timer&&x(b.timer);b.timer=0;var h=b.getScrollTop(),k=b.getScrollLeft();(0>(b.newscrolly-h)*(d-h)||0>(b.newscrollx-k)*(c-k))&&b.cancelScroll();b.newscrolly=d;b.newscrollx=c;if(!b.bouncescroll||!b.rail.visibility)0>b.newscrolly?b.newscrolly=0:b.newscrolly>b.page.maxh&&(b.newscrolly=b.page.maxh);if(!b.bouncescroll|| -!b.railh.visibility)0>b.newscrollx?b.newscrollx=0:b.newscrollx>b.page.maxw&&(b.newscrollx=b.page.maxw);b.dst={};b.dst.x=c-k;b.dst.y=d-h;b.dst.px=k;b.dst.py=h;var j=Math.round(Math.sqrt(Math.pow(b.dst.x,2)+Math.pow(b.dst.y,2)));b.dst.ax=b.dst.x/j;b.dst.ay=b.dst.y/j;var l=0,s=j;0==b.dst.x?(l=h,s=d,b.dst.ay=1,b.dst.py=0):0==b.dst.y&&(l=k,s=c,b.dst.ax=1,b.dst.px=0);j=b.getTransitionSpeed(j);e&&1>=e&&(j*=e);b.bzscroll=0=b.page.maxh||k==b.page.maxw&&c>=b.page.maxw)&&b.checkContentSize();var n=1;b.cancelAnimationFrame=!1;b.timer=1;b.onscrollstart&&!b.scrollrunning&&b.onscrollstart.call(b,{type:"scrollstart",current:{x:k,y:h},request:{x:c,y:d},end:{x:b.newscrollx,y:b.newscrolly},speed:j});f();(h==b.page.maxh&&d>=h||k==b.page.maxw&&c>=k)&&b.checkContentSize();b.noticeCursor()}},this.cancelScroll=function(){b.timer&&x(b.timer);b.timer=0;b.bzscroll=!1;b.scrollrunning=!1;return b}):(this.doScrollLeft=function(c, -d){var e=b.getScrollTop();b.doScrollPos(c,e,d)},this.doScrollTop=function(c,d){var e=b.getScrollLeft();b.doScrollPos(e,c,d)},this.doScrollPos=function(c,d){var e=c>b.page.maxw?b.page.maxw:c;0>e&&(e=0);var f=d>b.page.maxh?b.page.maxh:d;0>f&&(f=0);b.synched("scroll",function(){b.setScrollTop(f);b.setScrollLeft(e)})},this.cancelScroll=function(){});this.doScrollBy=function(c,d){var e=0,e=d?Math.floor((b.scroll.y-c)*b.scrollratio.y):(b.timer?b.newscrolly:b.getScrollTop(!0))-c;if(b.bouncescroll){var f= -Math.round(b.view.h/2);e<-f?e=-f:e>b.page.maxh+f&&(e=b.page.maxh+f)}b.cursorfreezed=!1;py=b.getScrollTop(!0);if(0>e&&0>=py)return b.noticeCursor();if(e>b.page.maxh&&py>=b.page.maxh)return b.checkContentSize(),b.noticeCursor();b.doScrollTop(e)};this.doScrollLeftBy=function(c,d){var e=0,e=d?Math.floor((b.scroll.x-c)*b.scrollratio.x):(b.timer?b.newscrollx:b.getScrollLeft(!0))-c;if(b.bouncescroll){var f=Math.round(b.view.w/2);e<-f?e=-f:e>b.page.maxw+f&&(e=b.page.maxw+f)}b.cursorfreezed=!1;px=b.getScrollLeft(!0); -if(0>e&&0>=px||e>b.page.maxw&&px>=b.page.maxw)return b.noticeCursor();b.doScrollLeft(e)};this.doScrollTo=function(c,d){d&&Math.round(c*b.scrollratio.y);b.cursorfreezed=!1;b.doScrollTop(c)};this.checkContentSize=function(){var c=b.getContentSize();(c.h!=b.page.h||c.w!=b.page.w)&&b.resize(!1,c)};b.onscroll=function(){b.rail.drag||b.cursorfreezed||b.synched("scroll",function(){b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y));b.railh&&(b.scroll.x=Math.round(b.getScrollLeft()*(1/b.scrollratio.x))); -b.noticeCursor()})};b.bind(b.docscroll,"scroll",b.onscroll);this.doZoomIn=function(c){if(!b.zoomactive){b.zoomactive=!0;b.zoomrestore={style:{}};var d="position top left zIndex backgroundColor marginTop marginBottom marginLeft marginRight".split(" "),h=b.win[0].style,k;for(k in d){var j=d[k];b.zoomrestore.style[j]="undefined"!=typeof h[j]?h[j]:""}b.zoomrestore.style.width=b.win.css("width");b.zoomrestore.style.height=b.win.css("height");b.zoomrestore.padding={w:b.win.outerWidth()-b.win.width(),h:b.win.outerHeight()- -b.win.height()};f.isios4&&(b.zoomrestore.scrollTop=e(window).scrollTop(),e(window).scrollTop(0));b.win.css({position:f.isios4?"absolute":"fixed",top:0,left:0,"z-index":C+100,margin:"0px"});d=b.win.css("backgroundColor");(""==d||/transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(d))&&b.win.css("backgroundColor","#fff");b.rail.css({"z-index":C+101});b.zoom.css({"z-index":C+102});b.zoom.css("backgroundPosition","0px -18px");b.resizeZoom();b.onzoomin&&b.onzoomin.call(b);return b.cancelEvent(c)}};this.doZoomOut= -function(c){if(b.zoomactive)return b.zoomactive=!1,b.win.css("margin",""),b.win.css(b.zoomrestore.style),f.isios4&&e(window).scrollTop(b.zoomrestore.scrollTop),b.rail.css({"z-index":b.zindex}),b.zoom.css({"z-index":b.zindex}),b.zoomrestore=!1,b.zoom.css("backgroundPosition","0px 0px"),b.onResize(),b.onzoomout&&b.onzoomout.call(b),b.cancelEvent(c)};this.doZoom=function(c){return b.zoomactive?b.doZoomOut(c):b.doZoomIn(c)};this.resizeZoom=function(){if(b.zoomactive){var c=b.getScrollTop();b.win.css({width:e(window).width()- -b.zoomrestore.padding.w+"px",height:e(window).height()-b.zoomrestore.padding.h+"px"});b.onResize();b.setScrollTop(Math.min(b.page.maxh,c))}};this.init();e.nicescroll.push(this)},L=function(e){var d=this;this.nc=e;this.steptime=this.lasttime=this.speedy=this.speedx=this.lasty=this.lastx=0;this.snapy=this.snapx=!1;this.demuly=this.demulx=0;this.lastscrolly=this.lastscrollx=-1;this.timer=this.chky=this.chkx=0;this.time=function(){return+new Date};this.reset=function(e,j){d.stop();var n=d.time();d.steptime= -0;d.lasttime=n;d.speedx=0;d.speedy=0;d.lastx=e;d.lasty=j;d.lastscrollx=-1;d.lastscrolly=-1};this.update=function(e,j){var n=d.time();d.steptime=n-d.lasttime;d.lasttime=n;var n=j-d.lasty,v=e-d.lastx,b=d.nc.getScrollTop(),m=d.nc.getScrollLeft(),b=b+n,m=m+v;d.snapx=0>m||m>d.nc.page.maxw;d.snapy=0>b||b>d.nc.page.maxh;d.speedx=v;d.speedy=n;d.lastx=e;d.lasty=j};this.stop=function(){d.nc.unsynched("domomentum2d");d.timer&&clearTimeout(d.timer);d.timer=0;d.lastscrollx=-1;d.lastscrolly=-1};this.doSnapy=function(e, -j){var n=!1;0>j?(j=0,n=!0):j>d.nc.page.maxh&&(j=d.nc.page.maxh,n=!0);0>e?(e=0,n=!0):e>d.nc.page.maxw&&(e=d.nc.page.maxw,n=!0);n&&d.nc.doScrollPos(e,j,d.nc.opt.snapbackspeed)};this.doMomentum=function(e){var j=d.time(),n=e?j+e:d.lasttime;e=d.nc.getScrollLeft();var v=d.nc.getScrollTop(),b=d.nc.page.maxh,m=d.nc.page.maxw;d.speedx=0=j-n;if(0>v||v>b||0>e||e>m)n=!1;e=d.speedx&&n?d.speedx:!1;if(d.speedy&&n&&d.speedy||e){var h=Math.max(16, -d.steptime);50q||q>m))e=0.1;if(d.speedy&&(r=Math.floor(d.lastscrolly-d.speedy*(1-d.demulxy)),d.lastscrolly=r,0>r||r>b))e=0.1;d.demulxy=Math.min(1,d.demulxy+e);d.nc.synched("domomentum2d", -function(){d.speedx&&(d.nc.getScrollLeft()!=d.chkx&&d.stop(),d.chkx=q,d.nc.setScrollLeft(q));d.speedy&&(d.nc.getScrollTop()!=d.chky&&d.stop(),d.chky=r,d.nc.setScrollTop(r));d.timer||(d.nc.hideCursor(),d.doSnapy(q,r))});1>d.demulxy?d.timer=setTimeout(u,h):(d.stop(),d.nc.hideCursor(),d.doSnapy(q,r))};u()}else d.doSnapy(d.nc.getScrollLeft(),d.nc.getScrollTop())}},z=e.fn.scrollTop;e.cssHooks.pageYOffset={get:function(j){var d=e.data(j,"__nicescroll")||!1;return d&&d.ishwscroll?d.getScrollTop():z.call(j)}, -set:function(j,d){var k=e.data(j,"__nicescroll")||!1;k&&k.ishwscroll?k.setScrollTop(parseInt(d)):z.call(j,d);return this}};e.fn.scrollTop=function(j){if("undefined"==typeof j){var d=this[0]?e.data(this[0],"__nicescroll")||!1:!1;return d&&d.ishwscroll?d.getScrollTop():z.call(this)}return this.each(function(){var d=e.data(this,"__nicescroll")||!1;d&&d.ishwscroll?d.setScrollTop(parseInt(j)):z.call(e(this),j)})};var B=e.fn.scrollLeft;e.cssHooks.pageXOffset={get:function(j){var d=e.data(j,"__nicescroll")|| -!1;return d&&d.ishwscroll?d.getScrollLeft():B.call(j)},set:function(j,d){var k=e.data(j,"__nicescroll")||!1;k&&k.ishwscroll?k.setScrollLeft(parseInt(d)):B.call(j,d);return this}};e.fn.scrollLeft=function(j){if("undefined"==typeof j){var d=this[0]?e.data(this[0],"__nicescroll")||!1:!1;return d&&d.ishwscroll?d.getScrollLeft():B.call(this)}return this.each(function(){var d=e.data(this,"__nicescroll")||!1;d&&d.ishwscroll?d.setScrollLeft(parseInt(j)):B.call(e(this),j)})};for(var F=function(j){var d=this; -this.length=0;this.name="nicescrollarray";this.each=function(e){for(var j=0,k=0;k"]], - ['shift + /', ["questionmark", "?"]] - ] - }; - //a-z and A-Z - for (aI = 65; aI <= 90; aI += 1) { - usLocale.map[aI] = String.fromCharCode(aI + 32); - usLocale.macros.push(['shift + ' + String.fromCharCode(aI + 32) + ', capslock + ' + String.fromCharCode(aI + 32), [String.fromCharCode(aI)]]); - } - registerLocale('us', usLocale); - getSetLocale('us'); - - - ////////// - // INIT // - ////////// - - //enable the library - enable(); - - - ///////// - // API // - ///////// - - //assemble the library and return it - KeyboardJS.enable = enable; - KeyboardJS.disable = disable; - KeyboardJS.activeKeys = getActiveKeys; - KeyboardJS.on = createBinding; - KeyboardJS.clear = removeBindingByKeyCombo; - KeyboardJS.clear.key = removeBindingByKeyName; - KeyboardJS.locale = getSetLocale; - KeyboardJS.locale.register = registerLocale; - KeyboardJS.macro = createMacro; - KeyboardJS.macro.remove = removeMacro; - KeyboardJS.key = {}; - KeyboardJS.key.name = getKeyName; - KeyboardJS.key.code = getKeyCode; - KeyboardJS.combo = {}; - KeyboardJS.combo.active = isSatisfiedCombo; - KeyboardJS.combo.parse = parseKeyCombo; - KeyboardJS.combo.stringify = stringifyKeyCombo; - return KeyboardJS; - - - ////////////////////// - // INSTANCE METHODS // - ////////////////////// - - /** - * Enables KeyboardJS - */ - function enable() { - if(window.addEventListener) { - document.addEventListener('keydown', keydown, false); - document.addEventListener('keyup', keyup, false); - window.addEventListener('blur', reset, false); - window.addEventListener('webkitfullscreenchange', reset, false); - window.addEventListener('mozfullscreenchange', reset, false); - } else if(window.attachEvent) { - document.attachEvent('onkeydown', keydown); - document.attachEvent('onkeyup', keyup); - window.attachEvent('onblur', reset); - } - } - - /** - * Exits all active bindings and disables KeyboardJS - */ - function disable() { - reset(); - if(window.removeEventListener) { - document.removeEventListener('keydown', keydown, false); - document.removeEventListener('keyup', keyup, false); - window.removeEventListener('blur', reset, false); - window.removeEventListener('webkitfullscreenchange', reset, false); - window.removeEventListener('mozfullscreenchange', reset, false); - } else if(window.detachEvent) { - document.detachEvent('onkeydown', keydown); - document.detachEvent('onkeyup', keyup); - window.detachEvent('onblur', reset); - } - } - - - //////////////////// - // EVENT HANDLERS // - //////////////////// - - /** - * Exits all active bindings. Optionally passes an event to all binding - * handlers. - * @param {KeyboardEvent} event [Optional] - */ - function reset(event) { - activeKeys = []; - pruneMacros(); - pruneBindings(event); - } - - /** - * Key down event handler. - * @param {KeyboardEvent} event - */ - function keydown(event) { - var keyNames, kI; - keyNames = getKeyName(event.keyCode); - if(keyNames.length < 1) { return; } - for(kI = 0; kI < keyNames.length; kI += 1) { - addActiveKey(keyNames[kI]); - } - executeMacros(); - executeBindings(event); - } - - /** - * Key up event handler. - * @param {KeyboardEvent} event - */ - function keyup(event) { - var keyNames, kI; - keyNames = getKeyName(event.keyCode); - if(keyNames.length < 1) { return; } - for(kI = 0; kI < keyNames.length; kI += 1) { - removeActiveKey(keyNames[kI]); - } - pruneMacros(); - pruneBindings(event); - } - - /** - * Accepts a key code and returns the key names defined by the current - * locale. - * @param {Number} keyCode - * @return {Array} keyNames An array of key names defined for the key - * code as defined by the current locale. - */ - function getKeyName(keyCode) { - return map[keyCode] || []; - } - - /** - * Accepts a key name and returns the key code defined by the current - * locale. - * @param {Number} keyName - * @return {Number|false} - */ - function getKeyCode(keyName) { - var keyCode; - for(keyCode in map) { - if(!map.hasOwnProperty(keyCode)) { continue; } - if(map[keyCode].indexOf(keyName) > -1) { return keyCode; } - } - return false; - } - - - //////////// - // MACROS // - //////////// - - /** - * Accepts a key combo and an array of key names to inject once the key - * combo is satisfied. - * @param {String} combo - * @param {Array} injectedKeys - */ - function createMacro(combo, injectedKeys) { - if(typeof combo !== 'string' && (typeof combo !== 'object' || typeof combo.push !== 'function')) { - throw new Error("Cannot create macro. The combo must be a string or array."); - } - if(typeof injectedKeys !== 'object' || typeof injectedKeys.push !== 'function') { - throw new Error("Cannot create macro. The injectedKeys must be an array."); - } - macros.push([combo, injectedKeys]); - } - - /** - * Accepts a key combo and clears any and all macros bound to that key - * combo. - * @param {String} combo - */ - function removeMacro(combo) { - var macro; - if(typeof combo !== 'string' && (typeof combo !== 'object' || typeof combo.push !== 'function')) { throw new Error("Cannot remove macro. The combo must be a string or array."); } - for(mI = 0; mI < macros.length; mI += 1) { - macro = macros[mI]; - if(compareCombos(combo, macro[0])) { - removeActiveKey(macro[1]); - macros.splice(mI, 1); - break; - } - } - } - - /** - * Executes macros against the active keys. Each macro's key combo is - * checked and if found to be satisfied, the macro's key names are injected - * into active keys. - */ - function executeMacros() { - var mI, combo, kI; - for(mI = 0; mI < macros.length; mI += 1) { - combo = parseKeyCombo(macros[mI][0]); - if(activeMacros.indexOf(macros[mI]) === -1 && isSatisfiedCombo(combo)) { - activeMacros.push(macros[mI]); - for(kI = 0; kI < macros[mI][1].length; kI += 1) { - addActiveKey(macros[mI][1][kI]); - } - } - } - } - - /** - * Prunes active macros. Checks each active macro's key combo and if found - * to no longer to be satisfied, each of the macro's key names are removed - * from active keys. - */ - function pruneMacros() { - var mI, combo, kI; - for(mI = 0; mI < activeMacros.length; mI += 1) { - combo = parseKeyCombo(activeMacros[mI][0]); - if(isSatisfiedCombo(combo) === false) { - for(kI = 0; kI < activeMacros[mI][1].length; kI += 1) { - removeActiveKey(activeMacros[mI][1][kI]); - } - activeMacros.splice(mI, 1); - mI -= 1; - } - } - } - - - ////////////// - // BINDINGS // - ////////////// - - /** - * Creates a binding object, and, if provided, binds a key down hander and - * a key up handler. Returns a binding object that emits keyup and - * keydown events. - * @param {String} keyCombo - * @param {Function} keyDownCallback [Optional] - * @param {Function} keyUpCallback [Optional] - * @return {Object} binding - */ - function createBinding(keyCombo, keyDownCallback, keyUpCallback) { - var api = {}, binding, subBindings = [], bindingApi = {}, kI, - subCombo; - - //break the combo down into a combo array - if(typeof keyCombo === 'string') { - keyCombo = parseKeyCombo(keyCombo); - } - - //bind each sub combo contained within the combo string - for(kI = 0; kI < keyCombo.length; kI += 1) { - binding = {}; - - //stringify the combo again - subCombo = stringifyKeyCombo([keyCombo[kI]]); - - //validate the sub combo - if(typeof subCombo !== 'string') { throw new Error('Failed to bind key combo. The key combo must be string.'); } - - //create the binding - binding.keyCombo = subCombo; - binding.keyDownCallback = []; - binding.keyUpCallback = []; - - //inject the key down and key up callbacks if given - if(keyDownCallback) { binding.keyDownCallback.push(keyDownCallback); } - if(keyUpCallback) { binding.keyUpCallback.push(keyUpCallback); } - - //stash the new binding - bindings.push(binding); - subBindings.push(binding); - } - - //build the binding api - api.clear = clear; - api.on = on; - return api; - - /** - * Clears the binding - */ - function clear() { - var bI; - for(bI = 0; bI < subBindings.length; bI += 1) { - bindings.splice(bindings.indexOf(subBindings[bI]), 1); - } - } - - /** - * Accepts an event name. and any number of callbacks. When the event is - * emitted, all callbacks are executed. Available events are key up and - * key down. - * @param {String} eventName - * @return {Object} subBinding - */ - function on(eventName ) { - var api = {}, callbacks, cI, bI; - - //validate event name - if(typeof eventName !== 'string') { throw new Error('Cannot bind callback. The event name must be a string.'); } - if(eventName !== 'keyup' && eventName !== 'keydown') { throw new Error('Cannot bind callback. The event name must be a "keyup" or "keydown".'); } - - //gather the callbacks - callbacks = Array.prototype.slice.apply(arguments, [1]); - - //stash each the new binding - for(cI = 0; cI < callbacks.length; cI += 1) { - if(typeof callbacks[cI] === 'function') { - if(eventName === 'keyup') { - for(bI = 0; bI < subBindings.length; bI += 1) { - subBindings[bI].keyUpCallback.push(callbacks[cI]); - } - } else if(eventName === 'keydown') { - for(bI = 0; bI < subBindings.length; bI += 1) { - subBindings[bI].keyDownCallback.push(callbacks[cI]); - } - } - } - } - - //construct and return the sub binding api - api.clear = clear; - return api; - - /** - * Clears the binding - */ - function clear() { - var cI, bI; - for(cI = 0; cI < callbacks.length; cI += 1) { - if(typeof callbacks[cI] === 'function') { - if(eventName === 'keyup') { - for(bI = 0; bI < subBindings.length; bI += 1) { - subBindings[bI].keyUpCallback.splice(subBindings[bI].keyUpCallback.indexOf(callbacks[cI]), 1); - } - } else { - for(bI = 0; bI < subBindings.length; bI += 1) { - subBindings[bI].keyDownCallback.splice(subBindings[bI].keyDownCallback.indexOf(callbacks[cI]), 1); - } - } - } - } - } - } - } - - /** - * Clears all binding attached to a given key combo. Key name order does not - * matter as long as the key combos equate. - * @param {String} keyCombo - */ - function removeBindingByKeyCombo(keyCombo) { - var bI, binding, keyName; - for(bI = 0; bI < bindings.length; bI += 1) { - binding = bindings[bI]; - if(compareCombos(keyCombo, binding.keyCombo)) { - bindings.splice(bI, 1); bI -= 1; - } - } - } - - /** - * Clears all binding attached to key combos containing a given key name. - * @param {String} keyName - */ - function removeBindingByKeyName(keyName) { - var bI, cI, binding; - if(keyName) { - for(bI = 0; bI < bindings.length; bI += 1) { - binding = bindings[bI]; - for(cI = 0; cI < binding.keyCombo.length; cI += 1) { - if(binding.keyCombo[kI].indexOf(keyName) > -1) { - bindings.splice(bI, 1); bI -= 1; - break; - } - } - } - } else { - bindings = []; - } - } - - /** - * Executes bindings that are active. Only allows the keys to be used once - * as to prevent binding overlap. - * @param {KeyboardEvent} event The keyboard event. - */ - function executeBindings(event) { - var bI, sBI, binding, bidningKeys, remainingKeys, cI, killEventBubble, kI, bindingKeysSatisfied, - index, sortedBindings = [], bindingWeight; - - remainingKeys = [].concat(activeKeys); - for(bI = 0; bI < bindings.length; bI += 1) { - bindingWeight = extractComboKeys(bindings[bI].keyCombo).length; - if(!sortedBindings[bindingWeight]) { sortedBindings[bindingWeight] = []; } - sortedBindings[bindingWeight].push(bindings[bI]); - } - for(sBI = sortedBindings.length - 1; sBI >= 0; sBI -= 1) { - if(!sortedBindings[sBI]) { continue; } - for(bI = 0; bI < sortedBindings[sBI].length; bI += 1) { - binding = sortedBindings[sBI][bI]; - bindingKeys = extractComboKeys(binding.keyCombo); - bindingKeysSatisfied = true; - for(kI = 0; kI < bindingKeys.length; kI += 1) { - if(remainingKeys.indexOf(bindingKeys[kI]) === -1) { - bindingKeysSatisfied = false; - break; - } - } - if(bindingKeysSatisfied && isSatisfiedCombo(binding.keyCombo)) { - activeBindings.push(binding); - for(kI = 0; kI < bindingKeys.length; kI += 1) { - index = remainingKeys.indexOf(bindingKeys[kI]); - if(index > -1) { - remainingKeys.splice(index, 1); - kI -= 1; - } - } - for(cI = 0; cI < binding.keyDownCallback.length; cI += 1) { - if (binding.keyDownCallback[cI](event, getActiveKeys(), binding.keyCombo) === false) { - killEventBubble = true; - } - } - if(killEventBubble === true) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - /** - * Removes bindings that are no longer satisfied by the active keys. Also - * fires the key up callbacks. - * @param {KeyboardEvent} event - */ - function pruneBindings(event) { - var bI, cI, binding, killEventBubble; - for(bI = 0; bI < activeBindings.length; bI += 1) { - binding = activeBindings[bI]; - if(isSatisfiedCombo(binding.keyCombo) === false) { - for(cI = 0; cI < binding.keyUpCallback.length; cI += 1) { - if (binding.keyUpCallback[cI](event, getActiveKeys(), binding.keyCombo) === false) { - killEventBubble = true; - } - } - if(killEventBubble === true) { - event.preventDefault(); - event.stopPropagation(); - } - activeBindings.splice(bI, 1); - bI -= 1; - } - } - } - - - /////////////////// - // COMBO STRINGS // - /////////////////// - - /** - * Compares two key combos returning true when they are functionally - * equivalent. - * @param {String} keyComboArrayA keyCombo A key combo string or array. - * @param {String} keyComboArrayB keyCombo A key combo string or array. - * @return {Boolean} - */ - function compareCombos(keyComboArrayA, keyComboArrayB) { - var cI, sI, kI; - keyComboArrayA = parseKeyCombo(keyComboArrayA); - keyComboArrayB = parseKeyCombo(keyComboArrayB); - if(keyComboArrayA.length !== keyComboArrayB.length) { return false; } - for(cI = 0; cI < keyComboArrayA.length; cI += 1) { - if(keyComboArrayA[cI].length !== keyComboArrayB[cI].length) { return false; } - for(sI = 0; sI < keyComboArrayA[cI].length; sI += 1) { - if(keyComboArrayA[cI][sI].length !== keyComboArrayB[cI][sI].length) { return false; } - for(kI = 0; kI < keyComboArrayA[cI][sI].length; kI += 1) { - if(keyComboArrayB[cI][sI].indexOf(keyComboArrayA[cI][sI][kI]) === -1) { return false; } - } - } - } - return true; - } - - /** - * Checks to see if a key combo string or key array is satisfied by the - * currently active keys. It does not take into account spent keys. - * @param {String} keyCombo A key combo string or array. - * @return {Boolean} - */ - function isSatisfiedCombo(keyCombo) { - var cI, sI, stage, kI, stageOffset = 0, index, comboMatches; - keyCombo = parseKeyCombo(keyCombo); - for(cI = 0; cI < keyCombo.length; cI += 1) { - comboMatches = true; - stageOffset = 0; - for(sI = 0; sI < keyCombo[cI].length; sI += 1) { - stage = [].concat(keyCombo[cI][sI]); - for(kI = stageOffset; kI < activeKeys.length; kI += 1) { - index = stage.indexOf(activeKeys[kI]); - if(index > -1) { - stage.splice(index, 1); - stageOffset = kI; - } - } - if(stage.length !== 0) { comboMatches = false; break; } - } - if(comboMatches) { return true; } - } - return false; - } - - /** - * Accepts a key combo array or string and returns a flat array containing all keys referenced by - * the key combo. - * @param {String} keyCombo A key combo string or array. - * @return {Array} - */ - function extractComboKeys(keyCombo) { - var cI, sI, kI, keys = []; - keyCombo = parseKeyCombo(keyCombo); - for(cI = 0; cI < keyCombo.length; cI += 1) { - for(sI = 0; sI < keyCombo[cI].length; sI += 1) { - keys = keys.concat(keyCombo[cI][sI]); - } - } - return keys; - } - - /** - * Parses a key combo string into a 3 dimensional array. - * - Level 1 - sub combos. - * - Level 2 - combo stages. A stage is a set of key name pairs that must - * be satisfied in the order they are defined. - * - Level 3 - each key name to the stage. - * @param {String|Array} keyCombo A key combo string. - * @return {Array} - */ - function parseKeyCombo(keyCombo) { - var s = keyCombo, i = 0, op = 0, ws = false, nc = false, combos = [], combo = [], stage = [], key = ''; - - if(typeof keyCombo === 'object' && typeof keyCombo.push === 'function') { return keyCombo; } - if(typeof keyCombo !== 'string') { throw new Error('Cannot parse "keyCombo" because its type is "' + (typeof keyCombo) + '". It must be a "string".'); } - - //remove leading whitespace - while(s.charAt(i) === ' ') { i += 1; } - while(true) { - if(s.charAt(i) === ' ') { - //white space & next combo op - while(s.charAt(i) === ' ') { i += 1; } - ws = true; - } else if(s.charAt(i) === ',') { - if(op || nc) { throw new Error('Failed to parse key combo. Unexpected , at character index ' + i + '.'); } - nc = true; - i += 1; - } else if(s.charAt(i) === '+') { - //next key - if(key.length) { stage.push(key); key = ''; } - if(op || nc) { throw new Error('Failed to parse key combo. Unexpected + at character index ' + i + '.'); } - op = true; - i += 1; - } else if(s.charAt(i) === '>') { - //next stage op - if(key.length) { stage.push(key); key = ''; } - if(stage.length) { combo.push(stage); stage = []; } - if(op || nc) { throw new Error('Failed to parse key combo. Unexpected > at character index ' + i + '.'); } - op = true; - i += 1; - } else if(i < s.length - 1 && s.charAt(i) === '!' && (s.charAt(i + 1) === '>' || s.charAt(i + 1) === ',' || s.charAt(i + 1) === '+')) { - key += s.charAt(i + 1); - op = false; - ws = false; - nc = false; - i += 2; - } else if(i < s.length && s.charAt(i) !== '+' && s.charAt(i) !== '>' && s.charAt(i) !== ',' && s.charAt(i) !== ' ') { - //end combo - if(op === false && ws === true || nc === true) { - if(key.length) { stage.push(key); key = ''; } - if(stage.length) { combo.push(stage); stage = []; } - if(combo.length) { combos.push(combo); combo = []; } - } - op = false; - ws = false; - nc = false; - //key - while(i < s.length && s.charAt(i) !== '+' && s.charAt(i) !== '>' && s.charAt(i) !== ',' && s.charAt(i) !== ' ') { - key += s.charAt(i); - i += 1; - } - } else { - //unknown char - i += 1; - continue; - } - //end of combos string - if(i >= s.length) { - if(key.length) { stage.push(key); key = ''; } - if(stage.length) { combo.push(stage); stage = []; } - if(combo.length) { combos.push(combo); combo = []; } - break; - } - } - return combos; - } - - /** - * Stringifys a key combo. - * @param {Array|String} keyComboArray A key combo array. If a key - * combo string is given it will be returned. - * @return {String} - */ - function stringifyKeyCombo(keyComboArray) { - var cI, ccI, output = []; - if(typeof keyComboArray === 'string') { return keyComboArray; } - if(typeof keyComboArray !== 'object' || typeof keyComboArray.push !== 'function') { throw new Error('Cannot stringify key combo.'); } - for(cI = 0; cI < keyComboArray.length; cI += 1) { - output[cI] = []; - for(ccI = 0; ccI < keyComboArray[cI].length; ccI += 1) { - output[cI][ccI] = keyComboArray[cI][ccI].join(' + '); - } - output[cI] = output[cI].join(' > '); - } - return output.join(' '); - } - - - ///////////////// - // ACTIVE KEYS // - ///////////////// - - /** - * Returns the a copy of the active keys array. - * @return {Array} - */ - function getActiveKeys() { - return [].concat(activeKeys); - } - - /** - * Adds a key to the active keys array, but only if it has not already been - * added. - * @param {String} keyName The key name string. - */ - function addActiveKey(keyName) { - if(keyName.match(/\s/)) { throw new Error('Cannot add key name ' + keyName + ' to active keys because it contains whitespace.'); } - if(activeKeys.indexOf(keyName) > -1) { return; } - activeKeys.push(keyName); - } - - /** - * Removes a key from the active keys array. - * @param {String} keyNames The key name string. - */ - function removeActiveKey(keyName) { - var keyCode = getKeyCode(keyName); - if(keyCode === '91' || keyCode === '92') { activeKeys = []; } //remove all key on release of super. - else { activeKeys.splice(activeKeys.indexOf(keyName), 1); } - } - - - ///////////// - // LOCALES // - ///////////// - - /** - * Registers a new locale. This is useful if you would like to add support for a new keyboard layout. It could also be useful for - * alternative key names. For example if you program games you could create a locale for your key mappings. Instead of key 65 mapped - * to 'a' you could map it to 'jump'. - * @param {String} localeName The name of the new locale. - * @param {Object} localeMap The locale map. - */ - function registerLocale(localeName, localeMap) { - - //validate arguments - if(typeof localeName !== 'string') { throw new Error('Cannot register new locale. The locale name must be a string.'); } - if(typeof localeMap !== 'object') { throw new Error('Cannot register ' + localeName + ' locale. The locale map must be an object.'); } - if(typeof localeMap.map !== 'object') { throw new Error('Cannot register ' + localeName + ' locale. The locale map is invalid.'); } - - //stash the locale - if(!localeMap.macros) { localeMap.macros = []; } - locales[localeName] = localeMap; - } - - /** - * Swaps the current locale. - * @param {String} localeName The locale to activate. - * @return {Object} - */ - function getSetLocale(localeName) { - - //if a new locale is given then set it - if(localeName) { - if(typeof localeName !== 'string') { throw new Error('Cannot set locale. The locale name must be a string.'); } - if(!locales[localeName]) { throw new Error('Cannot set locale to ' + localeName + ' because it does not exist. If you would like to submit a ' + localeName + ' locale map for KeyboardJS please submit it at https://github.com/RobertWHurst/KeyboardJS/issues.'); } - - //set the current map and macros - map = locales[localeName].map; - macros = locales[localeName].macros; - - //set the current locale - locale = localeName; - } - - //return the current locale - return locale; - } -}); diff --git a/packages/chatroom/client/external/webfonts.js b/packages/chatroom/client/external/webfonts.js deleted file mode 100644 index 4afcfb6..0000000 --- a/packages/chatroom/client/external/webfonts.js +++ /dev/null @@ -1,11 +0,0 @@ -WebFontConfig = { - google: { families: [ 'Lato::latin' ] } -}; -(function() { - var wf = document.createElement('script'); - wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js'; - wf.type = 'text/javascript'; - wf.async = 'true'; - var s = document.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(wf, s); -})(); diff --git a/packages/chatroom/client/lib/helpers.js b/packages/chatroom/client/lib/helpers.js deleted file mode 100644 index f3b5c80..0000000 --- a/packages/chatroom/client/lib/helpers.js +++ /dev/null @@ -1,3 +0,0 @@ -UI.registerHelper('defaultProfilePicture', function () { - return Superchat.defaultProfilePicture; -}); diff --git a/packages/chatroom/client/stylesheets/superchat.less b/packages/chatroom/client/stylesheets/superchat.less deleted file mode 100644 index 9ab130b..0000000 --- a/packages/chatroom/client/stylesheets/superchat.less +++ /dev/null @@ -1,142 +0,0 @@ -.no-padding { - padding: 0 !important; -} - -.send-msg { - cursor: pointer; - height: 34px; - width: 100%; -} - -/*#chat-messages-box { - height: 70%; - margin-bottom: 5px; -}*/ - -#messages { - font-family: 'Lato', sans-serif; - height: 100%; - border: 2px black solid; - overflow: scroll; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - border: 3px solid #cccccc; - background-color: #DFDFDF; - padding-right: 8px; - padding-bottom: 8px; - position: relative; - p { - font-size: 13px; - margin-bottom: 1px; - margin-top: 1px; - } - a { - text-decoration: none; - } - img { - height: 30px; - } - input { - height: 20px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - border: 3px solid #cccccc; - margin-top: 5px; - margin-left: 0; - margin-bottom: 0; - margin-right: 0; - } - hr { - margin: 0; - padding: 0; - } - .border-radius (@radius) { - border-radius: @radius; - -moz-border-radius: @radius; - -webkit-border-radius: @radius; - } - .img-circle { - .border-radius(500px); // crank the border-radius so it works with most reasonably sized images - border: 1px solid rgba(0, 0, 0, 0.2); - } -} - -#chat-info { - margin-top: 5px; - - .messages-counter { - line-height: 30px; - padding: 0; - } - - .online-users { - padding: 0; - } -} - -#msg-input { - margin-top: 5px; -} - -#scroll-to-bottom { - position: absolute; - text-align: center; - background-color: green; -} - -#msg { - height: 90px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - border: 3px solid #cccccc; - margin-top: 5px; - margin-left: 0; - margin-bottom: 0; - margin-right: 0; - float: left; -} - -#chat-wrapper { - position: relative; - h3 { - margin-top: 0px; - } -} - -#users-list { - position: absolute; - background-color: rgba(189, 189, 189, 0.93); - right: 146px; - bottom: -141px; - height: 145px; - width: 175px; - overflow: hidden; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - - h5 { - margin-left: 25px; - } - - ul { - list-style: none; - margin: 0; - padding: 0; - margin-left: 15px; - - li { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - margin-top: 5px; - } - img { - height: 25px; - margin-right: 5px; - } - } -} diff --git a/packages/chatroom/client/views/chatroom.html b/packages/chatroom/client/views/chatroom.html deleted file mode 100644 index 500bc22..0000000 --- a/packages/chatroom/client/views/chatroom.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - Chat - - - - {{#each msgs}} - - {{#with getProfile owner}} - {{#if name.givenName}}{{name.givenName}} {{name.familyName}}{{else}}{{displayName}}{{/if}} - {{/with}} - {{action}}: - - - {{msg}} - - {{/each}} - - - - - - - - - 500 - - - - - - - Send - - - - - - Users online - - {{#each onlineUsers}} - {{#with superchat}} - {{$or name.givenName ../profile.name}} {{name.familyName}} - {{/with}} - {{/each}} - - - - - diff --git a/packages/chatroom/client/views/chatroom.js b/packages/chatroom/client/views/chatroom.js deleted file mode 100644 index 410b66c..0000000 --- a/packages/chatroom/client/views/chatroom.js +++ /dev/null @@ -1,212 +0,0 @@ - -superChatMsgs = new Meteor.Collection(null); -superChatStream = new Meteor.Stream('superChatStream'); - -/* - * Streams - */ - -superChatStream.on('chat', function (message, host, action) { - if (arguments.length === 0) { - return; - } - - superChatMsgs.insert({ - msg: message, - owner: this.userId, - host: host, - action: action, - time: new Date() - }); - Template.chatroom.scrollToBottom(); - Template.chatroom.removeLastMessage(); -}); - -/* - * UI - */ - -Template.chatroom.scrollToBottom = function () { - _.defer(function() { - var chat = $('#messages'); - chat.scrollTop(chat.get(0).scrollHeight); - }); -}; - -Template.chatroom.removeLastMessage = function () { - var allMessages = superChatMsgs.find().fetch(); - - if (allMessages.length >= Superchat.messageLimitOnScreen) { - var lastMessage = allMessages[0]; - superChatMsgs.remove(lastMessage._id); - } -}; - -Template.chatroom.sendMsg = function () { - var user = Meteor.user(); - if (! user || - (user.superchat && typeof user.superchat.canChat !== 'undefined' && !user.superchat.canChat)) { - return; - } - - var $msg = $('#msg-input textarea'), - message = $msg.val(); - - $msg.val(''); - - if (! message) { - return; - } - - var owner = Meteor.userId(), - action = 'says', - coder = Session.get('coder'), - host = coder._id; - - Template.chatroom.removeLastMessage(); - superChatMsgs.insert({ - msg: message, - owner: owner, - host: host, - action: action, - time: new Date() - }); - superChatStream.emit('chat', message, host); - Template.chatroom.scrollToBottom(); - -}; - -Template.chatroom.insertAtCaret = function(txtarea, text) { - // got from here http://stackoverflow.com/questions/1064089/inserting-a-text-where-cursor-is-using-javascript-jquery - var scrollPos = txtarea.scrollTop; - var strPos = 0; - var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? "ff" : (document.selection ? "ie" : false ) ); - if (br == "ie") { - txtarea.focus(); - var range = document.selection.createRange(); - range.moveStart('character', -txtarea.value.length); - strPos = range.text.length; - } else if (br == "ff") - strPos = txtarea.selectionStart; - - var front = (txtarea.value).substring(0, strPos); - var back = (txtarea.value).substring(strPos, txtarea.value.length); - txtarea.value = front + text + back; - strPos = strPos + text.length; - if (br == "ie") { - txtarea.focus(); - var range = document.selection.createRange(); - range.moveStart('character', -txtarea.value.length); - range.moveStart('character', strPos); - range.moveEnd('character', 0); - range.select(); - } else if (br == "ff") { - txtarea.selectionStart = strPos; - txtarea.selectionEnd = strPos; - txtarea.focus(); - } - txtarea.scrollTop = scrollPos; -}; - -Template.chatroom.rendered = function () { - var self = this; - - _.defer(function () { - self.$('#messages, #users-list').niceScroll({ - autohidemode: false, - cursoropacitymin: 0.3, - cursoropacitymax: 0.3 - }); - }); - - self.banDeps = Deps.autorun(function banUserWhenFlood () { - if (! Session.equals('chatSubsReady', true)) { - return; - } - - var user = Meteor.user(); - var $msg = $('#msg-input textarea'); - var $sendMsgButton = $('.send-msg'); - - if (user && user.superchat && user.superchat.canChat === false) { - $msg.attr('disabled', 'disabled'); - $msg.val('You are banned due to flooding.'); - $sendMsgButton.attr('disabled', 'disabled'); - } else { - $msg.removeAttr('disabled'); - $msg.val(''); - $sendMsgButton.removeAttr('disabled'); - } - }); -}; - -Template.chatroom.destroyed = function () { - var self = this; - - self.$('#messages, #users-list').getNiceScroll().hide(); - - self.banDeps.stop(); -}; - -Template.chatroom.helpers({ - msgs: function () { - var coder = Session.get('coder'); - return superChatMsgs.find({host: coder._id}, {limit: Superchat.messageLimitOnScreen}); - }, - getProfile: function (userId) { - return userId && Meteor.users.findOne({_id: userId}).superchat; - }, - onlineUsers: function () { - var presences = Meteor.presences.find({userId: {$exists: true}}).fetch(), - ids = _.pluck(presences, 'userId'), - query = []; - - if (_.isEmpty(ids)) - return; - - query = ids.map(function (id) { - return { _id: id }; - }); - - window.QUERY = query; - return Meteor.users.find({ $or: query }); - } -}); - -Template.chatroom.events({ - 'click .send-msg': function () { - Template.chatroom.sendMsg(); - }, - 'keyup #msg-input textarea': function (event, t) { - var target = event.target, - len = target.value.length; - - if (len > 500) { - target.value = target.value.substring(0, 500); - } else { - t.$('.messages-counter').text(500 - len); - } - }, - 'click #chat-info .online-users button' : function (e, t) { - t.$('#users-list').toggle(); - }, - 'focus #msg-input textarea': function (event, t) { - var self = event.target; - KeyboardJS.on('shift + enter', function(){ - Template.chatroom.insertAtCaret(self, '\n'); - return false; - }); - - KeyboardJS.on('enter', function () { - if (t.$(self).attr('disabled') !== 'disabled') - Template.chatroom.sendMsg(); - return false; - }); - }, - 'blur #msg-input textarea': function (event) { - KeyboardJS.clear('enter'); - KeyboardJS.clear('shift + enter'); - } -}); - - diff --git a/packages/chatroom/lib/common.js b/packages/chatroom/lib/common.js deleted file mode 100644 index ff51b27..0000000 --- a/packages/chatroom/lib/common.js +++ /dev/null @@ -1,7 +0,0 @@ - -if (typeof Superchat === 'undefined') { - Superchat = {}; - Superchat.messageLimitOnScreen = 15; - Superchat.defaultProfilePicture = 'http://i.imgur.com/HKSh9X9.png'; -} - diff --git a/packages/chatroom/package.js b/packages/chatroom/package.js deleted file mode 100644 index 84d5005..0000000 --- a/packages/chatroom/package.js +++ /dev/null @@ -1,50 +0,0 @@ -Package.describe({ - summary: "Chat with Github Flavored Markdown and social login using Meteor Streams" -}); - -Package.on_use(function (api, where) { - var both = ['client', 'server']; - api.use([ - 'meteor', - 'standard-app-packages', - 'presence', - 'streams' - ], both); - - api.use([ - 'deps', - 'startup', - 'session', - 'templating', - 'less', - 'jquery', - 'marked', - ], 'client'); - - api.add_files([ - 'lib/common.js' - ], both); - - api.add_files([ - 'client/lib/helpers.js', - 'client/stylesheets/superchat.less', - 'client/views/chatroom.html', - 'client/views/chatroom.js' - ], 'client'); - api.add_files([ - 'client/compatibility/jquery.nicescroll.min.js', - 'client/compatibility/keyboard.js' - ], 'client', {raw: true}); - - api.add_files([ - 'server/publications.js', - 'server/unban.js' - ], 'server'); - - if (typeof api.export !== 'undefined') { - api.imply('reactive-path'); - api.imply('publish-composite'); - api.export('Superchat', both); - } - -}); diff --git a/packages/chatroom/server/publications.js b/packages/chatroom/server/publications.js deleted file mode 100644 index 375dfa4..0000000 --- a/packages/chatroom/server/publications.js +++ /dev/null @@ -1,58 +0,0 @@ -superChatStream = new Meteor.Stream('superChatStream'); - -superChatStream.permissions.read(function (eventName) { - return true; -}); - -superChatStream.permissions.write(function (eventName) { - if (! this.userId) { - return false; - } - - var user = Meteor.users.findOne({_id: this.userId}); - if (! user.superchat) { - user.superchat = {}; - Meteor.users.update({_id: user._id}, {$set: {superchat: {}}}); - } - - return true; -}); - -superChatStream.addFilter(function (eventName, args) { - var user = Meteor.users.findOne({_id: this.userId}), - message = args[0]; - - if (! this.userId || - (typeof user.superchat.canChat !== 'undefined' && !user.superchat.canChat), - message.length === 0) { - return []; - } - - var messagesInRow = user.superchat.messagesInRow, - lastMessageOn = user.superchat.lastMessageOn, - now = +(new Date()); - - if (messagesInRow >= 3) { - if (now - lastMessageOn <= 1000) { - Meteor.users.update({_id: user._id}, { - $set: { - 'superchat.lastMessageOn': +(new Date()), - 'superchat.canChat': false, - 'superchat.whenCanChat': now + (60 * 1000) - } - }); - } else { - Meteor.users.update({_id: user._id}, { - $set: {'superchat.lastMessageOn': +(new Date()), 'superchat.messagesInRow': 1} - }); - } - } else { - Meteor.users.update({_id: user._id}, { - $set: {'superchat.lastMessageOn': +(new Date())}, - $inc: {'superchat.messagesInRow': 1} - }); - } - - args.push('says'); - return args; -}); diff --git a/packages/chatroom/server/unban.js b/packages/chatroom/server/unban.js deleted file mode 100644 index de2fc09..0000000 --- a/packages/chatroom/server/unban.js +++ /dev/null @@ -1,12 +0,0 @@ -Meteor.setInterval(function () { - Meteor.users.find({'superchat.canChat': false}).forEach(function (user) { - var now = +(new Date()); - if (user.superchat.whenCanChat >= now) { - return; - } - - Meteor.users.update({_id: user._id}, { - $set: {'superchat.canChat': true, 'superchat.messagesInRow': 0} - }); - }); -}, 1000) diff --git a/packages/chatroom/smart.json b/packages/chatroom/smart.json deleted file mode 100644 index 364e25b..0000000 --- a/packages/chatroom/smart.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "superchat-streams", - "description": "Chat with Github Flavored Markdown and social login using Meteor Streams", - "homepage": "https://github.com/gabrielhpugliese/meteor_superchat_streams", - "author": "Gabriel Henrique Pugliese ", - "version": "0.5.4", - "git": "https://github.com/gabrielhpugliese/meteor_superchat_streams", - "packages": { - "presence": {}, - "streams": {} - } -} diff --git a/packages/npm-container/.npm/package/.gitignore b/packages/npm-container/.npm/package/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/packages/npm-container/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/npm-container/.npm/package/README b/packages/npm-container/.npm/package/README new file mode 100644 index 0000000..3d49255 --- /dev/null +++ b/packages/npm-container/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/npm-container/.npm/package/npm-shrinkwrap.json b/packages/npm-container/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000..1ac2f6d --- /dev/null +++ b/packages/npm-container/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,170 @@ +{ + "dependencies": { + "bitpay-node": { + "version": "0.0.4", + "dependencies": { + "request": { + "version": "2.53.0", + "dependencies": { + "bl": { + "version": "0.9.4", + "dependencies": { + "readable-stream": { + "version": "1.0.33", + "dependencies": { + "core-util-is": { + "version": "1.0.1" + }, + "isarray": { + "version": "0.0.1" + }, + "string_decoder": { + "version": "0.10.31" + }, + "inherits": { + "version": "2.0.1" + } + } + } + } + }, + "caseless": { + "version": "0.9.0" + }, + "forever-agent": { + "version": "0.5.2" + }, + "form-data": { + "version": "0.2.0", + "dependencies": { + "async": { + "version": "0.9.0" + } + } + }, + "json-stringify-safe": { + "version": "5.0.0" + }, + "mime-types": { + "version": "2.0.9", + "dependencies": { + "mime-db": { + "version": "1.7.0" + } + } + }, + "node-uuid": { + "version": "1.4.2" + }, + "qs": { + "version": "2.3.3" + }, + "tunnel-agent": { + "version": "0.4.0" + }, + "tough-cookie": { + "version": "0.12.1", + "dependencies": { + "punycode": { + "version": "1.3.2" + } + } + }, + "http-signature": { + "version": "0.10.1", + "dependencies": { + "assert-plus": { + "version": "0.1.5" + }, + "asn1": { + "version": "0.1.11" + }, + "ctype": { + "version": "0.5.3" + } + } + }, + "oauth-sign": { + "version": "0.6.0" + }, + "hawk": { + "version": "2.3.1", + "dependencies": { + "hoek": { + "version": "2.11.1" + }, + "boom": { + "version": "2.6.1" + }, + "cryptiles": { + "version": "2.0.4" + }, + "sntp": { + "version": "1.0.9" + } + } + }, + "aws-sign2": { + "version": "0.5.0" + }, + "stringstream": { + "version": "0.0.4" + }, + "combined-stream": { + "version": "0.0.7", + "dependencies": { + "delayed-stream": { + "version": "0.0.5" + } + } + }, + "isstream": { + "version": "0.1.1" + } + } + } + } + }, + "crypto-js": { + "version": "3.1.2-1" + }, + "debug": { + "version": "0.7.2" + }, + "googleapis": { + "version": "0.2.12-alpha", + "dependencies": { + "request": { + "version": "2.14.0", + "dependencies": { + "form-data": { + "version": "0.0.7", + "dependencies": { + "combined-stream": { + "version": "0.0.4", + "dependencies": { + "delayed-stream": { + "version": "0.0.5" + } + } + }, + "async": { + "version": "0.1.22" + } + } + }, + "mime": { + "version": "1.2.9" + } + } + }, + "async": { + "version": "0.2.6" + } + } + }, + "moment": { + "version": "1.0.0" + } + } +} diff --git a/packages/npm-container/index.js b/packages/npm-container/index.js new file mode 100644 index 0000000..1025083 --- /dev/null +++ b/packages/npm-container/index.js @@ -0,0 +1,9 @@ + Meteor.npmRequire = function(moduleName) { // 85 + var module = Npm.require(moduleName); // 86 + return module; // 87 + }; // 88 + // 89 + Meteor.require = function(moduleName) { // 90 + console.warn('Meteor.require is deprecated. Please use Meteor.npmRequire instead!'); // 91 + return Meteor.npmRequire(moduleName); // 92 + }; // 93 \ No newline at end of file diff --git a/packages/npm-container/package.js b/packages/npm-container/package.js new file mode 100644 index 0000000..91eaf73 --- /dev/null +++ b/packages/npm-container/package.js @@ -0,0 +1,21 @@ + var path = Npm.require('path'); // 97 + var fs = Npm.require('fs'); // 98 + // 99 + Package.describe({ // 100 + summary: 'Contains all your npm dependencies', // 101 + version: '1.0.0', // 102 + name: 'npm-container' // 103 + }); // 104 + // 105 + var packagesJsonFile = path.resolve('./packages.json'); // 106 + try { // 107 + var fileContent = fs.readFileSync(packagesJsonFile); // 108 + var packages = JSON.parse(fileContent.toString()); // 109 + Npm.depends(packages); // 110 + } catch(ex) { // 111 + console.error('ERROR: packages.json parsing error [ ' + ex.message + ' ]'); // 112 + } // 113 + // 114 + Package.onUse(function(api) { // 115 + api.add_files(['index.js', '../../packages.json'], 'server'); // 116 + }); // 117 \ No newline at end of file diff --git a/packages/shareit/.gitignore b/packages/shareit/.gitignore deleted file mode 100644 index 677a6fc..0000000 --- a/packages/shareit/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.build* diff --git a/packages/shareit/.travis.yml b/packages/shareit/.travis.yml deleted file mode 100644 index d826297..0000000 --- a/packages/shareit/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/ejPSng | /bin/sh" diff --git a/packages/shareit/LICENSE b/packages/shareit/LICENSE deleted file mode 100644 index 869e61e..0000000 --- a/packages/shareit/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Differential - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/shareit/README.md b/packages/shareit/README.md deleted file mode 100644 index 58f3046..0000000 --- a/packages/shareit/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Share it - -We've built social sharing buttons a few times and decided it was time to extract it to a package! The goal of this package is to do a few things: - -* Render proper OG and Twitter meta tags -* Support social sharing buttons with bootstrap-3 and font-awesome -* Expand to support other social platforms besides just twitter & facebook, in a configurable way - -See more in our [documentation](http://github.differential.io/shareit/) - diff --git a/packages/shareit/client/views/facebook/facebook.coffee b/packages/shareit/client/views/facebook/facebook.coffee deleted file mode 100644 index 1f0e001..0000000 --- a/packages/shareit/client/views/facebook/facebook.coffee +++ /dev/null @@ -1,38 +0,0 @@ -Template.shareit_fb.rendered = -> - return unless @data - $('meta[property^="og:"]').remove() - - # - # OpenGraph tags - # - - $('', { property: 'og:type', content: 'article' }).appendTo 'head' - $('', { property: 'og:site_name', content: location.hostname }).appendTo 'head' - $('', { property: 'og:url', content: location.origin + location.pathname }).appendTo 'head' - $('', { property: 'og:title', content: "#{@data.title}" }).appendTo 'head' - $('', { property: 'og:description', content: @data.excerpt }).appendTo 'head' - - if @data.thumbnail - img = @data.thumbnail() - if img - if not /^http(s?):\/\/+/.test(img) - img = location.origin + img - $('', { property: 'og:image', content: img }).appendTo 'head' - - - # - # Facebook share button - # - - preferred_url = @data.url || location.origin + location.pathname - url = encodeURIComponent preferred_url - - base = "https://www.facebook.com/sharer/sharer.php" - title = encodeURIComponent @data.title - summary = encodeURIComponent @data.excerpt - href = base + "?s=100&p[url]=" + url + "&p[title]=" + title + "&p[summary]=" + summary - - if img - href += "&p[images][0]=" + encodeURIComponent img - - @$(".fb-share").attr "href", href diff --git a/packages/shareit/client/views/facebook/facebook.html b/packages/shareit/client/views/facebook/facebook.html deleted file mode 100644 index 6d1d95e..0000000 --- a/packages/shareit/client/views/facebook/facebook.html +++ /dev/null @@ -1,3 +0,0 @@ - - Share on Facebook - diff --git a/packages/shareit/client/views/google/google.coffee b/packages/shareit/client/views/google/google.coffee deleted file mode 100644 index c5fda01..0000000 --- a/packages/shareit/client/views/google/google.coffee +++ /dev/null @@ -1,10 +0,0 @@ -Template.shareit_google.rendered = () -> - return unless @data - - # - # Google share button - # - - preferred_url = @data.url || location.origin + location.pathname - href = "https://plus.google.com/share?url=#{preferred_url}" - @$(".google-share").attr "href", href diff --git a/packages/shareit/client/views/google/google.html b/packages/shareit/client/views/google/google.html deleted file mode 100644 index 67787fa..0000000 --- a/packages/shareit/client/views/google/google.html +++ /dev/null @@ -1,6 +0,0 @@ - - - Share on Google+ - - diff --git a/packages/shareit/client/views/social.coffee b/packages/shareit/client/views/social.coffee deleted file mode 100644 index 9eb1d77..0000000 --- a/packages/shareit/client/views/social.coffee +++ /dev/null @@ -1,10 +0,0 @@ -Template.shareit.helpers({ - useFB: () -> - ShareIt.settings.useFB - - useTwitter: () -> - ShareIt.settings.useTwitter - - useGoogle: () -> - ShareIt.settings.useGoogle -}) diff --git a/packages/shareit/client/views/social.html b/packages/shareit/client/views/social.html deleted file mode 100644 index 5f5f5c6..0000000 --- a/packages/shareit/client/views/social.html +++ /dev/null @@ -1,15 +0,0 @@ - - - {{#if useFB}} - {{> shareit_fb}} - {{/if}} - - {{#if useTwitter}} - {{> shareit_twitter}} - {{/if}} - - {{#if useGoogle}} - {{> shareit_google}} - {{/if}} - - diff --git a/packages/shareit/client/views/social.less b/packages/shareit/client/views/social.less deleted file mode 100644 index 80ba51c..0000000 --- a/packages/shareit/client/views/social.less +++ /dev/null @@ -1,20 +0,0 @@ -.share-buttons { - .btn { - font-size: 16px; - } - - .fb-share { - background: #3B5998; - color: #fff; - } - - .tw-share { - color: #fff; - background: #4099FF; - } - - .google-share { - color: #fff; - background: #D34836; - } -} diff --git a/packages/shareit/client/views/twitter/twitter.coffee b/packages/shareit/client/views/twitter/twitter.coffee deleted file mode 100644 index 5253bbd..0000000 --- a/packages/shareit/client/views/twitter/twitter.coffee +++ /dev/null @@ -1,43 +0,0 @@ -Template.shareit_twitter.rendered = -> - return unless @data - $('meta[property^="twitter:"]').remove() - - if @data.thumbnail - img = @data.thumbnail() - if img - if not /^http(s?):\/\/+/.test(img) - img = location.origin + img - - # - # Twitter cards - # - - $('', { property: 'twitter:card', content: 'summary' }).appendTo 'head' - # What should go here? - #$('', { property: 'twitter:site', content: '' }).appendTo 'head' - - if @data.author - author = @data.author() - if author and author.profile and author.profile.twitter - $('', { property: 'twitter:creator', content: author.profile.twitter }).appendTo 'head' - - $('', { property: 'twitter:url', content: location.origin + location.pathname }).appendTo 'head' - $('', { property: 'twitter:title', content: "#{@data.title}" }).appendTo 'head' - $('', { property: 'twitter:description', content: @data.excerpt }).appendTo 'head' - $('', { property: 'twitter:image:src', content: img }).appendTo 'head' - - # - # Twitter share button - # - - preferred_url = @data.url || location.origin + location.pathname - url = encodeURIComponent preferred_url - - base = "https://twitter.com/intent/tweet" - text = encodeURIComponent @data.title - href = base + "?url=" + url + "&text=" + text - - if author and author.profile and author.profile.twitter - href += "&via=" + author.profile.twitter - - @$(".tw-share").attr "href", href diff --git a/packages/shareit/client/views/twitter/twitter.html b/packages/shareit/client/views/twitter/twitter.html deleted file mode 100644 index 9bffa94..0000000 --- a/packages/shareit/client/views/twitter/twitter.html +++ /dev/null @@ -1,5 +0,0 @@ - - - Share on Twitter - - diff --git a/packages/shareit/package.js b/packages/shareit/package.js deleted file mode 100644 index 02e9fee..0000000 --- a/packages/shareit/package.js +++ /dev/null @@ -1,26 +0,0 @@ -Package.describe({ - summary: 'A meteorite package that makes social sharing easy', - git: 'https://github.com/Differential/shareit', - version: '0.1.0' -}); - -Package.on_use(function(api) { - api.use(['coffeescript', 'less', 'templating', 'underscore'], 'client'); - - - api.imply('spiderable', ['client', 'server']); - api.add_files([ - 'shareit.coffee', - 'client/views/social.html', - 'client/views/social.coffee', - 'client/views/social.less', - 'client/views/facebook/facebook.html', - 'client/views/facebook/facebook.coffee', - 'client/views/twitter/twitter.html', - 'client/views/twitter/twitter.coffee', - 'client/views/google/google.html', - 'client/views/google/google.coffee' - ], 'client'); - - //api.export('Shareit', 'client'); -}); diff --git a/packages/shareit/packages/.gitignore b/packages/shareit/packages/.gitignore deleted file mode 100644 index 9b359f5..0000000 --- a/packages/shareit/packages/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/shareit -/phantomjs diff --git a/packages/shareit/shareit.coffee b/packages/shareit/shareit.coffee deleted file mode 100644 index 33b5bb8..0000000 --- a/packages/shareit/shareit.coffee +++ /dev/null @@ -1,38 +0,0 @@ -@ShareIt = { - settings: { - useFB: true, - useTwitter: true, - useGoogle: true - } - configure: (hash) -> - @settings = $.extend(@settings, hash) -} - -Meteor.startup -> - - # Twitter - window.twttr = do (d = document, s = 'script', id = 'twitter-wjs') -> - t = undefined - js = undefined - fjs = d.getElementsByTagName(s)[0] - return if d.getElementById(id) - js = d.createElement(s) - js.id = id - js.src = "https://platform.twitter.com/widgets.js" - fjs.parentNode.insertBefore js, fjs - window.twttr or (t = - _e: [] - ready: (f) -> - t._e.push f - ) - - # Facebook - js = undefined - id = "facebook-jssdk" - ref = document.getElementsByTagName("script")[0] - return if document.getElementById(id) - js = document.createElement("script") - js.id = id - js.async = true - js.src = "//connect.facebook.net/en_US/all.js" - ref.parentNode.insertBefore js, ref diff --git a/packages/shareit/smart.json b/packages/shareit/smart.json deleted file mode 100644 index e8cdfc7..0000000 --- a/packages/shareit/smart.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "shareit", - "description": "A meteorite package that makes social sharing easy", - "homepage": "https://github.com/Differential/shareit", - "author": "Differential (http://differential.io)", - "version": "0.1.0", - "git": "https://github.com/Differential/shareit.git", - "packages": { - "phantomjs": {} - } -} diff --git a/packages/shareit/tests/client.html b/packages/shareit/tests/client.html deleted file mode 100644 index 418fced..0000000 --- a/packages/shareit/tests/client.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - {{> shareit}} - - - -{{> shareit dataContext}} - diff --git a/packages/shareit/tests/client.js b/packages/shareit/tests/client.js deleted file mode 100644 index aaddc0d..0000000 --- a/packages/shareit/tests/client.js +++ /dev/null @@ -1,37 +0,0 @@ -Template.test_helper_shareit_with_data.dataContext = function() { - return {title: 'Test title'} -} - -renderToDiv = function(comp) { - div = document.createElement("DIV"); - UI.materialize(comp, div); - return div; -}; - -Tinytest.add("ShareIt - {{> shareit}} template renders", function(test) { - div = renderToDiv(Template.test_helper_shareit) - html = canonicalizeHtml(div.innerHTML) - test.include(html, "Share on Facebook") - test.include(html, "Share on Twitter") -}); - -Tinytest.add("ShareIt - {{> shareit}} template doesn't throw an exception from the rendered function", function(test) { - try { - Template.shareit.rendered() - } catch (e) { - console.log(e) - test.fail('The rendered function should not throw an error without data.') - } -}); - -Tinytest.addAsync("ShareIt - {{> shareit}} template renders valid share links", function(test, done) { - div = renderToDiv(Template.test_helper_shareit_with_data) - // This feels like a punt, should investigate more - Meteor.setTimeout(function() { - html = div.innerHTML - test.include(html, 'https://www.facebook.com/sharer/sharer.php?s=100&p[url]=http%3A%2F%2Flocalhost%3A3000%2F&p[title]=Test%20title&p[summary]=undefine') - test.include(html, 'https://twitter.com/intent/tweet?url=http%3A%2F%2Flocalhost%3A3000%2F&text=Test%20title') - // This is important for Async tests. - done() - }, 200); -}); diff --git a/packages/users-counter/.gitignore b/packages/users-counter/.gitignore deleted file mode 100644 index 677a6fc..0000000 --- a/packages/users-counter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.build* diff --git a/packages/users-counter/README.md b/packages/users-counter/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/packages/users-counter/both.js b/packages/users-counter/both.js deleted file mode 100644 index 03a03f2..0000000 --- a/packages/users-counter/both.js +++ /dev/null @@ -1 +0,0 @@ -Viewers = new Meteor.Collection('viewers'); diff --git a/packages/users-counter/client.js b/packages/users-counter/client.js deleted file mode 100644 index b493379..0000000 --- a/packages/users-counter/client.js +++ /dev/null @@ -1,23 +0,0 @@ -var UPDATE_INTERVAL = 3000; - -var updateViewer = function (viewerId, path, interval) { - if (interval) { - Meteor.clearInterval(interval); - } - - var interval = Meteor.setInterval(function () { - Meteor.call('heartbeat', viewerId, path, function (err, res) {}); - }, UPDATE_INTERVAL); - return interval; -}; - -Meteor.startup(function () { -// var uuid = Meteor.uuid(), -// interval = null; -// -// Deps.autorun(function () { -// var path = Path(); -// Meteor.subscribe('Viewers', path); -// interval = updateViewer(uuid, path, interval); -// }); -}); diff --git a/packages/users-counter/package.js b/packages/users-counter/package.js deleted file mode 100644 index d541d34..0000000 --- a/packages/users-counter/package.js +++ /dev/null @@ -1,36 +0,0 @@ -Package.describe({ - summary: "Chat with Github Flavored Markdown and social login using Meteor Streams" -}); - -Package.on_use(function (api, where) { - var both = ['client', 'server']; - // Client - api.use([ - 'deps', - 'session', - 'startup', - 'reactive-path' - ], 'client'); - - api.use([ - 'collection-hooks' - ], 'server'); - - api.add_files([ - 'both.js' - ], both); - - - api.add_files([ - 'client.js', - ], 'client'); - - // Server - api.add_files([ - 'server.js' - ], 'server'); - - if (typeof api.export !== 'undefined') { - api.export('Viewers'); - } -}); diff --git a/packages/users-counter/server.js b/packages/users-counter/server.js deleted file mode 100644 index d99a504..0000000 --- a/packages/users-counter/server.js +++ /dev/null @@ -1,39 +0,0 @@ -function addTimestamp (doc) { - doc.when = Date.now(); -} - -Viewers.before.insert(function (userId, doc) { - doc = addTimestamp(doc); -}); - -Viewers.before.update(function (userId, doc) { - doc = addTimestamp(doc); -}); - -Meteor.publish('Viewers', function (path) { - if (_.isEmpty(path)) { - return []; - } - - check(path, String); - return Viewers.find({path: path}, {fields: {when: 0, path: 0}}); -}); - -Meteor.methods({ - 'heartbeat': function (uuid, path) { - check(uuid, String); - check(path, String); - - Viewers.upsert({ uuid: uuid }, { $set: { path: path } }); - } -}) - -var CLEAN_INTERVAL = 20000; -Meteor.setInterval(function () { - var when = Date.now() - CLEAN_INTERVAL; - Viewers.remove({when: {$lt: when}}); -}, CLEAN_INTERVAL); - -Meteor.startup(function () { - Viewers._ensureIndex({uuid: true}, {unique: true}); -}); diff --git a/packages/users-counter/smart.json b/packages/users-counter/smart.json deleted file mode 100644 index 9292321..0000000 --- a/packages/users-counter/smart.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "users-counter", - "description": "Count users online", - "homepage": "https://github.com/gabrielhpugliese/meteor-users-counter", - "author": "Gabriel Henrique Pugliese ", - "version": "0.1.0", - "git": "https://github.com/gabrielhpugliese/meteor-users-counter" -} diff --git a/prod b/prod index ea82c11..8a7276f 100755 --- a/prod +++ b/prod @@ -66,16 +66,15 @@ sudo git clone $GIT_URL $APP_NAME; DEPLOY=" cd $APP_DIR; cd $APP_NAME; -sudo npm -g update meteorite; sudo git fetch --all; sudo git reset --hard origin/$GIT_BRANCH; sudo git checkout $GIT_BRANCH; +sudo git clean -f -d; sudo rm -rf ../bundle; -sudo rm -rf ../bundle.tgz; -sudo $METEOR_CMD update --force; -sudo $METEOR_CMD bundle ../bundle.tgz; -cd ..; -sudo tar -zxvf bundle.tgz; +sudo $METEOR_CMD build ../ --directory; +cd ../bundle/programs/server; +npm install; +cd ../../..; pm2 delete prod; mongo $APP_NAME $APP_DIR/$APP_NAME/mongo.config; METEOR_SETTINGS=\$(cat ${APP_DIR}/${APP_NAME}/prod.json) DEBUG=ct:* PORT=80 ROOT_URL=$ROOT_URL MONGO_URL=$MONGO_URL pm2 start bundle/main.js -x --name 'prod'; diff --git a/prod.config b/prod.config index e57569f..f52b9de 100644 --- a/prod.config +++ b/prod.config @@ -8,7 +8,7 @@ APP_HOST=coderstv.com GIT_URL=git@github.com:CodersTV/site.git # Does your project use meteorite, or plain meteor? -METEORITE=true +METEORITE=false # What's your app name? APP_NAME=coderstv diff --git a/server/apis/disqus.js b/server/apis/disqus.js index db06634..0bf676f 100644 --- a/server/apis/disqus.js +++ b/server/apis/disqus.js @@ -1,4 +1,4 @@ -var CryptoJS = Meteor.require('crypto-js'); +var CryptoJS = Meteor.npmRequire('crypto-js'); Meteor.methods({ disqusSSO: function () { diff --git a/server/cleanup.js b/server/cleanup.js index 0546d57..9067d88 100644 --- a/server/cleanup.js +++ b/server/cleanup.js @@ -4,9 +4,9 @@ // var CLEANUP_INTERVAL = 5 * 60 * 1000, var CLEANUP_INTERVAL = 60 * 1000; -var moment = Meteor.require('moment'); +var moment = Meteor.npmRequire('moment'); var Fiber = Npm.require('fibers'); -var debug = Meteor.require('debug')('ct:cleanup.js'); +var debug = Meteor.npmRequire('debug')('ct:cleanup.js'); Meteor.setInterval(function () { Channels.find({isLive: true}).forEach(function (channel) { diff --git a/server/collections/channels.js b/server/collections/channels.js index 38e5238..e5581ca 100644 --- a/server/collections/channels.js +++ b/server/collections/channels.js @@ -62,8 +62,6 @@ Channels.before.insert(function (userId, doc) { Channels.after.insert(function (userId, doc) { Channels.sendFollowEmail(userId, doc); - - Language.incVideos(doc.language); }); Channels.before.update(function (userId, doc, fieldNames, modifier, options) { @@ -72,8 +70,3 @@ Channels.before.update(function (userId, doc, fieldNames, modifier, options) { modifier.$set.finishedAt = +(new Date()); } }); - -Channels.after.remove(function (userId, doc) { - Language.decVideos(doc.language); -}); - diff --git a/server/collections/users.js b/server/collections/users.js index 6fa6d6d..0e6855a 100644 --- a/server/collections/users.js +++ b/server/collections/users.js @@ -4,7 +4,7 @@ * return Users.find({is_public: true}); * } */ -var debug = Meteor.require('debug')('ct:server:users.js'); +var debug = Meteor.npmRequire('debug')('ct:server:users.js'); var Fiber = Npm.require('fibers'); BetaUsers = new Meteor.Collection('betaUsers'); diff --git a/server/lib/google.js b/server/lib/google.js index d1a16bb..844e2b4 100644 --- a/server/lib/google.js +++ b/server/lib/google.js @@ -2,8 +2,8 @@ Google = {}; GPlus = {}; (function () { - var debug = Meteor.require('debug')('ct:google.js'); - var googleapis = Meteor.require('googleapis'); + var debug = Meteor.npmRequire('debug')('ct:google.js'); + var googleapis = Meteor.npmRequire('googleapis'); var OAuth2Client = googleapis.OAuth2Client; var googleAccount = ServiceConfiguration.configurations._collection.findOne({ service: 'google' diff --git a/smart.json b/smart.json deleted file mode 100644 index 60546e9..0000000 --- a/smart.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "packages": { - "handlebar-helpers": { - "git": "https://github.com/raix/Meteor-handlebar-helpers.git", - "tag": "v0.1.1" - }, - "npm": { - "git": "https://github.com/arunoda/meteor-npm.git", - "tag": "v0.2.6" - }, - "font-awesome": { - "git": "https://github.com/nate-strauser/meteor-font-awesome.git", - "tag": "v4.1.0" - }, - "mongo-counter": { - "git": "https://github.com/awwx/meteor-mongo-counter.git", - "tag": "v1.1.0" - }, - "presence": { - "git": "https://github.com/dburles/meteor-presence.git", - "tag": "v0.4.8" - }, - "roles": { - "git": "https://github.com/alanning/meteor-roles.git", - "tag": "v1.2.11" - }, - "collection-hooks": { - "git": "https://github.com/matb33/meteor-collection-hooks.git", - "tag": "v0.7.2" - }, - "handlebars-server": { - "git": "https://github.com/EventedMind/meteor-handlebars-server.git", - "tag": "v1.2.0" - }, - "sitemaps": { - "git": "https://github.com/gadicohen/meteor-sitemaps.git", - "tag": "v0.0.17" - }, - "marked": { - "git": "https://github.com/chuangbo/meteor-marked.git", - "tag": "v0.3.3" - }, - "iron-router": { - "git": "https://github.com/EventedMind/iron-router.git", - "tag": "v0.8.2" - }, - "users-counter": { - "path": "packages/users-counter" - }, - "chatroom": { - "path": "packages/chatroom" - }, - "bootstrap-3": { - "git": "https://github.com/mangasocial/meteor-bootstrap-3.git", - "tag": "v3.2.0-1" - }, - "fast-render": { - "git": "https://github.com/arunoda/meteor-fast-render.git", - "tag": "v1.0.0" - }, - "collection-helpers": { - "git": "https://github.com/dburles/meteor-collection-helpers.git", - "tag": "v0.3.1" - }, - "reactive-path": { - "git": "https://github.com/gabrielhpugliese/meteor-reactive-path", - "tag": "v0.1.4" - }, - "multiple-callbacks": { - "git": "https://github.com/brykov/meteor-multiple-callbacks.git", - "tag": "v0.1.3" - }, - "robots-txt": { - "git": "https://github.com/gadicohen/meteor-robots.txt.git", - "tag": "v0.0.8" - }, - "iron-layout": { - "git": "https://github.com/EventedMind/iron-layout.git", - "tag": "v0.2.0" - }, - "streams": { - "git": "https://github.com/arunoda/meteor-streams.git", - "tag": "v0.1.17" - }, - "blaze-layout": { - "git": "https://github.com/EventedMind/blaze-layout.git", - "tag": "v0.2.5" - }, - "iron-core": { - "git": "https://github.com/EventedMind/iron-core.git", - "tag": "v0.2.0" - }, - "iron-dynamic-template": { - "git": "https://github.com/EventedMind/iron-dynamic-template.git", - "tag": "v0.2.1" - }, - "kadira": { - "git": "git@github.com:meteorhacks/kadira.git", - "tag": "v2.12.0" - }, - "publish-composite": { - "git": "git@github.com:englue/meteor-publish-composite.git", - "tag": "v1.2.2" - }, - "tags": { - "git": "git@github.com:patrickleet/meteor-tags.git", - "tag": "v1.3" - } - } -}
- {{#with getProfile owner}} - {{#if name.givenName}}{{name.givenName}} {{name.familyName}}{{else}}{{displayName}}{{/if}} - {{/with}} - {{action}}: -
- {{msg}} -