<commit_before>/*
 ---

 script: create.js

 description: core content control creation and plugin loading routines

 copyright: (c) 2011 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI

 provides: [MUI.create, MUI.load, MUI.addPluginGroup, MUI.loadPluginGroups]

 ...
 */

MUI.append({

	addPluginGroup: function(group, name){
		MUI.options.pluginGroups[name] = group;
		MUI.options.path[name] = group.path;
	},

	loadPluginGroups:function(onload){
		var js = [];
		Object.each(MUI.options.pluginGroups, function(group, name){
			if (MUI.files['{' + name + '}mui-' + name + '.js'] != 'loaded'){
				MUI[name] = [];
				js = js.append(['{' + name + '}mui-' + name + '.js']);
			}
		});
		if (js.length > 0) new MUI.Require({'js':js, 'onload':onload });
		else return false;  // returns false to signal that everything is loaded
		return true;   // returns true to signal that it loading something
	},

	load:function(options){
		// convert none hash parameters to hash
		if (typeOf(options) == 'string') options = {control:options, loadOnly:true,onload:(arguments.length > 0) ? arguments[1] : null};
		if (typeOf(options) == 'array'){
			var controls = [];
			for (var j = 0; j < options.length; j++)
				controls.push({control:options[j]});
			options = {controls:controls, onload:(arguments.length > 1) ? arguments[1] : null, loadOnly:true};
		}
		if (typeOf(options) == 'object'){
			options.loadOnly = true;
		}
		MUI.create(options);
	},

	getControlAssets : function(control, js, css, traversed, name){
		if (typeOf(control) == 'string') control = {control:control};
		if (!traversed) traversed = [control.control];
		if (!name) name = control.control;
		name = name.replace(/(^MUI\.)/i, '');
		var cname = name.toLowerCase();

		// try and locate the requested item
		var config;
		var pgName;
		Object.each(MUI.options.pluginGroups, function(group, name){
			if (MUI[name][cname] != null){
				pgName = name;
				config = MUI[name][cname];
			}
		});
		if (config == null) return {js:js,css:css,config:null};

		// see if we can gather all of the dependency controls
		var dependsOn = config.dependsOn ? config.dependsOn : [];	// add configured dependencies if they exist
		if (config.childNode && control[config.childNode]){			// add child controls of the control has a childnode configured
			var children = control[config.childNode];
			if (typeof(children) != 'array') children = [children];				// some controls allow child nodes to be an array or a single node
			Object.each(control[config.childNode], function(child){
				var controlname = (child.control ? child.control : config.childType);
				if (typeof(controlname) == 'string'){
					traversed.include(controlname);
					MUI.getControlAssets(child, js, css, traversed, controlname);
				}
			})
		}
		// gather dependencies if we have some
		if (dependsOn.length > 0){
			Object.each(dependsOn, function(controlname){
				if (traversed.indexOf(controlname) >= 0 || control.control == controlname) return;  // make sure we do get into a runaway recursion
				MUI.getControlAssets(controlname, js, css, traversed);
			})
		}

		var path = {};
		var sname = MUI.options.pluginGroups[pgName].singularName;
		if (!config.location) config.location = cname;
		path[sname] = '{' + pgName + '}' + config.location + '/';

		if (config.paths) Object.each(config.paths, function(tpath, name){
			MUI.options.path[name] = MUI.replaceFields(tpath, path);
		});

		if (!config.js) js.push(path[sname] + cname + '.js');
		else js.combine(config.js);
		js = MUI.replaceFields(js, path);

		if (config.css) css.combine(config.css);
		css.combine(MUI.options.css);
		css = MUI.replaceFields(css, path);

		return {js:js,css:css,config:config};
	},

	areLoaded: function(listToCheck){
		for (var i = 0; i < listToCheck.length; i++){
			if (MUI.files[listToCheck[i]] != 'loaded') return false;
		}
		return true;
	},

	create:function(options){
		// convert none hash parameters to hash
		if (typeOf(options) == 'string') options = {control:options,onload:(arguments.length > 1) ? arguments[1] : null};
		if (!MUI.initialized) MUI.initialize(); // initialize mocha if needed

		if (this.loadPluginGroups(function(){ // make sure all all plugin/control group configurations are loaded
			MUI.create(options);
		})) return;

		// convert array of plugin names to controls request
		var controls = options.controls;
		if (!controls) controls = [];
		if (typeOf(options) == 'array'){
			for (var j = 0; j < options.length; j++)
				controls.push({control:options[j]});
			options = {controls:controls,onload:options.onload};
		}

		if (controls.length == 0) controls = [options]; // make sure we have an array for list of controls to load

		// gather all of the assests for the requested controls/plugins
		var r = {js:[],css:[],traversed:(MUI.traversed ? MUI.traversed : [])};
		var config;
		for (var i = 0; i < controls.length; i++){
			if (!controls[i].control) return;
			if (controls[i].fromHTML && controls[i].drawOnInit === undefined) controls[i].drawOnInit = false;
			config = MUI.getControlAssets(controls[i], r.js, r.css, r.traversed).config;
		}

		// if only one control was requested and it is loaded then return it
		if (controls.length == 1 && r.js.length > 0 && this.areLoaded[r.js]){
			if ((config && config.loadOnly) || options.loadOnly){
				if (config.onload) config.onload(config);
				return null;
			}
			var name = controls[0].control.replace(/(^MUI\.)/i, '');
			var klass = MUI[name];
			var obj = new klass(options);
			if (options.onNew) options.onNew(obj);
			if (options.fromHTML && obj.fromHTML) obj.fromHTML(options.content);
			new MUI.Require(r);
			return obj;
		}

		// build a callback function for the assests requested
		r.onload = function(){
			MUI.traversed = (MUI.traversed ? MUI.traversed : []).combine(r.traversed);
			if (this.onload) this.onload(this);

			controls.each(function(control){
				if (control.loadOnly || this.loadOnly) return;
				if (control.onload) control.onload(control);
				var name = control.control.replace(/(^MUI\.)/i, '');
				var klass = MUI[name];
				var obj = new klass(control);
				if (control.onNew) control.onNew(obj);
				if (control.fromHTML && obj.fromHTML) obj.fromHTML(options.content);
			}.bind(this));

		}.bind(options);
		new MUI.Require(r);
	}

});
<commit_msg>fix create when array of controls passed in<commit_after>/*
 ---

 script: create.js

 description: core content control creation and plugin loading routines

 copyright: (c) 2011 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI

 provides: [MUI.create, MUI.load, MUI.addPluginGroup, MUI.loadPluginGroups]

 ...
 */

MUI.append({

	addPluginGroup: function(group, name){
		MUI.options.pluginGroups[name] = group;
		MUI.options.path[name] = group.path;
	},

	loadPluginGroups:function(onload){
		var js = [];
		Object.each(MUI.options.pluginGroups, function(group, name){
			if (MUI.files['{' + name + '}mui-' + name + '.js'] != 'loaded'){
				MUI[name] = [];
				js = js.append(['{' + name + '}mui-' + name + '.js']);
			}
		});
		if (js.length > 0) new MUI.Require({'js':js, 'onload':onload });
		else return false;  // returns false to signal that everything is loaded
		return true;   // returns true to signal that it loading something
	},

	load:function(options){
		// convert none hash parameters to hash
		if (typeOf(options) == 'string') options = {control:options, loadOnly:true,onload:(arguments.length > 0) ? arguments[1] : null};
		if (typeOf(options) == 'array'){
			var controls = [];
			for (var j = 0; j < options.length; j++)
				controls.push({control:options[j]});
			options = {controls:controls, onload:(arguments.length > 1) ? arguments[1] : null, loadOnly:true};
		}
		if (typeOf(options) == 'object'){
			options.loadOnly = true;
		}
		MUI.create(options);
	},

	getControlAssets : function(control, js, css, traversed, name){
		if (typeOf(control) == 'string') control = {control:control};
		if (!traversed) traversed = [control.control];
		if (!name) name = control.control;
		name = name.replace(/(^MUI\.)/i, '');
		var cname = name.toLowerCase();

		// try and locate the requested item
		var config;
		var pgName;
		Object.each(MUI.options.pluginGroups, function(group, name){
			if (MUI[name][cname] != null){
				pgName = name;
				config = MUI[name][cname];
			}
		});
		if (config == null) return {js:js,css:css,config:null};

		// see if we can gather all of the dependency controls
		var dependsOn = config.dependsOn ? config.dependsOn : [];	// add configured dependencies if they exist
		if (config.childNode && control[config.childNode]){			// add child controls of the control has a childnode configured
			var children = control[config.childNode];
			if (typeof(children) != 'array') children = [children];				// some controls allow child nodes to be an array or a single node
			Object.each(control[config.childNode], function(child){
				var controlname = (child.control ? child.control : config.childType);
				if (typeof(controlname) == 'string'){
					traversed.include(controlname);
					MUI.getControlAssets(child, js, css, traversed, controlname);
				}
			})
		}
		// gather dependencies if we have some
		if (dependsOn.length > 0){
			Object.each(dependsOn, function(controlname){
				if (traversed.indexOf(controlname) >= 0 || control.control == controlname) return;  // make sure we do get into a runaway recursion
				MUI.getControlAssets(controlname, js, css, traversed);
			})
		}

		var path = {};
		var sname = MUI.options.pluginGroups[pgName].singularName;
		if (!config.location) config.location = cname;
		path[sname] = '{' + pgName + '}' + config.location + '/';

		if (config.paths) Object.each(config.paths, function(tpath, name){
			MUI.options.path[name] = MUI.replaceFields(tpath, path);
		});

		if (!config.js) js.push(path[sname] + cname + '.js');
		else js.combine(config.js);
		js = MUI.replaceFields(js, path);

		if (config.css) css.combine(config.css);
		css.combine(MUI.options.css);
		css = MUI.replaceFields(css, path);

		return {js:js,css:css,config:config};
	},

	areLoaded: function(listToCheck){
		for (var i = 0; i < listToCheck.length; i++){
			if (MUI.files[listToCheck[i]] != 'loaded') return false;
		}
		return true;
	},

	create:function(options){
		// convert none hash parameters to hash
		if (typeOf(options) == 'string') options = {control:options,onload:(arguments.length > 1) ? arguments[1] : null};
		if (!MUI.initialized) MUI.initialize(); // initialize mocha if needed

		if (this.loadPluginGroups(function(){ // make sure all all plugin/control group configurations are loaded
			MUI.create(options);
		})) return;

		// convert array of plugin names to controls request
		var controls = options.controls;
		if (!controls) controls = [];
		if (typeOf(options) == 'array'){
			for (var j = 0; j < options.length; j++)
				controls.push(options[j]);
			options = {controls:controls,onload:options.onload};
		}

		if (controls.length == 0) controls = [options]; // make sure we have an array for list of controls to load

		// gather all of the assets for the requested controls/plugins
		var r = {js:[],css:[],traversed:(MUI.traversed ? MUI.traversed : [])};
		var config;
		for (var i = 0; i < controls.length; i++){
			if (!controls[i].control) return;
			if (controls[i].fromHTML && controls[i].drawOnInit === undefined) controls[i].drawOnInit = false;
			config = MUI.getControlAssets(controls[i], r.js, r.css, r.traversed).config;
		}

		// if only one control was requested and it is loaded then return it
		if (controls.length == 1 && r.js.length > 0 && this.areLoaded[r.js]){
			if ((config && config.loadOnly) || options.loadOnly){
				if (config.onload) config.onload(config);
				return null;
			}
			var name = controls[0].control.replace(/(^MUI\.)/i, '');
			var klass = MUI[name];
			var obj = new klass(options);
			if (options.onNew) options.onNew(obj);
			if (options.fromHTML && obj.fromHTML) obj.fromHTML(options.content);
			new MUI.Require(r);
			return obj;
		}

		// build a callback function for the assets requested
		r.onload = function(){
			MUI.traversed = (MUI.traversed ? MUI.traversed : []).combine(r.traversed);
			if (this.onload) this.onload(this);

			controls.each(function(control){
				if (control.loadOnly || this.loadOnly) return;
				if (control.onload) control.onload(control);
				var name = control.control.replace(/(^MUI\.)/i, '');
				var klass = MUI[name];
				var obj = new klass(control);
				if (control.onNew) control.onNew(obj);
				if (control.fromHTML && obj.fromHTML) obj.fromHTML(options.content);
			}.bind(this));

		}.bind(options);
		new MUI.Require(r);
	}

});
<|endoftext|>


