From e1323c0295551ccc52274c67a07c6f39ee6fec2f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 26 Feb 2016 11:29:17 -0500 Subject: [PATCH 01/28] Updated js code so vendors can be added to the modules folder, so they can be required properly and we can finally get rid of that really annoying "mismatched anonymous" error in Require.js. First module to make the transition: Chart.js --- Gruntfile.js | 2 +- package.json | 1 + public/src/admin/general/dashboard.js | 4 +-- public/src/admin/manage/category.js | 7 +++-- src/meta.js | 1 + src/meta/js.js | 44 +++++++++++++++++++++++++++ src/views/admin/header.tpl | 1 - src/webserver.js | 1 + 8 files changed, 54 insertions(+), 7 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 36c054445f..0621f8c1a8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -57,7 +57,7 @@ module.exports = function(grunt) { files: ['public/**/*.less', 'node_modules/nodebb-*/*.less', 'node_modules/nodebb-*/*/*.less', 'node_modules/nodebb-*/*/*/*.less', 'node_modules/nodebb-*/*/*/*/*.less'] }, clientUpdated: { - files: ['public/src/**/*.js', 'node_modules/nodebb-*/*.js', 'node_modules/nodebb-*/*/*.js', 'node_modules/nodebb-*/*/*/*.js', 'node_modules/nodebb-*/*/*/*/*.js', 'node_modules/templates.js/lib/templates.js'] + files: ['public/src/**/*.js', '!public/src/modules/*.js', 'node_modules/nodebb-*/*.js', 'node_modules/nodebb-*/*/*.js', 'node_modules/nodebb-*/*/*/*.js', 'node_modules/nodebb-*/*/*/*/*.js', 'node_modules/templates.js/lib/templates.js'] }, serverUpdated: { files: ['*.js', 'install/*.js', 'src/**/*.js'] diff --git a/package.json b/package.json index 5dcb5e8cf8..5ff036175a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "autoprefixer": "^6.2.3", "bcryptjs": "~2.3.0", "body-parser": "^1.9.0", + "chart.js": "^1.0.2", "colors": "^1.1.0", "compression": "^1.1.0", "connect-ensure-login": "^0.1.1", diff --git a/public/src/admin/general/dashboard.js b/public/src/admin/general/dashboard.js index 930e996cdc..b23f57e3c8 100644 --- a/public/src/admin/general/dashboard.js +++ b/public/src/admin/general/dashboard.js @@ -1,7 +1,7 @@ "use strict"; -/*global define, ajaxify, app, socket, utils, bootbox, Chart, RELATIVE_PATH*/ +/*global define, ajaxify, app, socket, utils, bootbox, RELATIVE_PATH*/ -define('admin/general/dashboard', ['semver'], function(semver) { +define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) { var Admin = {}, intervals = { rooms: false, diff --git a/public/src/admin/manage/category.js b/public/src/admin/manage/category.js index a845b59790..32a4c99e9b 100644 --- a/public/src/admin/manage/category.js +++ b/public/src/admin/manage/category.js @@ -1,12 +1,13 @@ "use strict"; -/*global define, app, socket, ajaxify, RELATIVE_PATH, bootbox, templates, Chart */ +/*global define, app, socket, ajaxify, RELATIVE_PATH, bootbox, templates */ define('admin/manage/category', [ 'uploader', 'iconSelect', 'admin/modules/colorpicker', - 'autocomplete' -], function(uploader, iconSelect, colorpicker, autocomplete) { + 'autocomplete', + 'Chart' +], function(uploader, iconSelect, colorpicker, autocomplete, Chart) { var Category = {}; Category.init = function() { diff --git a/src/meta.js b/src/meta.js index 7a054b1836..8fec4c3444 100644 --- a/src/meta.js +++ b/src/meta.js @@ -62,6 +62,7 @@ var async = require('async'), async.apply(plugins.reloadRoutes), function(next) { async.parallel([ + async.apply(Meta.js.symlinkModules), async.apply(Meta.js.minify, 'nodebb.min.js'), async.apply(Meta.js.minify, 'acp.min.js'), async.apply(Meta.css.minify), diff --git a/src/meta/js.js b/src/meta/js.js index 314e10a400..506d872f87 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -7,6 +7,7 @@ var winston = require('winston'), _ = require('underscore'), nconf = require('nconf'), fs = require('fs'), + rimraf = require('rimraf'), file = require('../file'), plugins = require('../plugins'), emitter = require('../emitter'), @@ -43,6 +44,8 @@ module.exports = function(Meta) { 'public/src/variables.js', 'public/src/widgets.js' ], + + // files listed below are only available client-side, or are bundled in to reduce # of network requests on cold load rjs: [ 'public/src/client/footer.js', 'public/src/client/chats.js', @@ -77,10 +80,51 @@ module.exports = function(Meta) { 'public/src/modules/helpers.js', 'public/src/modules/sounds.js', 'public/src/modules/string.js' + ], + + // modules listed below are symlinked to public/src/modules so they can be defined anonymously + modules: [ + './node_modules/chart.js/Chart.js' ] } }; + Meta.js.symlinkModules = function(callback) { + // Symlink all defined modules to /public/src/modules + var modulesLoaded = 0, + targetPath; + + async.series([ + function(next) { + async.each(Meta.js.scripts.modules, function(localPath, next) { + targetPath = path.join(__dirname, '../../public/src/modules', path.basename(localPath)); + + async.waterfall([ + async.apply(fs.access, localPath, fs.R_OK), + async.apply(rimraf, targetPath), + async.apply(fs.link, localPath, targetPath) + ], function(err) { + if (err) { + winston.error('[meta/js] Could not symlink `' + localPath + '` to modules folder'); + } else { + winston.verbose('[meta/js] Symlinked `' + localPath + '` to modules folder'); + ++modulesLoaded; + } + + next(err); + }); + }, next); + } + ], function(err) { + if (err) { + winston.error('[meta/js] Encountered error while symlinking modules:' + err.message); + } + + winston.verbose('[meta/js] ' + modulesLoaded + ' of ' + Meta.js.scripts.modules.length + ' modules symlinked'); + callback(err); + }); + }; + Meta.js.minify = function(target, callback) { if (nconf.get('isPrimary') !== 'true') { if (typeof callback === 'function') { diff --git a/src/views/admin/header.tpl b/src/views/admin/header.tpl index 19b3b065cb..e445a66403 100644 --- a/src/views/admin/header.tpl +++ b/src/views/admin/header.tpl @@ -27,7 +27,6 @@ - diff --git a/src/webserver.js b/src/webserver.js index 4a46b54520..cf814feda9 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -92,6 +92,7 @@ function initializeNodeBB(callback) { function(next) { async.parallel([ async.apply(meta.templates.compile), + async.apply(meta.js.symlinkModules), async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, 'nodebb.min.js'), async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, 'acp.min.js'), async.apply(!skipLess ? meta.css.minify : meta.css.getFromFile), From 3871f6f191fcf69906c0584fc35c8ed0f4c50fee Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 26 Feb 2016 11:39:02 -0500 Subject: [PATCH 02/28] removed chart.js lib from repo --- public/vendor/chart.js/chart.min.js | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 public/vendor/chart.js/chart.min.js diff --git a/public/vendor/chart.js/chart.min.js b/public/vendor/chart.js/chart.min.js deleted file mode 100644 index 626e6c3cdb..0000000000 --- a/public/vendor/chart.js/chart.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/*! - * Chart.js - * http://chartjs.org/ - * Version: 1.0.1-beta.4 - * - * Copyright 2014 Nick Downie - * Released under the MIT license - * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md - */ -(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;this.width=t.canvas.width,this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof t.define&&t.define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),x=s.radians=function(t){return t*(Math.PI/180)},S=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),x=Math.round(f/v);(x>a||a>2*x)&&!h;)if(x>a)v*=2,x=Math.round(f/v),x%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,x=Math.round(f/v)}else v/=2,x=Math.round(f/v);return h&&(x=o,v=f/x),{steps:x,stepValue:v,min:p,max:p+x*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),b=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),st?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-b.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*b.easeInBounce(2*t):.5*b.easeOutBounce(2*t-1)+.5}}),w=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=(s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),s.animationLoop=function(t,i,e,s,n,o){var a=0,h=b[e]||b.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=w(l):n.apply(o)};w(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),L=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},k=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},P(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){L(t.chart.canvas,e,i)})}),F=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},R=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),T=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},M=s.fontString=function(t,i,e){return i+" "+t+"px "+e},W=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},z=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return T(this.chart),this},stop:function(){return s.cancelAnimFrame.call(t,this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=F(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:R(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),k(this,this.events),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;switch(t.fillStyle=this.fillColor,this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}z(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=M(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=W(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){z(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?W(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),tthis.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=W(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(x(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(x(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/(this.valuesCount-(this.offsetGridLines?0:1)),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a);t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+S(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+S(this.lineWidth),o=this.xLabelRotation>0;t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*x(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;ip&&(p=t.x+s,n=i),t.x-sp&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'
    <% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<% for (var i=0; i
  • <%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>'}; -i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(t/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)0&&ithis.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.ythis.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
      <% for (var i=0; i
    • <%if(segments[i].label){%><%=segments[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); \ No newline at end of file From 44aae7daa5e6751dac75bec2ccb264e609563b17 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 26 Feb 2016 12:12:12 -0500 Subject: [PATCH 03/28] removed hammer, updated semver, added mousetrap --- package.json | 3 ++- public/src/admin/admin.js | 24 +++++++++++++----------- public/src/client/chats.js | 10 +++++----- public/src/client/topic.js | 4 ++-- public/src/modules/search.js | 8 ++++---- public/vendor/hammer/hammer.min.js | 6 ------ public/vendor/mousetrap/mousetrap.js | 9 --------- src/meta/js.js | 4 ++-- src/views/admin/header.tpl | 2 -- 9 files changed, 28 insertions(+), 42 deletions(-) delete mode 100644 public/vendor/hammer/hammer.min.js delete mode 100644 public/vendor/mousetrap/mousetrap.js diff --git a/package.json b/package.json index 5ff036175a..4a24daa2d7 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "mkdirp": "~0.5.0", "mongodb": "~2.1.3", "morgan": "^1.3.2", + "mousetrap": "^1.5.3", "nconf": "~0.8.2", "nodebb-plugin-composer-default": "3.0.6", "nodebb-plugin-dbsearch": "0.3.1", @@ -67,7 +68,7 @@ "request": "^2.44.0", "rimraf": "~2.5.0", "rss": "^1.0.0", - "semver": "^5.0.1", + "semver": "^5.1.0", "serve-favicon": "^2.1.5", "sitemap": "^1.4.0", "socket.io": "^1.4.0", diff --git a/public/src/admin/admin.js b/public/src/admin/admin.js index 22258d4f66..173148ef5e 100644 --- a/public/src/admin/admin.js +++ b/public/src/admin/admin.js @@ -1,5 +1,5 @@ "use strict"; -/*global config, translator, componentHandler, define, socket, app, ajaxify, utils, bootbox, Mousetrap, Hammer, Slideout, RELATIVE_PATH*/ +/*global config, translator, componentHandler, define, socket, app, ajaxify, utils, bootbox, Slideout, RELATIVE_PATH*/ (function() { $(document).ready(function() { @@ -32,20 +32,22 @@ }); function setupKeybindings() { - Mousetrap.bind('ctrl+shift+a r', function() { - require(['admin/modules/instance'], function(instance) { - instance.reload(); + require(['mousetrap'], function(mousetrap) { + mousetrap.bind('ctrl+shift+a r', function() { + require(['admin/modules/instance'], function(instance) { + instance.reload(); + }); }); - }); - Mousetrap.bind('ctrl+shift+a R', function() { - socket.emit('admin.restart'); - }); + mousetrap.bind('ctrl+shift+a R', function() { + socket.emit('admin.restart'); + }); - Mousetrap.bind('/', function(e) { - $('#acp-search input').focus(); + mousetrap.bind('/', function(e) { + $('#acp-search input').focus(); - return false; + return false; + }); }); } diff --git a/public/src/client/chats.js b/public/src/client/chats.js index 21da307713..24c7a89192 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -1,8 +1,8 @@ 'use strict'; -/* globals define, config, app, ajaxify, utils, socket, templates, Mousetrap, bootbox */ +/* globals define, config, app, ajaxify, utils, socket, templates, bootbox */ -define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', 'translator'], function(components, S, sounds, infinitescroll, translator) { +define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', 'translator', 'mousetrap'], function(components, S, sounds, infinitescroll, translator, mousetrap) { var Chats = { initialised: false }; @@ -92,7 +92,7 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', }; Chats.addHotkeys = function() { - Mousetrap.bind('ctrl+up', function() { + mousetrap.bind('ctrl+up', function() { var activeContact = $('.chats-list .bg-primary'), prev = activeContact.prev(); @@ -100,7 +100,7 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', Chats.switchChat(prev.attr('data-roomid')); } }); - Mousetrap.bind('ctrl+down', function() { + mousetrap.bind('ctrl+down', function() { var activeContact = $('.chats-list .bg-primary'), next = activeContact.next(); @@ -108,7 +108,7 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', Chats.switchChat(next.attr('data-roomid')); } }); - Mousetrap.bind('up', function(e) { + mousetrap.bind('up', function(e) { if (e.target === components.get('chat/input').get(0)) { // Retrieve message id from messages list var message = components.get('chat/messages').find('.chat-message[data-self="1"]').last(); diff --git a/public/src/client/topic.js b/public/src/client/topic.js index c3e228f9ae..5772a570b3 100644 --- a/public/src/client/topic.js +++ b/public/src/client/topic.js @@ -93,7 +93,7 @@ define('forum/topic', [ } function handleTopicSearch() { - require(['search', 'mousetrap'], function(search, Mousetrap) { + require(['search', 'mousetrap'], function(search, mousetrap) { $('.topic-search') .on('click', '.prev', function() { search.topicDOM.prev(); @@ -102,7 +102,7 @@ define('forum/topic', [ search.topicDOM.next(); }); - Mousetrap.bind('ctrl+f', function(e) { + mousetrap.bind('ctrl+f', function(e) { if (config.topicSearchEnabled) { // If in topic, open search window and populate, otherwise regular behaviour var match = ajaxify.currentPage.match(/^topic\/([\d]+)/), diff --git a/public/src/modules/search.js b/public/src/modules/search.js index 7b889999ea..e24ecbed61 100644 --- a/public/src/modules/search.js +++ b/public/src/modules/search.js @@ -150,8 +150,8 @@ define('search', ['navigator', 'translator'], function(nav, translator) { Search.topicDOM.active = true; // Bind to esc - require(['mousetrap'], function(Mousetrap) { - Mousetrap.bind('esc', Search.topicDOM.end); + require(['mousetrap'], function(mousetrap) { + mousetrap.bind('esc', Search.topicDOM.end); }); } }; @@ -161,8 +161,8 @@ define('search', ['navigator', 'translator'], function(nav, translator) { Search.topicDOM.active = false; // Unbind esc - require(['mousetrap'], function(Mousetrap) { - Mousetrap.unbind('esc', Search.topicDOM.end); + require(['mousetrap'], function(mousetrap) { + mousetrap.unbind('esc', Search.topicDOM.end); }); }; diff --git a/public/vendor/hammer/hammer.min.js b/public/vendor/hammer/hammer.min.js deleted file mode 100644 index 575b810f47..0000000000 --- a/public/vendor/hammer/hammer.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! Hammer.JS - v2.0.4 - 2014-09-28 - * http://hammerjs.github.io/ - * - * Copyright (c) 2014 Jorik Tangelder; - * Licensed under the MIT license */ -!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(k(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e-1}function r(a){return a.trim().split(/\s+/g)}function s(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;dc[b]}):d.sort()),d}function v(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g1&&!c.firstMultiple?c.firstMultiple=E(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=F(d);b.timeStamp=nb(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=J(h,i),b.distance=I(h,i),C(c,b),b.offsetDirection=H(b.deltaX,b.deltaY),b.scale=g?L(g.pointers,d):1,b.rotation=g?K(g.pointers,d):0,D(c,b);var j=a.element;p(b.srcEvent.target,j)&&(j=b.srcEvent.target),b.target=j}function C(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};(b.eventType===yb||f.eventType===Ab)&&(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function D(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Bb&&(i>xb||h.velocity===d)){var j=h.deltaX-b.deltaX,k=h.deltaY-b.deltaY,l=G(i,j,k);e=l.x,f=l.y,c=mb(l.x)>mb(l.y)?l.x:l.y,g=H(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function E(a){for(var b=[],c=0;ce;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:lb(c/b),y:lb(d/b)}}function G(a,b,c){return{x:b/a||0,y:c/a||0}}function H(a,b){return a===b?Cb:mb(a)>=mb(b)?a>0?Db:Eb:b>0?Fb:Gb}function I(a,b,c){c||(c=Kb);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function J(a,b,c){c||(c=Kb);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function K(a,b){return J(b[1],b[0],Lb)-J(a[1],a[0],Lb)}function L(a,b){return I(b[0],b[1],Lb)/I(a[0],a[1],Lb)}function M(){this.evEl=Nb,this.evWin=Ob,this.allow=!0,this.pressed=!1,y.apply(this,arguments)}function N(){this.evEl=Rb,this.evWin=Sb,y.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function O(){this.evTarget=Ub,this.evWin=Vb,this.started=!1,y.apply(this,arguments)}function P(a,b){var c=t(a.touches),d=t(a.changedTouches);return b&(Ab|Bb)&&(c=u(c.concat(d),"identifier",!0)),[c,d]}function Q(){this.evTarget=Xb,this.targetIds={},y.apply(this,arguments)}function R(a,b){var c=t(a.touches),d=this.targetIds;if(b&(yb|zb)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=t(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return p(a.target,i)}),b===yb)for(e=0;eh&&(b.push(a),h=b.length-1):e&(Ab|Bb)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Tb={touchstart:yb,touchmove:zb,touchend:Ab,touchcancel:Bb},Ub="touchstart",Vb="touchstart touchmove touchend touchcancel";j(O,y,{handler:function(a){var b=Tb[a.type];if(b===yb&&(this.started=!0),this.started){var c=P.call(this,a,b);b&(Ab|Bb)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:tb,srcEvent:a})}}});var Wb={touchstart:yb,touchmove:zb,touchend:Ab,touchcancel:Bb},Xb="touchstart touchmove touchend touchcancel";j(Q,y,{handler:function(a){var b=Wb[a.type],c=R.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:tb,srcEvent:a})}}),j(S,y,{handler:function(a,b,c){var d=c.pointerType==tb,e=c.pointerType==vb;if(d)this.mouse.allow=!1;else if(e&&!this.mouse.allow)return;b&(Ab|Bb)&&(this.mouse.allow=!0),this.callback(a,b,c)},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var Yb=v(jb.style,"touchAction"),Zb=Yb!==d,$b="compute",_b="auto",ac="manipulation",bc="none",cc="pan-x",dc="pan-y";T.prototype={set:function(a){a==$b&&(a=this.compute()),Zb&&(this.manager.element.style[Yb]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){l(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),U(a.join(" "))},preventDefaults:function(a){if(!Zb){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=q(d,bc),f=q(d,dc),g=q(d,cc);return e||f&&c&Hb||g&&c&Ib?this.preventSrc(b):void 0}},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var ec=1,fc=2,gc=4,hc=8,ic=hc,jc=16,kc=32;V.prototype={defaults:{},set:function(a){return h(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=Y(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=Y(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=Y(a,this),-1===s(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=Y(a,this);var b=s(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(c.options.event+(b?W(d):""),a)}var c=this,d=this.state;hc>d&&b(!0),b(),d>=hc&&b(!0)},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=kc)},canEmit:function(){for(var a=0;af?Db:Eb,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Cb:0>g?Fb:Gb,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return Z.prototype.attrTest.call(this,a)&&(this.state&fc||!(this.state&fc)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=X(a.direction);b&&this.manager.emit(this.options.event+b,a),this._super.emit.call(this,a)}}),j(_,Z,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[bc]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&fc)},emit:function(a){if(this._super.emit.call(this,a),1!==a.scale){var b=a.scale<1?"in":"out";this.manager.emit(this.options.event+b,a)}}}),j(ab,V,{defaults:{event:"press",pointers:1,time:500,threshold:5},getTouchAction:function(){return[_b]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distanceb.time;if(this._input=a,!d||!c||a.eventType&(Ab|Bb)&&!f)this.reset();else if(a.eventType&yb)this.reset(),this._timer=e(function(){this.state=ic,this.tryEmit()},b.time,this);else if(a.eventType&Ab)return ic;return kc},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===ic&&(a&&a.eventType&Ab?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=nb(),this.manager.emit(this.options.event,this._input)))}}),j(bb,Z,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[bc]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&fc)}}),j(cb,Z,{defaults:{event:"swipe",threshold:10,velocity:.65,direction:Hb|Ib,pointers:1},getTouchAction:function(){return $.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Hb|Ib)?b=a.velocity:c&Hb?b=a.velocityX:c&Ib&&(b=a.velocityY),this._super.attrTest.call(this,a)&&c&a.direction&&a.distance>this.options.threshold&&mb(b)>this.options.velocity&&a.eventType&Ab},emit:function(a){var b=X(a.direction);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),j(db,V,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:2,posThreshold:10},getTouchAction:function(){return[ac]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distanceg||h.hasOwnProperty(g)&&(p[h[g]]=g)}e=p[d]?"keydown":"keypress"}"keypress"==e&&f.length&&(e="keydown");return{key:c,modifiers:f,action:e}}function F(a,b,d,c,e){q[a+":"+d]=b;a=a.replace(/\s+/g," ");var f=a.split(" ");1":".","?":"/","|":"\\"},G={option:"alt",command:"meta","return":"enter",escape:"esc",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},p,l={},q={},n={},D,z=!1,I=!1,u=!1;for(f=1;20>f;++f)h[111+f]="f"+f;for(f=0;9>=f;++f)h[f+96]=f;s(r,"keypress",y);s(r,"keydown",y);s(r,"keyup",y);var m={bind:function(a,b,d){a=a instanceof Array?a:[a];for(var c=0;c - - From 3f2872979fd8adb9f38c2d22d1384fba5c5d7fae Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 26 Feb 2016 12:34:48 -0500 Subject: [PATCH 04/28] added buzz --- public/vendor/buzz/buzz.js | 11 +++++++++++ public/vendor/buzz/buzz.min.js | 11 ----------- src/meta/js.js | 5 +++-- src/views/admin/header.tpl | 3 +-- src/views/partials/requirejs-config.tpl | 3 +-- 5 files changed, 16 insertions(+), 17 deletions(-) create mode 100644 public/vendor/buzz/buzz.js delete mode 100644 public/vendor/buzz/buzz.min.js diff --git a/public/vendor/buzz/buzz.js b/public/vendor/buzz/buzz.js new file mode 100644 index 0000000000..eae98a9dfe --- /dev/null +++ b/public/vendor/buzz/buzz.js @@ -0,0 +1,11 @@ + // ---------------------------------------------------------------------------- + // Buzz, a Javascript HTML5 Audio library + // v1.1.10 - Built 2015-04-20 13:05 + // Licensed under the MIT license. + // http://buzz.jaysalvat.com/ + // ---------------------------------------------------------------------------- + // Copyright (C) 2010-2015 Jay Salvat + // http://jaysalvat.com/ + // ---------------------------------------------------------------------------- + +(function(t,e){"use strict";"undefined"!=typeof module&&module.exports?module.exports=e():"function"==typeof define&&define.amd?define([],e):t.buzz=e()})(this,function(){"use strict";var t=window.AudioContext||window.webkitAudioContext,e={defaults:{autoplay:!1,duration:5e3,formats:[],loop:!1,placeholder:"--",preload:"metadata",volume:80,webAudioApi:!1,document:window.document},types:{mp3:"audio/mpeg",ogg:"audio/ogg",wav:"audio/wav",aac:"audio/aac",m4a:"audio/x-m4a"},sounds:[],el:document.createElement("audio"),getAudioContext:function(){if(void 0===this.audioCtx)try{this.audioCtx=t?new t:null}catch(e){this.audioCtx=null}return this.audioCtx},sound:function(t,n){function i(t){for(var e=[],n=t.length-1,i=0;n>=i;i++)e.push({start:t.start(i),end:t.end(i)});return e}function u(t){return t.split(".").pop()}n=n||{};var s=n.document||e.defaults.document,r=0,o=[],a={},h=e.isSupported();if(this.load=function(){return h?(this.sound.load(),this):this},this.play=function(){return h?(this.sound.play(),this):this},this.togglePlay=function(){return h?(this.sound.paused?this.sound.play():this.sound.pause(),this):this},this.pause=function(){return h?(this.sound.pause(),this):this},this.isPaused=function(){return h?this.sound.paused:null},this.stop=function(){return h?(this.setTime(0),this.sound.pause(),this):this},this.isEnded=function(){return h?this.sound.ended:null},this.loop=function(){return h?(this.sound.loop="loop",this.bind("ended.buzzloop",function(){this.currentTime=0,this.play()}),this):this},this.unloop=function(){return h?(this.sound.removeAttribute("loop"),this.unbind("ended.buzzloop"),this):this},this.mute=function(){return h?(this.sound.muted=!0,this):this},this.unmute=function(){return h?(this.sound.muted=!1,this):this},this.toggleMute=function(){return h?(this.sound.muted=!this.sound.muted,this):this},this.isMuted=function(){return h?this.sound.muted:null},this.setVolume=function(t){return h?(0>t&&(t=0),t>100&&(t=100),this.volume=t,this.sound.volume=t/100,this):this},this.getVolume=function(){return h?this.volume:this},this.increaseVolume=function(t){return this.setVolume(this.volume+(t||1))},this.decreaseVolume=function(t){return this.setVolume(this.volume-(t||1))},this.setTime=function(t){if(!h)return this;var e=!0;return this.whenReady(function(){e===!0&&(e=!1,this.sound.currentTime=t)}),this},this.getTime=function(){if(!h)return null;var t=Math.round(100*this.sound.currentTime)/100;return isNaN(t)?e.defaults.placeholder:t},this.setPercent=function(t){return h?this.setTime(e.fromPercent(t,this.sound.duration)):this},this.getPercent=function(){if(!h)return null;var t=Math.round(e.toPercent(this.sound.currentTime,this.sound.duration));return isNaN(t)?e.defaults.placeholder:t},this.setSpeed=function(t){return h?(this.sound.playbackRate=t,this):this},this.getSpeed=function(){return h?this.sound.playbackRate:null},this.getDuration=function(){if(!h)return null;var t=Math.round(100*this.sound.duration)/100;return isNaN(t)?e.defaults.placeholder:t},this.getPlayed=function(){return h?i(this.sound.played):null},this.getBuffered=function(){return h?i(this.sound.buffered):null},this.getSeekable=function(){return h?i(this.sound.seekable):null},this.getErrorCode=function(){return h&&this.sound.error?this.sound.error.code:0},this.getErrorMessage=function(){if(!h)return null;switch(this.getErrorCode()){case 1:return"MEDIA_ERR_ABORTED";case 2:return"MEDIA_ERR_NETWORK";case 3:return"MEDIA_ERR_DECODE";case 4:return"MEDIA_ERR_SRC_NOT_SUPPORTED";default:return null}},this.getStateCode=function(){return h?this.sound.readyState:null},this.getStateMessage=function(){if(!h)return null;switch(this.getStateCode()){case 0:return"HAVE_NOTHING";case 1:return"HAVE_METADATA";case 2:return"HAVE_CURRENT_DATA";case 3:return"HAVE_FUTURE_DATA";case 4:return"HAVE_ENOUGH_DATA";default:return null}},this.getNetworkStateCode=function(){return h?this.sound.networkState:null},this.getNetworkStateMessage=function(){if(!h)return null;switch(this.getNetworkStateCode()){case 0:return"NETWORK_EMPTY";case 1:return"NETWORK_IDLE";case 2:return"NETWORK_LOADING";case 3:return"NETWORK_NO_SOURCE";default:return null}},this.set=function(t,e){return h?(this.sound[t]=e,this):this},this.get=function(t){return h?t?this.sound[t]:this.sound:null},this.bind=function(t,e){if(!h)return this;t=t.split(" ");for(var n=this,i=function(t){e.call(n,t)},u=0;t.length>u;u++){var s=t[u],r=s;s=r.split(".")[0],o.push({idx:r,func:i}),this.sound.addEventListener(s,i,!0)}return this},this.unbind=function(t){if(!h)return this;t=t.split(" ");for(var e=0;t.length>e;e++)for(var n=t[e],i=n.split(".")[0],u=0;o.length>u;u++){var s=o[u].idx.split(".");(o[u].idx===n||s[1]&&s[1]===n.replace(".",""))&&(this.sound.removeEventListener(i,o[u].func,!0),o.splice(u,1))}return this},this.bindOnce=function(t,e){if(!h)return this;var n=this;return a[r++]=!1,this.bind(t+"."+r,function(){a[r]||(a[r]=!0,e.call(n)),n.unbind(t+"."+r)}),this},this.trigger=function(t,e){if(!h)return this;t=t.split(" ");for(var n=0;t.length>n;n++)for(var i=t[n],u=0;o.length>u;u++){var r=o[u].idx.split(".");if(o[u].idx===i||r[0]&&r[0]===i.replace(".","")){var a=s.createEvent("HTMLEvents");a.initEvent(r[0],!1,!0),a.originalEvent=e,this.sound.dispatchEvent(a)}}return this},this.fadeTo=function(t,n,i){function u(){setTimeout(function(){t>s&&t>o.volume?(o.setVolume(o.volume+=1),u()):s>t&&o.volume>t?(o.setVolume(o.volume-=1),u()):i instanceof Function&&i.apply(o)},r)}if(!h)return this;n instanceof Function?(i=n,n=e.defaults.duration):n=n||e.defaults.duration;var s=this.volume,r=n/Math.abs(s-t),o=this;return this.play(),this.whenReady(function(){u()}),this},this.fadeIn=function(t,e){return h?this.setVolume(0).fadeTo(100,t,e):this},this.fadeOut=function(t,e){return h?this.fadeTo(0,t,e):this},this.fadeWith=function(t,e){return h?(this.fadeOut(e,function(){this.stop()}),t.play().fadeIn(e),this):this},this.whenReady=function(t){if(!h)return null;var e=this;0===this.sound.readyState?this.bind("canplay.buzzwhenready",function(){t.call(e)}):t.call(e)},this.addSource=function(t){var n=this,i=s.createElement("source");return i.src=t,e.types[u(t)]&&(i.type=e.types[u(t)]),this.sound.appendChild(i),i.addEventListener("error",function(t){n.trigger("sourceerror",t)}),i},h&&t){for(var d in e.defaults)e.defaults.hasOwnProperty(d)&&void 0===n[d]&&(n[d]=e.defaults[d]);if(this.sound=s.createElement("audio"),n.webAudioApi){var l=e.getAudioContext();l&&(this.source=l.createMediaElementSource(this.sound),this.source.connect(l.destination))}if(t instanceof Array)for(var c in t)t.hasOwnProperty(c)&&this.addSource(t[c]);else if(n.formats.length)for(var f in n.formats)n.formats.hasOwnProperty(f)&&this.addSource(t+"."+n.formats[f]);else this.addSource(t);n.loop&&this.loop(),n.autoplay&&(this.sound.autoplay="autoplay"),this.sound.preload=n.preload===!0?"auto":n.preload===!1?"none":n.preload,this.setVolume(n.volume),e.sounds.push(this)}},group:function(t){function e(){for(var e=n(null,arguments),i=e.shift(),u=0;t.length>u;u++)t[u][i].apply(t[u],e)}function n(t,e){return t instanceof Array?t:Array.prototype.slice.call(e)}t=n(t,arguments),this.getSounds=function(){return t},this.add=function(e){e=n(e,arguments);for(var i=0;e.length>i;i++)t.push(e[i])},this.remove=function(e){e=n(e,arguments);for(var i=0;e.length>i;i++)for(var u=0;t.length>u;u++)if(t[u]===e[i]){t.splice(u,1);break}},this.load=function(){return e("load"),this},this.play=function(){return e("play"),this},this.togglePlay=function(){return e("togglePlay"),this},this.pause=function(t){return e("pause",t),this},this.stop=function(){return e("stop"),this},this.mute=function(){return e("mute"),this},this.unmute=function(){return e("unmute"),this},this.toggleMute=function(){return e("toggleMute"),this},this.setVolume=function(t){return e("setVolume",t),this},this.increaseVolume=function(t){return e("increaseVolume",t),this},this.decreaseVolume=function(t){return e("decreaseVolume",t),this},this.loop=function(){return e("loop"),this},this.unloop=function(){return e("unloop"),this},this.setSpeed=function(t){return e("setSpeed",t),this},this.setTime=function(t){return e("setTime",t),this},this.set=function(t,n){return e("set",t,n),this},this.bind=function(t,n){return e("bind",t,n),this},this.unbind=function(t){return e("unbind",t),this},this.bindOnce=function(t,n){return e("bindOnce",t,n),this},this.trigger=function(t){return e("trigger",t),this},this.fade=function(t,n,i,u){return e("fade",t,n,i,u),this},this.fadeIn=function(t,n){return e("fadeIn",t,n),this},this.fadeOut=function(t,n){return e("fadeOut",t,n),this}},all:function(){return new e.group(e.sounds)},isSupported:function(){return!!e.el.canPlayType},isOGGSupported:function(){return!!e.el.canPlayType&&e.el.canPlayType('audio/ogg; codecs="vorbis"')},isWAVSupported:function(){return!!e.el.canPlayType&&e.el.canPlayType('audio/wav; codecs="1"')},isMP3Supported:function(){return!!e.el.canPlayType&&e.el.canPlayType("audio/mpeg;")},isAACSupported:function(){return!!e.el.canPlayType&&(e.el.canPlayType("audio/x-m4a;")||e.el.canPlayType("audio/aac;"))},toTimer:function(t,e){var n,i,u;return n=Math.floor(t/3600),n=isNaN(n)?"--":n>=10?n:"0"+n,i=e?Math.floor(t/60%60):Math.floor(t/60),i=isNaN(i)?"--":i>=10?i:"0"+i,u=Math.floor(t%60),u=isNaN(u)?"--":u>=10?u:"0"+u,e?n+":"+i+":"+u:i+":"+u},fromTimer:function(t){var e=(""+t).split(":");return e&&3===e.length&&(t=3600*parseInt(e[0],10)+60*parseInt(e[1],10)+parseInt(e[2],10)),e&&2===e.length&&(t=60*parseInt(e[0],10)+parseInt(e[1],10)),t},toPercent:function(t,e,n){var i=Math.pow(10,n||0);return Math.round(100*t/e*i)/i},fromPercent:function(t,e,n){var i=Math.pow(10,n||0);return Math.round(e/100*t*i)/i}};return e}); \ No newline at end of file diff --git a/public/vendor/buzz/buzz.min.js b/public/vendor/buzz/buzz.min.js deleted file mode 100644 index 556ce7663b..0000000000 --- a/public/vendor/buzz/buzz.min.js +++ /dev/null @@ -1,11 +0,0 @@ - // ---------------------------------------------------------------------------- - // Buzz, a Javascript HTML5 Audio library - // v1.1.0 - released 2013-08-15 13:18 - // Licensed under the MIT license. - // http://buzz.jaysalvat.com/ - // ---------------------------------------------------------------------------- - // Copyright (C) 2010-2013 Jay Salvat - // http://jaysalvat.com/ - // ---------------------------------------------------------------------------- - -(function(t,n,e){"undefined"!=typeof module&&module.exports?module.exports=e():"function"==typeof n.define&&n.define.amd?define(t,[],e):n[t]=e()})("buzz",this,function(){var t={defaults:{autoplay:!1,duration:5e3,formats:[],loop:!1,placeholder:"--",preload:"metadata",volume:80,document:document},types:{mp3:"audio/mpeg",ogg:"audio/ogg",wav:"audio/wav",aac:"audio/aac",m4a:"audio/x-m4a"},sounds:[],el:document.createElement("audio"),sound:function(n,e){function i(t){for(var n=[],e=t.length-1,i=0;e>=i;i++)n.push({start:t.start(i),end:t.end(i)});return n}function u(t){return t.split(".").pop()}function s(n,e){var i=r.createElement("source");i.src=e,t.types[u(e)]&&(i.type=t.types[u(e)]),n.appendChild(i)}e=e||{};var r=e.document||t.defaults.document,o=0,a=[],h={},l=t.isSupported();if(this.load=function(){return l?(this.sound.load(),this):this},this.play=function(){return l?(this.sound.play(),this):this},this.togglePlay=function(){return l?(this.sound.paused?this.sound.play():this.sound.pause(),this):this},this.pause=function(){return l?(this.sound.pause(),this):this},this.isPaused=function(){return l?this.sound.paused:null},this.stop=function(){return l?(this.setTime(0),this.sound.pause(),this):this},this.isEnded=function(){return l?this.sound.ended:null},this.loop=function(){return l?(this.sound.loop="loop",this.bind("ended.buzzloop",function(){this.currentTime=0,this.play()}),this):this},this.unloop=function(){return l?(this.sound.removeAttribute("loop"),this.unbind("ended.buzzloop"),this):this},this.mute=function(){return l?(this.sound.muted=!0,this):this},this.unmute=function(){return l?(this.sound.muted=!1,this):this},this.toggleMute=function(){return l?(this.sound.muted=!this.sound.muted,this):this},this.isMuted=function(){return l?this.sound.muted:null},this.setVolume=function(t){return l?(0>t&&(t=0),t>100&&(t=100),this.volume=t,this.sound.volume=t/100,this):this},this.getVolume=function(){return l?this.volume:this},this.increaseVolume=function(t){return this.setVolume(this.volume+(t||1))},this.decreaseVolume=function(t){return this.setVolume(this.volume-(t||1))},this.setTime=function(t){if(!l)return this;var n=!0;return this.whenReady(function(){n===!0&&(n=!1,this.sound.currentTime=t)}),this},this.getTime=function(){if(!l)return null;var n=Math.round(100*this.sound.currentTime)/100;return isNaN(n)?t.defaults.placeholder:n},this.setPercent=function(n){return l?this.setTime(t.fromPercent(n,this.sound.duration)):this},this.getPercent=function(){if(!l)return null;var n=Math.round(t.toPercent(this.sound.currentTime,this.sound.duration));return isNaN(n)?t.defaults.placeholder:n},this.setSpeed=function(t){return l?(this.sound.playbackRate=t,this):this},this.getSpeed=function(){return l?this.sound.playbackRate:null},this.getDuration=function(){if(!l)return null;var n=Math.round(100*this.sound.duration)/100;return isNaN(n)?t.defaults.placeholder:n},this.getPlayed=function(){return l?i(this.sound.played):null},this.getBuffered=function(){return l?i(this.sound.buffered):null},this.getSeekable=function(){return l?i(this.sound.seekable):null},this.getErrorCode=function(){return l&&this.sound.error?this.sound.error.code:0},this.getErrorMessage=function(){if(!l)return null;switch(this.getErrorCode()){case 1:return"MEDIA_ERR_ABORTED";case 2:return"MEDIA_ERR_NETWORK";case 3:return"MEDIA_ERR_DECODE";case 4:return"MEDIA_ERR_SRC_NOT_SUPPORTED";default:return null}},this.getStateCode=function(){return l?this.sound.readyState:null},this.getStateMessage=function(){if(!l)return null;switch(this.getStateCode()){case 0:return"HAVE_NOTHING";case 1:return"HAVE_METADATA";case 2:return"HAVE_CURRENT_DATA";case 3:return"HAVE_FUTURE_DATA";case 4:return"HAVE_ENOUGH_DATA";default:return null}},this.getNetworkStateCode=function(){return l?this.sound.networkState:null},this.getNetworkStateMessage=function(){if(!l)return null;switch(this.getNetworkStateCode()){case 0:return"NETWORK_EMPTY";case 1:return"NETWORK_IDLE";case 2:return"NETWORK_LOADING";case 3:return"NETWORK_NO_SOURCE";default:return null}},this.set=function(t,n){return l?(this.sound[t]=n,this):this},this.get=function(t){return l?t?this.sound[t]:this.sound:null},this.bind=function(t,n){if(!l)return this;t=t.split(" ");for(var e=this,i=function(t){n.call(e,t)},u=0;t.length>u;u++){var s=t[u],r=s;s=r.split(".")[0],a.push({idx:r,func:i}),this.sound.addEventListener(s,i,!0)}return this},this.unbind=function(t){if(!l)return this;t=t.split(" ");for(var n=0;t.length>n;n++)for(var e=t[n],i=e.split(".")[0],u=0;a.length>u;u++){var s=a[u].idx.split(".");(a[u].idx==e||s[1]&&s[1]==e.replace(".",""))&&(this.sound.removeEventListener(i,a[u].func,!0),a.splice(u,1))}return this},this.bindOnce=function(t,n){if(!l)return this;var e=this;return h[o++]=!1,this.bind(t+"."+o,function(){h[o]||(h[o]=!0,n.call(e)),e.unbind(t+"."+o)}),this},this.trigger=function(t){if(!l)return this;t=t.split(" ");for(var n=0;t.length>n;n++)for(var e=t[n],i=0;a.length>i;i++){var u=a[i].idx.split(".");if(a[i].idx==e||u[0]&&u[0]==e.replace(".","")){var s=r.createEvent("HTMLEvents");s.initEvent(u[0],!1,!0),this.sound.dispatchEvent(s)}}return this},this.fadeTo=function(n,e,i){function u(){setTimeout(function(){n>s&&n>o.volume?(o.setVolume(o.volume+=1),u()):s>n&&o.volume>n?(o.setVolume(o.volume-=1),u()):i instanceof Function&&i.apply(o)},r)}if(!l)return this;e instanceof Function?(i=e,e=t.defaults.duration):e=e||t.defaults.duration;var s=this.volume,r=e/Math.abs(s-n),o=this;return this.play(),this.whenReady(function(){u()}),this},this.fadeIn=function(t,n){return l?this.setVolume(0).fadeTo(100,t,n):this},this.fadeOut=function(t,n){return l?this.fadeTo(0,t,n):this},this.fadeWith=function(t,n){return l?(this.fadeOut(n,function(){this.stop()}),t.play().fadeIn(n),this):this},this.whenReady=function(t){if(!l)return null;var n=this;0===this.sound.readyState?this.bind("canplay.buzzwhenready",function(){t.call(n)}):t.call(n)},l&&n){for(var d in t.defaults)t.defaults.hasOwnProperty(d)&&(e[d]=e[d]||t.defaults[d]);if(this.sound=r.createElement("audio"),n instanceof Array)for(var c in n)n.hasOwnProperty(c)&&s(this.sound,n[c]);else if(e.formats.length)for(var f in e.formats)e.formats.hasOwnProperty(f)&&s(this.sound,n+"."+e.formats[f]);else s(this.sound,n);e.loop&&this.loop(),e.autoplay&&(this.sound.autoplay="autoplay"),this.sound.preload=e.preload===!0?"auto":e.preload===!1?"none":e.preload,this.setVolume(e.volume),t.sounds.push(this)}},group:function(t){function n(){for(var n=e(null,arguments),i=n.shift(),u=0;t.length>u;u++)t[u][i].apply(t[u],n)}function e(t,n){return t instanceof Array?t:Array.prototype.slice.call(n)}t=e(t,arguments),this.getSounds=function(){return t},this.add=function(n){n=e(n,arguments);for(var i=0;n.length>i;i++)t.push(n[i])},this.remove=function(n){n=e(n,arguments);for(var i=0;n.length>i;i++)for(var u=0;t.length>u;u++)if(t[u]==n[i]){t.splice(u,1);break}},this.load=function(){return n("load"),this},this.play=function(){return n("play"),this},this.togglePlay=function(){return n("togglePlay"),this},this.pause=function(t){return n("pause",t),this},this.stop=function(){return n("stop"),this},this.mute=function(){return n("mute"),this},this.unmute=function(){return n("unmute"),this},this.toggleMute=function(){return n("toggleMute"),this},this.setVolume=function(t){return n("setVolume",t),this},this.increaseVolume=function(t){return n("increaseVolume",t),this},this.decreaseVolume=function(t){return n("decreaseVolume",t),this},this.loop=function(){return n("loop"),this},this.unloop=function(){return n("unloop"),this},this.setTime=function(t){return n("setTime",t),this},this.set=function(t,e){return n("set",t,e),this},this.bind=function(t,e){return n("bind",t,e),this},this.unbind=function(t){return n("unbind",t),this},this.bindOnce=function(t,e){return n("bindOnce",t,e),this},this.trigger=function(t){return n("trigger",t),this},this.fade=function(t,e,i,u){return n("fade",t,e,i,u),this},this.fadeIn=function(t,e){return n("fadeIn",t,e),this},this.fadeOut=function(t,e){return n("fadeOut",t,e),this}},all:function(){return new t.group(t.sounds)},isSupported:function(){return!!t.el.canPlayType},isOGGSupported:function(){return!!t.el.canPlayType&&t.el.canPlayType('audio/ogg; codecs="vorbis"')},isWAVSupported:function(){return!!t.el.canPlayType&&t.el.canPlayType('audio/wav; codecs="1"')},isMP3Supported:function(){return!!t.el.canPlayType&&t.el.canPlayType("audio/mpeg;")},isAACSupported:function(){return!!t.el.canPlayType&&(t.el.canPlayType("audio/x-m4a;")||t.el.canPlayType("audio/aac;"))},toTimer:function(t,n){var e,i,u;return e=Math.floor(t/3600),e=isNaN(e)?"--":e>=10?e:"0"+e,i=n?Math.floor(t/60%60):Math.floor(t/60),i=isNaN(i)?"--":i>=10?i:"0"+i,u=Math.floor(t%60),u=isNaN(u)?"--":u>=10?u:"0"+u,n?e+":"+i+":"+u:i+":"+u},fromTimer:function(t){var n=(""+t).split(":");return n&&3==n.length&&(t=3600*parseInt(n[0],10)+60*parseInt(n[1],10)+parseInt(n[2],10)),n&&2==n.length&&(t=60*parseInt(n[0],10)+parseInt(n[1],10)),t},toPercent:function(t,n,e){var i=Math.pow(10,e||0);return Math.round(100*t/n*i)/i},fromPercent:function(t,n,e){var i=Math.pow(10,e||0);return Math.round(n/100*t*i)/i}};return t}); \ No newline at end of file diff --git a/src/meta/js.js b/src/meta/js.js index 14356019c3..9476141ed1 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -32,7 +32,6 @@ module.exports = function(Meta) { 'public/vendor/tinycon/tinycon.js', 'public/vendor/xregexp/xregexp.js', 'public/vendor/xregexp/unicode/unicode-base.js', - 'public/vendor/buzz/buzz.min.js', 'public/vendor/autosize.js', './node_modules/templates.js/lib/templates.js', 'public/src/utils.js', @@ -84,7 +83,9 @@ module.exports = function(Meta) { // modules listed below are symlinked to public/src/modules so they can be defined anonymously modules: [ './node_modules/chart.js/Chart.js', - './node_modules/mousetrap/mousetrap.js' + './node_modules/mousetrap/mousetrap.js', + + 'public/vendor/buzz/buzz.js' ] } }; diff --git a/src/views/admin/header.tpl b/src/views/admin/header.tpl index ca1bf47f82..476ebda7a6 100644 --- a/src/views/admin/header.tpl +++ b/src/views/admin/header.tpl @@ -37,8 +37,7 @@ paths: { 'forum': '../client', 'admin': '../admin', - 'vendor': '../../vendor', - 'buzz': '../../vendor/buzz/buzz.min' + 'vendor': '../../vendor' } }); diff --git a/src/views/partials/requirejs-config.tpl b/src/views/partials/requirejs-config.tpl index 9ad5ea48fc..2d7332afd9 100644 --- a/src/views/partials/requirejs-config.tpl +++ b/src/views/partials/requirejs-config.tpl @@ -6,8 +6,7 @@ paths: { 'forum': '../client', 'admin': '../admin', - 'vendor': '../../vendor', - 'mousetrap': '../../bower/mousetrap/mousetrap' + 'vendor': '../../vendor' } }); \ No newline at end of file From b73af30a2bb9677aa93d04bbefc30c209a694f6d Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Sat, 12 Mar 2016 10:57:31 -0500 Subject: [PATCH 05/28] added git ignore file for modules directory --- public/src/modules/.gitignore | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 public/src/modules/.gitignore diff --git a/public/src/modules/.gitignore b/public/src/modules/.gitignore new file mode 100644 index 0000000000..d18329c844 --- /dev/null +++ b/public/src/modules/.gitignore @@ -0,0 +1,35 @@ +# Warning: This directory contains auto-generated files (symlinked), and should +# not be tracked by git. If you want to specifically have a file tracked by git, +# please include it in this file. + + + +# Ignore all files in this directory... +/* + +# except these folders... +!/settings + +# and these files... +!/.gitignore +!/alerts.js +!/autocomplete.js +!/chat.js +!/components.js +!/coverPhoto.js +!/csrf.js +!/helpers.js +!/iconSelect.js +!/navigator.js +!/notifications.js +!/postSelect.js +!/search.js +!/settings.js +!/share.js +!/sort.js +!/sounds.js +!/string.js +!/taskbar.js +!/topicSelect.js +!/translator.js +!/uploader.js From ad16c3db6b8a4a0bcc16f075e4d25d1653b49b1a Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 4 Apr 2016 18:51:10 -0400 Subject: [PATCH 06/28] updated Gruntfile to ignore js files in public/src/modules --- Gruntfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Gruntfile.js b/Gruntfile.js index a6aca2083a..f02fa6bf19 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -70,6 +70,7 @@ module.exports = function(grunt) { clientUpdated: { files: [ 'public/src/**/*.js', + '!public/src/modules/*.js', 'node_modules/nodebb-*/*.js', 'node_modules/nodebb-*/**/*.js', '!node_modules/nodebb-*/node_modules/**', 'node_modules/templates.js/lib/templates.js', From 94a505a6bbca6d36332ef723bdf88d3fff3ad72c Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 4 Apr 2016 20:43:21 -0400 Subject: [PATCH 07/28] removed symlink logic and using route bridging instead. Also allowed plugins to define modules from their plugin.json --- Gruntfile.js | 1 - public/src/modules/.gitignore | 35 --------------------------------- src/meta.js | 1 - src/meta/js.js | 37 +++++++++++++---------------------- src/plugins/load.js | 25 ++++++++++++++++++++--- src/webserver.js | 2 +- 6 files changed, 37 insertions(+), 64 deletions(-) delete mode 100644 public/src/modules/.gitignore diff --git a/Gruntfile.js b/Gruntfile.js index f02fa6bf19..a6aca2083a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -70,7 +70,6 @@ module.exports = function(grunt) { clientUpdated: { files: [ 'public/src/**/*.js', - '!public/src/modules/*.js', 'node_modules/nodebb-*/*.js', 'node_modules/nodebb-*/**/*.js', '!node_modules/nodebb-*/node_modules/**', 'node_modules/templates.js/lib/templates.js', diff --git a/public/src/modules/.gitignore b/public/src/modules/.gitignore deleted file mode 100644 index d18329c844..0000000000 --- a/public/src/modules/.gitignore +++ /dev/null @@ -1,35 +0,0 @@ -# Warning: This directory contains auto-generated files (symlinked), and should -# not be tracked by git. If you want to specifically have a file tracked by git, -# please include it in this file. - - - -# Ignore all files in this directory... -/* - -# except these folders... -!/settings - -# and these files... -!/.gitignore -!/alerts.js -!/autocomplete.js -!/chat.js -!/components.js -!/coverPhoto.js -!/csrf.js -!/helpers.js -!/iconSelect.js -!/navigator.js -!/notifications.js -!/postSelect.js -!/search.js -!/settings.js -!/share.js -!/sort.js -!/sounds.js -!/string.js -!/taskbar.js -!/topicSelect.js -!/translator.js -!/uploader.js diff --git a/src/meta.js b/src/meta.js index 78251d4996..ffc85c98bf 100644 --- a/src/meta.js +++ b/src/meta.js @@ -61,7 +61,6 @@ var async = require('async'), async.apply(plugins.clearRequireCache), async.apply(plugins.reload), async.apply(plugins.reloadRoutes), - async.apply(Meta.js.symlinkModules), async.apply(Meta.css.minify), async.apply(Meta.js.minify, 'nodebb.min.js'), async.apply(Meta.js.minify, 'acp.min.js'), diff --git a/src/meta/js.js b/src/meta/js.js index eaa7824705..168dce916c 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -6,7 +6,6 @@ var winston = require('winston'), async = require('async'), nconf = require('nconf'), fs = require('fs'), - rimraf = require('rimraf'), file = require('../file'), plugins = require('../plugins'), emitter = require('../emitter'), @@ -79,7 +78,7 @@ module.exports = function(Meta) { 'public/src/modules/string.js' ], - // modules listed below are symlinked to public/src/modules so they can be defined anonymously + // modules listed below are routed through express (/src/modules) so they can be defined anonymously modules: [ './node_modules/chart.js/Chart.js', './node_modules/mousetrap/mousetrap.js', @@ -89,38 +88,30 @@ module.exports = function(Meta) { } }; - Meta.js.symlinkModules = function(callback) { - // Symlink all defined modules to /public/src/modules - var modulesLoaded = 0, - targetPath; + Meta.js.bridgeModules = function(app, callback) { + // Add routes for AMD-type modules to serve those files + console.log('bridging modules:', Meta.js.scripts.modules); + var numBridged = 0; async.series([ function(next) { async.each(Meta.js.scripts.modules, function(localPath, next) { - targetPath = path.join(__dirname, '../../public/src/modules', path.basename(localPath)); - - async.waterfall([ - async.apply(fs.access, localPath, fs.R_OK), - async.apply(rimraf, targetPath), - async.apply(fs.link, localPath, targetPath) - ], function(err) { - if (err) { - winston.error('[meta/js] Could not symlink `' + localPath + '` to modules folder'); - } else { - winston.verbose('[meta/js] Symlinked `' + localPath + '` to modules folder'); - ++modulesLoaded; - } - - next(err); + app.get(path.join('/src/modules/', path.basename(localPath)), function(req, res) { + return res.sendFile(path.join(__dirname, '../../', localPath), { + maxAge: app.enabled('cache') ? 5184000000 : 0 + }); }); + + ++numBridged; + next(); }, next); } ], function(err) { if (err) { - winston.error('[meta/js] Encountered error while symlinking modules:' + err.message); + winston.error('[meta/js] Encountered error while bridging modules:' + err.message); } - winston.verbose('[meta/js] ' + modulesLoaded + ' of ' + Meta.js.scripts.modules.length + ' modules symlinked'); + winston.verbose('[meta/js] ' + numBridged + ' of ' + Meta.js.scripts.modules.length + ' modules bridged'); callback(err); }); }; diff --git a/src/plugins/load.js b/src/plugins/load.js index cf1ff27d9a..676008a85c 100644 --- a/src/plugins/load.js +++ b/src/plugins/load.js @@ -7,8 +7,10 @@ var fs = require('fs'), winston = require('winston'), nconf = require('nconf'), _ = require('underscore'), - file = require('../file'), - utils = require('../../public/src/utils'); + file = require('../file'); + +var utils = require('../../public/src/utils'), + meta = require('../meta'); module.exports = function(Plugins) { @@ -40,6 +42,9 @@ module.exports = function(Plugins) { function(next) { mapClientSideScripts(pluginData, next); }, + function(next) { + mapClientModules(pluginData, next); + }, function(next) { loadLanguages(pluginData, next); } @@ -163,7 +168,21 @@ module.exports = function(Plugins) { } callback(); - } + }; + + function mapClientModules(pluginData, callback) { + if (Array.isArray(pluginData.modules)) { + if (global.env === 'development') { + winston.verbose('[plugins] Found ' + pluginData.modules.length + ' AMD-style module(s) for plugin ' + pluginData.id); + } + + meta.js.scripts.modules = meta.js.scripts.modules.concat(pluginData.modules.map(function(file) { + return path.join('./node_modules/', pluginData.id, file); + })); + } + + callback(); + }; function loadLanguages(pluginData, callback) { if (typeof pluginData.languages !== 'string') { diff --git a/src/webserver.js b/src/webserver.js index 03375c4281..e667862561 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -84,10 +84,10 @@ function initializeNodeBB(callback) { function(next) { plugins.init(app, middleware, next); }, + async.apply(meta.js.bridgeModules, app), function(next) { async.series([ async.apply(meta.templates.compile), - async.apply(meta.js.symlinkModules), async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, 'nodebb.min.js'), async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, 'acp.min.js'), async.apply(meta.css.minify), From b6a10c77293d5a5993b8412470c89e4803ce4fbe Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 4 Apr 2016 21:26:49 -0400 Subject: [PATCH 08/28] removed console log --- src/meta/js.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/meta/js.js b/src/meta/js.js index 168dce916c..63c265a9cf 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -90,7 +90,6 @@ module.exports = function(Meta) { Meta.js.bridgeModules = function(app, callback) { // Add routes for AMD-type modules to serve those files - console.log('bridging modules:', Meta.js.scripts.modules); var numBridged = 0; async.series([ From 50ae2305b09f2c88290999cc781bd747c5178c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 5 Apr 2016 19:51:39 +0300 Subject: [PATCH 09/28] up emoji add apple --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b1a5794ac..6956893567 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "nconf": "~0.8.2", "nodebb-plugin-composer-default": "3.0.18", "nodebb-plugin-dbsearch": "1.0.1", - "nodebb-plugin-emoji-extended": "1.0.3", + "nodebb-plugin-emoji-apple": "1.0.3", + "nodebb-plugin-emoji-extended": "1.0.5", "nodebb-plugin-markdown": "5.0.1", "nodebb-plugin-mentions": "1.0.21", "nodebb-plugin-soundpack-default": "0.1.6", From 04fb7d5acc5872ad9e5ec54a2ccda9262ab33583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 5 Apr 2016 21:01:13 +0300 Subject: [PATCH 10/28] enable emoji-apple on install --- src/install.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/install.js b/src/install.js index 846f6f9050..aae92e5c23 100644 --- a/src/install.js +++ b/src/install.js @@ -440,7 +440,8 @@ function enableDefaultPlugins(next) { 'nodebb-widget-essentials', 'nodebb-rewards-essentials', 'nodebb-plugin-soundpack-default', - 'nodebb-plugin-emoji-extended' + 'nodebb-plugin-emoji-extended', + 'nodebb-plugin-emoji-apple' ], customDefaults = nconf.get('defaultPlugins'); From f406119fa1dd60a3fdbdea4630f2f05b961b77d9 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 5 Apr 2016 16:20:16 -0400 Subject: [PATCH 11/28] upped composer version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6956893567..53958971bd 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "mongodb": "~2.1.3", "morgan": "^1.3.2", "nconf": "~0.8.2", - "nodebb-plugin-composer-default": "3.0.18", + "nodebb-plugin-composer-default": "3.0.19", "nodebb-plugin-dbsearch": "1.0.1", "nodebb-plugin-emoji-apple": "1.0.3", "nodebb-plugin-emoji-extended": "1.0.5", From 053bbc06fa0c0df3726905feddc69f3ce629f04c Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 5 Apr 2016 20:07:55 -0400 Subject: [PATCH 12/28] fixes apapadimoulis/what-bugs#84 closes #4496 --- public/src/client/topic/posts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index 696b2f51ec..b79067ec3b 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -304,7 +304,7 @@ define('forum/topic/posts', [ }); image.attr('src', image.attr('data-src')); - if (image.parent().attr('href')) { + if (image.parent().attr('href') === 'about:blank') { image.parent().attr('href', image.attr('data-src')); } image.removeAttr('data-src'); From bf73c0de5f028f04882e8522045cb3f8ef5d4c94 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 5 Apr 2016 21:34:53 -0400 Subject: [PATCH 13/28] closes #3286 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 53958971bd..f00ed4dcac 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,8 @@ "nodebb-plugin-spam-be-gone": "0.4.6", "nodebb-rewards-essentials": "0.0.8", "nodebb-theme-lavender": "3.0.9", - "nodebb-theme-persona": "4.0.115", - "nodebb-theme-vanilla": "5.0.61", + "nodebb-theme-persona": "4.0.117", + "nodebb-theme-vanilla": "5.0.62", "nodebb-widget-essentials": "2.0.9", "nodemailer": "2.0.0", "nodemailer-sendmail-transport": "1.0.0", From 0d0e4fa94feb1803fcb83d192db184b5d93c4855 Mon Sep 17 00:00:00 2001 From: Ole R Date: Wed, 6 Apr 2016 23:57:45 +0200 Subject: [PATCH 14/28] Update dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f00ed4dcac..b194a0484a 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,8 @@ "nconf": "~0.8.2", "nodebb-plugin-composer-default": "3.0.19", "nodebb-plugin-dbsearch": "1.0.1", - "nodebb-plugin-emoji-apple": "1.0.3", - "nodebb-plugin-emoji-extended": "1.0.5", + "nodebb-plugin-emoji-one": "1.1.0", + "nodebb-plugin-emoji-extended": "1.1.0", "nodebb-plugin-markdown": "5.0.1", "nodebb-plugin-mentions": "1.0.21", "nodebb-plugin-soundpack-default": "0.1.6", From 5023935baf2cc1d75d0a4285fe39b5c0f130e6e9 Mon Sep 17 00:00:00 2001 From: Ole R Date: Wed, 6 Apr 2016 23:58:48 +0200 Subject: [PATCH 15/28] Enable nodebb-plugin-emoji-one by default --- src/install.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/install.js b/src/install.js index aae92e5c23..900a0e3ee4 100644 --- a/src/install.js +++ b/src/install.js @@ -441,7 +441,7 @@ function enableDefaultPlugins(next) { 'nodebb-rewards-essentials', 'nodebb-plugin-soundpack-default', 'nodebb-plugin-emoji-extended', - 'nodebb-plugin-emoji-apple' + 'nodebb-plugin-emoji-one' ], customDefaults = nconf.get('defaultPlugins'); From 430adc366c18573fce174a89e699fdc324f1769d Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 6 Apr 2016 21:49:43 -0400 Subject: [PATCH 16/28] fix #4498 --- public/src/modules/navigator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/modules/navigator.js b/public/src/modules/navigator.js index 3d65f6b8a0..0d1747598c 100644 --- a/public/src/modules/navigator.js +++ b/public/src/modules/navigator.js @@ -131,7 +131,7 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com } // If a threshold is undefined, try to determine one based on new index - if (threshold === undefined) { + if (threshold === undefined && ajaxify.data.template.topic === true) { if (atTop) { threshold = 0; } else { From 2e65e8ae7d5845d64e3615bb4d4b1e333d8bdbc7 Mon Sep 17 00:00:00 2001 From: NodeBB Misty Date: Thu, 7 Apr 2016 09:02:29 -0400 Subject: [PATCH 17/28] Latest translations and fallbacks --- public/language/ms/notifications.json | 12 ++++++------ public/language/ms/uploads.json | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/public/language/ms/notifications.json b/public/language/ms/notifications.json index dab972b82d..51291962f1 100644 --- a/public/language/ms/notifications.json +++ b/public/language/ms/notifications.json @@ -13,15 +13,15 @@ "new_message_from": "Pesanan baru daripada %1", "upvoted_your_post_in": "%1 telah mengundi naik kiriman and di %2.", "upvoted_your_post_in_dual": "%1dan %2 telah menambah undi pada kiriman anda di %3.", - "upvoted_your_post_in_multiple": "%1 dan %2 lagi telah menambah undi pada kiriman anda di %3. ", + "upvoted_your_post_in_multiple": "%1 dan %2 lagi telah menambah undi pada kiriman anda di %3.", "moved_your_post": "%1 telah memindahkan kiriman anda ke %2", "moved_your_topic": "%1 telah memindahkan %2", - "favourited_your_post_in": "%1 has bookmarked your post in %2.", - "favourited_your_post_in_dual": "%1 and %2 have bookmarked your post in %3.", - "favourited_your_post_in_multiple": "%1 and %2 others have bookmarked your post in %3.", + "favourited_your_post_in": "%1 telah menyukai kiriman anda di %2.", + "favourited_your_post_in_dual": "%1 dan %2 telah menyukai kiriman anda di %3.", + "favourited_your_post_in_multiple": "%1 dan %2 yang lain, telah menyukai kiriman anda di %3.", "user_flagged_post_in": "%1 menanda kiriman anda di %2", "user_flagged_post_in_dual": "%1 dan %2 telah menanda kiriman anda pada %3", - "user_flagged_post_in_multiple": "%1 dan %2 lagi telah mendanda kiriman anda pada %3", + "user_flagged_post_in_multiple": "%1 dan %2 lagi telah menanda kiriman anda pada %3", "user_posted_to": "%1 telah membalas kiriman kepada: %2", "user_posted_to_dual": "%1 dan %2 membalas kiriman : %3", "user_posted_to_multiple": "%1 dan %2 lagu membalas kiriman: %3", @@ -30,7 +30,7 @@ "user_started_following_you_dual": "%1 dan %2 mula mengikuti anda.", "user_started_following_you_multiple": "%1 dan %2 lagi mula mengikuti anda.", "new_register": "%1 menghantar jemputan pendaftaran.", - "new_register_multiple": "There are %1 registration requests awaiting review.", + "new_register_multiple": "Ada %1 permohonan ingin daftar yang sedang menunggu pengesahan.", "email-confirmed": "Emel Disahkan", "email-confirmed-message": "Terima kasih kerana mengesahkan emel anda. Akaun anda telah diaktifkan sepenuhnya.", "email-confirm-error-message": "Berlaku masalah semasa mengesahkan emel anda. Mungkin kod tidak sah atau tamat tempoh.", diff --git a/public/language/ms/uploads.json b/public/language/ms/uploads.json index 1622cb5693..c637c43fad 100644 --- a/public/language/ms/uploads.json +++ b/public/language/ms/uploads.json @@ -1,6 +1,6 @@ { - "uploading-file": "Uploading the file...", - "select-file-to-upload": "Select a file to upload!", - "upload-success": "File uploaded successfully!", - "maximum-file-size": "Maximum %1 kb" + "uploading-file": "Sedang memuatnaik fail...", + "select-file-to-upload": "Pilih fail yang hendak dimuatnaik!", + "upload-success": "Muatnaik fail berjaya!", + "maximum-file-size": "Maksima %1 kb" } \ No newline at end of file From ba44db5b5b6450c49226a18d1304c4e0de45b1e8 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 7 Apr 2016 10:47:13 -0400 Subject: [PATCH 18/28] updated dependency check logic to better handle missing dependencies --- app.js | 4 ++++ src/meta/dependencies.js | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index ed5238285e..fa8964fb35 100644 --- a/app.js +++ b/app.js @@ -207,6 +207,10 @@ function start() { winston.warn('One or more of NodeBB\'s dependent packages are out-of-date. Please run the following command to update them:'); winston.warn(' ./nodebb upgrade'); break; + case 'dependencies-missing': + winston.warn('One or more of NodeBB\'s dependent packages are missing. Please run the following command to update them:'); + winston.warn(' ./nodebb upgrade'); + break; default: if (err.stacktrace !== false) { winston.error(err.stack); diff --git a/src/meta/dependencies.js b/src/meta/dependencies.js index 5482ad3e7f..7da86113cf 100644 --- a/src/meta/dependencies.js +++ b/src/meta/dependencies.js @@ -12,7 +12,9 @@ module.exports = function(Meta) { Meta.dependencies = {}; Meta.dependencies.check = function(callback) { - var modules = Object.keys(pkg.dependencies); + var modules = Object.keys(pkg.dependencies), + depsOutdated = false, + depsMissing = false; winston.verbose('Checking dependencies for outdated modules'); async.every(modules, function(module, next) { @@ -33,15 +35,23 @@ module.exports = function(Meta) { next(true); } else { process.stdout.write('[' + 'outdated'.yellow + '] ' + module.bold + ' installed v' + pkgData.version + ', package.json requires ' + pkg.dependencies[module] + '\n'); - next(false); + depsOutdated = true; + next(true); } } catch(e) { - winston.error('[meta/dependencies] Could not read: ' + module); - process.exit(); + process.stdout.write('[' + 'missing'.red + '] ' + module.bold + ' is a required dependency but could not be found\n'); + depsMissing = true; + next(true); } }); }, function(ok) { - callback(!ok && global.env !== 'development' ? new Error('dependencies-out-of-date') : null); + if (depsMissing) { + callback(new Error('dependencies-missing')); + } else if (depsOutdated) { + callback(global.env !== 'development' ? new Error('dependencies-out-of-date') : null); + } else { + callback(null); + } }); }; }; From a9f966f23c4e56189fdfeae27a2111c312eff0e4 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 7 Apr 2016 11:32:18 -0400 Subject: [PATCH 19/28] closes #4503, /cc @BenLubar --- package.json | 4 ++-- public/language/en_GB/user.json | 3 +++ public/src/client/topic/posts.js | 2 +- src/controllers/api.js | 1 + src/user/settings.js | 2 ++ 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 85b43ccb9f..18a2444b9e 100644 --- a/package.json +++ b/package.json @@ -56,8 +56,8 @@ "nodebb-plugin-spam-be-gone": "0.4.6", "nodebb-rewards-essentials": "0.0.8", "nodebb-theme-lavender": "3.0.9", - "nodebb-theme-persona": "4.0.117", - "nodebb-theme-vanilla": "5.0.62", + "nodebb-theme-persona": "4.0.118", + "nodebb-theme-vanilla": "5.0.63", "nodebb-widget-essentials": "2.0.9", "nodemailer": "2.0.0", "nodemailer-sendmail-transport": "1.0.0", diff --git a/public/language/en_GB/user.json b/public/language/en_GB/user.json index 07c85aa19f..a6ae357177 100644 --- a/public/language/en_GB/user.json +++ b/public/language/en_GB/user.json @@ -104,6 +104,9 @@ "enable_topic_searching": "Enable In-Topic Searching", "topic_search_help": "If enabled, in-topic searching will override the browser's default page search behaviour and allow you to search through the entire topic, instead of what is only shown on screen", + "delay_image_loading": "Delay Image Loading", + "image_load_delay_help": "If enabled, images in topics will not load until they are scrolled into view", + "scroll_to_my_post": "After posting a reply, show the new post", "follow_topics_you_reply_to": "Follow topics that you reply to", diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index b79067ec3b..996dcbc6b9 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -263,7 +263,7 @@ define('forum/topic/posts', [ var images = components.get('post/content').find('img[data-state="unloaded"]'), visible = images.filter(function() { - return utils.isElementInViewport(this); + return config.delayImageLoading ? utils.isElementInViewport(this) : true; }), scrollTop = $(window).scrollTop(), adjusting = false, diff --git a/src/controllers/api.js b/src/controllers/api.js index 77ae7131ad..8a109aa9df 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -79,6 +79,7 @@ apiController.getConfig = function(req, res, next) { config.topicPostSort = settings.topicPostSort || config.topicPostSort; config.categoryTopicSort = settings.categoryTopicSort || config.categoryTopicSort; config.topicSearchEnabled = settings.topicSearchEnabled || false; + config.delayImageLoading = settings.delayImageLoading !== undefined ? settings.delayImageLoading : true; config.bootswatchSkin = settings.bootswatchSkin || config.bootswatchSkin; next(null, config); }); diff --git a/src/user/settings.js b/src/user/settings.js index 04e23e1152..e37e012f7e 100644 --- a/src/user/settings.js +++ b/src/user/settings.js @@ -75,6 +75,7 @@ module.exports = function(User) { settings.sendPostNotifications = parseInt(getSetting(settings, 'sendPostNotifications', 0), 10) === 1; settings.restrictChat = parseInt(getSetting(settings, 'restrictChat', 0), 10) === 1; settings.topicSearchEnabled = parseInt(getSetting(settings, 'topicSearchEnabled', 0), 10) === 1; + settings.delayImageLoading = parseInt(getSetting(settings, 'delayImageLoading', 1), 10) === 1; settings.bootswatchSkin = settings.bootswatchSkin || 'default'; settings.scrollToMyPost = parseInt(getSetting(settings, 'scrollToMyPost', 1), 10) === 1; @@ -120,6 +121,7 @@ module.exports = function(User) { sendPostNotifications: data.sendPostNotifications, restrictChat: data.restrictChat, topicSearchEnabled: data.topicSearchEnabled, + delayImageLoading: data.delayImageLoading, groupTitle: data.groupTitle, homePageRoute: data.homePageCustom || data.homePageRoute, scrollToMyPost: data.scrollToMyPost From c88ed663120fdeafee404a4ba5678188e3742102 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 7 Apr 2016 16:55:41 -0400 Subject: [PATCH 20/28] closes #4502 --- src/meta/css.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/meta/css.js b/src/meta/css.js index 12c5d49c20..264267d7c6 100644 --- a/src/meta/css.js +++ b/src/meta/css.js @@ -68,6 +68,7 @@ module.exports = function(Meta) { source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/css/smoothness/jquery-ui-1.10.4.custom.min.css";'; source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";'; + source += '\n@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";'; source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/flags.less";'; source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/blacklist.less";'; source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/generics.less";'; From 0449e014f669050677ac08a392896274bc2bf58f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 7 Apr 2016 17:47:17 -0400 Subject: [PATCH 21/28] updated some help text --- src/controllers/accounts/edit.js | 4 +++- src/views/admin/settings/uploads.tpl | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/controllers/accounts/edit.js b/src/controllers/accounts/edit.js index 09e824ecd9..2ae429b248 100644 --- a/src/controllers/accounts/edit.js +++ b/src/controllers/accounts/edit.js @@ -126,7 +126,9 @@ editController.uploadPicture = function (req, res, next) { } ], function(err, image) { fs.unlink(userPhoto.path, function(err) { - winston.error('unable to delete picture ' + userPhoto.path, err); + if (err) { + winston.warn('[user/picture] Unable to delete picture ' + userPhoto.path, err); + } }); if (err) { return next(err); diff --git a/src/views/admin/settings/uploads.tpl b/src/views/admin/settings/uploads.tpl index 76b053332b..4881f8dcd7 100644 --- a/src/views/admin/settings/uploads.tpl +++ b/src/views/admin/settings/uploads.tpl @@ -91,16 +91,25 @@
    +

    + (in pixels, default: 128 pixels) +

    +

    + (in kilobytes, default: 256 KiB) +

    +

    + (in kilobytes, default: 2,048 KiB) +

    From 4105565ed1cbd5f209d2d1a2e16e67ea0cde67e5 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 7 Apr 2016 17:50:53 -0400 Subject: [PATCH 22/28] upped composer version @BenLubar @RaceProUK --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18a2444b9e..a973a3e5b1 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "morgan": "^1.3.2", "mousetrap": "^1.5.3", "nconf": "~0.8.2", - "nodebb-plugin-composer-default": "3.0.19", + "nodebb-plugin-composer-default": "3.0.20", "nodebb-plugin-dbsearch": "1.0.1", "nodebb-plugin-emoji-one": "1.1.0", "nodebb-plugin-emoji-extended": "1.1.0", From c89a02bfb910c52d2550f58f6b6b2362b0f5bc5c Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 7 Apr 2016 17:53:11 -0400 Subject: [PATCH 23/28] upped composer again --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a973a3e5b1..d817fbd210 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "morgan": "^1.3.2", "mousetrap": "^1.5.3", "nconf": "~0.8.2", - "nodebb-plugin-composer-default": "3.0.20", + "nodebb-plugin-composer-default": "3.0.21", "nodebb-plugin-dbsearch": "1.0.1", "nodebb-plugin-emoji-one": "1.1.0", "nodebb-plugin-emoji-extended": "1.1.0", From e481ed21eb056fd4c37a779c8df20b4c7771b36f Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 7 Apr 2016 21:22:56 -0400 Subject: [PATCH 24/28] Using pid as discriminator for mergeId ... for favourite and upvote notifications. --- src/socket.io/helpers.js | 2 +- src/socket.io/posts/favourites.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/socket.io/helpers.js b/src/socket.io/helpers.js index 12a0e9d9b5..e4621811ca 100644 --- a/src/socket.io/helpers.js +++ b/src/socket.io/helpers.js @@ -80,7 +80,7 @@ SocketHelpers.sendNotificationToPostOwner = function(pid, fromuid, notification) pid: pid, nid: 'post:' + pid + ':uid:' + fromuid, from: fromuid, - mergeId: notification + '|' + postData.tid, + mergeId: notification + '|' + pid, topicTitle: results.topicTitle }, function(err, notification) { if (!err && notification) { diff --git a/src/socket.io/posts/favourites.js b/src/socket.io/posts/favourites.js index 6883ece06a..3d93afac08 100644 --- a/src/socket.io/posts/favourites.js +++ b/src/socket.io/posts/favourites.js @@ -124,11 +124,11 @@ module.exports = function(SocketPosts) { /* hooks: - filter.post.upvote - filter.post.downvote - filter.post.unvote - filter.post.favourite - filter.post.unfavourite + filter:post.upvote + filter:post.downvote + filter:post.unvote + filter:post.favourite + filter:post.unfavourite */ plugins.fireHook('filter:post.' + command, {data: data, uid: socket.uid}, function(err, filteredData) { if (err) { From a81285befa35899a8bd9c6aea656bf1fc2073903 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 8 Apr 2016 18:09:35 +0300 Subject: [PATCH 25/28] dont crash if category doesn't exist --- src/controllers/admin/categories.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/controllers/admin/categories.js b/src/controllers/admin/categories.js index 5444a087ea..04001e0f65 100644 --- a/src/controllers/admin/categories.js +++ b/src/controllers/admin/categories.js @@ -6,7 +6,7 @@ var categories = require('../../categories'); var privileges = require('../../privileges'); var analytics = require('../../analytics'); var plugins = require('../../plugins'); -var translator = require('../../../public/src/modules/translator') +var translator = require('../../../public/src/modules/translator'); var categoriesController = {}; @@ -19,12 +19,17 @@ categoriesController.get = function(req, res, next) { if (err) { return next(err); } + var category = data.category[0]; - plugins.fireHook('filter:admin.category.get', { req: req, res: res, category: data.category[0], privileges: data.privileges }, function(err, data) { + if (!category) { + return next(); + } + + plugins.fireHook('filter:admin.category.get', { req: req, res: res, category: category, privileges: data.privileges }, function(err, data) { if (err) { return next(err); } - data.category.name = translator.escape(data.category.name); + data.category.name = translator.escape(String(data.category.name)); res.render('admin/manage/category', { category: data.category, privileges: data.privileges From e23377580d3c02c7fa9148333e6e0e4685008e22 Mon Sep 17 00:00:00 2001 From: pichalite Date: Fri, 8 Apr 2016 23:55:10 +0000 Subject: [PATCH 26/28] fixes #4506 --- src/messaging/notifications.js | 2 +- src/views/emails/notif_chat.tpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/messaging/notifications.js b/src/messaging/notifications.js index c93cb16590..61f4f5d9ce 100644 --- a/src/messaging/notifications.js +++ b/src/messaging/notifications.js @@ -96,7 +96,7 @@ module.exports = function(Messaging) { message: messageObj, site_title: meta.config.title || 'NodeBB', url: nconf.get('url'), - fromUserslug: utils.slugify(messageObj.fromUser.username) + roomId: messageObj.roomId }, next); }, callback); }); diff --git a/src/views/emails/notif_chat.tpl b/src/views/emails/notif_chat.tpl index a0669f3bac..f1d5a5fc42 100644 --- a/src/views/emails/notif_chat.tpl +++ b/src/views/emails/notif_chat.tpl @@ -3,7 +3,7 @@

    {summary}:

    {message.content}
    -[[email:notif.chat.cta]] +[[email:notif.chat.cta]] From 006496efe350ed6d1dd82060b80c174b6a9635c2 Mon Sep 17 00:00:00 2001 From: Raphael Beer Date: Sun, 10 Apr 2016 14:09:33 +0200 Subject: [PATCH 27/28] Add pid to teaser ajaxify data --- src/controllers/categories.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/categories.js b/src/controllers/categories.js index 7ed087c704..aa882b9b43 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -66,7 +66,8 @@ categoriesController.list = function(req, res, next) { if (category && Array.isArray(category.posts) && category.posts.length) { category.teaser = { url: nconf.get('relative_path') + '/topic/' + category.posts[0].topic.slug + '/' + category.posts[0].index, - timestampISO: category.posts[0].timestampISO + timestampISO: category.posts[0].timestampISO, + pid: category.posts[0].pid }; } }); From f7ac1d89ffad60d810d639f53ca4303d9574021c Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 11 Apr 2016 14:40:54 +0300 Subject: [PATCH 28/28] fix undefined next --- src/routes/feeds.js | 4 ++-- src/sitemap.js | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/routes/feeds.js b/src/routes/feeds.js index bfa2945fb5..09f3f1826e 100644 --- a/src/routes/feeds.js +++ b/src/routes/feeds.js @@ -107,7 +107,7 @@ function generateForUserTopics(req, res, callback) { } ], function(err, userData) { if (err) { - return next(err); + return callback(err); } generateForTopics({ @@ -116,7 +116,7 @@ function generateForUserTopics(req, res, callback) { description: 'A list of topics that are posted by ' + userData.username, feed_url: '/user/' + userslug + '/topics.rss', site_url: '/user/' + userslug + '/topics' - }, 'uid:' + userData.uid + ':topics', req, res, next); + }, 'uid:' + userData.uid + ':topics', req, res, callback); }); } diff --git a/src/sitemap.js b/src/sitemap.js index 4c7efb73b5..00bb195809 100644 --- a/src/sitemap.js +++ b/src/sitemap.js @@ -1,16 +1,15 @@ 'use strict'; -var path = require('path'), - async = require('async'), - sm = require('sitemap'), - url = require('url'), - nconf = require('nconf'), - db = require('./database'), - categories = require('./categories'), - topics = require('./topics'), - privileges = require('./privileges'), - meta = require('./meta'), - utils = require('../public/src/utils'); +var async = require('async'); +var sm = require('sitemap'); +var nconf = require('nconf'); + +var db = require('./database'); +var categories = require('./categories'); +var topics = require('./topics'); +var privileges = require('./privileges'); +var meta = require('./meta'); +var utils = require('../public/src/utils'); var sitemap = { maps: { @@ -88,7 +87,7 @@ sitemap.getPages = function(callback) { changefreq: 'daily', priority: '0.4' }]; - + sitemap.maps.pages = sm.createSitemap({ hostname: nconf.get('url'), cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours