<commit_before>define('PredictionTree',['PredictionModel'],function(PredictionModel){
	'use strict';

var localFormCache = undefined;

if(localStorage!==undefined){
	if(localStorage.predictionStorage===undefined){
		localStorage.predictionStorage=JSON.stringify({});
		localFormCache = {};
	}else{
		localFormCache = JSON.parse(localStorage.predictionStorage);
	}
}
//var localFormCache = localStorage?localStorage.predictionStorage:undefined;

	function filter(baseKeyArray,_treeStructure){

		//expecting that baseKeyArray is in reverse order
			var filteredTreeStructureArray = {};
			if(baseKeyArray.length===0){
				return _treeStructure;
			}
			var _compareKeyvalue = baseKeyArray.pop();
			if(_treeStructure[_compareKeyvalue]!==undefined){
				return filter(baseKeyArray,_treeStructure[_compareKeyvalue][1]);
			}else{
				var tempNewTreeStructure = {}
				var allKeys = Object.keys(_treeStructure);
				allKeys.forEach(function(key){
					var _nextLevelChildren = Object.keys(_treeStructure[key][1]?_treeStructure[key][1]:{});
					var _childContainer	   = _treeStructure[key][1];
					_nextLevelChildren.forEach(function(_childKey){
						if(tempNewTreeStructure[_childKey]!==undefined){
							dynamicAppendToTree(tempNewTreeStructure,_childKey,_childContainer);
						}else{
							tempNewTreeStructure[_childKey] = _childContainer[_childKey];
						}
					});
				});

				return filter(baseKeyArray,tempNewTreeStructure);
			}
	}

function dynamicAppendToTree(tempNewTreeStructure,_childkey,_childContainer){
	if(tempNewTreeStructure[_childkey]!==undefined){
		tempNewTreeStructure[_childkey][0] = tempNewTreeStructure[_childkey][0] + _childContainer[_childkey][0];
		var tempChildKeys = Object.keys(_childContainer[_childkey][1]);
		var treeStructureChildContainer = tempNewTreeStructure[_childkey][1];
		var mergeStructureChildContainer = _childContainer[_childkey][1]
		if(tempChildKeys.length===0){
			return ;
		}else{
			tempChildKeys.forEach(function(_key){
				if(treeStructureChildContainer[_key]!==undefined){
					dynamicAppendToTree(treeStructureChildContainer,_key,mergeStructureChildContainer);
				}else{
					treeStructureChildContainer[_key] = mergeStructureChildContainer[_key];
				}
			})
			//return tempNewTreeStructure;
		}

	}
}

	var predictionTree = function(formName){

						var enableLearning = true;
						var enablePrediction = true;

						var _treeModel = [];

						/*var _treeStructure = {Software:[4,
														  {Enovia:[3,
														  			{FaBs:[2,
														  					{
																			'Java and JS':[4,{}]
																		  	}
																		  ],
																	BPS:[1,
																			{
																			'Java and BPS JS':[1,{}]
																			}
																		]
																	}
																   ],
															'3DExcite':[2,
														  			{'3DX':[1,
														  					{
																			'JS and C++':[1,{}]
																		  	}
																		  ],
																	 'BPS':[1,
														  					{
																			'JS and C++':[1,{}]
																		  	}
																		  ],
																	}
																   ],
															'Delmia':[5,
														  			{'Del1':[3,
														  					{
																			'JS and C++':[3,{}]
																		  	}
																		  ],
																	 'BPS':[2,
														  					{
																			'JS and C++':[2,{}]
																		  	}
																		  ],
																	}
																   ]
															}
														],
											'Team Lead':[1,
														  {Enovia:[1,
														  			{FaBs:[1,
														  					{
																			'Java':[1,{}]
																		  	}
																		  ]
																	 }
																   ]
															}
														]
											  };
*/

							var _treeStructure = {

												 };

							if(localFormCache!==undefined){
								if(localFormCache[formName]!==undefined){
									var formPredictionCache = JSON.parse(localFormCache[formName]);
									_treeModel = formPredictionCache['_treeModel']!==undefined?formPredictionCache['_treeModel']:[];
									_treeStructure = formPredictionCache['_treeStructure']!==undefined?formPredictionCache['_treeStructure']:{};
									enableLearning = formPredictionCache['enableLearning']!==undefined?formPredictionCache['enableLearning']:true;
									enablePrediction = formPredictionCache['enablePrediction']!==undefined?formPredictionCache['enablePrediction']:true;
								}
							}

						return 	{
									enableLearning:function(){
											enableLearning = true;
											this.storePredictionData();
									},
									disableLearning:function(){
											enableLearning = false;
											this.storePredictionData();
									},
									toggleLearning:function(state){
										if(state!==undefined && typeof state === 'boolean'){
											enableLearning = state;
										}else{
											enableLearning = !enableLearning;
										}

										this.storePredictionData();
											console.log("Form Learning is NOW..: "+enableLearning);
									},
									isLearningEnabled:function(){
										return enableLearning;
									},
									enablePrediction:function(){
											enableLearning = true;
											this.storePredictionData();
									},
									disablePrediction:function(){
											enableLearning = false;
											this.storePredictionData();
									},
									togglePrediction:function(state){
										if(state!==undefined && typeof state === 'boolean'){
											enablePrediction = state;
										}else{
											enablePrediction = !enablePrediction;
										}
										this.storePredictionData();
											console.log("Form Prediction is NOW..: "+enablePrediction);
									},
									isPredictionEnabled:function(){
										return enablePrediction;
									},
									resetPredictionData:function(){
										_treeStructure = {};
										_treeModel = [];
										this.storePredictionData();
									},
									convertToString: function(){
										var formPredictionData = {
																	'_treeModel' : _treeModel,
																	'_treeStructure' : _treeStructure,
																	'enableLearning' : enableLearning,
																	'enablePrediction': enablePrediction
																	}
										return JSON.stringify(formPredictionData);
									},
									convertToJSON: function(){
										return JSON.parse(_treeStructure);
									},
									setTreeStructure:function(treeStr){
										if(typeof treeStr==="object"){
											_treeStructure = treeStr;
										}else if(typeof treeStr==="string"){
											_treeStructure = this.convertToJSON(treeStr);
										}
									},
									learn:function(formContainer){

										if(enableLearning===false){
											console.log("Learing is disabled for this form");
											return false;
										}

										var inputFieldsList = $(formContainer).find('input');
										var record = {};

										if(_treeModel.length===0){
											var _semantics = {};
											inputFieldsList.toArray().filter(function(field){
																return 'true'===field.dataset.intel;
															}).forEach(function(field){
																	_semantics[field.id] = parseInt(field.dataset.w);
																	record[field.id]=field.value;
															});
											 var model = PredictionModel.setupModel(_semantics);
											this.setModel(model);
										}else{
											inputFieldsList.toArray().filter(function(field){
																return 'true'===field.dataset.intel;
															}).forEach(function(field){
																	record[field.id]=field.value;
															});
										}
										return this.addRecord(record);
									},
									printTreeStructure:function(){
										console.log(_treeStructure);

									},
									setModel:function(model){
										_treeModel = model?model:[];
									},
									storePredictionData:function(){
										if(localFormCache!==undefined){
											localFormCache[formName] = this.convertToString();
											localStorage.predictionStorage = JSON.stringify(localFormCache);
										}else{
											console.log("No local storage to store this Data");
										}
									},
									addRecord:function(record){
										//var modelSchemaKeys = Object.keys(_treeModel);
										if(enableLearning===false){
											console.log("Learing is disabled for this form");
											return false;
										}

										if(!PredictionModel.validateAgainstModel(_treeModel,record)){
											console.log(" Record failed to validate against Model");
											return false;
										}

										var newTreeStructure = {};
										var tempNewTreeStructure = newTreeStructure;
										var firstRecordKey = null;
										_treeModel.forEach(function(fieldIdKey){
											var value = record[fieldIdKey.id];
											if(null===firstRecordKey){
												firstRecordKey = value;
											}
											if(value!==undefined){
												tempNewTreeStructure[value] = [1,{}];
												tempNewTreeStructure = tempNewTreeStructure[value][1];
											}else{
												tempNewTreeStructure[' '] = [1,{}];
												tempNewTreeStructure = tempNewTreeStructure[' '][1];
											}

										});

										if(_treeStructure[firstRecordKey]!==undefined){
											dynamicAppendToTree(_treeStructure,firstRecordKey,newTreeStructure);
										}else{
											_treeStructure[firstRecordKey] = newTreeStructure[firstRecordKey];
										}

										this.storePredictionData();

										return true;

									},
									getFilterTreeStructure: function(baseKeyArray,contextTreeStructure){
										var _TreeStructureClone = $.extend(true, {}, _treeStructure);
										var localTreeStructure = contextTreeStructure?contextTreeStructure:_TreeStructureClone;
										return filter(baseKeyArray.reverse(),localTreeStructure);
									}

								};

	};

	return predictionTree;

});
<commit_msg>Delete PredictionTree.js<commit_after><|endoftext|>


<commit_before>function changePopupColor(event) { //changes the events object
	$("#popupTitleButton").removeClass("btn-success btn-inverse btn-warning btn-danger");
	if (event.valid == false) {
		$("#popupTitleButton").addClass("btn-inverse");
	} else if (event.staffAdded == 0) {
		$("#popupTitleButton").addClass("btn-danger");
	} else if (event.staffAdded < event.staffNeeded) {
		$("#popupTitleButton").addClass("btn-warning");
	} else if (event.staffAdded == event.staffNeeded) {
		$("#popupTitleButton").addClass("btn-success");
	}
}

$('#eventButton').click(function(e) {
	$('#eventButton').addClass('disabled');
	$('#popup').modalPopover('hide');
});

resizeMap = function() {
	var column_height = $(window).height();
	$('#calendar').fullCalendar('option', 'height', column_height - 40);
	//$("#calendar").css("height", + "px")
};