<commit_before>Dionysus.module('Course', function(Article, Dionysus, Backbone, Marionette){

  var baseTemplatePath = 'templates/home/course';

  var home = Marionette.ItemView.extend({
    initialize: function(options){
      this.slider = options.slider;
      this.top = options.top;
      this.sub = options.sub;
      this.approach = options.approach;
      this.videos = options.videos.content;
      this.videosTotal = options.videos.totalPages;
      this.videoCurrent = options.videos.number+1;
      this.reporter = options.reporter;
      this.room = options.room.content;
      this.roomTotal = options.room.totalPages;
      this.roomCurrent = options.room.number+1;
      this.offline = options.offline;
    },

    template:function(data){
      var template = JST[baseTemplatePath+'/home'];
      var html = template(data);
      return html;
    },

    updatePage: function(category){
      $.when(Dionysus.request('course:home:videos',category),
          Dionysus.request('course:home:room',category),
          Dionysus.request('course:home:offline',category)
      ).done(function(videos,room,offline){
            var videoTemplate = JST[baseTemplatePath+'/videos'];
            var html = videoTemplate({videos:videos.content});
            $('#videos').html(html);
            $('#pagenation-video').remove();
            $('#videoWrapper').append('

');
            if(videos.number+1 <= videos.totalPages){
              $('#pagenation-video').twbsPagination({
                totalPages: videos.totalPages,
                startPage: videos.number+1,
                visiblePages: 6,
                first: '第一页',
                prev: '前一页',
                next: '后一页',
                last: '最后一页',
                onPageClick: function(event,page){
                  var videoTemplate = JST[baseTemplatePath+'/videos'];
                  var category = $('.sub.green').prop('id');
                  $.when(Dionysus.request('course:home:videos',category,page-1)).done(function(data){
                    var html = videoTemplate({videos:data.content});
                    $('#videos').html(html);
                  });
                }
              });
            }

            var roomTemplate = JST[baseTemplatePath+'/room'];
            var rooms = roomTemplate({room:room.content});
            $('#room').html(rooms);
            $('#pagenation-room').remove();
            $('#roomWrapper').append('

');
            if(room.number+1 <= room.totalPages){
              $('#pagenation-room').twbsPagination({
                totalPages: room.totalPages,
                startPage: room.number+1,
                visiblePages: 6,
                first: '第一页',
                prev: '前一页',
                next: '后一页',
                last: '最后一页',
                onPageClick: function(event,page){
                  var videoTemplate = JST[baseTemplatePath+'/room'];
                  var category = $('.sub.green').prop('id');
                  $.when(Dionysus.request('course:home:room',category,page-1)).done(function(data){
                    var html = videoTemplate({room:data.content});
                    $('#room').html(html);
                  });
                }
              });
            }
            var offlineTemplate = JST[baseTemplatePath+'/offline'];
            var offlines = offlineTemplate({offline:offline.content});
            $('#offline').html(offlines);
            $('.button.room.reg').on('click', function(event){
              var clicking = $(event.target);
              var id = clicking.attr('data-id');
              $.getJSON("/controllers/courses/" + id + "/reg",function(data){
                toastr.success('课程注册成功');
              });
            });

            $('.button.offline.reg').on('click', function(event){
              var clicking = $(event.target);
              var id = clicking.attr('data-id');
              $.getJSON("/controllers/courses/" + id + "/reg",function(data){
                toastr.success('课程注册成功');
                $('#reg').text('已注册 ' + data.number + ' 人');
              });
            });
          });
    },

    onRender: function(){
      var that = this;
      this.$('#slider').flexslider();
      this.$('.ui.small.basic.button:nth-child(2)').toggleClass('basic green');
      if(this.videoCurrent <= this.videosTotal){
        this.$('#pagenation-video').twbsPagination({
          totalPages: this.videosTotal,
          startPage: this.videoCurrent,
          visiblePages: 6,
          first: '第一页',
          prev: '前一页',
          next: '后一页',
          last: '最后一页',
          onPageClick: function(event,page){
            var videoTemplate = JST[baseTemplatePath+'/videos'];
            var category = $('.sub.green').prop('id');
            $.when(Dionysus.request('course:home:videos',category,page-1)).done(function(data){
              var html = videoTemplate({videos:data.content});
              $('#videos').html(html);
            });
          }
        });
      }
      if(this.roomCurrent <= this.roomTotal){
        this.$('#pagenation-room').twbsPagination({
          totalPages: this.roomTotal,
          startPage: this.roomCurrent,
          visiblePages: 6,
          first: '第一页',
          prev: '前一页',
          next: '后一页',
          last: '最后一页',
          onPageClick: function(event,page){
            var roomTemplate = JST[baseTemplatePath+'/room'];
            var category = $('.sub.green').prop('id');
            $.when(Dionysus.request('course:home:room',category,page-1)).done(function(data){
              var html = roomTemplate({room:data.content});
              $('#room').html(html);
            });
          }
        });
      }
      this.$('#subCats').on('click',function(event){
        var clicking = $(event.target);
          var current = $(this).find('.green');
          if(current.prop('id') !== clicking.prop('id')){
            current.toggleClass('basic green');
            clicking.toggleClass('basic green');
            that.updatePage(clicking.prop('id'));
          }
      });
      this.$('#topCats').on('click',function(event){
        var clicking = $(event.target);
        var current = $(this).find('.green');
        if(current.prop('id') !== clicking.prop('id')){
          current.toggleClass('basic green');
          clicking.toggleClass('basic green');
          var clickedCategory = _.findWhere(that.top,{id:parseInt(clicking.prop('id'))});
          var subTemplate = JST[baseTemplatePath+'/subcats'];
          var html = subTemplate({sub:clickedCategory.children});
          $('#subCats').html(html);
          var sub = $('#subCats').find('.button:nth-child(2)');
          sub.toggleClass('basic green');
          var id = sub.prop('id');
          that.updatePage(id);
        }
      });
      this.$('#approach').on('click',function(event){
        var clicking = $(event.target);
        var current = $(this).find('.green');
        if(current.text() !== clicking.text()){
          current.toggleClass('basic green');
          clicking.toggleClass('basic green');
          var href = clicking.attr('href');
          $('html,body').animate({
            scrollTop: $(href).offset().top
          }, 1000);
        }

      });
      this.$('.button.room.reg').on('click', function(event){
        var clicking = $(event.target);
        var id = clicking.attr('data-id');
        $.getJSON("/controllers/courses/" + id + "/reg",function(data){
          toastr.success('课程注册成功');
        });
      });

      this.$('.button.offline.reg').on('click', function(event){
        var clicking = $(event.target);
        var id = clicking.attr('data-id');
        $.getJSON("/controllers/courses/" + id + "/reg",function(data){
          toastr.success('课程注册成功');
          $('#reg').text('已注册 ' + data.number + ' 人');
        });
      });
    },

    serializeData: function(){
      return this;
    }
  });

  var detail = Marionette.ItemView.extend({
     initialize : function(options){
       this.course = options.course;
       this.courses = options.courses;
       this.comments = options.comments;
     },
    template:function(data){
      var template = JST[baseTemplatePath+'/detail'];
      var html = template(data);
      return html;
    },
    serializeData: function(){
      return this;
    },
    onRender: function(){
      var id = this.course.id;
      this.$('#body').append(this.course.body);
      this.$('.submit.button').on('click',function(){
        var comment = $('#comment').val();
        $.ajax({
          type: "POST",
          url: "/controllers/courses/"+id + "/feedbacks",
          data: JSON.stringify({comment:comment}),
          success: function(data){
            var templeComment = JST[baseTemplatePath+'/comment'];
            var html = templeComment(data);
            $('.ui.comments').prepend(html);
          },
          dataType: "json",
          contentType: "application/json"
        });
      });
    }
  });

  var CourseController = Marionette.Controller.extend({
    showCourseHome: function(){
      Dionysus.mainRegion.show(new Dionysus.Common.Views.Loading());
      $.when(Dionysus.request('course:home:categories'),Dionysus.request('course:home:slider'))
            .done(function(categories,slider){
                var options = {slider:slider};
                options.approach = [{name:"录制视频",href:"#approach"},{name:"在线课堂",href:"#second"},{name:"离线课程",href:"#offline"}];
                options.top = [];
                _.map(categories,function(category){
                  options.top.push(category);
                });
                options.sub = categories[0].children;
                var category;
                if(options.sub.length > 0){
                  category = options.sub[0].id;
                }else{
                  category = categories[0].id;
                }
                $.when(Dionysus.request('course:home:videos',category),
                       Dionysus.request('course:home:room',category),
                       Dionysus.request('course:home:offline',category)
                ).done(function(videos,room,offline){
                      options.videos = videos;
                      options.room = room;
                      options.offline = offline.content;
                      var view = new home(options);
                      Dionysus.mainRegion.show(view);
                    });
            });
    },
    showCourse:function(id){
      $.when(Dionysus.request('course:home:detail',id),Dionysus.request('course:home:detail:courses'),Dionysus.request('course:home:detail:comments',id)).done(function(course,courses,comments){
        var detailView = new detail({course:course,courses:courses,comments:comments});
        Dionysus.mainRegion.show(detailView);
      });
    }
  });
  Dionysus.addInitializer(function () {
    new Marionette.AppRouter({
      appRoutes: {
        'courses(/)': 'showCourseHome',
        'courses/:id(/)' : 'showCourse'
      },
      controller: new CourseController()
    });
  });
});
<commit_msg>fix bug for course module<commit_after>Dionysus.module('Course', function(Article, Dionysus, Backbone, Marionette){

  var baseTemplatePath = 'templates/home/course';
  var loader = '

';

  var home = Marionette.ItemView.extend({
    initialize: function(options){
      this.slider = options.slider;
      this.top = options.top;
      this.sub = options.sub;
      this.approach = options.approach;
      this.videos = options.videos.content;
      this.videosTotal = options.videos.totalPages;
      this.videoCurrent = options.videos.number+1;
      this.reporter = options.reporter;
      this.room = options.room.content;
      this.roomTotal = options.room.totalPages;
      this.roomCurrent = options.room.number+1;
      this.offline = options.offline;
    },

    template:function(data){
      var template = JST[baseTemplatePath+'/home'];
      var html = template(data);
      return html;
    },

    updatePage: function(category){
      $('#videos').html(loader);
      $('#room').html(loader);
      $('#offline').html(loader);
      $.when(Dionysus.request('course:home:videos',category),
          Dionysus.request('course:home:room',category),
          Dionysus.request('course:home:offline',category)
      ).done(function(videos,room,offline){
            var videoTemplate = JST[baseTemplatePath+'/videos'];
            var html = videoTemplate({videos:videos.content});
            $('#videos').html(html);
            $('#pagenation-video').remove();
            $('#videoWrapper').append('

');
            if(videos.number+1 <= videos.totalPages){
              $('#pagenation-video').twbsPagination({
                totalPages: videos.totalPages,
                startPage: videos.number+1,
                visiblePages: 6,
                first: '第一页',
                prev: '前一页',
                next: '后一页',
                last: '最后一页',
                onPageClick: function(event,page){
                  var videoTemplate = JST[baseTemplatePath+'/videos'];
                  var category = $('.sub.green').prop('id');
                  $.when(Dionysus.request('course:home:videos',category,page-1)).done(function(data){
                    var html = videoTemplate({videos:data.content});
                    $('#videos').html(html);
                  });
                }
              });
            }

            var roomTemplate = JST[baseTemplatePath+'/room'];
            var rooms = roomTemplate({room:room.content});
            $('#room').html(rooms);
            $('#pagenation-room').remove();
            $('#roomWrapper').append('

');
            if(room.number+1 <= room.totalPages){
              $('#pagenation-room').twbsPagination({
                totalPages: room.totalPages,
                startPage: room.number+1,
                visiblePages: 6,
                first: '第一页',
                prev: '前一页',
                next: '后一页',
                last: '最后一页',
                onPageClick: function(event,page){
                  var videoTemplate = JST[baseTemplatePath+'/room'];
                  var category = $('.sub.green').prop('id');
                  $.when(Dionysus.request('course:home:room',category,page-1)).done(function(data){
                    var html = videoTemplate({room:data.content});
                    $('#room').html(html);
                  });
                }
              });
            }
            var offlineTemplate = JST[baseTemplatePath+'/offline'];
            var offlines = offlineTemplate({offline:offline.content});
            $('#offline').html(offlines);
            $('.button.room.reg').on('click', function(event){
              var clicking = $(event.target);
              var id = clicking.attr('data-id');
              $.getJSON("/controllers/courses/" + id + "/reg",function(data){
                toastr.success('课程注册成功');
              });
            });

            $('.button.offline.reg').on('click', function(event){
              var clicking = $(event.target);
              var id = clicking.attr('data-id');
              $.getJSON("/controllers/courses/" + id + "/reg",function(data){
                toastr.success('课程注册成功');
                $('#reg').text('已注册 ' + data.number + ' 人');
              });
            });
          });
    },

    onRender: function(){
      var that = this;
      this.$('#slider').flexslider();
      this.$('.ui.small.basic.button:nth-child(2)').toggleClass('basic green');
      if(this.videoCurrent <= this.videosTotal){
        this.$('#pagenation-video').twbsPagination({
          totalPages: this.videosTotal,
          startPage: this.videoCurrent,
          visiblePages: 6,
          first: '第一页',
          prev: '前一页',
          next: '后一页',
          last: '最后一页',
          onPageClick: function(event,page){
            var videoTemplate = JST[baseTemplatePath+'/videos'];
            var category = $('.sub.green').prop('id');
            $.when(Dionysus.request('course:home:videos',category,page-1)).done(function(data){
              var html = videoTemplate({videos:data.content});
              $('#videos').html(html);
            });
          }
        });
      }
      if(this.roomCurrent <= this.roomTotal){
        this.$('#pagenation-room').twbsPagination({
          totalPages: this.roomTotal,
          startPage: this.roomCurrent,
          visiblePages: 6,
          first: '第一页',
          prev: '前一页',
          next: '后一页',
          last: '最后一页',
          onPageClick: function(event,page){
            var roomTemplate = JST[baseTemplatePath+'/room'];
            var category = $('.sub.green').prop('id');
            $.when(Dionysus.request('course:home:room',category,page-1)).done(function(data){
              var html = roomTemplate({room:data.content});
              $('#room').html(html);
            });
          }
        });
      }
      this.$('#subCats').on('click',function(event){
        var clicking = $(event.target);
          var current = $(this).find('.green');
          if(current.prop('id') !== clicking.prop('id')){
            current.toggleClass('basic green');
            clicking.toggleClass('basic green');
            that.updatePage(clicking.prop('id'));
          }
      });
      this.$('#topCats').on('click',function(event){
        var clicking = $(event.target);
        var current = $(this).find('.green');
        if(current.prop('id') !== clicking.prop('id')){
          current.toggleClass('basic green');
          clicking.toggleClass('basic green');
          var clickedCategory = _.findWhere(that.top,{id:parseInt(clicking.prop('id'))});
          var subTemplate = JST[baseTemplatePath+'/subcats'];
          var html = subTemplate({sub:clickedCategory.children});
          $('#subCats').html(html);
          var sub = $('#subCats').find('.button:nth-child(2)');
          sub.toggleClass('basic green');
          var id = sub.prop('id');
          that.updatePage(id);
        }
      });
      this.$('#approach').on('click',function(event){
        var clicking = $(event.target);
        var current = $(this).find('.green');
        if(current.text() !== clicking.text()){
          current.toggleClass('basic green');
          clicking.toggleClass('basic green');
          var href = clicking.attr('href');
          $('html,body').animate({
            scrollTop: $(href).offset().top
          }, 1000);
        }

      });
      this.$('.button.room.reg').on('click', function(event){
        var clicking = $(event.target);
        var id = clicking.attr('data-id');
        $.getJSON("/controllers/courses/" + id + "/reg",function(data){
          toastr.success('课程注册成功');
        });
      });

      this.$('.button.offline.reg').on('click', function(event){
        var clicking = $(event.target);
        var id = clicking.attr('data-id');
        $.getJSON("/controllers/courses/" + id + "/reg",function(data){
          toastr.success('课程注册成功');
          $('#reg').text('已注册 ' + data.number + ' 人');
        });
      });
    },

    serializeData: function(){
      return this;
    }
  });

  var detail = Marionette.ItemView.extend({
     initialize : function(options){
       this.course = options.course;
       this.courses = options.courses;
       this.comments = options.comments;
     },
    template:function(data){
      var template = JST[baseTemplatePath+'/detail'];
      var html = template(data);
      return html;
    },
    serializeData: function(){
      return this;
    },
    onRender: function(){
      var id = this.course.id;
      this.$('#body').append(this.course.body);
      this.$('.submit.button').on('click',function(){
        var comment = $('#comment').val();
        $.ajax({
          type: "POST",
          url: "/controllers/courses/"+id + "/feedbacks",
          data: JSON.stringify({comment:comment}),
          success: function(data){
            var templeComment = JST[baseTemplatePath+'/comment'];
            var html = templeComment(data);
            $('.ui.comments').prepend(html);
          },
          dataType: "json",
          contentType: "application/json"
        });
      });
    }
  });

  var CourseController = Marionette.Controller.extend({
    showCourseHome: function(){
      Dionysus.mainRegion.show(new Dionysus.Common.Views.Loading());
      $.when(Dionysus.request('course:home:categories'),Dionysus.request('course:home:slider'))
            .done(function(categories,slider){
                var options = {slider:slider};
                options.approach = [{name:"录制视频",href:"#approach"},{name:"在线课堂",href:"#second"},{name:"离线课程",href:"#offline"}];
                options.top = [];
                _.map(categories,function(category){
                  options.top.push(category);
                });
                options.sub = categories[0].children;
                var category;
                if(options.sub.length > 0){
                  category = options.sub[0].id;
                }else{
                  category = categories[0].id;
                }
                $.when(Dionysus.request('course:home:videos',category),
                       Dionysus.request('course:home:room',category),
                       Dionysus.request('course:home:offline',category)
                ).done(function(videos,room,offline){
                      options.videos = videos;
                      options.room = room;
                      options.offline = offline.content;
                      var view = new home(options);
                      Dionysus.mainRegion.show(view);
                    });
            });
    },
    showCourse:function(id){
      $.when(Dionysus.request('course:home:detail',id),Dionysus.request('course:home:detail:courses'),Dionysus.request('course:home:detail:comments',id)).done(function(course,courses,comments){
        var detailView = new detail({course:course,courses:courses,comments:comments});
        Dionysus.mainRegion.show(detailView);
      });
    }
  });
  Dionysus.addInitializer(function () {
    new Marionette.AppRouter({
      appRoutes: {
        'courses(/)': 'showCourseHome',
        'courses/:id(/)' : 'showCourse'
      },
      controller: new CourseController()
    });
  });
});
<|endoftext|>


<commit_before>"use strict";

const importCsvFromRestApi = require('./toolkit/importCsvFromRestApi.js');

const url = "https://earthquake.usgs.gov/fdsnws/event/1/query.csv?starttime=2017-01-01&endtime=2017-03-02";
importCsvFromRestApi(url)
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error(err);
    });
<commit_msg>Update listing-3.12.js<commit_after>"use strict";

const importCsvFromRestApi = require('./toolkit/importCsvFromRestApi.js');

const url = "https://earthquake.usgs.gov/fdsnws/event/1/query.csv?starttime=2017-01-01&endtime=2017-03-02&limit=20000";
importCsvFromRestApi(url)
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error(err);
    });