function setTimeline(view) { //this is borrowed from stackoverflow
	var parentDiv = jQuery(".fc-agenda-slots:visible").parent();
	var timeline = parentDiv.children(".timeline");
	if (timeline.length == 0) { //if timeline isn't there, add it
		timeline = jQuery("
").addClass("timeline");
		parentDiv.prepend(timeline);
	}
	var curTime = new Date();
	var curCalView = jQuery("#calendar").fullCalendar('getView');
	if (curCalView.visStart < curTime && curCalView.visEnd > curTime) {
		timeline.show();
	} else {
		timeline.hide();
		return;
	}
	var curSeconds = (curTime.getHours() * 60 * 60) + (curTime.getMinutes() * 60) + curTime.getSeconds();
	var percentOfDay = curSeconds / 86400; //24 * 60 * 60 = 86400, # of seconds in a day
	var topLoc = Math.floor(parentDiv.height() * percentOfDay);
	timeline.css("top", topLoc + "px");
	if (curCalView.name == "agendaWeek") { //week view, don't want the timeline to go the whole way across
		var dayCol = jQuery(".fc-today:visible");
		var left = dayCol.position().left + 1;
		var width = dayCol.width() - 2;
		timeline.css({
			left: left + "px",
			width: width + "px"
		});
	}
}

Array.prototype.removeItem = function(a) { //try to avoid changing Array.prototype
	for (i = 0; i < this.length; i++) {
		if (this[i] == a) {
			for (i2 = i; i2 < this.length - 1; i2++) {
				this[i2] = this[i2 + 1];
			}
			this.length = this.length - 1
			return;
		}
	}
}

function dropdownActiveFix() {
	$('a').removeClass('drop-active');
	$('a[href="#' + Backbone.history.fragment + '"]').addClass('drop-active');

}

$('.modal').on('show', function() {
	$('#popup').css('opacity', 0.7);
}).on('hide', function() {
	$('#popup').css('opacity', 1);
});

// The functions above are mostly done
var lastClick, lastRightClick;

// BACKBONE.JS ROUTER SECTION
var AppRouter = Backbone.Router.extend({
	routes: {
		"printToday": "printToday",
		"recentVideo": "recentVideo",
		"*filter": "all"
	}
});

//User info must be imported for this part
var username = 'ckorkut';

var app = new AppRouter;

app.on('route:printToday', function() {
	console.log('printToday');
});
app.on('route:recentVideo', function() {
	console.log('recentVideo');
});

app.on('route:all', function(filter) {
	dropdownActiveFix();
	if (filter == null) {
		//Show all of events
		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log('all');

	} else if (filter == 'hideCancelled') {

		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			if (event.valid == false) {
				event.className.push('hide');
			}
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log(filter);
	} else if (filter == 'unstaffed') {
		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			if (event.staffAdded == event.staffNeeded || event.valid == false) {
				event.className.push('hide');
			}
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log(filter);
	} else if (filter == 'onlyMine') {
		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			if (event.people.indexOf(username) == -1) {
				event.className.push('hide');
			}
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log(filter);
	}
});

Backbone.history.start();

var lastClickedEvent;
$('a[href="#staffEvent"]').click(function(e) {
	//This part should get the event data and update staff adding modal box
	$('.eventName').html(lastClickedEvent.title);
	$.ajax({
		type: "GET",
		url: "staff/get/" + lastClickedEvent.id,
	}).done(function(data) {
			console.log(data);
	});
});

// Solves Bootstrap typeahead dropdown problem
$('.collapse').on({
	hide: function() {
		$(this).css('overflow', 'hidden');

		//$(this).hide();
	},
	click: function() {
		$('.collapse').css('overflow', 'visible');
	},
	shown: function() {
		$('.collapse').css('overflow', 'visible');
	}
});
$('button[data-target="#viewdetails"]').click(function() {
	$(this).toggleClass("active");
});

var inventoryProto = {
	suggestion_url: "inventory/all",
	//These methods below have to send AJAX requests to update the inventory.
	onRemove: function(pill) {
		var id = pill.data('tag-id');
		// do something...
		console.log('pill with ID ' + id + ' removed');
	},
	onBeforeAdd: function(pill) { //
		var id = pill.data('tag-id');
		// do something...
		console.log('pill with ID ' + id + ' added');
		return pill; //has to return pill
	}
};

$(document).ready(function() {

	var date = new Date();
	var d = date.getDate();
	var m = date.getMonth();
	var y = date.getFullYear();
	$('#popup').modalPopover({
		target: '#eventButton',
		placement: 'bottom',
		backdrop: false
	});

	$('#calendar').fullCalendar({
		header: {
			left: 'prevYear,prev,next,nextYear today',
			center: 'title',
			right: 'month,agendaWeek,agendaDay'

		},
		editable: false,
		allDaySlot: false,
		allDayDefault: false,
		firstDay: date.getDay(),
		eventBorderColor: 'black',
		windowResize: function(view) {
			resizeMap();
		},
		eventClick: function(calEvent, jsEvent, view) {

			//This function should contain specific stuff like opening the event-based selection/description box etc

			//front-end eye-candy stuff
			symbol = '';
			if (calEvent.video == true) {
				symbol += ' ';
			}
			$('#popup').modalPopover('show');
			$('#eventButton').removeClass('disabled');
			changePopupColor(calEvent);

			//Popover update with event information
			$('#popupTitle').html(symbol + calEvent.title);
			$('#popupStaffInfo').html(calEvent.staffAdded + '/' + calEvent.staffNeeded);
			$('#popupContentInside').html(calEvent.desc);
			$('#popupContentHeader').html('' + defaults.dayNames[calEvent.start.getDay()] + ' | ' + calEvent.loc + '');

			//Inventory update
			var inventoryOptions = {
				values_url: 'inventory/existing/' + calEvent.id,
			};
			$.extend(inventoryOptions,inventoryProto);
			$('#inventory').html('');
			$('#inventory').tags(inventoryOptions);
			lastClickedEvent = calEvent;
		},
		eventRightClick: function(calEvent, jsEvent, view) {
			jsEvent.preventDefault(); //Right click event only prevents default because context menu is binded in eventRender
			lastClickedEvent = calEvent;
		},
		eventRender: function(event, element) {
			//Adding all events to an array for event filtering with Backbone.js router
			symbol = '';
			if (event.video == true) {
				symbol += ' ';
			}
			element.find('.fc-event-title').html(symbol + event.title);
			element.contextmenu({
				'target': '#context-menu'
			});

		},
		viewRender: function(view, element) {
			//console.log(view.name);
			try {
				setTimeline();
			} catch (err) {}
		},
		newEventsComplete: function() { //after each ajax request to the server, new events also filtered by this way
			var currentUrl = Backbone.history.fragment;
			if (currentUrl != '') {
				app.navigate('', {
					trigger: true
				});
				app.navigate(currentUrl, {
					trigger: true
				});
			}
		},
		eventSources: [{
			url: 'events/', // Shows all events BUT need it to show only events to certain location
			ignoreTimezone: false
		}],
	});

	//Important: especially not using defaultView option of FullCalendar, for efficient use of lazyFetching.
	$('#calendar').fullCalendar('changeView', 'agendaWeek');
	//Loads the whole month events, and shows them from memory, instead of a new request for each prev/next click.
	resizeMap();
	$('#leftGroup').prependTo('.fc-header-left');
	$('#rightGroup').appendTo('.fc-header-right');

	$('#timepicker5').timepicker({
		template: false,
		showInputs: false,
		minuteStep: 5,
		defaultTime: '9:45 AM'
	});
	$('#timepicker6').timepicker({
		template: false,
		showInputs: false,
		minuteStep: 5,
		defaultTime: '11:45 AM'
	});
	$('.combobox').combobox();

	//should look for ways to modify inventory tags because recalling the method just appends. maybe recreating this for each event click.

});<commit_msg>var name change<commit_after>function changePopupColor(event) { //changes the events object
	$("#popupTitleButton").removeClass("btn-success btn-inverse btn-warning btn-danger");
	if (event.valid == false) {
		$("#popupTitleButton").addClass("btn-inverse");
	} else if (event.staffAdded == 0) {
		$("#popupTitleButton").addClass("btn-danger");
	} else if (event.staffAdded < event.staffNeeded) {
		$("#popupTitleButton").addClass("btn-warning");
	} else if (event.staffAdded == event.staffNeeded) {
		$("#popupTitleButton").addClass("btn-success");
	}
}

$('#eventButton').click(function(e) {
	$('#eventButton').addClass('disabled');
	$('#popup').modalPopover('hide');
});

resizeMap = function() {
	var column_height = $(window).height();
	$('#calendar').fullCalendar('option', 'height', column_height - 40);
	//$("#calendar").css("height", + "px")
};

function setTimeline(view) { //this is borrowed from stackoverflow
	var parentDiv = jQuery(".fc-agenda-slots:visible").parent();
	var timeline = parentDiv.children(".timeline");
	if (timeline.length == 0) { //if timeline isn't there, add it
		timeline = jQuery("
").addClass("timeline");
		parentDiv.prepend(timeline);
	}
	var curTime = new Date();
	var curCalView = jQuery("#calendar").fullCalendar('getView');
	if (curCalView.visStart < curTime && curCalView.visEnd > curTime) {
		timeline.show();
	} else {
		timeline.hide();
		return;
	}
	var curSeconds = (curTime.getHours() * 60 * 60) + (curTime.getMinutes() * 60) + curTime.getSeconds();
	var percentOfDay = curSeconds / 86400; //24 * 60 * 60 = 86400, # of seconds in a day
	var topLoc = Math.floor(parentDiv.height() * percentOfDay);
	timeline.css("top", topLoc + "px");
	if (curCalView.name == "agendaWeek") { //week view, don't want the timeline to go the whole way across
		var dayCol = jQuery(".fc-today:visible");
		var left = dayCol.position().left + 1;
		var width = dayCol.width() - 2;
		timeline.css({
			left: left + "px",
			width: width + "px"
		});
	}
}

Array.prototype.removeItem = function(a) { //try to avoid changing Array.prototype
	for (i = 0; i < this.length; i++) {
		if (this[i] == a) {
			for (i2 = i; i2 < this.length - 1; i2++) {
				this[i2] = this[i2 + 1];
			}
			this.length = this.length - 1
			return;
		}
	}
}

function dropdownActiveFix() {
	$('a').removeClass('drop-active');
	$('a[href="#' + Backbone.history.fragment + '"]').addClass('drop-active');
}

$('.modal').on('show', function() {
	$('#popup').css('opacity', 0.7);
}).on('hide', function() {
	$('#popup').css('opacity', 1);
});

// The functions above are mostly done
var lastClick, lastRightClick;

// BACKBONE.JS ROUTER SECTION
var AppRouter = Backbone.Router.extend({
	routes: {
		"printToday": "printToday",
		"recentVideo": "recentVideo",
		"*filter": "all"
	}
});

//User info must be imported for this part: work on BACKBONE JS SESSION
var username = 'ckorkut';

var app = new AppRouter;

app.on('route:printToday', function() {
	console.log('printToday');
});
app.on('route:recentVideo', function() {
	console.log('recentVideo');
});

app.on('route:all', function(filter) {
	dropdownActiveFix();
	if (filter == null) {
		//Show all of events
		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log('all');

	} else if (filter == 'hideCancelled') {

		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			if (event.valid == false) {
				event.className.push('hide');
			}
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log(filter);
	} else if (filter == 'unstaffed') {
		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			if (event.staffAdded == event.staffNeeded || event.valid == false) {
				event.className.push('hide');
			}
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log(filter);
	} else if (filter == 'onlyMine') {
		$('#calendar').fullCalendar('clientEvents', function(event) {
			event.className.removeItem('hide');
			if (event.people.indexOf(username) == -1) {
				event.className.push('hide');
			}
			$('#calendar').fullCalendar('updateEvent', event);
		});
		console.log(filter);
	}
});

Backbone.history.start();

var lastClickedEvent;
$('a[href="#staffEvent"]').click(function(e) {
	//This part should get the event data and update staff adding modal box
	$('.eventName').html(lastClickedEvent.title);
	$.ajax({
		type: "GET",
		url: "staff/get/" + lastClickedEvent.id,
	}).done(function(data) {
			console.log(data);
	});
});

// Solves Bootstrap typeahead dropdown problem
$('.collapse').on({
	hide: function() {
		$(this).css('overflow', 'hidden');

		//$(this).hide();
	},
	click: function() {
		$('.collapse').css('overflow', 'visible');
	},
	shown: function() {
		$('.collapse').css('overflow', 'visible');
	}
});
$('button[data-target="#viewdetails"]').click(function() {
	$(this).toggleClass("active");
});

var _inventoryProto = {
	suggestion_url: "inventory/all",
	//These methods below have to send AJAX requests to update the inventory.
	onRemove: function(pill) {
		var id = pill.data('tag-id');
		// do something...
		console.log('pill with ID ' + id + ' removed');
	},
	onBeforeAdd: function(pill) { //
		var id = pill.data('tag-id');
		// do something...
		console.log('pill with ID ' + id + ' added');
		return pill; //has to return pill
	}
};

$(document).ready(function() {

	var date = new Date();
	var d = date.getDate();
	var m = date.getMonth();
	var y = date.getFullYear();
	$('#popup').modalPopover({
		target: '#eventButton',
		placement: 'bottom',
		backdrop: false
	});

	$('#calendar').fullCalendar({
		header: {
			left: 'prevYear,prev,next,nextYear today',
			center: 'title',
			right: 'month,agendaWeek,agendaDay'

		},
		editable: false,
		allDaySlot: false,
		allDayDefault: false,
		firstDay: date.getDay(),
		eventBorderColor: 'black',
		windowResize: function(view) {
			resizeMap();
		},
		eventClick: function(calEvent, jsEvent, view) {

			//This function should contain specific stuff like opening the event-based selection/description box etc

			//front-end eye-candy stuff
			symbol = '';
			if (calEvent.video == true) {
				symbol += ' ';
			}
			$('#popup').modalPopover('show');
			$('#eventButton').removeClass('disabled');
			changePopupColor(calEvent);

			//Popover update with event information
			$('#popupTitle').html(symbol + calEvent.title);
			$('#popupStaffInfo').html(calEvent.staffAdded + '/' + calEvent.staffNeeded);
			$('#popupContentInside').html(calEvent.desc);
			$('#popupContentHeader').html('' + defaults.dayNames[calEvent.start.getDay()] + ' | ' + calEvent.loc + '');

			//Inventory update
			var inventoryOptions = {
				values_url: 'inventory/existing/' + calEvent.id,
			};
			$.extend(inventoryOptions,_inventoryProto);
			$('#inventory').html('');
			$('#inventory').tags(inventoryOptions);
			lastClickedEvent = calEvent;
		},
		eventRightClick: function(calEvent, jsEvent, view) {
			jsEvent.preventDefault(); //Right click event only prevents default because context menu is binded in eventRender
			lastClickedEvent = calEvent;
		},
		eventRender: function(event, element) {
			//Adding all events to an array for event filtering with Backbone.js router
			symbol = '';
			if (event.video == true) {
				symbol += ' ';
			}
			element.find('.fc-event-title').html(symbol + event.title);
			element.contextmenu({
				'target': '#context-menu'
			});

		},
		viewRender: function(view, element) {
			//console.log(view.name);
			try {
				setTimeline();
			} catch (err) {}
		},
		newEventsComplete: function() { //after each ajax request to the server, new events also filtered by this way
			var currentUrl = Backbone.history.fragment;
			if (currentUrl != '') {
				app.navigate('', {
					trigger: true
				});
				app.navigate(currentUrl, {
					trigger: true
				});
			}
		},
		eventSources: [{
			url: 'events/', // Shows all events BUT need it to show only events to certain location
			ignoreTimezone: false
		}],
	});

	//Important: especially not using defaultView option of FullCalendar, for efficient use of lazyFetching.
	$('#calendar').fullCalendar('changeView', 'agendaWeek');
	//Loads the whole month events, and shows them from memory, instead of a new request for each prev/next click.
	resizeMap();
	$('#leftGroup').prependTo('.fc-header-left');
	$('#rightGroup').appendTo('.fc-header-right');

	$('#timepicker5').timepicker({
		template: false,
		showInputs: false,
		minuteStep: 5,
		defaultTime: '9:45 AM'
	});
	$('#timepicker6').timepicker({
		template: false,
		showInputs: false,
		minuteStep: 5,
		defaultTime: '11:45 AM'
	});
	$('.combobox').combobox();

	//should look for ways to modify inventory tags because recalling the method just appends. maybe recreating this for each event click.

});<|endoftext|>


<commit_before>var _ = require('underscore');
var bcrypt = require('bcrypt-nodejs');
var FieldType = require('../Type');
var util = require('util');

/**
 * password FieldType Constructor
 * @extends Field
 * @api public
 */
function password (list, path, options) {
	this._nativeType = String;
	this._underscoreMethods = ['format', 'compare'];
	this._fixedSize = 'full';
	// You can't sort on password fields
	options.nosort = true;
	options.nofilter = true; // TODO: remove this when 0.4 is merged
	this.workFactor = options.workFactor || 10;
	password.super_.call(this, list, path, options);
}
util.inherits(password, FieldType);

/**
 * Registers the field on the List's Mongoose Schema.
 *
 * Adds ...
 *
 * @api public
 */
password.prototype.addToSchema = function () {
	var field = this;
	var schema = this.list.schema;
	var needs_hashing = '__' + field.path + '_needs_hashing';

	this.paths = {
		hash: this.options.hashPath || this._path.append('_hash'),
		confirm: this.options.confirmPath || this._path.append('_confirm'),
	};

	schema.path(this.path, _.defaults({
		type: String,
		set: function (newValue) {
			this[needs_hashing] = true;
			return newValue;
		},
	}, this.options));

	schema.virtual(this.paths.hash).set(function (newValue) {
		this.set(field.path, newValue);
		this[needs_hashing] = false;
	});

	schema.pre('save', function (next) {
		if (!this.isModified(field.path) || !this[needs_hashing]) {
			return next();
		}
		if (!this.get(field.path)) {
			this.set(field.path, undefined);
			return next();
		}
		var item = this;
		bcrypt.genSalt(field.workFactor, function (err, salt) {
			if (err) {
				return next(err);
			}
			bcrypt.hash(item.get(field.path), salt, function () {}, function (err, hash) {
				if (err) {
					return next(err);
				}
				// override the cleartext password with the hashed one
				item.set(field.path, hash);
				next();
			});
		});
	});
	this.bindUnderscoreMethods();
};

/**
 * Add filters to a query
 */
password.prototype.addFilterToQuery = function (filter, query) {
	query = query || {};
	query[this.path] = (filter.exists) ? { $ne: null } : null;
	return query;
};

/**
 * Formats the field value
 *
 * Password fields are always formatted as a random no. of asterisks,
 * because the saved hash should never be displayed nor the length
 * of the actual password hinted at.
 *
 * @api public
 */
password.prototype.format = function (item) {
	if (!item.get(this.path)) return '';
	var len = Math.round(Math.random() * 4) + 6;
	var stars = '';
	for (var i = 0; i < len; i++) stars += '*';
	return stars;
};

/**
 * Compares
 *
 * @api public
 */
password.prototype.compare = function (item, candidate, callback) {
	if (typeof callback !== 'function') throw new Error('Password.compare() requires a callback function.');
	var value = item.get(this.path);
	if (!value) return callback(null, false);
	bcrypt.compare(candidate, item.get(this.path), callback);
};

/**
 * Asynchronously confirms that the provided password is valid
 */
password.prototype.validateInput = function (data, callback) {
	var result = true;
	var detail;
	// TODO: this is brittle and won't work with nested fields. needs better
	// support of pulling nested paths out of objects before we can fix it.
	if (this.paths.confirm in data) {
		result = data[this.path] === data[this.paths.confirm];
		if (!result) detail = 'passwords must match';
	}
	// TODO: we could support a password complexity option (or regexp) here
	process.nextTick(function () { callback(result, detail); });
};

/**
 * Asynchronously confirms that the provided password is valid
 */
password.prototype.validateRequiredInput = function (item, data, callback) {
	var result = this.getValueFromData(data);
	process.nextTick(function () { callback(result); });
};

/**
 * If password fields are required, check that either a value has been
 * provided or already exists in the field.
 *
 * Otherwise, input is always considered valid, as providing an empty
 * value will not change the password.
 *
 * @api public
 */
password.prototype.inputIsValid = function (data, required, item) {
	if (data[this.path] && this.paths.confirm in data) {
		return data[this.path] === data[this.paths.confirm] ? true : false;
	}
	if (data[this.path] || data[this.paths.hash] || (item && item.get(this.path))) return true;
	return required ? false : true;
};

/**
 * Updates the value for this field in the item from a data object
 *
 * Will accept either the field path, or paths.hash to bypass bcrypt
 *
 * @api public
 */
password.prototype.updateItem = function (item, data, callback) {
	if (this.path in data) {
		item.set(this.path, data[this.path]);
	} else if (this.paths.hash in data) {
		item.set(this.paths.hash, data[this.paths.hash]);
	}
	process.nextTick(callback);
};

/* Export Field Type */
module.exports = password;
<commit_msg>Fixing password validation when provided undefined values<commit_after>var _ = require('underscore');
var bcrypt = require('bcrypt-nodejs');
var FieldType = require('../Type');
var util = require('util');

/**
 * password FieldType Constructor
 * @extends Field
 * @api public
 */
function password (list, path, options) {
	this._nativeType = String;
	this._underscoreMethods = ['format', 'compare'];
	this._fixedSize = 'full';
	// You can't sort on password fields
	options.nosort = true;
	options.nofilter = true; // TODO: remove this when 0.4 is merged
	this.workFactor = options.workFactor || 10;
	password.super_.call(this, list, path, options);
}
util.inherits(password, FieldType);

/**
 * Registers the field on the List's Mongoose Schema.
 *
 * Adds ...
 *
 * @api public
 */
password.prototype.addToSchema = function () {
	var field = this;
	var schema = this.list.schema;
	var needs_hashing = '__' + field.path + '_needs_hashing';

	this.paths = {
		hash: this.options.hashPath || this._path.append('_hash'),
		confirm: this.options.confirmPath || this._path.append('_confirm'),
	};

	schema.path(this.path, _.defaults({
		type: String,
		set: function (newValue) {
			this[needs_hashing] = true;
			return newValue;
		},
	}, this.options));

	schema.virtual(this.paths.hash).set(function (newValue) {
		this.set(field.path, newValue);
		this[needs_hashing] = false;
	});

	schema.pre('save', function (next) {
		if (!this.isModified(field.path) || !this[needs_hashing]) {
			return next();
		}
		if (!this.get(field.path)) {
			this.set(field.path, undefined);
			return next();
		}
		var item = this;
		bcrypt.genSalt(field.workFactor, function (err, salt) {
			if (err) {
				return next(err);
			}
			bcrypt.hash(item.get(field.path), salt, function () {}, function (err, hash) {
				if (err) {
					return next(err);
				}
				// override the cleartext password with the hashed one
				item.set(field.path, hash);
				next();
			});
		});
	});
	this.bindUnderscoreMethods();
};

/**
 * Add filters to a query
 */
password.prototype.addFilterToQuery = function (filter, query) {
	query = query || {};
	query[this.path] = (filter.exists) ? { $ne: null } : null;
	return query;
};

/**
 * Formats the field value
 *
 * Password fields are always formatted as a random no. of asterisks,
 * because the saved hash should never be displayed nor the length
 * of the actual password hinted at.
 *
 * @api public
 */
password.prototype.format = function (item) {
	if (!item.get(this.path)) return '';
	var len = Math.round(Math.random() * 4) + 6;
	var stars = '';
	for (var i = 0; i < len; i++) stars += '*';
	return stars;
};

/**
 * Compares
 *
 * @api public
 */
password.prototype.compare = function (item, candidate, callback) {
	if (typeof callback !== 'function') throw new Error('Password.compare() requires a callback function.');
	var value = item.get(this.path);
	if (!value) return callback(null, false);
	bcrypt.compare(candidate, item.get(this.path), callback);
};

/**
 * Asynchronously confirms that the provided password is valid
 */
password.prototype.validateInput = function (data, callback) {
	var result = true;
	var detail;
	// TODO: this is brittle and won't work with nested fields. needs better
	// support of pulling nested paths out of objects before we can fix it.
	if (this.paths.confirm in data) {
		result = data[this.path] === data[this.paths.confirm];
		if (!result) detail = 'passwords must match';
	}
	// TODO: we could support a password complexity option (or regexp) here
	process.nextTick(function () { callback(result, detail); });
};

/**
 * Asynchronously confirms that the provided password is valid
 */
password.prototype.validateRequiredInput = function (item, data, callback) {
	var value = this.getValueFromData(data);
	var result = value ? true : false;
	if (!result && value === undefined && item && item.get(this.path)) result = true;
	process.nextTick(function () { callback(result); });
};

/**
 * If password fields are required, check that either a value has been
 * provided or already exists in the field.
 *
 * Otherwise, input is always considered valid, as providing an empty
 * value will not change the password.
 *
 * @api public
 */
password.prototype.inputIsValid = function (data, required, item) {
	if (data[this.path] && this.paths.confirm in data) {
		return data[this.path] === data[this.paths.confirm] ? true : false;
	}
	if (data[this.path] || data[this.paths.hash] || (item && item.get(this.path))) return true;
	return required ? false : true;
};

/**
 * Updates the value for this field in the item from a data object
 *
 * Will accept either the field path, or paths.hash to bypass bcrypt
 *
 * @api public
 */
password.prototype.updateItem = function (item, data, callback) {
	// TODO: this is brittle and won't work with nested fields. needs better
	// support of pulling nested paths out of objects before we can fix it.
	if (this.path in data) {
		item.set(this.path, data[this.path]);
	} else if (this.paths.hash in data) {
		item.set(this.paths.hash, data[this.paths.hash]);
	}
	process.nextTick(callback);
};

/* Export Field Type */
module.exports = password;
<|endoftext|>


<commit_before>APP.components.notificatonCenter = (function() {
    const DROPDOWN_OPEN = 'jq-dropdown-open';
    var $notificationsContainer;
    var $notificationsTrigger;

    function init() {
        console.log("INIT NOTIFICATION CENTER");
        $(window).load(function() {
          $notificationsContainer = $("[data-behavior='notifications-container']");
          $notificationsTrigger = $("[data-behavior='notifications-trigger']");
          if ($notificationsContainer.length > 0) setup()
        });
    }

    function setup() {
        $notificationsTrigger.click(markAsSeen);
        update();
    }

    function update() {
        setTimeout(function() {
          if (notificationCenterOpen()) {
            console.log("CLOSED");
              update();
          } else {
              pollServer();
          }
        }, 3000);
    }

    function pollServer() {
        $.ajax({
            url: "/notifications",
            dataType: "script",
            type: "GET",
            success: function() {
                update();
                console.log("SUCCESSFULL GET DATA REQUEST")
            }
        });
    }

    function markAsSeen() {
        $.ajax({
            url: "/notifications/mark_as_seen",
            dataType: "script",
            type: "POST",
            data: {ids: currentNotificationIds()},
            success: function() {
                console.log("SUCCESSFULL MARK AS SEEN REQUEST")
            },
            error: function() {
                console.log("UNSUCCESSFULL MARK AS SEEN REQUEST")
            }
        });
    }

    function currentNotificationIds() {
        var $notificationItems = $("[data-behavior='notifications-item']");
        var notificationIds = [].map.call($notificationItems, function(obj) {
            return obj['id'].replace('notification_', '');
        });
        return JSON.stringify(notificationIds);
    }

    function notificationCenterOpen() {
        return $notificationsTrigger.hasClass(DROPDOWN_OPEN);
    }

    return {
        init: init
    }

})();
<commit_msg>notification center poll when opening close #174<commit_after>APP.components.notificatonCenter = (function() {
    const DROPDOWN_OPEN = 'jq-dropdown-open';
    var $notificationsContainer;
    var $notificationsTrigger;

    function init() {
        console.log("INIT NOTIFICATION CENTER");
        $(window).load(function() {
          $notificationsContainer = $("[data-behavior='notifications-container']");
          $notificationsTrigger = $("[data-behavior='notifications-trigger']");
          if ($notificationsContainer.length > 0) setup()
        });
    }

    function setup() {
        $notificationsTrigger.click(handleClick);
        updateLoop();
    }

    function updateLoop() {
        setTimeout(function() {
          if (notificationCenterOpen()) {
            console.log("CLOSED");
              updateLoop();
          } else {
              pollServer(updateLoop);
          }
        }, 3000);
    }

    function handleClick() {
        if (!notificationCenterOpen()) {
            pollServer(markAsSeen)
        }
    }

    function pollServer(onSuccessCallback) {
        $.ajax({
            url: "/notifications",
            dataType: "script",
            type: "GET",
            success: function() {
                onSuccessCallback();
                console.log("SUCCESSFULL GET DATA REQUEST")
            }
        });
    }

    function markAsSeen() {
        $.ajax({
            url: "/notifications/mark_as_seen",
            dataType: "script",
            type: "POST",
            data: {ids: currentNotificationIds()},
            success: function() {
                console.log("SUCCESSFULL MARK AS SEEN REQUEST")
            },
            error: function() {
                console.log("UNSUCCESSFULL MARK AS SEEN REQUEST")
            }
        });
    }

    function currentNotificationIds() {
        var $notificationItems = $("[data-behavior='notifications-item']");
        var notificationIds = [].map.call($notificationItems, function(obj) {
            return obj['id'].replace('notification_', '');
        });
        return JSON.stringify(notificationIds);
    }

    function notificationCenterOpen() {
        return $notificationsTrigger.hasClass(DROPDOWN_OPEN);
    }

    return {
        init: init
    }

})();
<|endoftext|>


<commit_before>var _splice = function(array, begin) {
  var result = [];

  begin = begin || 0;

  // Add the ones we need
  for (var i = begin; i < array.length; i++)
    result.push(array[i]);

  return result;
};

Dictionary = function(list) {
  var self = this;
  // Dictionary
  self.lookup = {};
  self.list = [];

  self.initial = [];

  // If user sets a list
  if (list instanceof Dictionary) {
    // Clone the initial list
    self.initial = list.clone();
    // We set the clone
    self.set(list.clone());
  } else if (list) {
    // Clone the array
    self.initial = _splice(list);
    // Just set the list
    self.set(list);
  }

};

Dictionary.prototype.add = function(value) {
  var self = this;
  // Make sure not to add existing values / words
  if (!self.exists(value)) {
    // Add value to keyword list
    // We return the index - note this can be 0 :)
    return this.lookup[value] = this.list.push(value) -1;
  }

  return this.lookup[value];
};

Dictionary.prototype.addList = function(list) {
  // Iterate over the list of values
  if (list)
    for (var i = 0; i < list.length; i++)
      this.add(list[i]);
};

Dictionary.prototype.set = function(list) {
  // Reset the this.lookup
  this.lookup = {};
  this.list = [];
  // Add the list
  this.addList(list);
};