<|endoftext|>


<commit_before>angular.module('player')
	.controller('ScorecardController', ScorecardController);

function ScorecardController($scope, $stateParams, localStorage, FooseyService)
{
	_.each(localStorage.getObject('players'), function(player){
		if(player.playerID == $stateParams.playerID)
			$scope.name = player.displayName;
	});

	// set up the player
	FooseyService.getPlayer($stateParams.playerID).then(
		function(response){
			$scope.player = response.data;
		});

	// set up charts
	setUpCharts();

	// set up the charts for the scorecard page
	function setUpCharts()
	{
		$scope.charts = [];
		$scope.subtitle = 'Data from All Time';

		FooseyService.getEloHistory($stateParams.playerID).then(
			function successCallback(response)
			{
				// Get chart data
				var chartData = response.data;

				// Set up ELO Rating chart
				$scope.charts.push(getEloChartOptions(_.pluck(chartData, 'elo'), _.pluck(chartData, 'date')));
			});

		FooseyService.getWinRateHistory($stateParams.playerID).then(
			function successCallback(response)
			{
				// Get chart data
				var chartData = response.data;

				// Set up Win Rate chart
				$scope.charts.push(getPercentChartOptions(_.pluck(chartData, 'winRate'), _.pluck(chartData, 'date')));
			});
	}

	// define options for the ELO Rating chart
	function getEloChartOptions(data, dates)
	{
		return {
			title: 'ELO Rating',
			subtitle: $scope.subtitle,
			yAxis: 'ELO',
			class: 'elo',
			data: data,
			dates: dates
		};
	}

	// define options for the Win Percentage chart
	function getPercentChartOptions(data, dates)
	{
		return {
			title: 'Percent Games Won',
			subtitle: $scope.subtitle,
			yAxis: 'Percent',
			class: 'percent',
			data: data,
			dates: dates
		};
	}
}<commit_msg>Force elo chart to be first<commit_after>angular.module('player')
	.controller('ScorecardController', ScorecardController);