Dictionary.prototype.remove = function(value) {
  var self = this;
  // Make sure theres something to remove
  if (self.exists(value)) {
    var result = [];
    // copy the this.lookup
    for (var i = 0; i < this.list.length; i++)
      if (i !== self.index(value)) result.push(this.list[i]);
    // Set the new list of this.lookup
    this.set(result);
  }
};

Dictionary.prototype.withoutInitial = function() {
  return _splice(this.list, this.initial.length);
};

Dictionary.prototype.value = function(index) {
  return this.list[index];
};

Dictionary.prototype.index = function(value) {
  return this.lookup[value];
};

Dictionary.prototype.exists = function(value) {
  return (typeof this.index(value) !== 'undefined');
};

Dictionary.prototype.clone = function() {
  return _splice(this.list);
};

Dictionary.prototype.getArray = function() {
  return this.list;
};

Dictionary.prototype.getLookup = function() {
  return this.lookup;
};
<commit_msg>refactor into toArray and toObject<commit_after>var _splice = function(array, begin) {
  var result = [];

  begin = begin || 0;

  // Add the ones we need
  for (var i = begin; i < array.length; i++)
    result.push(array[i]);

  return result;
};

Dictionary = function(list) {
  var self = this;
  // Dictionary
  self.lookup = {};
  self.list = [];

  self.initial = [];

  // If user sets a list
  if (list instanceof Dictionary) {
    // Clone the initial list
    self.initial = list.clone();
    // We set the clone
    self.set(list.clone());
  } else if (list) {
    // Clone the array
    self.initial = _splice(list);
    // Just set the list
    self.set(list);
  }

};