function ScorecardController($scope, $stateParams, localStorage, FooseyService)
{
	_.each(localStorage.getObject('players'), function(player){
		if(player.playerID == $stateParams.playerID)
			$scope.name = player.displayName;
	});

	// set up the player
	FooseyService.getPlayer($stateParams.playerID).then(
		function(response){
			$scope.player = response.data;
		});

	// set up charts
	setUpCharts();

	// set up the charts for the scorecard page
	function setUpCharts()
	{
		$scope.charts = [];
		$scope.subtitle = 'Data from All Time';

		FooseyService.getEloHistory($stateParams.playerID).then(
			function successCallback(response)
			{
				// Get chart data
				var chartData = response.data;

				// Set up ELO Rating chart
				$scope.charts.unshift(getEloChartOptions(_.pluck(chartData, 'elo'), _.pluck(chartData, 'date')));
			});

		FooseyService.getWinRateHistory($stateParams.playerID).then(
			function successCallback(response)
			{
				// Get chart data
				var chartData = response.data;

				// Set up Win Rate chart
				$scope.charts.push(getPercentChartOptions(_.pluck(chartData, 'winRate'), _.pluck(chartData, 'date')));
			});
	}

	// define options for the ELO Rating chart
	function getEloChartOptions(data, dates)
	{
		return {
			title: 'ELO Rating',
			subtitle: $scope.subtitle,
			yAxis: 'ELO',
			class: 'elo',
			data: data,
			dates: dates
		};
	}

	// define options for the Win Percentage chart
	function getPercentChartOptions(data, dates)
	{
		return {
			title: 'Percent Games Won',
			subtitle: $scope.subtitle,
			yAxis: 'Percent',
			class: 'percent',
			data: data,
			dates: dates
		};
	}
}<|endoftext|>


<commit_before>/*global module, require*/
var util = require('util'),
    sys = require('sys'),
    fs = require('fs'),
    path = require('path'),
    step = require('step'),
    _ = require('underscore'),
    assets = require('../assets'),
    error = require('../error');

// Expects: config.root
var Base = module.exports = function (config) {
    _.extend(this, config);
};

Base.prototype = {
    loadAsset: function (assetConfig) {
        if ('url' in assetConfig) {
            var lookupUrl = this.siteGraph.lookupIndex('asset', 'url', assetConfig.url);
            if (lookupUrl.length) {
                return lookupUrl[0];
            }
        }
        if (!('baseUrl' in assetConfig)) {
            if ('url' in assetConfig || 'originalUrl' in assetConfig) {
                assetConfig.baseUrl = path.dirname(assetConfig.url || assetConfig.originalUrl);
            } else {
                throw new Error("Couldn't work out baseUrl for asset: " + sys.inspect(assetConfig));
            }
        }
        if (!('type' in assetConfig)) {
            var extension = ('url' in assetConfig) && path.extname(assetConfig.url).replace(/^\./, "");
            if (extension && extension in assets.typeByExtension) {
                assetConfig.type = assets.typeByExtension[extension];
            } else {
                // FIXME: Extract mime type from data: urls
                throw new Error("No type in assetConfig and couldn't work it out from the url: " + sys.inspect(assetConfig));
            }
        }
        var Constructor = assets.byType[assetConfig.type];
        if (!('originalSrc' in assetConfig)) {
            assetConfig.originalSrcProxy = this.getOriginalSrcProxy(assetConfig, Constructor.prototype.encoding);
        }
        var asset = new Constructor(assetConfig);
        this.siteGraph.registerAsset(asset);
        return asset;
    },

    populate: function (originAsset, includeRelationLambda, cb) {
        var that = this,
            seenAssetUrls = {};
        (function traverse(asset, cb) {
            if ('url' in asset) {
                if (seenAssetUrls[asset.url]) {
                    return cb();
                }
                seenAssetUrls[asset.url] = true;
            }
            var filteredOriginalRelations;
            step(
                function () {
                    asset.getOriginalRelations(this);
                },
                error.passToFunction(cb, function (originalRelations) {
                    filteredOriginalRelations = originalRelations.filter(includeRelationLambda);
                    if (filteredOriginalRelations.length) {
                        var group = this.group();
                        filteredOriginalRelations.forEach(function (relation) {
                            that.resolveAssetConfig(relation.assetConfig, relation.from.baseUrl, group());
                        }, this);
                    } else {
                        return cb();
                    }
                }),
                error.passToFunction(cb, function (resolvedAssetConfigArrays) {
                    var initializedRelations = [];
                    function initializeAndRegisterRelation(relation) {
                        if (!('url' in relation.assetConfig)) {
                            // Inline asset, copy baseUrl from asset
                            relation.assetConfig.baseUrl = asset.baseUrl;
                        }
                        relation.to = that.loadAsset(relation.assetConfig);
                        if (initializedRelations.length) {
                            that.siteGraph.registerRelation(relation, 'after', initializedRelations[initializedRelations.length - 1);
                        } else {
                            that.siteGraph.registerRelation(relation, 'first');
                        }
                        initializedRelations.push(relation);
                    }
                    resolvedAssetConfigArrays.forEach(function (resolvedAssetConfigs, i) {
                        var originalRelation = filteredOriginalRelations[i];
                        if (resolvedAssetConfigs.length === 0) {
                            asset.detachRelation(originalRelation);
                        } else if (resolvedAssetConfigs.length === 1) {
                            originalRelation.assetConfig = resolvedAssetConfigs[0];
                            initializeAndRegisterRelation(originalRelation);
                        } else if (asset.attachRelation) {
                            var previous = originalRelation;
                            resolvedAssetConfigs.forEach(function (resolvedAssetConfig) {
                                var relation = new originalRelation.constructor({
                                    from: asset,
                                    assetConfig: resolvedAssetConfig
                                });
                                relation.from.attachRelation(relation, 'after', previous);
                                initializeAndRegisterRelation(relation);
                                previous = relation;
                            });
                            asset.detachRelation(originalRelation);
                        } else {
                            cb(new Error("assetConfig resolved to multiple, and " + originalRelation.type + " doesn't support attachRelation"));
                        }
                    }, this);
                    if (initializedRelations.length) {
                        initializedRelations.forEach(function (relation) {
                            traverse(relation.to, this.parallel());
                        }, this);
                    } else {
                        process.nextTick(this);
                    }
                }),
                cb
            );
        })(originAsset, cb);
    }
};
<commit_msg>Simplified loaders/Base a little<commit_after>/*global module, require*/
var util = require('util'),
    sys = require('sys'),
    fs = require('fs'),
    path = require('path'),
    step = require('step'),
    _ = require('underscore'),
    assets = require('../assets'),
    error = require('../error');

// Expects: config.root
var Base = module.exports = function (config) {
    _.extend(this, config);
};

Base.prototype = {
    loadAsset: function (assetConfig) {
        if ('url' in assetConfig) {
            var lookupUrl = this.siteGraph.lookupIndex('asset', 'url', assetConfig.url);
            if (lookupUrl.length) {
                return lookupUrl[0];
            }
        }
        if (!('baseUrl' in assetConfig)) {
            if ('url' in assetConfig || 'originalUrl' in assetConfig) {
                assetConfig.baseUrl = path.dirname(assetConfig.url || assetConfig.originalUrl);
            } else {
                throw new Error("Couldn't work out baseUrl for asset: " + sys.inspect(assetConfig));
            }
        }
        if (!('type' in assetConfig)) {
            var extension = ('url' in assetConfig) && path.extname(assetConfig.url).replace(/^\./, "");
            if (extension && extension in assets.typeByExtension) {
                assetConfig.type = assets.typeByExtension[extension];
            } else {
                // FIXME: Extract mime type from data: urls
                throw new Error("No type in assetConfig and couldn't work it out from the url: " + sys.inspect(assetConfig));
            }
        }
        var Constructor = assets.byType[assetConfig.type];
        if (!('originalSrc' in assetConfig)) {
            assetConfig.originalSrcProxy = this.getOriginalSrcProxy(assetConfig, Constructor.prototype.encoding);
        }
        var asset = new Constructor(assetConfig);
        this.siteGraph.registerAsset(asset);
        return asset;
    },

    populate: function (originAsset, includeRelationLambda, cb) {
        var that = this,
            seenAssetUrls = {};
        (function traverse(asset, cb) {
            if ('url' in asset) {
                if (seenAssetUrls[asset.url]) {
                    return cb();
                }
                seenAssetUrls[asset.url] = true;
            }
            var filteredOriginalRelations;
            step(
                function () {
                    asset.getOriginalRelations(this);
                },
                error.passToFunction(cb, function (originalRelations) {
                    filteredOriginalRelations = originalRelations.filter(includeRelationLambda);
                    if (filteredOriginalRelations.length) {
                        var group = this.group();
                        filteredOriginalRelations.forEach(function (relation) {
                            that.resolveAssetConfig(relation.assetConfig, relation.from.baseUrl, group());
                        }, this);
                    } else {
                        return cb();
                    }
                }),
                error.passToFunction(cb, function (resolvedAssetConfigArrays) {
                    var initializedRelations = [];
                    function initializeAndRegisterRelation(relation) {
                        if (!('url' in relation.assetConfig)) {
                            // Inline asset, copy baseUrl from asset
                            relation.assetConfig.baseUrl = asset.baseUrl;
                        }
                        relation.to = that.loadAsset(relation.assetConfig);
                        if (initializedRelations.length) {
                            that.siteGraph.registerRelation(relation, 'after', initializedRelations[initializedRelations.length - 1]);
                        } else {
                            that.siteGraph.registerRelation(relation, 'first');
                        }
                        initializedRelations.push(relation);
                    }
                    resolvedAssetConfigArrays.forEach(function (resolvedAssetConfigs, i) {
                        var originalRelation = filteredOriginalRelations[i];
                        if (resolvedAssetConfigs.length === 0) {
                            asset.detachRelation(originalRelation);
                        } else if (resolvedAssetConfigs.length === 1) {
                            originalRelation.assetConfig = resolvedAssetConfigs[0];
                            initializeAndRegisterRelation(originalRelation);
                        } else if (asset.attachRelation) {
                            resolvedAssetConfigs.forEach(function (resolvedAssetConfig) {
                                var relation = new originalRelation.constructor({
                                    from: asset,
                                    assetConfig: resolvedAssetConfig
                                });
                                relation.from.attachRelation(relation, 'before', originalRelation);
                                initializeAndRegisterRelation(relation);
                            });
                            asset.detachRelation(originalRelation);
                        } else {
                            cb(new Error("assetConfig resolved to multiple, and " + originalRelation.type + " doesn't support attachRelation"));
                        }
                    }, this);
                    if (initializedRelations.length) {
                        initializedRelations.forEach(function (relation) {
                            traverse(relation.to, this.parallel());
                        }, this);
                    } else {
                        process.nextTick(this);
                    }
                }),
                cb
            );
        })(originAsset, cb);
    }
};
<|endoftext|>


<commit_before>/**
 * Shopware UI - ComboBox Override
 *
 * This files provides an override to address the
 * boundlist easier in our Selenium Tests.
 *
 * The override adds an addtional HTML5 "data"-attrbute
 * to the element.
 *
 * shopware AG (c) 2012. All rights reserved.
 *
 * @link http://www.shopware.de/
 * @author t.garcia
 * @date 2012-05-03
 * @license http://www.shopware.de/license
 * @package overrides
 */
Ext.override(Ext.form.field.Time,
/** @lends Ext.form.field.Time */
{
    /** Extends the default function to allow parsing partial times using the alternative formats. */
    safeParse: function(value, format){
        var me = this,
            utilDate = Ext.Date,
            parsedDate,
            result = null,
            altFormats = me.altFormats,
            altFormatsArray = me.altFormatsArray,
            j = 0,
            len;

        if (utilDate.formatContainsDateInfo(format)) {
            // assume we've been given a full date
            result = utilDate.parse(value, format);
        } else {
            // Use our initial safe date
            parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
            if (parsedDate) {
                result = parsedDate;
            } else {
                if (!result && altFormats) {
                    altFormatsArray = altFormatsArray || altFormats.split('|');
                    len = altFormatsArray.length;
                    for (; j < len && !result; ++j) {
                        parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + altFormatsArray[j]);
                        if (parsedDate) {
                            result = parsedDate;
                        }
                    }
                }
            }
        }
        return result;
    }
});<commit_msg>SW-4473 - Improve JS comments<commit_after>/**
 * Shopware UI - Time field Override
 *
 * Extends the default safeParse function to allow
 * parsing partial times using the alternative formats
 *
 * Shopware AG (c) 2013. All rights reserved.
 *
 * @link http://www.shopware.de/
 * @author t.garcia
 * @date 2013-11-10
 * @license http://www.shopware.de/license
 * @package overrides
 */