Dictionary.prototype.add = function(value) {
  var self = this;
  // Make sure not to add existing values / words
  if (!self.exists(value)) {
    // Add value to keyword list
    // We return the index - note this can be 0 :)
    return this.lookup[value] = this.list.push(value) -1;
  }

  return this.lookup[value];
};

Dictionary.prototype.addList = function(list) {
  // Iterate over the list of values
  if (list)
    for (var i = 0; i < list.length; i++)
      this.add(list[i]);
};

Dictionary.prototype.set = function(list) {
  // Reset the this.lookup
  this.lookup = {};
  this.list = [];
  // Add the list
  this.addList(list);
};

Dictionary.prototype.remove = function(value) {
  var self = this;
  // Make sure theres something to remove
  if (self.exists(value)) {
    var result = [];
    // copy the this.lookup
    for (var i = 0; i < this.list.length; i++)
      if (i !== self.index(value)) result.push(this.list[i]);
    // Set the new list of this.lookup
    this.set(result);
  }
};

Dictionary.prototype.withoutInitial = function() {
  return _splice(this.list, this.initial.length);
};

Dictionary.prototype.value = function(index) {
  return this.list[index];
};

Dictionary.prototype.index = function(value) {
  return this.lookup[value];
};

Dictionary.prototype.exists = function(value) {
  return (typeof this.index(value) !== 'undefined');
};

Dictionary.prototype.clone = function() {
  return _splice(this.list);
};

Dictionary.prototype.toArray = function() {
  return this.list;
};

Dictionary.prototype.toObject = function() {
  return this.lookup;
};
<|endoftext|>


<commit_before>var inspector = require('..')();
var expect = require('expect.js');

describe("url-inspector", function suite() {
	it("should inspect large file without downloading it entirely", function(done) {
		this.timeout(2000);
		inspector('https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.3.3.tar.xz', function(err, meta) {
			expect(err).to.not.be.ok();
			expect(meta.type).to.be('data');
			done();
		});
	});
	it("should return meta with thumbnail as data-uri", function(done) {
		this.timeout(2000);
		inspector('https://upload.wikimedia.org/wikipedia/commons/b/bd/1110_desktop_visual.jpg', function(err, meta) {
			expect(err).to.not.be.ok();
			expect(meta.type).to.be('image');
			expect(meta.thumbnail.indexOf('image/jpeg') > 0).to.be.ok();
			done();
		});
	});
});
<commit_msg>Test youtube url<commit_after>var inspector = require('..')();
var expect = require('expect.js');

describe("url-inspector", function suite() {
	it("should inspect large file without downloading it entirely", function(done) {
		this.timeout(5000);
		inspector('https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.3.3.tar.xz', function(err, meta) {
			expect(err).to.not.be.ok();
			expect(meta.type).to.be('data');
			done();
		});
	});
	it("should return meta with thumbnail as data-uri", function(done) {
		this.timeout(5000);
		inspector('https://upload.wikimedia.org/wikipedia/commons/b/bd/1110_desktop_visual.jpg', function(err, meta) {
			expect(err).to.not.be.ok();
			expect(meta.type).to.be('image');
			expect(meta.thumbnail.indexOf('image/jpeg') > 0).to.be.ok();
			done();
		});
	});
	it("should return meta with thumbnail as data-uri for a youtube video", function(done) {
		this.timeout(5000);
		inspector('https://www.youtube.com/watch?v=CtP8VABF5pk', function(err, meta) {
			expect(err).to.not.be.ok();
			expect(meta.type).to.be('video');
			expect(meta.thumbnail.indexOf('youtu') > 0).to.be.ok();
			done();
		});
	});
});
<|endoftext|>


<commit_before>const { assign } = require('lodash')
const { globalFields } = require('../../macros')

const labels = require('../labels')
const {
  contact,
  communicationChannel,
  service,
  subject,
  notes,
  date,
  serviceHeading,
  participantsHeading,
  detailsHeading,
  notesHeading,
  adviser,
  policyAreas,
  feedbackPolicyRequest,
  feedbackPolicyIssueType,
  feedbackPolicyNotes,
} = require('./fields')

function addCountriesDiscussed (featureFlags) {
  if (!featureFlags['interaction-add-countries']) {
    return []
  } else {
    return [
      {
        macroName: 'MultipleChoiceField',
        type: 'radio',
        name: 'was_country_discussed',
        modifier: 'inline',
        optional: false,
        options: [
          {
            label: 'Yes',
            value: 'true',
          },
          {
            label: 'No',
            value: 'false',
          },
        ],
      },
      ...[
        'future_countries',
        'export_countries',
        'no_interest_countries',
      ].map((name) => ({
        macroName: 'Typeahead',
        name,
        hint: 'Add all that you discussed',
        modifier: 'subfield',
        condition: {
          name: 'was_country_discussed',
          value: 'true',
        },
        isAsync: false,
        isLabelHidden: false,
        useSubLabel: false,
        placeholder: 'Search countries',
        classes: 'c-form-group--no-filter',
        multipleSelect: true,
        options: globalFields.countries.options(),
        target: 'metadata',
      })),
    ]
  }
}

module.exports = function ({
  returnLink,
  returnText,
  buttonText,
  contacts = [],
  services = [],
  channels = [],
  advisers = [],
  hiddenFields,
  areas,
  types,
  company,
  featureFlags,
}) {
  return {
    returnLink,
    returnText,
    buttonText,
    hiddenFields,
    children: [
      serviceHeading,
      ...service(services),
      participantsHeading(company),
      contact(contacts),
      adviser(advisers),
      detailsHeading,
      date,
      communicationChannel(channels),
      notesHeading,
      subject,
      notes,
      feedbackPolicyRequest,
      feedbackPolicyIssueType(types),
      {
        ...policyAreas(areas),
        modifier: 'subfield',
        condition: {
          name: 'was_policy_feedback_provided',
          value: 'true',
        },
      },
      feedbackPolicyNotes,
      ...addCountriesDiscussed(featureFlags),
    ].map(field => {
      return assign(field, {
        label: field.label || labels.interaction[field.name],
      })
    }),
  }
}
<commit_msg>Stop Typeahead from auto submitting when adding countries<commit_after>const { assign } = require('lodash')
const { globalFields } = require('../../macros')

const labels = require('../labels')
const {
  contact,
  communicationChannel,
  service,
  subject,
  notes,
  date,
  serviceHeading,
  participantsHeading,
  detailsHeading,
  notesHeading,
  adviser,
  policyAreas,
  feedbackPolicyRequest,
  feedbackPolicyIssueType,
  feedbackPolicyNotes,
} = require('./fields')

function addCountriesDiscussed (featureFlags) {
  if (!featureFlags['interaction-add-countries']) {
    return []
  } else {
    return [
      {
        macroName: 'MultipleChoiceField',
        type: 'radio',
        name: 'was_country_discussed',
        modifier: 'inline',
        optional: false,
        options: [
          {
            label: 'Yes',
            value: 'true',
          },
          {
            label: 'No',
            value: 'false',
          },
        ],
      },
      ...[
        'future_countries',
        'export_countries',
        'no_interest_countries',
      ].map((name) => ({
        macroName: 'Typeahead',
        name,
        hint: 'Add all that you discussed',
        modifier: 'subfield',
        condition: {
          name: 'was_country_discussed',
          value: 'true',
        },
        isAsync: false,
        isLabelHidden: false,
        useSubLabel: false,
        placeholder: 'Search countries',
        classes: 'c-form-group--no-filter',
        multipleSelect: true,
        options: globalFields.countries.options(),
        target: 'metadata',
        autoSubmit: false,
      })),
    ]
  }
}

module.exports = function ({
  returnLink,
  returnText,
  buttonText,
  contacts = [],
  services = [],
  channels = [],
  advisers = [],
  hiddenFields,
  areas,
  types,
  company,
  featureFlags,
}) {
  return {
    returnLink,
    returnText,
    buttonText,
    hiddenFields,
    children: [
      serviceHeading,
      ...service(services),
      participantsHeading(company),
      contact(contacts),
      adviser(advisers),
      detailsHeading,
      date,
      communicationChannel(channels),
      notesHeading,
      subject,
      notes,
      feedbackPolicyRequest,
      feedbackPolicyIssueType(types),
      {
        ...policyAreas(areas),
        modifier: 'subfield',
        condition: {
          name: 'was_policy_feedback_provided',
          value: 'true',
        },
      },
      feedbackPolicyNotes,
      ...addCountriesDiscussed(featureFlags),
    ].map(field => {
      return assign(field, {
        label: field.label || labels.interaction[field.name],
      })
    }),
  }
}
<|endoftext|>


<commit_before><commit_msg>Updated xhr parameters.<commit_after><|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name Teem.controller:ProjectsCtrl
 * @description
 * # ProjectsCtrl
 * Controller of the Teem
 */

angular.module('Teem')
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      // Transition from old project paths
      .when('/communities/:communityId/projects', {
        redirectTo: function(params) {
          return '/communities/' + params.communityId + '/teems';
        }
      })
      .when('/home/projects', {
        redirectTo: function() {
          return '/home/teems';
        }
      })
      .when('/projects', {
        redirectTo: function() {
          return '/teems';
        }
      })
      .when('/communities/:communityId/teems', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      })
      .when('/home/teems', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      })
      .when('/teems', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      });
  }])
  .controller('ProjectsCtrl', [
  'SessionSvc', '$scope', '$location', '$route', 'time',
  'CommunitiesSvc', 'ProjectsSvc', 'ProfilesSvc', '$timeout', 'Loading',
  function (SessionSvc, $scope, $location, $route, time,
  CommunitiesSvc, ProjectsSvc, ProfilesSvc, $timeout, Loading) {
    var communityId = $route.current.params.communityId;

    $scope.translationData = {};

    if (communityId) {
      $scope.context = 'community';
    } else if ($location.path() === '/home/teems' || $location.path().startsWith('/teems/')) {
      $scope.context = 'home';
    } else {
      $scope.context = 'public';
    }

    function getCommunities(projects) {

      /*
      Map of projects by community:
        keys: communityId,
        values: list of projects that belong to the community in the key
      */
      var communityProjects = {};

      angular.forEach(projects, function(p) {
        p.loadedCommunities = [];

        angular.forEach(p.communities, function(id) {
          if(!communityProjects[id]) {
            communityProjects[id] = [];
          }

          communityProjects[id].push(p);
        });
      });

      // get all the communities referred from projects in <projects>
      CommunitiesSvc.all({ ids: Object.getOwnPropertyNames(communityProjects)})
        .then(function(coms){
          // add the community information to all the projects that belog to them
          angular.forEach(coms, function(c){
            angular.forEach(communityProjects[c.id], function(proj){
              proj.loadedCommunities.push(c);
            });
          });
        });
    }

    SessionSvc.onLoad(function(){
      switch ($scope.context) {
        case 'community':
          Loading.show(CommunitiesSvc.findByUrlId($route.current.params.communityId)).
            then(function(community){
              $scope.community = community;

              $scope.translationData.community = community.name;

              Loading.show(community.myAndPublicProjects()).
                then(function (projects){

                  $scope.projects = projects;

                });
            });

          break;
        case 'home':
          SessionSvc.loginRequired($scope, function() {
            Loading.show(ProjectsSvc.all({ contributor: SessionSvc.users.current() })).
              then(function(projects) {
                getCommunities(projects);

                $scope.projects = projects;

                $scope.translationData.count = projects.length;
              });
          });

          break;
        default:
          Loading.show(ProjectsSvc.all({ shareMode: 'public' })).
            then(function(projects) {
              getCommunities(projects);

              $scope.projects = projects;
            });
      }
    });
  }]);
<commit_msg>Exclude current project in "My Teems" section in project section view.<commit_after>'use strict';

/**
 * @ngdoc function
 * @name Teem.controller:ProjectsCtrl
 * @description
 * # ProjectsCtrl
 * Controller of the Teem
 */

angular.module('Teem')
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      // Transition from old project paths
      .when('/communities/:communityId/projects', {
        redirectTo: function(params) {
          return '/communities/' + params.communityId + '/teems';
        }
      })
      .when('/home/projects', {
        redirectTo: function() {
          return '/home/teems';
        }
      })
      .when('/projects', {
        redirectTo: function() {
          return '/teems';
        }
      })
      .when('/communities/:communityId/teems', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      })
      .when('/home/teems', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      })
      .when('/teems', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      });
  }])
  .controller('ProjectsCtrl', [
  'SessionSvc', '$scope', '$location', '$route', 'time',
  'CommunitiesSvc', 'ProjectsSvc', 'ProfilesSvc', '$timeout', 'Loading',
  function (SessionSvc, $scope, $location, $route, time,
  CommunitiesSvc, ProjectsSvc, ProfilesSvc, $timeout, Loading) {
    var communityId = $route.current.params.communityId;
    var projectId = $location.path().startsWith('/teems/') && $route.current.params.id;

    $scope.translationData = {};

    if (communityId) {
      $scope.context = 'community';
    } else if (projectId) {
      $scope.context = 'project';
    } else if ($location.path() === '/home/teems') {
      $scope.context = 'home';
    } else {
      $scope.context = 'public';
    }

    function getCommunities(projects) {

      /*
      Map of projects by community:
        keys: communityId,
        values: list of projects that belong to the community in the key
      */
      var communityProjects = {};

      angular.forEach(projects, function(p) {
        p.loadedCommunities = [];

        angular.forEach(p.communities, function(id) {
          if(!communityProjects[id]) {
            communityProjects[id] = [];
          }

          communityProjects[id].push(p);
        });
      });

      // get all the communities referred from projects in <projects>
      CommunitiesSvc.all({ ids: Object.getOwnPropertyNames(communityProjects)})
        .then(function(coms){
          // add the community information to all the projects that belog to them
          angular.forEach(coms, function(c){
            angular.forEach(communityProjects[c.id], function(proj){
              proj.loadedCommunities.push(c);
            });
          });
        });
    }

    SessionSvc.onLoad(function(){
      switch ($scope.context) {
        case 'community':
          Loading.show(CommunitiesSvc.findByUrlId($route.current.params.communityId)).
            then(function(community){
              $scope.community = community;

              $scope.translationData.community = community.name;

              Loading.show(community.myAndPublicProjects()).
                then(function (projects){

                  $scope.projects = projects;

                });
            });

          break;
        case 'home':
        case 'project':
          SessionSvc.loginRequired($scope, function() {
            Loading.show(ProjectsSvc.all({ contributor: SessionSvc.users.current() })).
              then(function(projects) {

                // Exclude current project
                if (projectId) {
                  projects = projects.filter(project => project._urlId !== projectId);
                }

                getCommunities(projects);

                $scope.projects = projects;

                $scope.translationData.count = projects.length;
              });
          });

          break;
        default:
          Loading.show(ProjectsSvc.all({ shareMode: 'public' })).
            then(function(projects) {
              getCommunities(projects);

              $scope.projects = projects;
            });
      }
    });
  }]);
<|endoftext|>