Ext.override(Ext.form.field.Time,
/** @lends Ext.form.field.Time */
{
    /** Extends the default function to allow parsing partial times using the alternative formats. */
    safeParse: function(value, format){
        var me = this,
            utilDate = Ext.Date,
            parsedDate,
            result = null,
            altFormats = me.altFormats,
            altFormatsArray = me.altFormatsArray,
            j = 0,
            len;

        if (utilDate.formatContainsDateInfo(format)) {
            // assume we've been given a full date
            result = utilDate.parse(value, format);
        } else {
            // Use our initial safe date
            parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
            if (parsedDate) {
                result = parsedDate;
            } else {
                if (!result && altFormats) {
                    altFormatsArray = altFormatsArray || altFormats.split('|');
                    len = altFormatsArray.length;
                    for (; j < len && !result; ++j) {
                        parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + altFormatsArray[j]);
                        if (parsedDate) {
                            result = parsedDate;
                        }
                    }
                }
            }
        }
        return result;
    }
});<|endoftext|>


<commit_before>/*
Copyright (c) 2014-2015 F-Secure
See LICENSE for details
*/
'use strict';

// dummy comment for test commit
// lokki-server main file
var conf = require('./lib/config');
var logger = require('./lib/logger');

// Express application
var express = require('express');

var app = express();
var NotificationWorker = require('./locmap/lib/notificationWorker');
var notificationWorker = new NotificationWorker();

var methodOverride = require('method-override');

var bodyParser = require('body-parser');

app.use(express.logger('dev')); // 'default', 'short', 'tiny', 'dev'
app.use(express.compress()); // gzip
app.use(methodOverride());

//  app.use(bodyParser());

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: true}));

//  parse application/json
app.use(bodyParser.json());

// Security related headers to all paths
app.use(function (req, res, next) {
    // Force browser not to guess type but use content-type exactly.
    // Requires content-type headers to be correctly set.
    res.setHeader('X-Content-Type-Options', 'nosniff');

    // Prevent reflected XSS
    // Could have incompatibilities with older browsers. Works on our test phones.
    res.setHeader('X-XSS-Protection', '1, mode=block');

    // Prevents showing data in a frame
    res.setHeader('X-Frame-Options', 'Deny');

    return next();
});

// Security headers for /api (JSON-related)
app.use('/api', function (req, res, next) {
    // Browser shows reply as downloadable instead of injecting into page.
    res.setHeader('Content-Disposition', 'attachment; filename="json-response.txt');
    return next();
});

if (conf.get('neverCrash')) {
    // do not allow production server to crash
    process.on('uncaughtException', function (err) {
        // handle the error safely
        logger.error('uncaughtException:', err);
        logger.error(err.stack);
    });
}

// Root site
app.get('/', function (req, res) {
    res.send('Welcome to Lokki!

');
});

// Import LocMap routes
require('./locmap/locmap-server')(app);

// Entry point
if (require.main === module) {

    var port = conf.get('port');

    app.listen(port, function () {
        logger.info('Lokki-Server listening on %d', port);
    });

    // Not run on local server, interferes with unit tests.
    // TODO Error handling?
    if (conf.get('pushNotifications')) {
        // Run pending notifications check in configured intervals.
        setInterval(function () {
            notificationWorker.doNotificationsCheck(function () {});
        }, conf.get('locMapConfig').notificationCheckPollingInterval * 1000);
    }
} else {
    module.exports = app; // Exports the app to importing module
}
<commit_msg>revert test commit<commit_after>/*
Copyright (c) 2014-2015 F-Secure
See LICENSE for details
*/

'use strict';

// lokki-server main file
var conf = require('./lib/config');
var logger = require('./lib/logger');

// Express application
var express = require('express');

var app = express();
var NotificationWorker = require('./locmap/lib/notificationWorker');
var notificationWorker = new NotificationWorker();

var methodOverride = require('method-override');

var bodyParser = require('body-parser');

app.use(express.logger('dev')); // 'default', 'short', 'tiny', 'dev'
app.use(express.compress()); // gzip
app.use(methodOverride());

//  app.use(bodyParser());

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: true}));

//  parse application/json
app.use(bodyParser.json());

// Security related headers to all paths
app.use(function (req, res, next) {
    // Force browser not to guess type but use content-type exactly.
    // Requires content-type headers to be correctly set.
    res.setHeader('X-Content-Type-Options', 'nosniff');

    // Prevent reflected XSS
    // Could have incompatibilities with older browsers. Works on our test phones.
    res.setHeader('X-XSS-Protection', '1, mode=block');

    // Prevents showing data in a frame
    res.setHeader('X-Frame-Options', 'Deny');

    return next();
});

// Security headers for /api (JSON-related)
app.use('/api', function (req, res, next) {
    // Browser shows reply as downloadable instead of injecting into page.
    res.setHeader('Content-Disposition', 'attachment; filename="json-response.txt');
    return next();
});

if (conf.get('neverCrash')) {
    // do not allow production server to crash
    process.on('uncaughtException', function (err) {
        // handle the error safely
        logger.error('uncaughtException:', err);
        logger.error(err.stack);
    });
}