<commit_before>define([
	'jquery',
	'underscore',
	'backbone',
	'libs/marked/marked',
	'text!templates/style/page.html',
	'config',
	'jscssp',
	'pagedown',
	'libs/prism/prism',
	'libs/parseuri/parseuri',
	'libs/less/less-1.3.3.min'
],
function($, _, Backbone, marked, stylePageTemplate, config, jscssp, Pagedown, hljs, parseuri){
	var that = null;
	var StylePage = Backbone.View.extend({
		el: '.kalei-page',
		render: function () {

			that = this;

			var configDir;
			var configPath;
			var styleUrl;
			var styleExt;
			var styleDir = this.options.style;

			if(styleDir === null) {
				if(config.css_path) {
					styleUrl = config.css_path;
				} else if(config.css_path_url) {
					console.log('NOT supported yet');
				} else if(config.css_paths) {
					configPath = config.css_paths[0].substr(config.css_paths[0].lastIndexOf('/'));
					configDir =	window.location.protocol + '//' +
								window.location.hostname +
								(window.location.port === '' ? '' : ':'+ window.location.port) +
								window.location.pathname;
					styleUrl = configDir + 'scss' + configPath;
					window.location.href = configDir + '#' + configPath;;
				} else {
					console.log('PUT SOMETHING IN THE CONFIG.JS!! C\'MON.....!');
				}
			} else {
				if(styleDir.substr(0,1) === '/') {
					// Non relative.
					configDir = configPath.substr(0, configPath.lastIndexOf('/'));
					var pUrl = parseuri(configDir);
					styleUrl = pUrl.protocol + '://' + pUrl.host + (pUrl.port === '' ? '' : ':'+ pUrl) + styleDir;
				} else {
					configPath = styleDir;
					configDir =	window.location.protocol + '//' +
								window.location.hostname +
								(window.location.port === '' ? '' : ':'+ window.location.port) +
								window.location.pathname;
					styleExt = configPath.substr(configPath.lastIndexOf('.')+1);
					styleUrl = configDir + styleExt + '/' + configPath;
				}
			}

			styleExt = styleUrl.substr(styleUrl.lastIndexOf('.')+1);

			// If a stylesheet is already loaded, don't load it again.
			// if(!$('link[href="' + styleUrl + '"]').length) {
			// 	$('head').append('<link rel="stylesheet" href="' + styleUrl + '"" type="text/' + styleExt +'" />');
			// }

			// var navToggle = $('.nav');

			// navToggle.click(function(){
			// 	$('body').removeClass('loading').toggleClass('nav-open');
			// });

			// $('.kalei-page').click(function(){
			// 	$('body').removeClass('nav-open');
			// });

			var scroll = $(window).scrollTop();
			if(scroll !== 0) {
				$('body').animate({ // Scroll to top
					scrollTop: 0
				}, '200');
			}

			$('.kalei-menu__list__item__link').removeClass('active');

			if(window.location.hash !== '') {
				$('[href="' + window.location.hash + '"]').addClass('active');
			}

			require(['text!'+ styleUrl], function (stylesheet) {
				var parser = null;
				var regex = /(?:.*\/)(.*)\.(css|less|sass|scss)$/gi;
				var result = regex.exec(styleUrl);
					// result[0] Original Input.
					// result[1] Filename.
					// result[2] Extension.

				var page = {blocks:[]};

				switch (result[2]) {
					case 'css':
							parser = new jscssp();
							stylesheet = parser.parse(stylesheet, false, true);
							page = that.compute_css(stylesheet);
						break;
					case 'less':
							parser = new(less.Parser)({
								paths: [configDir + '/'], // Specify search paths for @import directives.
							});
							parser.parse(stylesheet, function (err, tree) {
								stylesheet = tree;
							});
							page = that.compute_less(stylesheet);
						break;
					case 'scss':
							// Thanks, so many thanks to Oriol Torras @uriusfurius.
							function findImports(str, basepath) {
								var url = configDir + styleExt + '/';
								var regex = /(?:(?![\/*]])[^\/* ]|^ *)@import ['"](.*?)['"](?![^*]*?\*\/)/g;
								var match, matches = [];
								while ((match = regex.exec(str)) !== null) {
									matches.push(match[1]);
								}
								// console.log('Import Matches ---->', matches);
								_.each(matches, function(match) {
									// Check if is a filename
									var path = match.split('/');
									var filename, fullpath, _basepath = basepath;
									if (path.length > 1) {
										filename = path.pop();
										var something, basepathParts;
										if (_basepath) {
											basepathParts = _basepath.split('/');
										}
										while ((something = path.shift()) === '..') {
											basepathParts.pop();
										}
										if (something) {
											path.unshift(something);
										}
										_basepath = (basepathParts ? basepathParts.join('/') + '/' : '') + path.join('/');
									} else {
										filename = path.join('');
									}
									filename = '_' + filename + '.' + styleExt;
									fullpath = _basepath + '/' + filename;
									// console.log('filename:', filename);
									// console.log('basepath:', _basepath);
									// console.log('fullpath:', fullpath);

									var importContent = Module.read(url + fullpath);
									Sass.writeFile(match, importContent);

									findImports(importContent, _basepath);
								});
							}

							configPath = configPath.substr(0, configPath.lastIndexOf('/'));
							// Recursive function to find all @imports.
							findImports(stylesheet, configPath);
							// Writes style sheet so sass.js can compile it.
							Sass.writeFile(styleUrl, stylesheet);
							// Compiles Sass stylesheet into CSS.
							var stylesheetCompiled = Sass.compile(stylesheet);
							// // Embeds CSS styles in .
							// var style = document.createElement('style');
							// var attr = document.createAttribute('id');
							// var fileName = styleUrl.substr(styleUrl.lastIndexOf('/')+1);
							// fileName = fileName.substr(0, fileName.lastIndexOf('.'));
							// attr.value = fileName;
							// style.setAttributeNode(attr);
							// style.textContent = stylesheetCompiled;
							// if(!$('style[id="' + fileName + '"]').length) {
							// 	document.head.appendChild(style);
							// }
							// Parses the CSS.
							parser = new jscssp();
							stylesheet = parser.parse(stylesheetCompiled, false, true);
							page = that.compute_css(stylesheet);

						break;
				}

				console.log((new Date()).getTime() + " bottom", page)

				$('.kalei-sheet-submenu').hide();
				var submenu = $('
');

				////////////NEEDS TO BE EXPORTED TO Menu.js
				_.each(page.blocks, function (block) {
					if (block.heading !== '') {
						console.log(block.heading);
						var li = $('
');
						li.append($('
').text(block.heading));
						submenu.append(li);
					}
					// if(block.stylesheet !== 'undefined') {
					// 	console.log(block.stylesheet);
					// 	li.append($('
').append('

' + block.stylesheet + '

'));
					// }
				});

				$('li:first-child', submenu).addClass('active');
				$('.kalei-sheet-submenu', $('[data-sheet="' + that.options.style + '"]')).html(submenu).show();
				////////////NEEDS TO BE EXPORTED TO Menu.js

				$(that.el).html(_.template(stylePageTemplate, {_:_, page: page, config: config}));

				// Prism's colour coding in  blocks.
				Prism.highlightAll();
				// Prism's File Highlight plugin function.
				fileHighlight();

				$(window).scroll(function () {
					var scroll = $(window).scrollTop();
					// if(scroll === 0) {
					// 	$('.kalei-nav').removeClass('is-disabled');
					// } else {
					// 	$('.kalei-nav').addClass('is-disabled');
					// }
					$(".kalei-page__item").each(function() {
						if(that.is_on_screen($(this), 20)) {
							$(".kalei-sheet-submenu li").removeClass('active');
							$(".kalei-sheet-submenu li:contains('" + $(this).find('> h1').text() +"')").addClass('active');
						}
					});
				});

				// Call for fixie.
				fixie.init();

				// If the last element of the page is higher than window.height(),
				// some additional padding-bottom is added so it stops at the top of the page.
				// If the last element is lower, it doesn't add any padding-bottom.
				// But we can think of something smarter.
				function paddingBottom() {
					if($('.kalei-page__item').length !== 0) {
						var pageHeight = $(window).height();
						var lastElHeight = $('.kalei-page__item:last').outerHeight(); // outerHeight() returns height + padding).
						var lastElPaddingTop = $('.kalei-page__item:last').css('padding-top');
						var lastElPaddingBottom = $('.kalei-page__item:last').css('padding-bottom');
						lastElPaddingTop = parseInt(lastElPaddingTop.substr(0, lastElPaddingTop.length - 2)); // Removes px from string and converts string to number.
						lastElPaddingBottom = parseInt(lastElPaddingBottom.substr(0, lastElPaddingBottom.length - 2)); // Removes px from string and converts string to number.
						lastElPaddingTotal = lastElPaddingTop+lastElPaddingBottom;
						if(lastElHeight >= pageHeight) {
							$(that.el).css({ 'padding-bottom' : 0 });
						} else {
							$(that.el).css({ 'padding-bottom' : (pageHeight-lastElHeight) });
						}
					}
				}

				setTimeout(paddingBottom, 2000);

			});
		},

		is_on_screen: function(el, offset) {

			var win = $(window);

			var viewport = {
				top : win.scrollTop()
			};

			viewport.bottom = viewport.top + win.height();

			var bounds = el.offset();

			return (!(viewport.top + offset < bounds.top || viewport.top > bounds.bottom));

		},

		compute_css: function(stylesheet) {
			console.log("compute_css()")
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};

			_.each(stylesheet.cssRules, function(rule) {
				switch (rule.type) {
					// Standard rule?
					case 1:
						break;
					// Import Rule (@import)
					case 3:
						// We need to import jsscp doesn't compile imports.
						if(window.location.hash === '') {
							result = $('.kalei-menu__list__item__link').attr('href');
							window.location.href =	window.location.protocol +
													'//' + window.location.hostname +
													(window.location.port === '' ? '' : ':'+ window.location.port) +
													window.location.pathname + result;
						}
						stylesheet.deleteRule(rule);
						break;
					// Comment Block.
					case 101:
						if(window.location.hash !== '') {
							page.blocks = page.blocks.concat(that.parse_commentblock(rule.parsedCssText))
						}
						break;
				}
			});

			page.css = stylesheet.cssText();

			var parser = new(less.Parser);
			var stylesheet;
			page.css = ".code-render { " + page.css + " }";
			parser.parse(page.css, function (err, tree) {
				stylesheet = tree;
			});

			page.css = stylesheet.toCSS({ compress: true });
			return page;
		},

		compute_less: function(stylesheet) {
			console.log("compute_less()")
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};

			console.log(stylesheet)

			_.each(stylesheet.rules, function(rule) {
				// Comment block.
				if (rule.silent !== null) {
					page.blocks = page.blocks.concat(that.parse_commentblock(rule.value))
				// Standard Rule.
				} else if (rule.rules !== null) {

				//Import Rule
				} else if (rule.path !== null) {
					// var previous_heading = page.blocks.length - 1;
					// if (typeof page.blocks[previous_heading].import_rule == "undefined") {
					//     page.blocks[previous_heading].import_rule = []
					// }
					// page.blocks[previous_heading].import_rule.push(rule.path)
				}
			});

			page.css = stylesheet.toCSS({ compress: true });
			page.css = ".code-render { " + page.css + " }";
			page.css = stylesheet.toCSS({ compress: true });
			return page;
		},

		parse_commentblock: function (comment_block_text) {
			// Removes /* & */.
			comment_block_text = comment_block_text.replace(/(?:\/\*)|(?:\*\/)/gi, '');

			marked.setOptions(_.extend({
					sanitize: false,
					gfm: true
				},
				config.marked_options || {}
			));

			var lexedCommentblock = marked.lexer(comment_block_text);
			// Lexer appends definition links to returned token object.
			var lexerLinks = lexedCommentblock.links || {};

			var return_val = [];
			var block_def = {
				content: [],
				heading: "",
			};

			var block = _.clone(block_def);

			_.each(lexedCommentblock, function (comment) {
				switch (comment.type) {
					case "code":
						// If there's no language:
						// Push the code without example nor language header.
						if (!comment.lang) {
							block.content.push(comment);
						// If the code is not "markup" (html):
						// Push the code without example but with language header.
						} else if (comment.lang !== 'markup') {
							block.content.push({
								type: 'html',
								text: '
' + comment.lang + '
'
							});
							block.content.push(comment);
						// If it's "markup" (html):
						// Push the code for an example with language header.
						} else {
							block.content.push({
								type: 'html',
								text: '
' + comment.text + '
' +
										'
html
'
							});
							block.content.push(comment);
						}
						break;
					case "heading":
						if (block.heading !== '' && comment.depth === 1) {
							// Multiple headings in one comment block.
							// We want to break them up.
							// Parse the content blocks and return the HTML to display.
							block.content.links = lexerLinks;
							block.content = marked.parser(block.content);
							return_val.push(block);
							block = _.clone(block_def);
						}
						if (comment.depth === 1) {
							block.heading = comment.text;
							block.content.push(comment);
						} else if (comment.depth >= 2) {
							block.stylesheet = comment.text;
							block.content.push(comment);
						}
						break;
					default:
						// Push everything else.
						block.content.push(comment);
						break;
				}
			});

			// Parse the content blocks and return the HTML to display.
			block.content.links = lexerLinks
			block.content = marked.parser(block.content)

			return_val.push(block);
			return return_val;
		},

	});
	return StylePage;
});
<commit_msg>Cleaned up comments and console.logs<commit_after>define([
	'jquery',
	'underscore',
	'backbone',
	'libs/marked/marked',
	'text!templates/style/page.html',
	'config',
	'jscssp',
	'libs/prism/prism',
	'libs/parseuri/parseuri',
	'libs/less/less-1.3.3.min'
],
function($, _, Backbone, marked, stylePageTemplate, config, jscssp, parseuri){
	var that = null;
	var StylePage = Backbone.View.extend({
		el: '.kalei-page',
		render: function () {

			that = this;

			var configDir;
			var configPath;
			var styleUrl;
			var styleExt;
			var styleDir = this.options.style;

			if(styleDir === null) {
				if(config.css_path) {
					styleUrl = config.css_path;
				} else if(config.css_path_url) {
					console.log('NOT supported yet');
				} else if(config.css_paths) {
					configPath = config.css_paths[0].substr(config.css_paths[0].lastIndexOf('/'));
					configDir =	window.location.protocol + '//' +
								window.location.hostname +
								(window.location.port === '' ? '' : ':'+ window.location.port) +
								window.location.pathname;
					styleUrl = configDir + 'scss' + configPath;
					window.location.href = configDir + '#' + configPath;;
				} else {
					console.log('PUT SOMETHING IN THE CONFIG.JS!! C\'MON.....!');
				}
			} else {
				if(styleDir.substr(0,1) === '/') {
					// Non relative.
					configDir = configPath.substr(0, configPath.lastIndexOf('/'));
					var pUrl = parseuri(configDir);
					styleUrl = pUrl.protocol + '://' + pUrl.host + (pUrl.port === '' ? '' : ':'+ pUrl) + styleDir;
				} else {
					configPath = styleDir;
					configDir =	window.location.protocol + '//' +
								window.location.hostname +
								(window.location.port === '' ? '' : ':'+ window.location.port) +
								window.location.pathname;
					styleExt = configPath.substr(configPath.lastIndexOf('.')+1);
					styleUrl = configDir + styleExt + '/' + configPath;
				}
			}

			styleExt = styleUrl.substr(styleUrl.lastIndexOf('.')+1);

			// If a stylesheet is already loaded, don't load it again.
			// if(!$('link[href="' + styleUrl + '"]').length) {
			// 	$('head').append('<link rel="stylesheet" href="' + styleUrl + '"" type="text/' + styleExt +'" />');
			// }

			// var navToggle = $('.nav');

			// navToggle.click(function(){
			// 	$('body').removeClass('loading').toggleClass('nav-open');
			// });

			// $('.kalei-page').click(function(){
			// 	$('body').removeClass('nav-open');
			// });

			var scroll = $(window).scrollTop();
			if(scroll !== 0) {
				$('body').animate({ // Scroll to top
					scrollTop: 0
				}, '200');
			}

			$('.kalei-menu__list__item__link').removeClass('active');

			if(window.location.hash !== '') {
				$('[href="' + window.location.hash + '"]').addClass('active');
			}

			require(['text!'+ styleUrl], function (stylesheet) {
				var parser = null;
				var regex = /(?:.*\/)(.*)\.(css|less|sass|scss)$/gi;
				var result = regex.exec(styleUrl);
					// result[0] Original Input.
					// result[1] Filename.
					// result[2] Extension.

				var page = {blocks:[]};

				switch (result[2]) {
					case 'css':
							parser = new jscssp();
							stylesheet = parser.parse(stylesheet, false, true);
							page = that.compute_css(stylesheet);
						break;
					case 'less':
							parser = new(less.Parser)({
								paths: [configDir + '/'], // Specify search paths for @import directives.
							});
							parser.parse(stylesheet, function (err, tree) {
								stylesheet = tree;
							});
							page = that.compute_less(stylesheet);
						break;
					case 'scss':
							// Thanks, so many thanks to Oriol Torras @uriusfurius.
							function findImports(str, basepath) {
								var url = configDir + styleExt + '/';
								var regex = /(?:(?![\/*]])[^\/* ]|^ *)@import ['"](.*?)['"](?![^*]*?\*\/)/g;
								var match, matches = [];
								while ((match = regex.exec(str)) !== null) {
									matches.push(match[1]);
								}
								_.each(matches, function(match) {
									// Check if is a filename
									var path = match.split('/');
									var filename, fullpath, _basepath = basepath;
									if (path.length > 1) {
										filename = path.pop();
										var something, basepathParts;
										if (_basepath) {
											basepathParts = _basepath.split('/');
										}
										while ((something = path.shift()) === '..') {
											basepathParts.pop();
										}
										if (something) {
											path.unshift(something);
										}
										_basepath = (basepathParts ? basepathParts.join('/') + '/' : '') + path.join('/');
									} else {
										filename = path.join('');
									}
									filename = '_' + filename + '.' + styleExt;
									fullpath = _basepath + '/' + filename;

									var importContent = Module.read(url + fullpath);
									Sass.writeFile(match, importContent);

									findImports(importContent, _basepath);
								});
							}

							configPath = configPath.substr(0, configPath.lastIndexOf('/'));
							// Recursive function to find all @imports.
							findImports(stylesheet, configPath);
							// Writes style sheet so sass.js can compile it.
							Sass.writeFile(styleUrl, stylesheet);
							// Compiles Sass stylesheet into CSS.
							var stylesheetCompiled = Sass.compile(stylesheet);
							// // Embeds CSS styles in .
							// var style = document.createElement('style');
							// var attr = document.createAttribute('id');
							// var fileName = styleUrl.substr(styleUrl.lastIndexOf('/')+1);
							// fileName = fileName.substr(0, fileName.lastIndexOf('.'));
							// attr.value = fileName;
							// style.setAttributeNode(attr);
							// style.textContent = stylesheetCompiled;
							// if(!$('style[id="' + fileName + '"]').length) {
							// 	document.head.appendChild(style);
							// }
							// Parses the CSS.
							parser = new jscssp();
							stylesheet = parser.parse(stylesheetCompiled, false, true);
							page = that.compute_css(stylesheet);

						break;
				}

				console.log((new Date()).getTime() + " bottom", page)

				$('.kalei-sheet-submenu').hide();
				var submenu = $('
');

				////////////NEEDS TO BE EXPORTED TO Menu.js
				_.each(page.blocks, function (block) {
					if (block.heading !== '') {
						var li = $('
');
						li.append($('
').text(block.heading));
						submenu.append(li);
					}
					// if(block.stylesheet !== 'undefined') {
					// 	console.log(block.stylesheet);
					// 	li.append($('
').append('

' + block.stylesheet + '

'));
					// }
				});

				$('li:first-child', submenu).addClass('active');
				$('.kalei-sheet-submenu', $('[data-sheet="' + that.options.style + '"]')).html(submenu).show();
				////////////NEEDS TO BE EXPORTED TO Menu.js

				$(that.el).html(_.template(stylePageTemplate, {_:_, page: page, config: config}));

				// Prism's colour coding in  blocks.
				Prism.highlightAll();
				// Prism's File Highlight plugin function.
				fileHighlight();

				$(window).scroll(function () {
					var scroll = $(window).scrollTop();
					$(".kalei-page__item").each(function() {
						if(that.is_on_screen($(this), 20)) {
							$(".kalei-sheet-submenu li").removeClass('active');
							$(".kalei-sheet-submenu li:contains('" + $(this).find('> h1').text() +"')").addClass('active');
						}
					});
				});

				// Call for Fixie.
				fixie.init();

				// If the last element of the page is higher than window.height(),
				// some additional padding-bottom is added so it stops at the top of the page.
				// If the last element is lower, it doesn't add any padding-bottom.
				// But we can think of something smarter.
				function paddingBottom() {
					if($('.kalei-page__item').length !== 0) {
						var pageHeight = $(window).height();
						var lastElHeight = $('.kalei-page__item:last').outerHeight(); // outerHeight() returns height + padding).
						var lastElPaddingTop = $('.kalei-page__item:last').css('padding-top');
						var lastElPaddingBottom = $('.kalei-page__item:last').css('padding-bottom');
						lastElPaddingTop = parseInt(lastElPaddingTop.substr(0, lastElPaddingTop.length - 2)); // Removes px from string and converts string to number.
						lastElPaddingBottom = parseInt(lastElPaddingBottom.substr(0, lastElPaddingBottom.length - 2)); // Removes px from string and converts string to number.
						lastElPaddingTotal = lastElPaddingTop+lastElPaddingBottom;
						if(lastElHeight >= pageHeight) {
							$(that.el).css({ 'padding-bottom' : 0 });
						} else {
							$(that.el).css({ 'padding-bottom' : (pageHeight-lastElHeight) });
						}
					}
				}

				setTimeout(paddingBottom, 2000);

			});
		},

		is_on_screen: function(el, offset) {

			var win = $(window);

			var viewport = {
				top : win.scrollTop()
			};

			viewport.bottom = viewport.top + win.height();

			var bounds = el.offset();

			return (!(viewport.top + offset < bounds.top || viewport.top > bounds.bottom));

		},

		compute_css: function(stylesheet) {
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};

			_.each(stylesheet.cssRules, function(rule) {
				switch (rule.type) {
					// Standard rule?
					case 1:
						break;
					// Import Rule (@import)
					case 3:
						// We need to import jsscp doesn't compile imports.
						if(window.location.hash === '') {
							result = $('.kalei-menu__list__item__link').attr('href');
							window.location.href =	window.location.protocol +
													'//' + window.location.hostname +
													(window.location.port === '' ? '' : ':'+ window.location.port) +
													window.location.pathname + result;
						}
						stylesheet.deleteRule(rule);
						break;
					// Comment Block.
					case 101:
						if(window.location.hash !== '') {
							page.blocks = page.blocks.concat(that.parse_commentblock(rule.parsedCssText))
						}
						break;
				}
			});

			page.css = stylesheet.cssText();

			var parser = new(less.Parser);
			var stylesheet;
			page.css = ".code-render { " + page.css + " }";
			parser.parse(page.css, function (err, tree) {
				stylesheet = tree;
			});

			page.css = stylesheet.toCSS();
			return page;
		},

		compute_less: function(stylesheet) {
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};

			_.each(stylesheet.rules, function(rule) {
				// Comment block.
				if (rule.silent !== null) {
					page.blocks = page.blocks.concat(that.parse_commentblock(rule.value))
				// Standard Rule.
				} else if (rule.rules !== null) {

				//Import Rule
				} else if (rule.path !== null) {
					// var previous_heading = page.blocks.length - 1;
					// if (typeof page.blocks[previous_heading].import_rule == "undefined") {
					//     page.blocks[previous_heading].import_rule = []
					// }
					// page.blocks[previous_heading].import_rule.push(rule.path)
				}
			});

			page.css = stylesheet.toCSS({ compress: true });
			page.css = ".code-render { " + page.css + " }";
			page.css = stylesheet.toCSS({ compress: true });
			return page;
		},

		parse_commentblock: function (comment_block_text) {
			// Removes /* & */.
			comment_block_text = comment_block_text.replace(/(?:\/\*)|(?:\*\/)/gi, '');

			marked.setOptions(_.extend({
					sanitize: false,
					gfm: true
				},
				config.marked_options || {}
			));

			var lexedCommentblock = marked.lexer(comment_block_text);
			// Lexer appends definition links to returned token object.
			var lexerLinks = lexedCommentblock.links || {};

			var return_val = [];
			var block_def = {
				content: [],
				heading: "",
			};

			var block = _.clone(block_def);

			_.each(lexedCommentblock, function (comment) {
				switch (comment.type) {
					case "code":
						// If there's no language:
						// Push the code without example nor language header.
						if (!comment.lang) {
							block.content.push(comment);
						// If the code is not "markup" (html):
						// Push the code without example but with language header.
						} else if (comment.lang !== 'markup') {
							block.content.push({
								type: 'html',
								text: '
' + comment.lang + '
'
							});
							block.content.push(comment);
						// If it's "markup" (html):
						// Push the code for an example with language header.
						} else {
							block.content.push({
								type: 'html',
								text: '
' + comment.text + '
' +
										'
html
'
							});
							block.content.push(comment);
						}
						break;
					case "heading":
						if (block.heading !== '' && comment.depth === 1) {
							// Multiple headings in one comment block.
							// We want to break them up.
							// Parse the content blocks and return the HTML to display.
							block.content.links = lexerLinks;
							block.content = marked.parser(block.content);
							return_val.push(block);
							block = _.clone(block_def);
						}
						if (comment.depth === 1) {
							block.heading = comment.text;
							block.content.push(comment);
						} else if (comment.depth >= 2) {
							block.stylesheet = comment.text;
							block.content.push(comment);
						}
						break;
					default:
						// Push everything else.
						block.content.push(comment);
						break;
				}
			});

			// Parse the content blocks and return the HTML to display.
			block.content.links = lexerLinks
			block.content = marked.parser(block.content)

			return_val.push(block);
			return return_val;
		},

	});
	return StylePage;
});
<|endoftext|>