// Root site
app.get('/', function (req, res) {
    res.send('Welcome to Lokki!

');
});

// Import LocMap routes
require('./locmap/locmap-server')(app);

// Entry point
if (require.main === module) {

    var port = conf.get('port');

    app.listen(port, function () {
        logger.info('Lokki-Server listening on %d', port);
    });

    // Not run on local server, interferes with unit tests.
    // TODO Error handling?
    if (conf.get('pushNotifications')) {
        // Run pending notifications check in configured intervals.
        setInterval(function () {
            notificationWorker.doNotificationsCheck(function () {});
        }, conf.get('locMapConfig').notificationCheckPollingInterval * 1000);
    }
} else {
    module.exports = app; // Exports the app to importing module
}
<|endoftext|>


<commit_before>document.addEventListener('DOMContentLoaded', function() {
M.AutoInit();
});

  function createCard(cardType) {
	var newDiv = document.createElement("DIV");
	newDiv.className = "col s12 m6 l3 xl3 cardToDelete";
	newDiv.innerHTML = `

			  <img src="images/`+cardType+`.jpg">
			  `+cardType+`
			  delete

`+cardType+`

				remove
				add

	`;
	cardArea = document.getElementById("cardArea");
    cardArea.appendChild(newDiv);
	$('.closeBtn').on('click', function(){
    $(this).closest(".cardToDelete").remove();
});
 }

// delete a card
$('.closeBtn').on('click', function(){
    $(this).closest(".cardToDelete").remove();
});

//$('.deletePerson').click(function(){ console.log('Delete me'); return false; });

function displayScreen(screenID) {
	$('.TGEscreen').hide();
	$('#'+screenID+'').show();
}
function getRandomPeopleAttributes() {
	return {
		firstNamesMale: ['Jean-Michel','Jean-Pierre','Jean-Philippe','Jean-Paul','Jean-Marcel','Kevin','Killian','Mohammed','Ashton','Brad','Harrison','Bonaventure','Desire','Yunic','Dartagnan'],
		firstNamesFemale: ['Fatima','Barbara','Monica','Priscilia','Stephanie','Kelly','Nicole','Morgan','Jessica','Cindy','Kloe','Kim','Britney','Shakira','Beberly','Merica','Appaloosa','Melanomia','Heaven Lee'],
		lastNames: ['Bjornsonn','Al Belgiki','Dupont','Dugenou','Smith','Gaywad','Trump','Buttz','Ballz','Goodfornothing','Retard','Primitive','Kumar','Singh','Buzzbuzz','Nutgrabber','Ballbuster','Bieber','Van Damme','Van Varenberg','Daerdenne','Bin Batman','Neanderthal','Cromagnon','Uga-uga'],
	}
}

function getInitialState() {
	return {
		people: [
			{name: "denis", gender: "Male",age: "32", photo: "images/denis.jpg", diplomas : [0,1,2]},
			{name: "asal", gender: "Female",age: "28", photo: "images/asal.jpg", diplomas : [0,1,2,3]}
		]
	}
}

function getConfig() {
	return {
		diplomaList: [
			{name: 'Basic', icon: 'fas fa-gavel', color: '#9e9e9e'},
			{name: 'Engineer 1', icon: 'fas fa-wrench', color: '#b87333'},
			{name: 'Engineer 2', icon: 'fas fa-wrench', color: '#C0C0C0'},
			{name: 'Engineer 3', icon: 'fas fa-wrench', color: '#FFDF00'},
		]
	}
}

function makeUL(peopleArray) {
    // Create the list element:
    var list = document.createElement('ul');
	list.className = "collection";

    for (var i = 0; i < peopleArray.length; i++) {
        // Create the list item:
        var item = document.createElement('li');
		item.className = 'collection-item avatar'

		// create and append the thumbnail
		var thumb = document.createElement('IMG');
		thumb.src = peopleArray[i].photo;
		thumb.className = "circle"
		item.appendChild(thumb);

		// Create the title
		var title = document.createElement('span');
		title.className = 'title';
		title.appendChild(document.createTextNode(peopleArray[i].name + ' '));
		// gender logo
		var genderLogo = document.createElement('i');
		if (peopleArray[i].gender == 'Male') {genderLogo.className = "fas fa-mars"} else {genderLogo.className = "fas fa-venus"}
		title.appendChild(genderLogo);
		item.appendChild(title);

		// create and append the second line content
		var secondLineContent = document.createElement('p');

			// badges education
			// for all entries in diploma
			for (var j = 0; j < peopleArray[i].diplomas.length; j++) {
				diploma = config.diplomaList[peopleArray[i].diplomas[j]]
				console.log('Iteration '+j+' of loop over diplomas of '+peopleArray[i].name+' found '+diploma.name);
				var diplomaLogo = document.createElement('i');
				diplomaLogo.className = diploma.icon;
				diplomaLogo.style.color = diploma.color;
				secondLineContent.appendChild(diplomaLogo);
			}
		item.appendChild(secondLineContent);

		// append the text content
        //item.appendChild(document.createTextNode(peopleArray[i].name));

		// append the delete icon
		var linkDelete = document.createElement('a');
		linkDelete.className = 'secondary-content deletePerson';
		linkDelete.href = '#!'
		//linkDelete.onclick = "test"
		linkDelete.addEventListener("click", test, false);
		var deleteIcon = document.createElement('i');
		deleteIcon.className = 'material-icons';
		deleteIcon.appendChild(document.createTextNode('delete'))
		linkDelete.appendChild(deleteIcon);
		item.appendChild(linkDelete);

        // Add it to the list:
        list.appendChild(item);
    }

    // Finally, return the constructed list:
    return list;
}

// Add the contents of options[0] to #jobsScreen:
function generatePeopleDOM(divID) {
	document.getElementById(divID).appendChild(makeUL(state.people));
}

function clearPeopleDOM(divID) {
	var myNode = document.getElementById(divID);
	while (myNode.firstChild) {
		myNode.removeChild(myNode.firstChild);
	}
}

function addPerson_BE() {
	var newPerson = {name: "harry", gender: "Male",age: "15"};
	state.people.push(newPerson);
}

function addRandomPerson_BE() {
	// get the list of random names
	var randomPeopleAttributes = getRandomPeopleAttributes();
	// pick a random last name
	var randomIndex = Math.round(Math.random()*(randomPeopleAttributes.lastNames.length-1))
	var lastName = randomPeopleAttributes.lastNames[randomIndex]
	// decide whether the person is male or female
	if (Math.random() > 0.5) {
		var gender = 'Male'
		// pick a random picture in the images
		randomIndex = Math.round(Math.random()*65)+1
		var imgName='images/People/Males/image-'+randomIndex+'.jpg'
		// pick a random first name
		randomIndex = Math.round(Math.random()*(randomPeopleAttributes.firstNamesMale.length-1));
		var firstName = randomPeopleAttributes.firstNamesMale[randomIndex];
	} else {
		var gender = 'Female'
		// pick a random picture in the images
		randomIndex = Math.round(Math.random()*65)+1
		var imgName='images/People/Females/image-'+randomIndex+'.jpg'
		// pick a random first name
		randomIndex = Math.round(Math.random()*(randomPeopleAttributes.firstNamesFemale.length-1));
		var firstName = randomPeopleAttributes.firstNamesFemale[randomIndex];
	}

	var newPerson = {name: firstName + ' ' +lastName, gender: gender,age: "15", photo: imgName, diplomas : [0]};
	state.people.push(newPerson);
}

function addAndRefresh(divID) {
	addRandomPerson_BE();
	refreshPeopleList_FE();
}

function refreshPeopleList_FE() {
	divID = 'peopleListArea';
	clearPeopleDOM(divID);
	generatePeopleDOM(divID);
}

function test() {
	alert('Yeah you clicked');
}

// initialization
var state = getInitialState();
var config = getConfig();
generatePeopleDOM('peopleListArea');<commit_msg>Better diploma icons<commit_after>document.addEventListener('DOMContentLoaded', function() {
M.AutoInit();
});

  function createCard(cardType) {
	var newDiv = document.createElement("DIV");
	newDiv.className = "col s12 m6 l3 xl3 cardToDelete";
	newDiv.innerHTML = `

			  <img src="images/`+cardType+`.jpg">
			  `+cardType+`
			  delete

`+cardType+`

				remove
				add

	`;
	cardArea = document.getElementById("cardArea");
    cardArea.appendChild(newDiv);
	$('.closeBtn').on('click', function(){
    $(this).closest(".cardToDelete").remove();
});
 }

// delete a card
$('.closeBtn').on('click', function(){
    $(this).closest(".cardToDelete").remove();
});

//$('.deletePerson').click(function(){ console.log('Delete me'); return false; });

function displayScreen(screenID) {
	$('.TGEscreen').hide();
	$('#'+screenID+'').show();
}
function getRandomPeopleAttributes() {
	return {
		firstNamesMale: ['Jean-Michel','Jean-Pierre','Jean-Philippe','Jean-Paul','Jean-Marcel','Kevin','Killian','Mohammed','Ashton','Brad','Harrison','Bonaventure','Desire','Yunic','Dartagnan'],
		firstNamesFemale: ['Fatima','Barbara','Monica','Priscilia','Stephanie','Kelly','Nicole','Morgan','Jessica','Cindy','Kloe','Kim','Britney','Shakira','Beberly','Merica','Appaloosa','Melanomia','Heaven Lee'],
		lastNames: ['Bjornsonn','Al Belgiki','Dupont','Dugenou','Smith','Gaywad','Trump','Buttz','Ballz','Goodfornothing','Retard','Primitive','Kumar','Singh','Buzzbuzz','Nutgrabber','Ballbuster','Bieber','Van Damme','Van Varenberg','Daerdenne','Bin Batman','Neanderthal','Cromagnon','Uga-uga'],
	}
}

function getInitialState() {
	return {
		people: [
			{name: "denis", gender: "Male",age: "32", photo: "images/denis.jpg", diplomas : [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]},
			{name: "asal", gender: "Female",age: "28", photo: "images/asal.jpg", diplomas : [2,5,8,11,14]}
		]
	}
}

/* function getConfig() {
	return {
		diplomaList: [
			{name: 'Level 1', icon: 'fas fa-graduation-cap', color: '#b87333'},
			{name: 'Level 2', icon: 'fas fa-graduation-cap', color: '#C0C0C0'},
			{name: 'Level 3', icon: 'fas fa-graduation-cap', color: '#FFDF00'},
			{name: 'Engineer 1', icon: 'fas fa-wrench', color: '#b87333'},
			{name: 'Engineer 2', icon: 'fas fa-wrench', color: '#C0C0C0'},
			{name: 'Engineer 3', icon: 'fas fa-wrench', color: '#FFDF00'},
			{name: 'Doctor 1', icon: 'fas fa-stethoscope', color: '#b87333'},
			{name: 'Doctor 2', icon: 'fas fa-stethoscope', color: '#C0C0C0'},
			{name: 'Doctor 3', icon: 'fas fa-stethoscope', color: '#FFDF00'},
			{name: 'Hunter 1', icon: 'fab fa-grunt', color: '#b87333'},
			{name: 'Hunter 2', icon: 'fab fa-grunt', color: '#C0C0C0'},
			{name: 'Hunter 3', icon: 'fab fa-grunt', color: '#FFDF00'},

		]
	}
} */

function getConfig() {
	return {
		diplomaList: [
			{name: 'Level 1', icon: 'fas fa-graduation-cap', color: '#b87333'},
			{name: 'Level 2', icon: 'fas fa-graduation-cap', color: '#C0C0C0'},
			{name: 'Level 3', icon: 'fas fa-graduation-cap', color: '#FFDF00'},
			{name: 'Engineer 1', icon: 'fas fa-wrench', color: '#b87333'},
			{name: 'Engineer 2', icon: 'fas fa-wrench', color: '#C0C0C0'},
			{name: 'Engineer 3', icon: 'fas fa-wrench', color: '#FFDF00'},
			{name: 'Doctor 1', icon: 'fas fa-briefcase-medical', color: '#b87333'},
			{name: 'Doctor 2', icon: 'fas fa-briefcase-medical', color: '#C0C0C0'},
			{name: 'Doctor 3', icon: 'fas fa-briefcase-medical', color: '#FFDF00'},
			{name: 'Food 1', icon: 'fas fa-utensils', color: '#b87333'},
			{name: 'Food 2', icon: 'fas fa-utensils', color: '#C0C0C0'},
			{name: 'Food 3', icon: 'fas fa-utensils', color: '#FFDF00'},
			{name: 'Warrior 1', icon: 'fas fa-shield-alt', color: '#b87333'},
			{name: 'Warrior 2', icon: 'fas fa-shield-alt', color: '#C0C0C0'},
			{name: 'Warrior 3', icon: 'fas fa-shield-alt', color: '#FFDF00'},

		]
	}
}

function makeUL(peopleArray) {
    // Create the list element:
    var list = document.createElement('ul');
	list.className = "collection";

	// for each person
    for (var i = 0; i < peopleArray.length; i++) {
        // Create the list item:
        var item = document.createElement('li');
		item.className = 'collection-item avatar'

		// create and append the thumbnail
		var thumb = document.createElement('IMG');
		thumb.src = peopleArray[i].photo;
		thumb.className = "circle"
		item.appendChild(thumb);

		// Create the title
		var title = document.createElement('span');
		title.className = 'title';
		title.appendChild(document.createTextNode(peopleArray[i].name + ' '));
		// gender logo
		var genderLogo = document.createElement('i');
		if (peopleArray[i].gender == 'Male') {genderLogo.className = "fas fa-mars"} else {genderLogo.className = "fas fa-venus"}
		title.appendChild(genderLogo);
		item.appendChild(title);

		// create and append the second line content
		var secondLineContent = document.createElement('p');
		// sort the list of detained diplomas alphabetically, so the icons align
		peopleArray[i].diplomas.sort(function(a, b){return a - b});
			// badges education
			// for all entries in diploma
			for (var j = 0; j < peopleArray[i].diplomas.length; j++) {
				diploma = config.diplomaList[peopleArray[i].diplomas[j]]
				console.log('Iteration '+j+' of loop over diplomas of '+peopleArray[i].name+' found '+diploma.name);
				var diplomaLogo = document.createElement('i');
				diplomaLogo.className = diploma.icon;
				diplomaLogo.style.color = diploma.color;
				secondLineContent.appendChild(diplomaLogo);
				secondLineContent.appendChild(document.createTextNode(" "))
			}
		item.appendChild(secondLineContent);

		// append the text content
        //item.appendChild(document.createTextNode(peopleArray[i].name));

		// append the delete icon
		var linkDelete = document.createElement('a');
		linkDelete.className = 'secondary-content deletePerson';
		linkDelete.href = '#!'
		//linkDelete.onclick = "test"
		linkDelete.addEventListener("click", test, false);
		var deleteIcon = document.createElement('i');
		deleteIcon.className = 'material-icons';
		deleteIcon.appendChild(document.createTextNode('delete'))
		linkDelete.appendChild(deleteIcon);
		item.appendChild(linkDelete);

        // Add it to the list:
        list.appendChild(item);
    }

    // Finally, return the constructed list:
    return list;
}

// Add the contents of options[0] to #jobsScreen:
function generatePeopleDOM(divID) {
	document.getElementById(divID).appendChild(makeUL(state.people));
}

function clearPeopleDOM(divID) {
	var myNode = document.getElementById(divID);
	while (myNode.firstChild) {
		myNode.removeChild(myNode.firstChild);
	}
}

function addPerson_BE() {
	var newPerson = {name: "harry", gender: "Male",age: "15"};
	state.people.push(newPerson);
}

function addRandomPerson_BE() {
	// get the list of random names
	var randomPeopleAttributes = getRandomPeopleAttributes();
	// pick a random last name
	var randomIndex = Math.round(Math.random()*(randomPeopleAttributes.lastNames.length-1))
	var lastName = randomPeopleAttributes.lastNames[randomIndex]
	// decide whether the person is male or female
	if (Math.random() > 0.5) {
		var gender = 'Male'
		// pick a random picture in the images
		randomIndex = Math.round(Math.random()*65)+1
		var imgName='images/People/Males/image-'+randomIndex+'.jpg'
		// pick a random first name
		randomIndex = Math.round(Math.random()*(randomPeopleAttributes.firstNamesMale.length-1));
		var firstName = randomPeopleAttributes.firstNamesMale[randomIndex];
	} else {
		var gender = 'Female'
		// pick a random picture in the images
		randomIndex = Math.round(Math.random()*65)+1
		var imgName='images/People/Females/image-'+randomIndex+'.jpg'
		// pick a random first name
		randomIndex = Math.round(Math.random()*(randomPeopleAttributes.firstNamesFemale.length-1));
		var firstName = randomPeopleAttributes.firstNamesFemale[randomIndex];
	}

	var newPerson = {name: firstName + ' ' +lastName, gender: gender,age: "15", photo: imgName, diplomas : [0]};
	state.people.push(newPerson);
}

function addAndRefresh(divID) {
	addRandomPerson_BE();
	refreshPeopleList_FE();
}

function refreshPeopleList_FE() {
	divID = 'peopleListArea';
	clearPeopleDOM(divID);
	generatePeopleDOM(divID);
}

function test() {
	alert('Yeah you clicked');
}

// initialization
var state = getInitialState();
var config = getConfig();
generatePeopleDOM('peopleListArea');<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source", "Tone/source/BufferSource"], function(Tone){

	"use strict";

	/**
	 *  @class  Tone.Player is an audio file player with start, loop, and stop functions.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string|AudioBuffer} url Either the AudioBuffer or the url from
	 *                                  which to load the AudioBuffer
	 *  @param {function=} onload The function to invoke when the buffer is loaded.
	 *                            Recommended to use Tone.Buffer.on('load') instead.
	 *  @example
	 * var player = new Tone.Player("./path/to/sample.mp3").toMaster();
	 * //play as soon as the buffer is loaded
	 * player.autostart = true;
	 */
	Tone.Player = function(url){

		var options;
		if (url instanceof Tone.Buffer){
			url = url.get();
			options = Tone.Player.defaults;
		} else {
			options = Tone.defaults(arguments, ["url", "onload"], Tone.Player);
		}
		Tone.Source.call(this, options);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  If the file should play as soon
		 *  as the buffer is loaded.
		 *  @type {boolean}
		 *  @example
		 * //will play as soon as it's loaded
		 * var player = new Tone.Player({
		 * 	"url" : "./path/to/sample.mp3",
		 * 	"autostart" : true,
		 * }).toMaster();
		 */
		this.autostart = options.autostart;

		/**
		 *  the buffer
		 *  @private
		 *  @type {Tone.Buffer}
		 */
		this._buffer = new Tone.Buffer({
			"url" : options.url,
			"onload" : this._onload.bind(this, options.onload),
			"reverse" : options.reverse
		});
		if (url instanceof AudioBuffer){
			this._buffer.set(url);
		}

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 *  @private
		 */
		this._loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = options.playbackRate;

		/**
		 *  Enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing. Otherwise,
		 *  successive calls to Tone.Player.start will only start
		 *  the sample if it had played all the way through.
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onload" : Tone.noOp,
		"playbackRate" : 1,
		"loop" : false,
		"autostart" : false,
		"loopStart" : 0,
		"loopEnd" : 0,
		"retrigger" : false,
		"reverse" : false,
	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 *  Note: this does not need to be called if a url
	 *  was passed in to the constructor. Only use this
	 *  if you want to manually load a new url.
	 * @param {string} url The url of the buffer to load.
	 *                     Filetype support depends on the
	 *                     browser.
	 *  @param  {function=} callback The function to invoke once
	 *                               the sample is loaded.
	 *  @returns {Promise}
	 */
	Tone.Player.prototype.load = function(url, callback){
		return this._buffer.load(url, this._onload.bind(this, callback));
	};

	/**
	 * Internal callback when the buffer is loaded.
	 * @private
	 */
	Tone.Player.prototype._onload = function(callback){
		callback = Tone.defaultArg(callback, Tone.noOp);
		callback(this);
		if (this.autostart){
			this.start();
		}
	};

	/**
	 *  Play the buffer at the given startTime. Optionally add an offset
	 *  and/or duration which will play the buffer from a position
	 *  within the buffer for the given duration.
	 *
	 *  @param  {Time} [startTime=now] When the player should start.
	 *  @param  {Time} [offset=0] The offset from the beginning of the sample
	 *                                 to start at.
	 *  @param  {Time=} duration How long the sample should play. If no duration
	 *                                is given, it will default to the full length
	 *                                of the sample (minus any offset)
	 *  @returns {Tone.Player} this
	 *  @memberOf Tone.Player#
	 *  @method start
	 *  @name start
	 */

	/**
	 *  Internal start method
	 *  @private
	 */
	Tone.Player.prototype._start = function(startTime, offset, duration){
		//if it's a loop the default offset is the loopstart point
		if (this._loop){
			offset = Tone.defaultArg(offset, this._loopStart);
		} else {
			//otherwise the default offset is 0
			offset = Tone.defaultArg(offset, 0);
		}

		//compute the values in seconds
		offset = this.toSeconds(offset);
		duration = Tone.defaultArg(duration, Math.max(this._buffer.duration - offset, 0));
		duration = this.toSeconds(duration);
		startTime = this.toSeconds(startTime);

		// //make the source
		this._source = new Tone.BufferSource({
			"buffer" : this._buffer,
			"loop" : this._loop,
			"loopStart" : this._loopStart,
			"loopEnd" : this._loopEnd,
			"playbackRate" : this._playbackRate
		}).connect(this.output);

		//set the looping properties
		if (!this._loop && !this._synced){
			//if it's not looping, set the state change at the end of the sample
			this._state.setStateAtTime(Tone.State.Stopped, startTime + duration);
		}

		//start it
		if (this._loop){
			this._source.start(startTime, offset);
		} else {
			this._source.start(startTime, offset, duration);
		}
		return this;
	};

	/**
	 *  Stop playback.
	 *  @private
	 *  @param  {Time} [time=now]
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype._stop = function(time){
		if (this._source){
			this._source.stop(this.toSeconds(time));
		}
		return this;
	};

	/**
	 *  Seek to a specific time in the player's buffer. If the
	 *  source is no longer playing at that time, it will stop.
	 *  If you seek to a time that
	 *  @param {Time} offset The time to seek to.
	 *  @param {Time=} time The time for the seek event to occur.
	 *  @return {Tone.Player} this
	 *  @example
	 * source.start(0.2);
	 * source.stop(0.4);
	 */
	Tone.Player.prototype.seek = function(offset, time){
		time = this.toSeconds(time);
		if (this._state.getValueAtTime(time) === Tone.State.Started){
			offset = this.toSeconds(offset);
			// if it's currently playing, stop it
			this._stop(time);
			//restart it at the given time
			this._start(time, offset);
		}
		return this;
	};

	/**
	 *  Set the loop start and end. Will only loop if loop is
	 *  set to true.
	 *  @param {Time} loopStart The loop end time
	 *  @param {Time} loopEnd The loop end time
	 *  @returns {Tone.Player} this
	 *  @example
	 * //loop 0.1 seconds of the file.
	 * player.setLoopPoints(0.2, 0.3);
	 * player.loop = true;
	 */
	Tone.Player.prototype.setLoopPoints = function(loopStart, loopEnd){
		this.loopStart = loopStart;
		this.loopEnd = loopEnd;
		return this;
	};

	/**
	 * If loop is true, the loop will start at this position.
	 * @memberOf Tone.Player#
	 * @type {Time}
	 * @name loopStart
	 */
	Object.defineProperty(Tone.Player.prototype, "loopStart", {
		get : function(){
			return this._loopStart;
		},
		set : function(loopStart){
			this._loopStart = loopStart;
			if (this._source){
				this._source.loopStart = this.toSeconds(loopStart);
			}
		}
	});

	/**
	 * If loop is true, the loop will end at this position.
	 * @memberOf Tone.Player#
	 * @type {Time}
	 * @name loopEnd
	 */
	Object.defineProperty(Tone.Player.prototype, "loopEnd", {
		get : function(){
			return this._loopEnd;
		},
		set : function(loopEnd){
			this._loopEnd = loopEnd;
			if (this._source){
				this._source.loopEnd = this.toSeconds(loopEnd);
			}
		}
	});

	/**
	 * The audio buffer belonging to the player.
	 * @memberOf Tone.Player#
	 * @type {Tone.Buffer}
	 * @name buffer
	 */
	Object.defineProperty(Tone.Player.prototype, "buffer", {
		get : function(){
			return this._buffer;
		},
		set : function(buffer){
			this._buffer.set(buffer);
		}
	});

	/**
	 * If the buffer should loop once it's over.
	 * @memberOf Tone.Player#
	 * @type {boolean}
	 * @name loop
	 */
	Object.defineProperty(Tone.Player.prototype, "loop", {
		get : function(){
			return this._loop;
		},
		set : function(loop){
			this._loop = loop;
			if (this._source){
				this._source.loop = loop;
			}
		}
	});

	/**
	 * The playback speed. 1 is normal speed. This is not a signal because
	 * Safari and iOS currently don't support playbackRate as a signal.
	 * @memberOf Tone.Player#
	 * @type {number}
	 * @name playbackRate
	 */
	Object.defineProperty(Tone.Player.prototype, "playbackRate", {
		get : function(){
			return this._playbackRate;
		},
		set : function(rate){
			this._playbackRate = rate;
			if (this._source) {
				this._source.playbackRate.value = rate;
			}
		}
	});

	/**
	 * The direction the buffer should play in
	 * @memberOf Tone.Player#
	 * @type {boolean}
	 * @name reverse
	 */
	Object.defineProperty(Tone.Player.prototype, "reverse", {
		get : function(){
			return this._buffer.reverse;
		},
		set : function(rev){
			this._buffer.reverse = rev;
		}
	});

	/**
	 * If all the buffer is loaded
	 * @memberOf Tone.Player#
	 * @type {Boolean}
	 * @name loaded
	 * @readOnly
	 */
	Object.defineProperty(Tone.Player.prototype, "loaded", {
		get : function(){
			return this._buffer.loaded;
		}
	});

	/**
	 *  Dispose and disconnect.
	 *  @return {Tone.Player} this
	 */
	Tone.Player.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer.dispose();
		this._buffer = null;
		return this;
	};

	return Tone.Player;
});
<commit_msg>adding fadeIn/Out to Player<commit_after>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source", "Tone/source/BufferSource"], function(Tone){

	"use strict";

	/**
	 *  @class  Tone.Player is an audio file player with start, loop, and stop functions.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string|AudioBuffer} url Either the AudioBuffer or the url from
	 *                                  which to load the AudioBuffer
	 *  @param {function=} onload The function to invoke when the buffer is loaded.
	 *                            Recommended to use Tone.Buffer.on('load') instead.
	 *  @example
	 * var player = new Tone.Player("./path/to/sample.mp3").toMaster();
	 * //play as soon as the buffer is loaded
	 * player.autostart = true;
	 */
	Tone.Player = function(url){

		var options;
		if (url instanceof Tone.Buffer){
			url = url.get();
			options = Tone.Player.defaults;
		} else {
			options = Tone.defaults(arguments, ["url", "onload"], Tone.Player);
		}
		Tone.Source.call(this, options);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  If the file should play as soon
		 *  as the buffer is loaded.
		 *  @type {boolean}
		 *  @example
		 * //will play as soon as it's loaded
		 * var player = new Tone.Player({
		 * 	"url" : "./path/to/sample.mp3",
		 * 	"autostart" : true,
		 * }).toMaster();
		 */
		this.autostart = options.autostart;

		/**
		 *  the buffer
		 *  @private
		 *  @type {Tone.Buffer}
		 */
		this._buffer = new Tone.Buffer({
			"url" : options.url,
			"onload" : this._onload.bind(this, options.onload),
			"reverse" : options.reverse
		});
		if (url instanceof AudioBuffer){
			this._buffer.set(url);
		}

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 *  @private
		 */
		this._loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = options.playbackRate;

		/**
		 *  Enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing. Otherwise,
		 *  successive calls to Tone.Player.start will only start
		 *  the sample if it had played all the way through.
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;

		/**
		 *  The fadeIn time of the amplitude envelope.
		 *  @type {Time}
		 */
		this.fadeIn = options.fadeIn;

		/**
		 *  The fadeOut time of the amplitude envelope.
		 *  @type {Time}
		 */
		this.fadeOut = options.fadeOut;
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onload" : Tone.noOp,
		"playbackRate" : 1,
		"loop" : false,
		"autostart" : false,
		"loopStart" : 0,
		"loopEnd" : 0,
		"retrigger" : false,
		"reverse" : false,
		"fadeIn" : 0,
		"fadeOut" : 0

	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 *  Note: this does not need to be called if a url
	 *  was passed in to the constructor. Only use this
	 *  if you want to manually load a new url.
	 * @param {string} url The url of the buffer to load.
	 *                     Filetype support depends on the
	 *                     browser.
	 *  @param  {function=} callback The function to invoke once
	 *                               the sample is loaded.
	 *  @returns {Promise}
	 */
	Tone.Player.prototype.load = function(url, callback){
		return this._buffer.load(url, this._onload.bind(this, callback));
	};

	/**
	 * Internal callback when the buffer is loaded.
	 * @private
	 */
	Tone.Player.prototype._onload = function(callback){
		callback = Tone.defaultArg(callback, Tone.noOp);
		callback(this);
		if (this.autostart){
			this.start();
		}
	};

	/**
	 *  Play the buffer at the given startTime. Optionally add an offset
	 *  and/or duration which will play the buffer from a position
	 *  within the buffer for the given duration.
	 *
	 *  @param  {Time} [startTime=now] When the player should start.
	 *  @param  {Time} [offset=0] The offset from the beginning of the sample
	 *                                 to start at.
	 *  @param  {Time=} duration How long the sample should play. If no duration
	 *                                is given, it will default to the full length
	 *                                of the sample (minus any offset)
	 *  @returns {Tone.Player} this
	 *  @memberOf Tone.Player#
	 *  @method start
	 *  @name start
	 */

	/**
	 *  Internal start method
	 *  @private
	 */
	Tone.Player.prototype._start = function(startTime, offset, duration){
		//if it's a loop the default offset is the loopstart point
		if (this._loop){
			offset = Tone.defaultArg(offset, this._loopStart);
		} else {
			//otherwise the default offset is 0
			offset = Tone.defaultArg(offset, 0);
		}

		//compute the values in seconds
		offset = this.toSeconds(offset);
		duration = Tone.defaultArg(duration, Math.max(this._buffer.duration - offset, 0));
		duration = this.toSeconds(duration);
		startTime = this.toSeconds(startTime);

		// //make the source
		this._source = new Tone.BufferSource({
			"buffer" : this._buffer,
			"loop" : this._loop,
			"loopStart" : this._loopStart,
			"loopEnd" : this._loopEnd,
			"playbackRate" : this._playbackRate,
			"fadeIn" : this.fadeIn,
			"fadeOut" : this.fadeOut,
		}).connect(this.output);

		//set the looping properties
		if (!this._loop && !this._synced){
			//if it's not looping, set the state change at the end of the sample
			this._state.setStateAtTime(Tone.State.Stopped, startTime + duration);
		}

		//start it
		if (this._loop){
			this._source.start(startTime, offset);
		} else {
			this._source.start(startTime, offset, duration);
		}
		return this;
	};

	/**
	 *  Stop playback.
	 *  @private
	 *  @param  {Time} [time=now]
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype._stop = function(time){
		if (this._source){
			this._source.stop(this.toSeconds(time));
		}
		return this;
	};

	/**
	 *  Seek to a specific time in the player's buffer. If the
	 *  source is no longer playing at that time, it will stop.
	 *  If you seek to a time that
	 *  @param {Time} offset The time to seek to.
	 *  @param {Time=} time The time for the seek event to occur.
	 *  @return {Tone.Player} this
	 *  @example
	 * source.start(0.2);
	 * source.stop(0.4);
	 */
	Tone.Player.prototype.seek = function(offset, time){
		time = this.toSeconds(time);
		if (this._state.getValueAtTime(time) === Tone.State.Started){
			offset = this.toSeconds(offset);
			// if it's currently playing, stop it
			this._stop(time);
			//restart it at the given time
			this._start(time, offset);
		}
		return this;
	};

	/**
	 *  Set the loop start and end. Will only loop if loop is
	 *  set to true.
	 *  @param {Time} loopStart The loop end time
	 *  @param {Time} loopEnd The loop end time
	 *  @returns {Tone.Player} this
	 *  @example
	 * //loop 0.1 seconds of the file.
	 * player.setLoopPoints(0.2, 0.3);
	 * player.loop = true;
	 */
	Tone.Player.prototype.setLoopPoints = function(loopStart, loopEnd){
		this.loopStart = loopStart;
		this.loopEnd = loopEnd;
		return this;
	};

	/**
	 * If loop is true, the loop will start at this position.
	 * @memberOf Tone.Player#
	 * @type {Time}
	 * @name loopStart
	 */
	Object.defineProperty(Tone.Player.prototype, "loopStart", {
		get : function(){
			return this._loopStart;
		},
		set : function(loopStart){
			this._loopStart = loopStart;
			if (this._source){
				this._source.loopStart = this.toSeconds(loopStart);
			}
		}
	});

	/**
	 * If loop is true, the loop will end at this position.
	 * @memberOf Tone.Player#
	 * @type {Time}
	 * @name loopEnd
	 */
	Object.defineProperty(Tone.Player.prototype, "loopEnd", {
		get : function(){
			return this._loopEnd;
		},
		set : function(loopEnd){
			this._loopEnd = loopEnd;
			if (this._source){
				this._source.loopEnd = this.toSeconds(loopEnd);
			}
		}
	});

	/**
	 * The audio buffer belonging to the player.
	 * @memberOf Tone.Player#
	 * @type {Tone.Buffer}
	 * @name buffer
	 */
	Object.defineProperty(Tone.Player.prototype, "buffer", {
		get : function(){
			return this._buffer;
		},
		set : function(buffer){
			this._buffer.set(buffer);
		}
	});

	/**
	 * If the buffer should loop once it's over.
	 * @memberOf Tone.Player#
	 * @type {boolean}
	 * @name loop
	 */
	Object.defineProperty(Tone.Player.prototype, "loop", {
		get : function(){
			return this._loop;
		},
		set : function(loop){
			this._loop = loop;
			if (this._source){
				this._source.loop = loop;
			}
		}
	});

	/**
	 * The playback speed. 1 is normal speed. This is not a signal because
	 * Safari and iOS currently don't support playbackRate as a signal.
	 * @memberOf Tone.Player#
	 * @type {number}
	 * @name playbackRate
	 */
	Object.defineProperty(Tone.Player.prototype, "playbackRate", {
		get : function(){
			return this._playbackRate;
		},
		set : function(rate){
			this._playbackRate = rate;
			if (this._source) {
				this._source.playbackRate.value = rate;
			}
		}
	});

	/**
	 * The direction the buffer should play in
	 * @memberOf Tone.Player#
	 * @type {boolean}
	 * @name reverse
	 */
	Object.defineProperty(Tone.Player.prototype, "reverse", {
		get : function(){
			return this._buffer.reverse;
		},
		set : function(rev){
			this._buffer.reverse = rev;
		}
	});

	/**
	 * If all the buffer is loaded
	 * @memberOf Tone.Player#
	 * @type {Boolean}
	 * @name loaded
	 * @readOnly
	 */
	Object.defineProperty(Tone.Player.prototype, "loaded", {
		get : function(){
			return this._buffer.loaded;
		}
	});

	/**
	 *  Dispose and disconnect.
	 *  @return {Tone.Player} this
	 */
	Tone.Player.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer.dispose();
		this._buffer = null;
		return this;
	};

	return Tone.Player;
});
<|endoftext|>