<commit_before>/*global $, setTimeout, jQuery, content, window, document, observable, MM*/
MM.MapRepository = function (activityLog, alert, networkTimeoutMillis) {
	'use strict';
	var self = this, idea, changed, saving;
	observable(this);
	MM.relevantMapTracker(this, activityLog);
	this.loadMap = function (map_url, mapId) {
		activityLog.log("loading map [" + map_url + "]");
		var alertId = alert.show('Please wait, loading the map...', ''),
			jsonLoadSuccess = function (result) {
				alert.hide(alertId);
				idea = content(result);
				activityLog.log("loaded JSON map document");
				$(window).bind('beforeunload', function () {
					if (changed && !saving) {
						return 'There are unsaved changes.';
					}
				});
				idea.addEventListener('changed', function (command, args) {
					saving = false;
					if (!changed) {
						$("#toolbarShare").hide();
						$("#toolbarSave").show();
						$("#menuExport").hide();
						$('#menuPublish').effect('highlight');
						activityLog.log('Map', 'Edit');
						changed = true;
					}
					activityLog.log(['Map', command].concat(args));
				});
				activityLog.log('Map', 'View', mapId);
				self.dispatchEvent('mapLoaded', idea);
			},
			jsonFail = function (xhr, textStatus, errorMsg) {
				activityLog.error("Error loading map document [" + map_url + "] status=" + textStatus + " error msg= " + errorMsg);
				alert.hide(alertId);
				alert.show(
					'Unfortunately, there was a problem loading the map.',
					'An automated error report was sent and we will look into this as soon as possible',
					'error'
				);
			},
			jsonTryProxy = function (map_url) {
				activityLog.log('Map', 'ProxyLoad', mapId);
				$.ajax(
					'/s3proxy/' + mapId,
					{ dataType: 'json', success: jsonLoadSuccess, error: jsonFail }
				);
			};
		$.ajax(
			map_url,
			{ dataType: 'json', success: jsonLoadSuccess, error: jsonTryProxy }
		);
	};
	this.publishMap = function () {
		saving = true;
		var publishing = true,
			saveTimeoutOccurred = function () {
				publishing = false;
				$('#menuPublish').text('Save').addClass('btn-primary').attr("disabled", false);
				$('#toolbarSave p').show();
				alert.show(
					'Unfortunately, there was a problem saving the map.',
					'Please try again later. We have sent an error report and we will look into this as soon as possible',
					'error'
				);
				activityLog.error('Map save failed');
			},
			submitS3Form = function (result) {
				var name;
				publishing = false;
				$("#s3form [name='file']").val(JSON.stringify(idea));
				for (name in result) {
					$('#s3form [name=' + name + ']').val(result[name]);
				}
				saving = true;
				self.dispatchEvent('Before Upload', result.s3UploadIdentifier, idea);
				$('#s3form').submit();
			},
			fetchPublishingConfig = function () {
				activityLog.log('Fetching publishing config');
				$.ajax(
					"/publishingConfig",
					{
						dataType: 'json',
						cache: false,
						success: submitS3Form,
						error: function (result) {
							if (publishing) {
								setTimeout(fetchPublishingConfig, 1000);
							}
						}
					}
				);
			};
		setTimeout(saveTimeoutOccurred, networkTimeoutMillis);
		fetchPublishingConfig();
	};
};
MM.relevantMapTracker = function (mapRepository, activityLog) {
	'use strict';
	var startedFromNew = function (idea) {
		return idea.id === 1;
	},
		isNodeRelevant = function (ideaNode) {
			return ideaNode.title && ideaNode.title.search(/MindMup|Lancelot|cunning|brilliant|Press Space|famous|Luke|daddy/) === -1;
		},
		isNodeIrrelevant = function (ideaNode) {
			return !isNodeRelevant(ideaNode);
		},
		isMapRelevant = function (idea) {
			return startedFromNew(idea) && idea.find(isNodeRelevant).length > 5 && idea.find(isNodeIrrelevant).length < 3;
		},
		wasRelevantOnLoad;
	mapRepository.addEventListener('mapLoaded', function (idea) {
		wasRelevantOnLoad = isMapRelevant(idea);
	});
	mapRepository.addEventListener('Before Upload', function (id, idea) {
		if (isMapRelevant(idea) && !wasRelevantOnLoad) {
			activityLog.log('Map', 'Created Relevant', id);
		} else if (wasRelevantOnLoad) {
			activityLog.log('Map', 'Saved Relevant', id);
		} else {
			activityLog.log('Map', 'Saved Irrelevant', id);
		}
	});
};
<commit_msg>map repository cleanup: extracted map loading/saving status & alerts out of map repository<commit_after>/*global $, setTimeout, jQuery, content, window, document, observable, MM*/
MM.MapRepository = function (activityLog, alert, networkTimeoutMillis) {
	'use strict';
	var self = this, idea, changed, saving;
	observable(this);
	MM.relevantMapTracker(this, activityLog);
	MM.todoAlertManagement(this, alert);
	this.loadMap = function (map_url, mapId) {
		self.dispatchEvent('mapLoading', map_url, mapId);
		activityLog.log("loading map [" + map_url + "]");
		var jsonLoadSuccess = function (result) {
				idea = content(result);
				activityLog.log("loaded JSON map document");
				$(window).bind('beforeunload', function () {
					if (changed && !saving) {
						return 'There are unsaved changes.';
					}
				});
				idea.addEventListener('changed', function (command, args) {
					saving = false;
					if (!changed) {
						$("#toolbarShare").hide();
						$("#toolbarSave").show();
						$("#menuExport").hide();
						$('#menuPublish').effect('highlight');
						activityLog.log('Map', 'Edit');
						changed = true;
					}
					activityLog.log(['Map', command].concat(args));
				});
				activityLog.log('Map', 'View', mapId);
				self.dispatchEvent('mapLoaded', idea);
			},
			jsonFail = function (xhr, textStatus, errorMsg) {
				self.dispatchEvent('mapLoadingFailed');
				activityLog.error("Error loading map document [" + map_url + "] status=" + textStatus + " error msg= " + errorMsg);
			},
			jsonTryProxy = function (map_url) {
				activityLog.log('Map', 'ProxyLoad', mapId);
				$.ajax(
					'/s3proxy/' + mapId,
					{ dataType: 'json', success: jsonLoadSuccess, error: jsonFail }
				);
			};
		$.ajax(
			map_url,
			{ dataType: 'json', success: jsonLoadSuccess, error: jsonTryProxy }
		);
	};
	this.publishMap = function () {
		saving = true;
		var publishing = true,
			saveTimeoutOccurred = function () {
				publishing = false;
				$('#menuPublish').text('Save').addClass('btn-primary').attr("disabled", false);
				$('#toolbarSave p').show();
				self.dispatchEvent('mapSavingFailed');
				activityLog.error('Map save failed');
			},
			submitS3Form = function (result) {
				var name;
				publishing = false;
				$("#s3form [name='file']").val(JSON.stringify(idea));
				for (name in result) {
					$('#s3form [name=' + name + ']').val(result[name]);
				}
				saving = true;
				self.dispatchEvent('Before Upload', result.s3UploadIdentifier, idea);
				$('#s3form').submit();
			},
			fetchPublishingConfig = function () {
				activityLog.log('Fetching publishing config');
				$.ajax(
					"/publishingConfig",
					{
						dataType: 'json',
						cache: false,
						success: submitS3Form,
						error: function (result) {
							if (publishing) {
								setTimeout(fetchPublishingConfig, 1000);
							}
						}
					}
				);
			};
		setTimeout(saveTimeoutOccurred, networkTimeoutMillis);
		fetchPublishingConfig();
	};
};
MM.relevantMapTracker = function (mapRepository, activityLog) {
	'use strict';
	var startedFromNew = function (idea) {
		return idea.id === 1;
	},
		isNodeRelevant = function (ideaNode) {
			return ideaNode.title && ideaNode.title.search(/MindMup|Lancelot|cunning|brilliant|Press Space|famous|Luke|daddy/) === -1;
		},
		isNodeIrrelevant = function (ideaNode) {
			return !isNodeRelevant(ideaNode);
		},
		isMapRelevant = function (idea) {
			return startedFromNew(idea) && idea.find(isNodeRelevant).length > 5 && idea.find(isNodeIrrelevant).length < 3;
		},
		wasRelevantOnLoad;
	mapRepository.addEventListener('mapLoaded', function (idea) {
		wasRelevantOnLoad = isMapRelevant(idea);
	});
	mapRepository.addEventListener('Before Upload', function (id, idea) {
		if (isMapRelevant(idea) && !wasRelevantOnLoad) {
			activityLog.log('Map', 'Created Relevant', id);
		} else if (wasRelevantOnLoad) {
			activityLog.log('Map', 'Saved Relevant', id);
		} else {
			activityLog.log('Map', 'Saved Irrelevant', id);
		}
	});
};
MM.todoAlertManagement = function (mapRepository, alert) {
	'use strict';
	var alertId;
	mapRepository.addEventListener('mapLoading', function () {
		alertId = alert.show('Please wait, loading the map...', '');
	});
	mapRepository.addEventListener('mapLoaded', function () {
		alert.hide(alertId);
	});
	mapRepository.addEventListener('mapLoadingFailed', function () {
		alert.hide(alertId);
		alert.show(
			'Unfortunately, there was a problem loading the map.',
			'An automated error report was sent and we will look into this as soon as possible',
			'error'
		);
	});
	mapRepository.addEventListener('mapSavingFailed', function () {
		alert.show(
			'Unfortunately, there was a problem saving the map.',
			'Please try again later. We have sent an error report and we will look into this as soon as possible',
			'error'
		);
	});
};
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

const ipcRenderer = require('electron').ipcRenderer;

var initData = {};

function styleBody(body) {
	if (!body) {
		return
	}
	body.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast');
	body.classList.add(initData.activeTheme);
}

function getTarget() {
	return document.getElementById('_target');
}

function handleInnerClick(event) {
	if (!event || !event.view || !event.view.document) {
		return;
	}
	var node = event.target;
	while (node) {
		if (node.tagName === "A" && node.href) {
			var baseElement = event.view.document.getElementsByTagName("base")[0];
			if (node.getAttribute("href") === "#") {
				event.view.scrollTo(0, 0);
			} else if (node.hash && (node.getAttribute("href") === node.hash || (baseElement && node.href.indexOf(baseElement.href) >= 0))) {
				var scrollTarget = event.view.document.getElementById(node.hash.substr(1, node.hash.length - 1));
				if (scrollTarget) {
					scrollTarget.scrollIntoView();
				}
			} else {
				ipcRenderer.sendToHost("did-click-link", node.href);
			}
			event.preventDefault();
			break;
		}
		node = node.parentNode;
	}
}

document.addEventListener("DOMContentLoaded", function (event) {
	ipcRenderer.on('baseUrl', function (event, value) {
		initData.baseUrl = value;
	});

	ipcRenderer.on('styles', function (event, value, activeTheme) {
		initData.styles = value;
		initData.activeTheme = activeTheme;

		// webview
		var target = getTarget()
		if (!target) {
			return;
		}
		var body = target.contentDocument.getElementsByTagName('body');
		styleBody(body[0]);

		// iframe
		defaultStyles = target.contentDocument.getElementById('_defaultStyles');
		if (defaultStyles) {
			defaultStyles.innerHTML = initData.styles;
		}
	});

	// propagate focus
	ipcRenderer.on('focus', function () {
		const target = getTarget();
		if (target) {
			target.contentWindow.focus();
		}
	});

	// update iframe-contents
	ipcRenderer.on('content', function (event, value) {
		const text = value.join('\n');
		const newDocument = new DOMParser().parseFromString(text, 'text/html');

		// know what happens here
		const stats = {
			scriptTags: newDocument.documentElement.querySelectorAll('script').length,
			inputTags: newDocument.documentElement.querySelectorAll('input').length,
			styleTags: newDocument.documentElement.querySelectorAll('style').length,
			linkStyleSheetTags: newDocument.documentElement.querySelectorAll('link[rel=stylesheet]').length,
			stringLen: text.length
		};

		// set base-url if applicable
		if (initData.baseUrl && newDocument.head.getElementsByTagName('base').length === 0) {
			const baseElement = document.createElement('base');
			baseElement.href = initData.baseUrl;
			newDocument.head.appendChild(baseElement);
		}

		// apply default styles
		const defaultStyles = newDocument.createElement('style');
		defaultStyles.id = '_defaultStyles';
		defaultStyles.innerHTML = initData.styles;
		if (newDocument.head.hasChildNodes()) {
			newDocument.head.insertBefore(defaultStyles, newDocument.head.firstChild);
		} else {
			newDocument.head.appendChild(defaultStyles);
		}

		styleBody(newDocument.body);

		const frame = getTarget();
		if (frame) {
			frame.setAttribute('id', '_oldTarget');
		}

		// keep current scrollTop around and use later
		const scrollTop = frame && frame.contentDocument && frame.contentDocument.body ? frame.contentDocument.body.scrollTop : 0;

		const newFrame = document.createElement('iframe');
		newFrame.setAttribute('id', '_target');
		newFrame.setAttribute('frameborder', '0');
		newFrame.setAttribute('sandbox', 'allow-scripts allow-forms allow-same-origin');
		newFrame.style.cssText = "margin: 0; overflow: hidden; position: absolute; width: 100%; height: 100%; display: none";
		document.body.appendChild(newFrame);

		// write new content onto iframe
		newFrame.contentDocument.open('text/html', 'replace');
		newFrame.contentWindow.onbeforeunload = function (e) {
			console.log('prevented webview navigation');
			return false;
		};

		// workaround for https://github.com/Microsoft/vscode/issues/12865
		// check new scrollTop and reset if neccessary
		newFrame.contentWindow.addEventListener('DOMContentLoaded', function () {
			if (newFrame.contentDocument.body && scrollTop !== newFrame.contentDocument.body.scrollTop) {
				newFrame.contentDocument.body.scrollTop = scrollTop;
			}

			// bubble out link-clicks
			if (newFrame.contentDocument.body) {
				newFrame.contentDocument.body.addEventListener('click', handleInnerClick);
			}

			if (frame) {
				document.body.removeChild(frame);
			}
			newFrame.style.display = 'block';
		});

		// set DOCTYPE for newDocument explicitly as DOMParser.parseFromString strips it off
		// and DOCTYPE is needed in the iframe to ensure that the user agent stylesheet is correctly overridden
		newFrame.contentDocument.write('<!DOCTYPE html>');
		newFrame.contentDocument.write(newDocument.documentElement.innerHTML);
		newFrame.contentDocument.close();

		ipcRenderer.sendToHost('did-set-content', stats);
	});

	// Forward message to the embedded iframe
	ipcRenderer.on('message', function (event, data) {
		const target = getTarget();
		if (target) {
			target.contentWindow.postMessage(data, document.location.origin);
		}
	});

	// forward messages from the embedded iframe
	window.onmessage = function (message) {
		ipcRenderer.sendToHost(message.data.command, message.data.data);
	};

	// signal ready
	ipcRenderer.sendToHost('webview-ready', process.pid);
});<commit_msg>Address old iframes potentially not being freed as part of #24671<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

const ipcRenderer = require('electron').ipcRenderer;

var initData = {};

function styleBody(body) {
	if (!body) {
		return
	}
	body.classList.remove('vscode-light', 'vscode-dark', 'vscode-high-contrast');
	body.classList.add(initData.activeTheme);
}

function getTarget() {
	return document.getElementById('_target');
}

function handleInnerClick(event) {
	if (!event || !event.view || !event.view.document) {
		return;
	}
	var node = event.target;
	while (node) {
		if (node.tagName === "A" && node.href) {
			var baseElement = event.view.document.getElementsByTagName("base")[0];
			if (node.getAttribute("href") === "#") {
				event.view.scrollTo(0, 0);
			} else if (node.hash && (node.getAttribute("href") === node.hash || (baseElement && node.href.indexOf(baseElement.href) >= 0))) {
				var scrollTarget = event.view.document.getElementById(node.hash.substr(1, node.hash.length - 1));
				if (scrollTarget) {
					scrollTarget.scrollIntoView();
				}
			} else {
				ipcRenderer.sendToHost("did-click-link", node.href);
			}
			event.preventDefault();
			break;
		}
		node = node.parentNode;
	}
}

document.addEventListener("DOMContentLoaded", function (event) {
	ipcRenderer.on('baseUrl', function (event, value) {
		initData.baseUrl = value;
	});

	ipcRenderer.on('styles', function (event, value, activeTheme) {
		initData.styles = value;
		initData.activeTheme = activeTheme;

		// webview
		var target = getTarget()
		if (!target) {
			return;
		}
		var body = target.contentDocument.getElementsByTagName('body');
		styleBody(body[0]);

		// iframe
		defaultStyles = target.contentDocument.getElementById('_defaultStyles');
		if (defaultStyles) {
			defaultStyles.innerHTML = initData.styles;
		}
	});

	// propagate focus
	ipcRenderer.on('focus', function () {
		const target = getTarget();
		if (target) {
			target.contentWindow.focus();
		}
	});

	// update iframe-contents
	ipcRenderer.on('content', function (event, value) {
		const text = value.join('\n');
		const newDocument = new DOMParser().parseFromString(text, 'text/html');

		// know what happens here
		const stats = {
			scriptTags: newDocument.documentElement.querySelectorAll('script').length,
			inputTags: newDocument.documentElement.querySelectorAll('input').length,
			styleTags: newDocument.documentElement.querySelectorAll('style').length,
			linkStyleSheetTags: newDocument.documentElement.querySelectorAll('link[rel=stylesheet]').length,
			stringLen: text.length
		};

		// set base-url if applicable
		if (initData.baseUrl && newDocument.head.getElementsByTagName('base').length === 0) {
			const baseElement = document.createElement('base');
			baseElement.href = initData.baseUrl;
			newDocument.head.appendChild(baseElement);
		}

		// apply default styles
		const defaultStyles = newDocument.createElement('style');
		defaultStyles.id = '_defaultStyles';
		defaultStyles.innerHTML = initData.styles;
		if (newDocument.head.hasChildNodes()) {
			newDocument.head.insertBefore(defaultStyles, newDocument.head.firstChild);
		} else {
			newDocument.head.appendChild(defaultStyles);
		}

		styleBody(newDocument.body);

		const frame = getTarget();
		if (frame) {
			frame.setAttribute('id', '_oldTarget');
		}

		// keep current scrollTop around and use later
		const scrollTop = frame && frame.contentDocument && frame.contentDocument.body ? frame.contentDocument.body.scrollTop : 0;

		const newFrame = document.createElement('iframe');
		newFrame.setAttribute('id', '_target');
		newFrame.setAttribute('frameborder', '0');
		newFrame.setAttribute('sandbox', 'allow-scripts allow-forms allow-same-origin');
		newFrame.style.cssText = "margin: 0; overflow: hidden; position: absolute; width: 100%; height: 100%; display: none";
		document.body.appendChild(newFrame);

		// write new content onto iframe
		newFrame.contentDocument.open('text/html', 'replace');
		newFrame.contentWindow.onbeforeunload = function (e) {
			console.log('prevented webview navigation');
			return false;
		};

		// workaround for https://github.com/Microsoft/vscode/issues/12865
		// check new scrollTop and reset if neccessary
		newFrame.contentWindow.addEventListener('DOMContentLoaded', function (e) {
			const contentDocument = e.target;
			if (contentDocument.body) {
				if (scrollTop !== contentDocument.body.scrollTop) {
					contentDocument.body.scrollTop = scrollTop;
				}

				// bubble out link-clicks
				contentDocument.body.addEventListener('click', handleInnerClick);
			}

			// Clean up old frames
			[].forEach.call(document.body.getElementsByTagName('iframe'), frame => {
				if (frame.id !== '_target') {
					document.body.removeChild(frame);
				}
			});

			const newFrame = document.getElementById('_target');
			if (newFrame.contentDocument === contentDocument) {
				newFrame.style.display = 'block';
			}
		});

		// set DOCTYPE for newDocument explicitly as DOMParser.parseFromString strips it off
		// and DOCTYPE is needed in the iframe to ensure that the user agent stylesheet is correctly overridden
		newFrame.contentDocument.write('<!DOCTYPE html>');
		newFrame.contentDocument.write(newDocument.documentElement.innerHTML);
		newFrame.contentDocument.close();

		ipcRenderer.sendToHost('did-set-content', stats);
	});

	// Forward message to the embedded iframe
	ipcRenderer.on('message', function (event, data) {
		const target = getTarget();
		if (target) {
			target.contentWindow.postMessage(data, document.location.origin);
		}
	});

	// forward messages from the embedded iframe
	window.onmessage = function (message) {
		ipcRenderer.sendToHost(message.data.command, message.data.data);
	};

	// signal ready
	ipcRenderer.sendToHost('webview-ready', process.pid);
});<|endoftext|>


<commit_before>var columnify = require('columnify')
var columnsOptins = {
  showHeaders: false,
  minWidth: 35,
  columnSplitter: ' |    '
}

function reportDisabledMethod(model, methods) {
  const joinedMethods = methods.join(', ')
  const modelName = 'Disabled Remote Model ' + model.sharedClass.name
  var data = {}
  data[modelName] = joinedMethods
  if (methods.length)
    console.log(columnify(data, columnsOptins))
}

module.exports = {
  /**
   * Options for methodsToDisable:
   * @param model
   * @param methodsToDisable array
   */
  disableOnlyTheseMethods(model, methodsToDisable) {
    methodsToDisable.forEach(function (method) {
      model.disableRemoteMethodByName(method)
    })
    reportDisabledMethod(model, methodsToDisable)
  }
}
<commit_msg>Implement Disable REST Methods Except Function<commit_after>var columnify = require('columnify')
var columnsOptins = {
  showHeaders: false,
  minWidth: 35,
  columnSplitter: ' |    '
}

const relationMethodPrefixes = [
  'prototype.__findById__',
  'prototype.__destroyById__',
  'prototype.__updateById__',
  'prototype.__exists__',
  'prototype.__link__',
  'prototype.__get__',
  'prototype.__create__',
  'prototype.__update__',
  'prototype.__destroy__',
  'prototype.__unlink__',
  'prototype.__count__',
  'prototype.__delete__'
]

function reportDisabledMethod(model, methods) {
  const joinedMethods = methods.join(', ')
  const modelName = 'Disabled Remote Model ' + model.sharedClass.name
  var data = {}
  data[modelName] = joinedMethods
  if (methods.length)
    console.log(columnify(data, columnsOptins))
}

module.exports = {
  /**
   * Options for methodsToDisable:
   * @param model
   * @param methodsToDisable array
   */
  disableOnlyTheseMethods(model, methodsToDisable) {
    methodsToDisable.forEach(function (method) {
      model.disableRemoteMethodByName(method)
    })
    reportDisabledMethod(model, methodsToDisable)
  },

  /**
   * Options for disableAllExcept:
   * @param model
   * @param methodsToEnable array
   */
  disableAllExcept(model, methodsToExpose) {
    const
      excludedMethods = methodsToExpose || []
    var hiddenMethods = []

    if (model && model.sharedClass) {
      model.sharedClass.methods().forEach(disableMethod)
      Object.keys(model.definition.settings.relations).forEach(disableRelatedMethods)
    }

    function disableRelatedMethods(relation) {
      relationMethodPrefixes.forEach(function (prefix) {
        var methodName = prefix + relation

        disableMethod({
          name: methodName
        })
      })
    }

    function disableMethod(method) {
      var methodName = method.name

      if (excludedMethods.indexOf(methodName) < 0) {
        model.disableRemoteMethodByName(methodName)
        hiddenMethods.push(methodName)
      }
    }
  }
}
<|endoftext|>


<commit_before>odoo.define('staff_management.BookingCalendar', function (require) {
"use strict";

var core = require('web.core');
/*
var time = require('web.time');
var Model = require('web.DataModel');
*/
var form_common = require('web.form_common');
var StaffCalendar = require('staff_management.StaffCalendar');
var Tooltip = require('staff_management.Tooltip');

var _t = core._t;

var BookingCalendar = StaffCalendar.extend({

	template: "PersonalScheduleView",

	init:function(){
		this._super.apply(this,arguments);
	},

	// destroy, restore scheduler fonctions
	destroy:function(){
		this._super();
	},

	get_fc_init_options: function () {
		//Documentation here : http://arshaw.com/fullcalendar/docs/
		var self = this;
		return  $.extend({}, this._super(), {

			eventClick: function(event){
				self.open_event_staff(event.id,event.booking_name);
			},
			select: function (start_date, end_date, all_day, _js_event, _view) {
				var data_template = self.get_event_data({
					start: start_date,
					end: end_date,
					allDay: all_day,
				});
				self.slow_create(data_template);
			},
			eventRender: function(event, element) {

				var color = self.color_palette[0];
				if(event.meal_included){
					color = self.color_palette[1];
				}

				element.text(self.format_hour(event.hour_from)+' '+event.booking_name);
				element.css({'background': color});
				element.css({'border-color': color});

				element.mouseenter(event, function(evt){
					Tooltip.show($(this), self.get_tooltip_content(evt.data));
				}).mouseleave(Tooltip.hide);

			},
		});
	},

	get_tooltip_content: function(event){
		var div = $('<div>');
		div.append($('<div>').text(this.format_hour(event.hour_from)+' - '+this.format_hour(event.hour_to)));
		div.append($('<div>').text(event.booking_name));
		div.append($('<div>').text(event.nbr_adult+' '+_t('adults')));
		div.append($('<div>').text(event.nbr_child+' '+_t('children')));
		if(event.meal_included){
			div.append($('<div>').text(_t('Meal included')));
		}
		if(event.observation){
			div.append($('<div>').text(event.observation));
		}
		return div;
	},

	event_data_transform: function(evt) {
		var r = this._super.apply(this,arguments);
		r.booking_name = evt.booking_name;
		r.hour_from = evt.hour_from;
		r.hour_to = evt.hour_to;
		r.observation = evt.observation;
		r.nbr_adult = evt.nbr_adult;
		r.nbr_child = evt.nbr_child;
		r.meal_included = evt.meal_included;
		return r;
	},

	get_title: function () {
		return _t("Create booking");
	},
	get_form_popup_infos: function() {
		var infos = {
			view_id: false,
			title: this.name,
		};
		if (!(_.isUndefined(this.ViewManager))) {
			infos.view_id = this.ViewManager.get_view_id('form');
		}
		return infos;
	},
	slow_create: function(data){
		// TODO - refactor
		alert('not ready');
		/*
		var self = this;
		var defaults = {};

		_.each(data, function(val, field_name) {
			defaults['default_' + field_name] = val;
		});

		var pop_infos = self.get_form_popup_infos();
		var pop = new instance.web.form.FormOpenPopup(this);
		var context = new instance.web.CompoundContext(this.dataset.context, defaults);
		pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), {
			title: this.get_title(),
			disable_multiple_selection: true,
			view_id: pop_infos.view_id,
			// Ensuring we use ``self.dataset`` and DO NOT create a new one.
			create_function: function(data, options) {
				return self.dataset.create(data, options).done(function(r) {
				}).fail(function (r, event) {
				   if (!r.data.message) { //else manage by openerp
						throw new Error(r);
				   }
				});
			},
			read_function: function(id, fields, options) {
				return self.dataset.read_ids.apply(self.dataset, arguments).done(function() {
				}).fail(function (r, event) {
					if (!r.data.message) { //else manage by openerp
						throw new Error(r);
					}
				});
			},
		});
		var form_controller = pop.view_form;
		form_controller.on("load_record", self, function(){
			self.setPopupFieldsAction(pop);
		});
		pop.on('closed', self, function() {
			self.$calendar.fullCalendar('unselect');
		});
		pop.on('create_completed', self, function(id) {
			self.$calendar.fullCalendar('unselect');
			self.$calendar.fullCalendar('refetchEvents');
		});
		*/
	},

	open_event_staff: function(id, title) {
		var self = this;
		if (! this.open_popup_action) {
			var index = this.dataset.get_id_index(id);
			this.dataset.index = index;
			if (this.write_right) {
				this.do_switch_view('form', null, { mode: "edit" });
			} else {
				this.do_switch_view('form', null, { mode: "view" });
			}
		}
		else {
			// TODO - check
			/*
			var pop = new instance.web.form.FormOpenPopup(this);
			pop.show_element(this.dataset.model, id, this.dataset.get_context(), {
				title: _.str.sprintf(_t("View: %s"),title),
				view_id: +this.open_popup_action,
				res_id: id,
				target: 'new',
			});

			var form_controller = pop.view_form;
			form_controller.on("load_record", self, function(){
				button_delete = _.str.sprintf("<button class='oe_button oe_bold delme'><span> %s </span></button>",_t("Delete"));

				self.setPopupFieldsAction(pop);
				pop.$el.closest(".modal").find(".modal-footer").prepend(button_delete);

				$('.delme').click(
					function() {
						$('.oe_form_button_cancel').trigger('click');
						self.remove_event(id);
					}
				);
			});

			pop.on("saved", self, function(){
				self.$calendar.fullCalendar('refetchEvents');
			});
			*/
			var dialog = new form_common.FormViewDialog(this, {
				res_model: this.dataset.model,
				res_id: id,
				context: this.dataset.get_context(),
				title: _.str.sprintf(_t("View: %s"),title),
				view_id: +this.open_popup_action,
				readonly: false,
				buttons: [
					{text: _t("Save"), classes: 'btn-primary', close: true, click: function() {
						this.view_form.save();
					}},
					{text: _t("Remove"), close: true, click: function() {
						self.remove_event(id);
						/*
						self.dataset.write(evt.id, {'task_id': false}, {}).done(function() {
							self.refresh_events();
						});
						*/
					}},
					{text: _t("Close"), close: true}
				],
				write_function: function(id, data, _options) {
					return self.dataset.write(id, data, {}).done(function() {
						self.$calendar.fullCalendar('refetchEvents');
					});
				}
			}).open();

		}
		return false;
	},

	setPopupFieldsAction: function(pop){
		var self = this;
		var jdom = pop.$el;

		var fields = [
			// adults
			'staff_nbr_adult',
			'staff_price_adult',
			// children
			'staff_nbr_child',
			'staff_price_child',
			// wheelchairs
			'staff_nbr_wheelchair',
			'staff_price_wheelchair',
			// meals (checkbox not included here)
			'staff_meal_price_adult',
			'staff_meal_price_child'
		];

		var field_values = {};

		for(var i in fields){
			var field = fields[i];
			field_values[field] = this.getPopupFieldValue(pop, field);
			jdom.find('.'+field+' input').keyup({'pop': pop, 'field': field}, function(evt){
				if(evt.data.field.indexOf('staff_meal_price') == 0){
					if(self.getPopupFieldValue(evt.data.pop, evt.data.field) != field_values[evt.data.field]){
						evt.data.pop.view_form.set_values({'meal_included': true});
						field_values[evt.data.field] = self.getPopupFieldValue(evt.data.pop, evt.data.field);
					}
				}
				self.updatePopupTotalPrice(evt.data.pop);
			});
		}

		// meal checkbox
		jdom.find('.staff_meal_included input').change(pop, function(evt){
			self.updatePopupTotalPrice(evt.data);
		});

		// meal observation for the checkbox
		var old_field_value = self.getPopupFieldValue(pop, 'staff_meal_observation');
		jdom.find('.staff_meal_observation textarea').keyup(pop, function(evt){
			if($(this).val() != old_field_value){
				evt.data.view_form.set_values({'meal_included': true});
				old_field_value = $(this).val();
			}
		});

	},

	updatePopupTotalPrice: function(pop){
		var totalPrice = 0;

		var nbr_adult = this.getPopupFieldValue(pop, 'staff_nbr_adult');
		var price_adult = this.getPopupFieldValue(pop, 'staff_price_adult');
		totalPrice += nbr_adult * price_adult;

		var nbr_child = this.getPopupFieldValue(pop, 'staff_nbr_child');
		var price_child = this.getPopupFieldValue(pop, 'staff_price_child');
		totalPrice += nbr_child * price_child;

		var nbr_wheelchair = this.getPopupFieldValue(pop, 'staff_nbr_wheelchair');
		var price_wheelchair = this.getPopupFieldValue(pop, 'staff_price_wheelchair');
		totalPrice += nbr_wheelchair * price_wheelchair;

		if(pop.$el.find('.staff_meal_included input').is(':checked')){
			var meal_price_adult = this.getPopupFieldValue(pop, 'staff_meal_price_adult');
			totalPrice += nbr_adult * meal_price_adult;

			var meal_price_child = this.getPopupFieldValue(pop, 'staff_meal_price_child');
			totalPrice += nbr_child * meal_price_child;
		}

		pop.view_form.set_values({'total_price': totalPrice});
	},

	getPopupFieldValue: function(pop, fieldClass){
		var val = parseFloat(pop.$el.find('.'+fieldClass+' input').val());
		if(isNaN(val)){
			return 0;
		}
		return val;
	},
});

core.view_registry.add('calendar_booking', BookingCalendar);

return BookingCalendar;
});
<commit_msg>Fix form popups & price updater<commit_after>odoo.define('staff_management.BookingCalendar', function (require) {
"use strict";

var core = require('web.core');
var form_common = require('web.form_common');
var StaffCalendar = require('staff_management.StaffCalendar');
var Tooltip = require('staff_management.Tooltip');

var _t = core._t;

var BookingCalendar = StaffCalendar.extend({

	template: "PersonalScheduleView",

	init:function(){
		this._super.apply(this,arguments);
	},

	// destroy, restore scheduler fonctions
	destroy:function(){
		this._super();
	},

	get_fc_init_options: function () {
		//Documentation here : http://arshaw.com/fullcalendar/docs/
		var self = this;
		return  $.extend({}, this._super(), {

			eventClick: function(event){
				self.open_event_staff(event.id,event.booking_name);
			},
			select: function (start_date, end_date, all_day, _js_event, _view) {
				var data_template = self.get_event_data({
					start: start_date,
					end: end_date,
					allDay: all_day,
				});
				self.slow_create(data_template);
			},
			eventRender: function(event, element) {

				var color = self.color_palette[0];
				if(event.meal_included){
					color = self.color_palette[1];
				}

				element.text(self.format_hour(event.hour_from)+' '+event.booking_name);
				element.css({'background': color});
				element.css({'border-color': color});

				element.mouseenter(event, function(evt){
					Tooltip.show($(this), self.get_tooltip_content(evt.data));
				}).mouseleave(Tooltip.hide);

			},
		});
	},

	get_tooltip_content: function(event){
		var div = $('<div>');
		div.append($('<div>').text(this.format_hour(event.hour_from)+' - '+this.format_hour(event.hour_to)));
		div.append($('<div>').text(event.booking_name));
		div.append($('<div>').text(event.nbr_adult+' '+_t('adults')));
		div.append($('<div>').text(event.nbr_child+' '+_t('children')));
		if(event.meal_included){
			div.append($('<div>').text(_t('Meal included')));
		}
		if(event.observation){
			div.append($('<div>').text(event.observation));
		}
		return div;
	},

	event_data_transform: function(evt) {
		var r = this._super.apply(this,arguments);
		r.booking_name = evt.booking_name;
		r.hour_from = evt.hour_from;
		r.hour_to = evt.hour_to;
		r.observation = evt.observation;
		r.nbr_adult = evt.nbr_adult;
		r.nbr_child = evt.nbr_child;
		r.meal_included = evt.meal_included;
		return r;
	},

	get_title: function () {
		return _t("Create booking");
	},
	get_form_popup_infos: function() {
		var infos = {
			view_id: false,
			title: this.name,
		};
		if (!(_.isUndefined(this.ViewManager))) {
			infos.view_id = this.ViewManager.get_view_id('form');
		}
		return infos;
	},
	slow_create: function(data){
		var self = this;
		var defaults = {};

		_.each(data, function(val, field_name) {
			defaults['default_' + field_name] = val;
		});

		var pop_infos = self.get_form_popup_infos();

		var dialog = new form_common.FormViewDialog(this, {
			res_model: this.dataset.model,
			context: defaults,
			title: this.get_title(),
			view_id: pop_infos.view_id,
			readonly: false,
			disable_multiple_selection: true
		}).open();
		dialog.on('record_saved', this, function(){
			self.$calendar.fullCalendar('refetchEvents');
			self.$calendar.fullCalendar('unselect');
		});
		dialog.on('closed', this, function(){
			self.$calendar.fullCalendar('unselect');
		});
		dialog.view_form.on("load_record", this, function(){
			self.setPopupFieldsAction(dialog);
		});
	},

	open_event_staff: function(id, title) {
		var self = this;
		if (! this.open_popup_action) {
			var index = this.dataset.get_id_index(id);
			this.dataset.index = index;
			if (this.write_right) {
				this.do_switch_view('form', null, { mode: "edit" });
			} else {
				this.do_switch_view('form', null, { mode: "view" });
			}
		}
		else {
			var dialog = new form_common.FormViewDialog(this, {
				res_model: this.dataset.model,
				res_id: id,
				context: this.dataset.get_context(),
				title: _.str.sprintf(_t("View: %s"),title),
				view_id: +this.open_popup_action,
				readonly: false,
				buttons: [
					{text: _t("Save"), classes: 'btn-primary', close: true, click: function() {
						this.view_form.save();
					}},
					{text: _t("Remove"), close: true, click: function() {
						self.remove_event(id);
					}},
					{text: _t("Close"), close: true}
				],
				write_function: function(id, data, _options) {
					return self.dataset.write(id, data, {}).done(function() {
						self.$calendar.fullCalendar('refetchEvents');
					});
				}
			}).open();
			dialog.view_form.on("load_record", this, function(){
				self.setPopupFieldsAction(dialog);
			});
		}
		return false;
	},

	setPopupFieldsAction: function(pop){
		var self = this;
		var jdom = pop.$el;

		var fields = [
			// adults
			'staff_nbr_adult',
			'staff_price_adult',
			// children
			'staff_nbr_child',
			'staff_price_child',
			// wheelchairs
			'staff_nbr_wheelchair',
			'staff_price_wheelchair',
			// meals (checkbox not included here)
			'staff_meal_price_adult',
			'staff_meal_price_child'
		];

		var field_values = {};

		for(var i in fields){
			var field = fields[i];
			field_values[field] = this.getPopupFieldValue(pop, field);
			jdom.find('.'+field+' input').keyup({'pop': pop, 'field': field}, function(evt){
				if(evt.data.field.indexOf('staff_meal_price') == 0){
					if(self.getPopupFieldValue(evt.data.pop, evt.data.field) != field_values[evt.data.field]){
						evt.data.pop.view_form.set_values({'meal_included': true});
						field_values[evt.data.field] = self.getPopupFieldValue(evt.data.pop, evt.data.field);
					}
				}
				self.updatePopupTotalPrice(evt.data.pop);
			});
		}

		// meal checkbox
		jdom.find('.staff_meal_included input').change(pop, function(evt){
			self.updatePopupTotalPrice(evt.data);
		});

		// meal observation for the checkbox
		var old_field_value = self.getPopupFieldValue(pop, 'staff_meal_observation');
		jdom.find('.staff_meal_observation textarea').keyup(pop, function(evt){
			if($(this).val() != old_field_value){
				evt.data.view_form.set_values({'meal_included': true});
				old_field_value = $(this).val();
			}
		});

	},

	updatePopupTotalPrice: function(pop){
		var totalPrice = 0;

		var nbr_adult = this.getPopupFieldValue(pop, 'staff_nbr_adult');
		var price_adult = this.getPopupFieldValue(pop, 'staff_price_adult');
		totalPrice += nbr_adult * price_adult;

		var nbr_child = this.getPopupFieldValue(pop, 'staff_nbr_child');
		var price_child = this.getPopupFieldValue(pop, 'staff_price_child');
		totalPrice += nbr_child * price_child;

		var nbr_wheelchair = this.getPopupFieldValue(pop, 'staff_nbr_wheelchair');
		var price_wheelchair = this.getPopupFieldValue(pop, 'staff_price_wheelchair');
		totalPrice += nbr_wheelchair * price_wheelchair;

		if(pop.$el.find('.staff_meal_included input').is(':checked')){
			var meal_price_adult = this.getPopupFieldValue(pop, 'staff_meal_price_adult');
			totalPrice += nbr_adult * meal_price_adult;

			var meal_price_child = this.getPopupFieldValue(pop, 'staff_meal_price_child');
			totalPrice += nbr_child * meal_price_child;
		}

		pop.view_form.set_values({'total_price': totalPrice});
	},

	getPopupFieldValue: function(pop, fieldClass){
		var val = parseFloat(pop.$el.find('.'+fieldClass+' input').val());
		if(isNaN(val)){
			return 0;
		}
		return val;
	},
});

core.view_registry.add('calendar_booking', BookingCalendar);

return BookingCalendar;
});
<|endoftext|>


<commit_before>class Header extends React.Component { // eslint-disable-line no-unused-vars
    render() {
        return(

                        cede.io

{user.username}

        );
    }

    rerenderGamesList(event){
        event.preventDefault();

        ReactDOM.render(
            <GamesList />,
            document.getElementById('content')
        );
    }
}
<commit_msg>Fix name in header<commit_after>class Header extends React.Component { // eslint-disable-line no-unused-vars
    render() {
        return(

                        cede.io

{user.username}

        );
    }

    rerenderGamesList(event){
        event.preventDefault();

        ReactDOM.render(
            <GamesList />,
            document.getElementById('content')
        );
    }
}
<|endoftext|>


<commit_before>const cacheName = 'cache-v3'
const precacheResources = [
  '/',
  'index.html',
  'img/icons/android-chrome-192x192.png',
  'img/icons/android-chrome-512x512.png',
  'img/icons/android-chrome-maskable-192x192.png',
  'img/icons/android-chrome-maskable-512x512.png',
  'img/icons/apple-touch-icon-120x120.png',
  'img/icons/apple-touch-icon-152x152.png',
  'img/icons/apple-touch-icon-180x180.png',
  'img/icons/apple-touch-icon-60x60.png',
  'img/icons/apple-touch-icon-76x76.png',
  'img/icons/apple-touch-icon.png',
  'img/icons/favicon-16x16.png',
  'img/icons/favicon-32x32.png',
  'img/icons/msapplication-icon-144x144.png',
  'img/icons/mstile-150x150.png',
  'img/icons/safari-pinned-tab.svg'
]

self.addEventListener('install', event => {
  console.log('Service worker has been installed.')
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => {
        return cache.addAll(precacheResources)
      })
  )
})

self.addEventListener('activate', async event => {
  console.log('Service worker has been activated.')
  event.waitUntil(
    caches.keys().then((keyList) => {
      return Promise.all(keyList.map((key) => {
        if (key !== cacheName) {
          return caches.delete(key)
        }
      }))
    })
  )
})

self.addEventListener('fetch', event => {
  event.respondWith(caches.match(event.request)
    .then(cachedResponse => {
      if (cachedResponse) {
        return cachedResponse;
      }
      return fetch(event.request)
    })
  )
})

self.addEventListener('message', event => {
  console.log('message', JSON.stringify(event))
})
<commit_msg>bug fix<commit_after>const cacheName = 'cache-v4'
const precacheResources = [
  '/',
  'index.html',
  'img/icons/android-chrome-192x192.png',
  'img/icons/android-chrome-512x512.png',
  'img/icons/android-chrome-maskable-192x192.png',
  'img/icons/android-chrome-maskable-512x512.png',
  'img/icons/apple-touch-icon-120x120.png',
  'img/icons/apple-touch-icon-152x152.png',
  'img/icons/apple-touch-icon-180x180.png',
  'img/icons/apple-touch-icon-60x60.png',
  'img/icons/apple-touch-icon-76x76.png',
  'img/icons/apple-touch-icon.png',
  'img/icons/favicon-16x16.png',
  'img/icons/favicon-32x32.png',
  'img/icons/msapplication-icon-144x144.png',
  'img/icons/mstile-150x150.png',
  'img/icons/safari-pinned-tab.svg'
]

self.addEventListener('install', event => {
  console.log('Service worker has been installed.')
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => {
        return cache.addAll(precacheResources)
      })
  )
})

self.addEventListener('activate', async event => {
  console.log('Service worker has been activated.')
  event.waitUntil(
    caches.keys().then((keyList) => {
      return Promise.all(keyList.map((key) => {
        if (key !== cacheName) {
          return caches.delete(key)
        }
      }))
    })
  )
})

self.addEventListener('fetch', event => {
  event.respondWith(caches.match(event.request)
    .then(cachedResponse => {
      if (cachedResponse) {
        return cachedResponse;
      }
      return fetch(event.request)
    })
  )
})

self.addEventListener('message', event => {
  console.log('message', JSON.stringify(event))
})
<|endoftext|>


<commit_before>/*
 * jquery.draggable
 * https://github.com/ducksboard/gridster.js
 *
 * Copyright (c) 2012 ducksboard
 * Licensed under the MIT licenses.
 */

;(function(root, factory) {

    if (typeof define === 'function' && define.amd) {
        define('gridster-draggable', ['jquery'], factory);
    } else {
        root.GridsterDraggable = factory(root.$ || root.jQuery);
    }

}(this, function($) {

    var defaults = {
        items: 'li',
        distance: 1,
        limit: true,
        offset_left: 0,
        autoscroll: true,
        ignore_dragging: ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON'], // or function
        handle: null,
        container_width: 0,  // 0 == auto
        move_element: true,
        helper: false,  // or 'clone'
        remove_helper: true,
        scroll_target: null
        // drag: function(e) {},
        // start : function(e, ui) {},
        // stop : function(e) {}
    };

    var $window = $(window);
    var dir_map = { x : 'left', y : 'top' };
    var isTouch = !!('ontouchstart' in window);

    var capitalize = function(str) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    };

    var idCounter = 0;
    var uniqId = function() {
        return ++idCounter + '';
    };

    /**
    * Basic drag implementation for DOM elements inside a container.
    * Provide start/stop/drag callbacks.
    *
    * @class Draggable
    * @param {HTMLElement} el The HTMLelement that contains all the widgets
    *  to be dragged.
    * @param {Object} [options] An Object with all options you want to
    *        overwrite:
    *    @param {HTMLElement|String} [options.items] Define who will
    *     be the draggable items. Can be a CSS Selector String or a
    *     collection of HTMLElements.
    *    @param {Number} [options.distance] Distance in pixels after mousedown
    *     the mouse must move before dragging should start.
    *    @param {Boolean} [options.limit] Constrains dragging to the width of
    *     the container
    *    @param {Object|Function} [options.ignore_dragging] Array of node names
    *      that sould not trigger dragging, by default is `['INPUT', 'TEXTAREA',
    *      'SELECT', 'BUTTON']`. If a function is used return true to ignore dragging.
    *    @param {offset_left} [options.offset_left] Offset added to the item
    *     that is being dragged.
    *    @param {Number} [options.drag] Executes a callback when the mouse is
    *     moved during the dragging.
    *    @param {Number} [options.start] Executes a callback when the drag
    *     starts.
    *    @param {Number} [options.stop] Executes a callback when the drag stops.
    * @return {Object} Returns `el`.
    * @constructor
    */
    function Draggable(el, options) {
      this.options = $.extend({}, defaults, options);
      this.$document = $(document);
      this.$container = $(el);
      this.$scroll_target = this.options.scroll_target;
      this.$dragitems = $(this.options.items, this.$container);
      this.is_dragging = false;
      this.player_min_left = 0 + this.options.offset_left;
      this.id = uniqId();
      this.ns = '.gridster-draggable-' + this.id;
      this.init();
    }

    Draggable.defaults = defaults;

    var fn = Draggable.prototype;

    fn.init = function() {
        var pos = this.$container.css('position');
        this.calculate_dimensions();
        this.$container.css('position', pos === 'static' ? 'relative' : pos);
        this.disabled = false;
        this.events();

        $(window).bind(this.nsEvent('resize'),
            throttle($.proxy(this.calculate_dimensions, this), 200));
    };

    fn.nsEvent = function(ev) {
        return (ev || '') + this.ns;
    };

    fn.events = function() {
        this.pointer_events = {
            start: this.nsEvent('touchstart') + ' ' + this.nsEvent('mousedown'),
            move: this.nsEvent('touchmove') + ' ' + this.nsEvent('mousemove'),
            end: this.nsEvent('touchend') + ' ' + this.nsEvent('mouseup'),
        };

        this.$container.on(this.nsEvent('selectstart'),
            $.proxy(this.on_select_start, this));

        this.$container.on(this.pointer_events.start, this.options.items,
            $.proxy(this.drag_handler, this));

        this.$document.on(this.pointer_events.end, $.proxy(function(e) {
            this.is_dragging = false;
            if (this.disabled) { return; }
            this.$document.off(this.pointer_events.move);
            if (this.drag_start) {
                this.on_dragstop(e);
            }
        }, this));
    };

    fn.get_actual_pos = function($el) {
        var pos = $el.position();
        return pos;
    };

    fn.get_mouse_pos = function(e) {
        if (e.originalEvent && e.originalEvent.touches) {
            var oe = e.originalEvent;
            e = oe.touches.length ? oe.touches[0] : oe.changedTouches[0];
        }

        return {
            left: e.clientX,
            top: e.clientY
        };
    };

    fn.get_offset = function(e) {
        e.preventDefault();
        var mouse_actual_pos = this.get_mouse_pos(e);
        var diff_x = Math.round(
            mouse_actual_pos.left - this.mouse_init_pos.left);
        var diff_y = Math.round(mouse_actual_pos.top - this.mouse_init_pos.top);

        var left = Math.round(this.el_init_offset.left +
            diff_x - this.baseX + $(window).scrollLeft() - this.win_offset_x);
        var top = Math.round(this.el_init_offset.top +
            diff_y - this.baseY + $(window).scrollTop() - this.win_offset_y);

        if (this.options.limit) {
            if (left > this.player_max_left) {
                left = this.player_max_left;
            } else if(left < this.player_min_left) {
                left = this.player_min_left;
            }
        }

        return {
            position: {
                left: left,
                top: top
            },
            pointer: {
                left: mouse_actual_pos.left,
                top: mouse_actual_pos.top,
                diff_left: diff_x + ($(window).scrollLeft() - this.win_offset_x),
                diff_top: diff_y + ($(window).scrollTop() - this.win_offset_y)
            }
        };
    };

    fn.get_drag_data = function(e) {
        var offset = this.get_offset(e);
        offset.$player = this.$player;
        offset.$helper = this.helper ? this.$helper : this.$player;

        return offset;
    };

    fn.set_limits = function(container_width) {
        container_width || (container_width = this.$container.width());
        this.player_max_left = (container_width - this.player_width +
            - this.options.offset_left);

        this.options.container_width = container_width;

        return this;
    };

    fn.scroll_in = function(axis, data) {
        var dir_prop = dir_map[axis];

        var area_size = 50;
        var scroll_inc = 30;

        var is_x = axis === 'x';
        var window_size = is_x ? this.window_width : this.window_height;
        var doc_size = is_x ? $(document).width() : $(document).height();
        var player_size = is_x ? this.$player.width() : this.$player.height();

        var next_scroll;
        var scroll_offset = $window['scroll' + capitalize(dir_prop)]();
        var min_window_pos = scroll_offset;
        var max_window_pos = min_window_pos + window_size;

        var mouse_next_zone = max_window_pos - area_size;  // down/right
        var mouse_prev_zone = min_window_pos + area_size;  // up/left

        var abs_mouse_pos = min_window_pos + data.pointer[dir_prop];

        var max_player_pos = (doc_size - window_size + player_size);

        if (abs_mouse_pos >= mouse_next_zone) {
            next_scroll = scroll_offset + scroll_inc;
            if (next_scroll < max_player_pos) {
                $window['scroll' + capitalize(dir_prop)](next_scroll);
                this['scroll_offset_' + axis] += scroll_inc;
            }
        }

        if (abs_mouse_pos <= mouse_prev_zone) {
            next_scroll = scroll_offset - scroll_inc;
            if (next_scroll > 0) {
                $window['scroll' + capitalize(dir_prop)](next_scroll);
                this['scroll_offset_' + axis] -= scroll_inc;
            }
        }

        return this;
    };

    fn.manage_scroll = function(data) {
        this.scroll_in('x', data);
        this.scroll_in('y', data);
    };

    fn.calculate_dimensions = function(e) {
        this.window_height = $window.height();
        this.window_width = $window.width();
    };

    fn.drag_handler = function(e) {
        var node = e.target.nodeName;
        // skip if drag is disabled, or click was not done with the mouse primary button
        if (this.disabled || e.which !== 1 && !isTouch) {
            return;
        }

        if (this.ignore_drag(e)) {
            return;
        }

        var self = this;
        var first = true;
        this.$player = $(e.currentTarget);

        this.el_init_pos = this.get_actual_pos(this.$player);
        this.mouse_init_pos = this.get_mouse_pos(e);
        this.offsetY = this.mouse_init_pos.top - this.el_init_pos.top;

        this.$document.on(this.pointer_events.move, function(mme) {
            var mouse_actual_pos = self.get_mouse_pos(mme);
            var diff_x = Math.abs(
                mouse_actual_pos.left - self.mouse_init_pos.left);
            var diff_y = Math.abs(
                mouse_actual_pos.top - self.mouse_init_pos.top);
            if (!(diff_x > self.options.distance ||
                diff_y > self.options.distance)
                ) {
                return false;
            }

            if (first) {
                first = false;
                self.on_dragstart.call(self, mme);
                return false;
            }

            if (self.is_dragging === true) {
                self.on_dragmove.call(self, mme);
            }

            return false;
        });

        if (!isTouch) { return false; }
    };

    fn.on_dragstart = function(e) {
        e.preventDefault();

        if (this.is_dragging) { return this; }

        this.drag_start = this.is_dragging = true;

        if (this.$scroll_target) {
          this.previous_scroll = this.$scroll_target.scrollTop();
          this.$scroll_target.on('scroll.gridster', $.proxy(this.on_scroll, this));
        }

        var offset = this.$container.offset();
        this.baseX = Math.round(offset.left);
        this.baseY = Math.round(offset.top);
        this.initial_container_width = this.options.container_width || this.$container.width();

        if (this.options.helper === 'clone') {
            this.$helper = this.$player.clone()
                .appendTo(this.$container).addClass('helper');
            this.helper = true;
        } else {
            this.helper = false;
        }

        this.win_offset_y = $(window).scrollTop();
        this.win_offset_x = $(window).scrollLeft();
        this.scroll_offset_y = 0;
        this.scroll_offset_x = 0;
        this.el_init_offset = this.$player.offset();
        this.player_width = this.$player.width();
        this.player_height = this.$player.height();

        this.set_limits(this.options.container_width);

        if (this.options.start) {
            this.options.start.call(this.$player, e, this.get_drag_data(e));
        }
        return false;
    };

    fn.on_dragmove = function(e) {
        var data = this.get_drag_data(e);

        this.options.autoscroll && this.manage_scroll(data);

        if (this.options.move_element) {
            (this.helper ? this.$helper : this.$player).css({
                'position': 'absolute',
                'left' : data.position.left,
                'top' : data.position.top
            });
        }

        var last_position = this.last_position || data.position;

        data.prev_position = last_position;

        if (this.options.drag) {
            this.options.drag.call(this.$player, e, data);
        }

        this.last_position = data.position;
        return false;
    };

    fn.on_scroll = function(e) {
      if (this.$scroll_target) {
        var current_scroll = this.$scroll_target.scrollTop();
        var scroll_amount = current_scroll - this.previous_scroll;

        console.log("previous_scroll", this.previous_scroll);
        console.log("current_scroll", current_scroll);
        console.log("Scrolled by ", scroll_amount);

        this.previous_scroll = current_scroll;
      }
    };

    fn.on_dragstop = function(e) {
        var data = this.get_drag_data(e);
        this.drag_start = false;

        if (this.options.stop) {
            this.options.stop.call(this.$player, e, data);
        }

        if (this.helper && this.options.remove_helper) {
            this.$helper.remove();
        }

        if (this.$scroll_target) {
          this.$scroll_target.off('scroll.gridster');
        }

        return false;
    };

    fn.on_select_start = function(e) {
        if (this.disabled) { return; }

        if (this.ignore_drag(e)) {
            return;
        }

        return false;
    };

    fn.enable = function() {
        this.disabled = false;
    };

    fn.disable = function() {
        this.disabled = true;
    };

    fn.destroy = function() {
        this.disable();

        this.$container.off(this.ns);
        this.$document.off(this.ns);
        $(window).off(this.ns);

        $.removeData(this.$container, 'drag');
    };

    fn.ignore_drag = function(event) {
        if (this.options.handle) {
            return !$(event.target).is(this.options.handle);
        }

        if ($.isFunction(this.options.ignore_dragging)) {
            return this.options.ignore_dragging(event);
        }

        return $(event.target).is(this.options.ignore_dragging.join(', '));
    };

    //jQuery adapter
    $.fn.drag = function ( options ) {
        return new Draggable(this, options);
    };

    return Draggable;

}));
<commit_msg>Account for scroll while dragging<commit_after>/*
 * jquery.draggable
 * https://github.com/ducksboard/gridster.js
 *
 * Copyright (c) 2012 ducksboard
 * Licensed under the MIT licenses.
 */

;(function(root, factory) {

    if (typeof define === 'function' && define.amd) {
        define('gridster-draggable', ['jquery'], factory);
    } else {
        root.GridsterDraggable = factory(root.$ || root.jQuery);
    }

}(this, function($) {

    var defaults = {
        items: 'li',
        distance: 1,
        limit: true,
        offset_left: 0,
        autoscroll: true,
        ignore_dragging: ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON'], // or function
        handle: null,
        container_width: 0,  // 0 == auto
        move_element: true,
        helper: false,  // or 'clone'
        remove_helper: true,
        scroll_target: null
        // drag: function(e) {},
        // start : function(e, ui) {},
        // stop : function(e) {}
    };

    var $window = $(window);
    var dir_map = { x : 'left', y : 'top' };
    var isTouch = !!('ontouchstart' in window);

    var capitalize = function(str) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    };

    var idCounter = 0;
    var uniqId = function() {
        return ++idCounter + '';
    };

    /**
    * Basic drag implementation for DOM elements inside a container.
    * Provide start/stop/drag callbacks.
    *
    * @class Draggable
    * @param {HTMLElement} el The HTMLelement that contains all the widgets
    *  to be dragged.
    * @param {Object} [options] An Object with all options you want to
    *        overwrite:
    *    @param {HTMLElement|String} [options.items] Define who will
    *     be the draggable items. Can be a CSS Selector String or a
    *     collection of HTMLElements.
    *    @param {Number} [options.distance] Distance in pixels after mousedown
    *     the mouse must move before dragging should start.
    *    @param {Boolean} [options.limit] Constrains dragging to the width of
    *     the container
    *    @param {Object|Function} [options.ignore_dragging] Array of node names
    *      that sould not trigger dragging, by default is `['INPUT', 'TEXTAREA',
    *      'SELECT', 'BUTTON']`. If a function is used return true to ignore dragging.
    *    @param {offset_left} [options.offset_left] Offset added to the item
    *     that is being dragged.
    *    @param {Number} [options.drag] Executes a callback when the mouse is
    *     moved during the dragging.
    *    @param {Number} [options.start] Executes a callback when the drag
    *     starts.
    *    @param {Number} [options.stop] Executes a callback when the drag stops.
    * @return {Object} Returns `el`.
    * @constructor
    */
    function Draggable(el, options) {
      this.options = $.extend({}, defaults, options);
      this.$document = $(document);
      this.$container = $(el);
      this.$scroll_target = this.options.scroll_target;
      this.$dragitems = $(this.options.items, this.$container);
      this.is_dragging = false;
      this.player_min_left = 0 + this.options.offset_left;
      this.id = uniqId();
      this.ns = '.gridster-draggable-' + this.id;
      this.init();
    }

    Draggable.defaults = defaults;

    var fn = Draggable.prototype;

    fn.init = function() {
        var pos = this.$container.css('position');
        this.calculate_dimensions();
        this.$container.css('position', pos === 'static' ? 'relative' : pos);
        this.disabled = false;
        this.events();

        $(window).bind(this.nsEvent('resize'),
            throttle($.proxy(this.calculate_dimensions, this), 200));
    };

    fn.nsEvent = function(ev) {
        return (ev || '') + this.ns;
    };

    fn.events = function() {
        this.pointer_events = {
            start: this.nsEvent('touchstart') + ' ' + this.nsEvent('mousedown'),
            move: this.nsEvent('touchmove') + ' ' + this.nsEvent('mousemove'),
            end: this.nsEvent('touchend') + ' ' + this.nsEvent('mouseup'),
        };

        this.$container.on(this.nsEvent('selectstart'),
            $.proxy(this.on_select_start, this));

        this.$container.on(this.pointer_events.start, this.options.items,
            $.proxy(this.drag_handler, this));

        this.$document.on(this.pointer_events.end, $.proxy(function(e) {
            this.is_dragging = false;
            if (this.disabled) { return; }
            this.$document.off(this.pointer_events.move);
            if (this.drag_start) {
                this.on_dragstop(e);
            }
        }, this));
    };

    fn.get_actual_pos = function($el) {
        var pos = $el.position();
        return pos;
    };

    fn.get_mouse_pos = function(e) {
        if (e.originalEvent && e.originalEvent.touches) {
            var oe = e.originalEvent;
            e = oe.touches.length ? oe.touches[0] : oe.changedTouches[0];
        }

        return {
            left: e.clientX,
            top: e.clientY
        };
    };

    fn.get_offset = function(e) {
        e.preventDefault();
        var mouse_actual_pos = this.get_mouse_pos(e);
        var diff_x = Math.round(
            mouse_actual_pos.left - this.mouse_init_pos.left);
        var diff_y = Math.round(mouse_actual_pos.top - this.mouse_init_pos.top);

        var left = Math.round(this.el_init_offset.left +
            diff_x - this.baseX + $(window).scrollLeft() - this.win_offset_x);
        var top = Math.round(this.el_init_offset.top +
            diff_y - this.baseY + $(window).scrollTop() - this.win_offset_y);

        if (this.options.limit) {
            if (left > this.player_max_left) {
                left = this.player_max_left;
            } else if(left < this.player_min_left) {
                left = this.player_min_left;
            }
        }

        return {
            position: {
                left: left,
                top: top
            },
            pointer: {
                left: mouse_actual_pos.left,
                top: mouse_actual_pos.top,
                diff_left: diff_x + ($(window).scrollLeft() - this.win_offset_x),
                diff_top: diff_y + ($(window).scrollTop() - this.win_offset_y)
            }
        };
    };

    fn.get_drag_data = function(e) {
        var offset = this.get_offset(e);
        offset.$player = this.$player;
        offset.$helper = this.helper ? this.$helper : this.$player;

        return offset;
    };

    fn.set_limits = function(container_width) {
        container_width || (container_width = this.$container.width());
        this.player_max_left = (container_width - this.player_width +
            - this.options.offset_left);

        this.options.container_width = container_width;

        return this;
    };

    fn.scroll_in = function(axis, data) {
        var dir_prop = dir_map[axis];

        var area_size = 50;
        var scroll_inc = 30;

        var is_x = axis === 'x';
        var window_size = is_x ? this.window_width : this.window_height;
        var doc_size = is_x ? $(document).width() : $(document).height();
        var player_size = is_x ? this.$player.width() : this.$player.height();

        var next_scroll;
        var scroll_offset = $window['scroll' + capitalize(dir_prop)]();
        var min_window_pos = scroll_offset;
        var max_window_pos = min_window_pos + window_size;

        var mouse_next_zone = max_window_pos - area_size;  // down/right
        var mouse_prev_zone = min_window_pos + area_size;  // up/left

        var abs_mouse_pos = min_window_pos + data.pointer[dir_prop];

        var max_player_pos = (doc_size - window_size + player_size);

        if (abs_mouse_pos >= mouse_next_zone) {
            next_scroll = scroll_offset + scroll_inc;
            if (next_scroll < max_player_pos) {
                $window['scroll' + capitalize(dir_prop)](next_scroll);
                this['scroll_offset_' + axis] += scroll_inc;
            }
        }

        if (abs_mouse_pos <= mouse_prev_zone) {
            next_scroll = scroll_offset - scroll_inc;
            if (next_scroll > 0) {
                $window['scroll' + capitalize(dir_prop)](next_scroll);
                this['scroll_offset_' + axis] -= scroll_inc;
            }
        }

        return this;
    };

    fn.manage_scroll = function(data) {
        this.scroll_in('x', data);
        this.scroll_in('y', data);
    };

    fn.calculate_dimensions = function(e) {
        this.window_height = $window.height();
        this.window_width = $window.width();
    };

    fn.drag_handler = function(e) {
        var node = e.target.nodeName;
        // skip if drag is disabled, or click was not done with the mouse primary button
        if (this.disabled || e.which !== 1 && !isTouch) {
            return;
        }

        if (this.ignore_drag(e)) {
            return;
        }

        var self = this;
        var first = true;
        this.$player = $(e.currentTarget);

        this.el_init_pos = this.get_actual_pos(this.$player);
        this.mouse_init_pos = this.get_mouse_pos(e);
        this.offsetY = this.mouse_init_pos.top - this.el_init_pos.top;

        this.$document.on(this.pointer_events.move, function(mme) {
            var mouse_actual_pos = self.get_mouse_pos(mme);
            var diff_x = Math.abs(
                mouse_actual_pos.left - self.mouse_init_pos.left);
            var diff_y = Math.abs(
                mouse_actual_pos.top - self.mouse_init_pos.top);
            if (!(diff_x > self.options.distance ||
                diff_y > self.options.distance)
                ) {
                return false;
            }

            if (first) {
                first = false;
                self.on_dragstart.call(self, mme);
                return false;
            }

            if (self.is_dragging === true) {
                self.on_dragmove.call(self, mme);
            }

            return false;
        });

        if (!isTouch) { return false; }
    };

    fn.on_dragstart = function(e) {
        e.preventDefault();

        if (this.is_dragging) { return this; }

        this.drag_start = this.is_dragging = true;

        if (this.$scroll_target) {
          this.previous_scroll = this.$scroll_target.scrollTop();
          this.$scroll_target.on('scroll.gridster', $.proxy(this.on_scroll, this));
          this.initial_scroll = this.previous_scroll;
        }

        var offset = this.$container.offset();
        this.baseX = Math.round(offset.left);
        this.baseY = Math.round(offset.top);
        this.initial_container_width = this.options.container_width || this.$container.width();

        if (this.options.helper === 'clone') {
            this.$helper = this.$player.clone()
                .appendTo(this.$container).addClass('helper');
            this.helper = true;
        } else {
            this.helper = false;
        }

        this.win_offset_y = $(window).scrollTop();
        this.win_offset_x = $(window).scrollLeft();
        this.scroll_offset_y = 0;
        this.scroll_offset_x = 0;
        this.el_init_offset = this.$player.offset();
        this.player_width = this.$player.width();
        this.player_height = this.$player.height();

        this.set_limits(this.options.container_width);

        if (this.options.start) {
            this.options.start.call(this.$player, e, this.get_drag_data(e));
        }
        return false;
    };

    fn.on_dragmove = function(e) {
        var data = this.get_drag_data(e);

        this.options.autoscroll && this.manage_scroll(data);

        if (this.$scroll_target) {
          var current_scroll = this.$scroll_target.scrollTop();
          console.log("initial_scroll", this.initial_scroll);
          console.log("current_scroll", current_scroll);

          data.position.top = data.position.top + current_scroll - this.initial_scroll;
        }

        if (this.options.move_element) {
            (this.helper ? this.$helper : this.$player).css({
                'position': 'absolute',
                'left' : data.position.left,
                'top' : data.position.top
            });
        }

        var last_position = this.last_position || data.position;

        data.prev_position = last_position;

        if (this.options.drag) {
            this.options.drag.call(this.$player, e, data);
        }

        this.last_position = data.position;
        return false;
    };

    fn.on_scroll = function(e) {
      if (this.$scroll_target) {
        var current_scroll = this.$scroll_target.scrollTop();
        var scroll_amount = current_scroll - this.previous_scroll;

        console.log("previous_scroll", this.previous_scroll);
        console.log("current_scroll", current_scroll);
        console.log("Scrolled by ", scroll_amount);

        var new_position = {
          left: this.last_position.left,
          top: this.last_position.top + scroll_amount
        };

        (this.helper ? this.$helper : this.$player).css({
            'position': 'absolute',
            'left' : new_position.left,
            'top' : new_position.top
        });

        this.previous_scroll = current_scroll;
        this.last_position = new_position;
        return false;
      }
    };

    fn.on_dragstop = function(e) {
        var data = this.get_drag_data(e);
        this.drag_start = false;

        if (this.options.stop) {
            this.options.stop.call(this.$player, e, data);
        }

        if (this.helper && this.options.remove_helper) {
            this.$helper.remove();
        }

        if (this.$scroll_target) {
          this.$scroll_target.off('scroll.gridster');
        }

        return false;
    };

    fn.on_select_start = function(e) {
        if (this.disabled) { return; }

        if (this.ignore_drag(e)) {
            return;
        }

        return false;
    };

    fn.enable = function() {
        this.disabled = false;
    };

    fn.disable = function() {
        this.disabled = true;
    };

    fn.destroy = function() {
        this.disable();

        this.$container.off(this.ns);
        this.$document.off(this.ns);
        $(window).off(this.ns);

        $.removeData(this.$container, 'drag');
    };

    fn.ignore_drag = function(event) {
        if (this.options.handle) {
            return !$(event.target).is(this.options.handle);
        }

        if ($.isFunction(this.options.ignore_dragging)) {
            return this.options.ignore_dragging(event);
        }

        return $(event.target).is(this.options.ignore_dragging.join(', '));
    };

    //jQuery adapter
    $.fn.drag = function ( options ) {
        return new Draggable(this, options);
    };

    return Draggable;

}));
<|endoftext|>


<commit_before>var inputVideo, animationCanvas, overlayCanvas, octx, outputCanvas, outctx;
var faces, heads;

var SNOW = false;  // turn on particle system
var FACEREC = false; // turn on face detection
var FACE_BOX = false; // turn on face boxes

var propdir = "/static/img/"

// locs is an array of locations to put clones of the image
// each element in array is an object that provides an x and y location
// to move it to that is a proportion of the container size and either a
// reference height or width to scale things according to the container size
// eg a height of 0.25 would mean 0.25 x container height which would be
// determined and then the actual height of the asset scaled accordingly.
var props = {
    tree: {
        active: false,
        file: propdir + "tree.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 1.0
        },
        locs: [
            {
                x: 0.5, y: 1.0,
                h: 0.65,
            },
        ],
    },
    mistletoe: {
        active: false,
        file: propdir + "mistletoe.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.0,
        },
        locs: [
            {
                x: 0.5, y: 0.0,
                h: 0.25,
            },
        ],
    },
    sleigh: {
        active: false,
        file: propdir + "sleigh.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.85
        },
        locs: [
            {
                x: 0.5, y: 1.0,
                h: 0.75,
            },
        ],
    },
    present: {
        active: true,
        file: propdir + "present.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.95
        },
        locs: [
            {
                x: 0.35, y: 1.0,
                h: 0.15,
            },
            {
                x: 0.65, y: 1.0,
                h: 0.10,
            },
            {
                x: 0.58, y: 1.0,
                h: 0.08,
            },
        ],
    },
     wreath: {
        active: false,
        file: propdir + "wreath.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.5,
        },
        locs: [
            {
                x: 0.5, y: 0.5,
                h: 0.90,
            },
        ],
    },
};

var current_prop = props.wreath;
//var current_prop = props.tree;

function animate() {
    // do the relevant animation steps if needed.

    requestAnimationFrame( animate );

    overlays();

    if (SNOW) {
        particle_animator();
        renderer.render( scene, camera );
    }

}

function overlays() {
    // generate any overlays that are required

    octx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);

    for (var prop in props) {
        if (props.hasOwnProperty(prop)) {
            if (props[prop].active) {
                draw_prop(props[prop], octx, overlayCanvas);
            }
        }
    }

    if (FACEREC) {
        if (typeof(heads) !== 'undefined') {
            heads.forEach(function(head) {
                octx.save();
                // translate the context to the specific point where you want
                // to draw the boxes.
                draw_head_prop(current_prop, head, octx);
                if (FACE_BOX) {
                    draw_face_box(head);
                }

                octx.restore();
            });
        }
    }
}

function draw_prop(prop, ctx, canv) {
    // draw a static prop to the context

    canv_h = canv.height;
    canv_w = canv.width;

    prop_h = prop.img.height;
    prop_w = prop.img.width;

    prop.locs.forEach(function(loc) {
        // go through each location that the prop needs to be put and
        // then scale / place it appropriately.
        var sf = 1.0;
        if (typeof(loc.h) != "undefined") {
            //scale by height
            sf = (loc.h * canv_h) / prop_h;
        } else if (typof(loc.w) != "undefined") {
            // scale by width
            sf = (loc.w * canv_w) / prop_w;
        }

        var dw = prop.img.width * sf;
        var dh = prop.img.height * sf;
        var dx = (canv_w * loc.x) - (prop.origin.x * dw);
        var dy = (canv_h * loc.y) - (prop.origin.y * dh);

        //console.log(canv_h, prop.img.height, prop.img.height * sf, sf, dy, dh, (prop.origin.y * sf));
        ctx.drawImage(prop.img, dx, dy, dw, dh);
    });

}

function draw_head_prop(prop, head, ctx) {

    // given head and prop, add it to the overlay
    var sf = head.width / prop.ref.width; // determine scale factor based on head size
    var dw = prop.img.width * sf;
    var dh = prop.img.height * sf;
    var dx = head.x - (prop.origin.x * sf);
    var dy = head.y - (prop.origin.y * sf);
    ctx.drawImage(prop.img, dx, dy, dw, dh);

}

function draw_face_box(head) {
    // draws the boxes around the face etc
    // face box
    octx.strokeStyle = "rgba(210,50,240, 0.6)";
    octx.lineWidth = 2;
    octx.strokeRect(head.x, head.y, head.width, head.height);
    octx.fillStyle = "rgba(210, 50, 240, 0.3)";
    octx.fillRect(head.x, head.y, head.width, head.height);
}

function take_snapshot() {

    if (SNOW) {
        // we need to render an animation frame to make sure the frame buffer
        // is good then load it into an image and copy that to the canvas context
        animate();
        var img = new Image;
        img.src = renderer.domElement.toDataURL('image/png');;

        img.onload = function() {
            composite_canvases(img);
            update_image_list();
        };
    } else {
        composite_canvases();
        update_image_list();
    }
}

function composite_canvases(render_image) {
    // composites the images together as required
    // render image provided optionally
    outctx.drawImage(inputVideo, 0, 0);
    outctx.drawImage(overlayCanvas, 0, 0, 480, 360, 0, 0, 640, 480);

    if (SNOW) {
        outctx.drawImage(render_image, 0, 0, 480, 360, 0, 0, 640, 480);
    }

    data_uri = outputCanvas.toDataURL("image/jpeg", 1.0);
}

function initiate_video() {
    // sets up the video stream if we need it
    window.navigator.getUserMedia( {
        /**video: {
            width: 640, height: 480
        },**/
	video: true,
    },
    function(stream) {
	try {
            inputVideo.src = window.URL.createObjectURL(stream);
        } catch (err) {
            inputVideo.src = stream;
        }
        /**inputVideo.onloadedmetadata = function(e) {
            inputVideo.play();
        };**/
    },
    function(err) {
        console.log("couldn't initiate video stream");
        console.log(err);
    });

}

function photobooth_init() {
    // run this to initialise various callbacks etc.

    console.log("Setting up with, FACE REC: %s SNOW: %s", FACEREC, SNOW);

    var prop_holder = document.getElementById("prop-holder");
    // load the various images in.
    for (var prop in props) {
        if (props.hasOwnProperty(prop)) {

            var p = props[prop];
            p.img.src = p.file;

            p.onLoad = function(img) {
                // add any further handling in here

                var li = document.createElement("li");
                var i = document.createElement("img");
                i.setAttribute('onclick', 'toggle_prop("' + prop + '")');
                i.setAttribute('src', img.src);
                i.setAttribute('class', 'off');
                i.setAttribute('id', prop);

                li.appendChild(i);
                prop_holder.appendChild(li);
            }(p.img);
        }
    }

    // add the status update callback for when we get messages to display them
    messaging.status_notifier(status_update);

	inputVideo = document.getElementById('inputVideo');

	animationCanvas = document.getElementById('animationCanvas');

	overlayCanvas = document.getElementById('overlayCanvas');
	octx = overlayCanvas.getContext('2d');

	outputCanvas = document.getElementById('outputCanvas');
	outctx = outputCanvas.getContext('2d');

	// set the output to be flipped (this makes output like a mirror)
	outctx.translate(outputCanvas.width, 0);
	outctx.scale(-1, 1);

    if (FACEREC) {

        faces = new tracking.ObjectTracker(['face']);
        faces.setInitialScale(4);
        faces.setStepSize(2);
        faces.setEdgesDensity(0.1);

        faces.on('track', function(event) {
            if (event.data.length === 0) {
                // No objects were detected in this frame.
            } else {
                heads = event.data;
            }
        });

        tracking.track(inputVideo, faces, { camera: true });
    } else {
        initiate_video();
    }

	// start up the particle system if needed.
    if (SNOW) {
	    three_init();
    }

    // start any animation sequences that are needed
	animate();

}

<commit_msg>removed presents from default<commit_after>var inputVideo, animationCanvas, overlayCanvas, octx, outputCanvas, outctx;
var faces, heads;

var SNOW = false;  // turn on particle system
var FACEREC = false; // turn on face detection
var FACE_BOX = false; // turn on face boxes

var propdir = "/static/img/"

// locs is an array of locations to put clones of the image
// each element in array is an object that provides an x and y location
// to move it to that is a proportion of the container size and either a
// reference height or width to scale things according to the container size
// eg a height of 0.25 would mean 0.25 x container height which would be
// determined and then the actual height of the asset scaled accordingly.
var props = {
    tree: {
        active: false,
        file: propdir + "tree.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 1.0
        },
        locs: [
            {
                x: 0.5, y: 1.0,
                h: 0.65,
            },
        ],
    },
    mistletoe: {
        active: false,
        file: propdir + "mistletoe.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.0,
        },
        locs: [
            {
                x: 0.5, y: 0.0,
                h: 0.25,
            },
        ],
    },
    sleigh: {
        active: false,
        file: propdir + "sleigh.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.85
        },
        locs: [
            {
                x: 0.5, y: 1.0,
                h: 0.75,
            },
        ],
    },
    present: {
        active: false,
        file: propdir + "present.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.95
        },
        locs: [
            {
                x: 0.35, y: 1.0,
                h: 0.15,
            },
            {
                x: 0.65, y: 1.0,
                h: 0.10,
            },
            {
                x: 0.58, y: 1.0,
                h: 0.08,
            },
        ],
    },
     wreath: {
        active: false,
        file: propdir + "wreath.svg",
        img: new Image(),
        origin: {
            x: 0.5, y: 0.5,
        },
        locs: [
            {
                x: 0.5, y: 0.5,
                h: 0.90,
            },
        ],
    },
};

var current_prop = props.wreath;
//var current_prop = props.tree;

function animate() {
    // do the relevant animation steps if needed.

    requestAnimationFrame( animate );

    overlays();

    if (SNOW) {
        particle_animator();
        renderer.render( scene, camera );
    }

}

function overlays() {
    // generate any overlays that are required

    octx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);

    for (var prop in props) {
        if (props.hasOwnProperty(prop)) {
            if (props[prop].active) {
                draw_prop(props[prop], octx, overlayCanvas);
            }
        }
    }

    if (FACEREC) {
        if (typeof(heads) !== 'undefined') {
            heads.forEach(function(head) {
                octx.save();
                // translate the context to the specific point where you want
                // to draw the boxes.
                draw_head_prop(current_prop, head, octx);
                if (FACE_BOX) {
                    draw_face_box(head);
                }

                octx.restore();
            });
        }
    }
}

function draw_prop(prop, ctx, canv) {
    // draw a static prop to the context

    canv_h = canv.height;
    canv_w = canv.width;

    prop_h = prop.img.height;
    prop_w = prop.img.width;

    prop.locs.forEach(function(loc) {
        // go through each location that the prop needs to be put and
        // then scale / place it appropriately.
        var sf = 1.0;
        if (typeof(loc.h) != "undefined") {
            //scale by height
            sf = (loc.h * canv_h) / prop_h;
        } else if (typof(loc.w) != "undefined") {
            // scale by width
            sf = (loc.w * canv_w) / prop_w;
        }

        var dw = prop.img.width * sf;
        var dh = prop.img.height * sf;
        var dx = (canv_w * loc.x) - (prop.origin.x * dw);
        var dy = (canv_h * loc.y) - (prop.origin.y * dh);

        //console.log(canv_h, prop.img.height, prop.img.height * sf, sf, dy, dh, (prop.origin.y * sf));
        ctx.drawImage(prop.img, dx, dy, dw, dh);
    });

}

function draw_head_prop(prop, head, ctx) {

    // given head and prop, add it to the overlay
    var sf = head.width / prop.ref.width; // determine scale factor based on head size
    var dw = prop.img.width * sf;
    var dh = prop.img.height * sf;
    var dx = head.x - (prop.origin.x * sf);
    var dy = head.y - (prop.origin.y * sf);
    ctx.drawImage(prop.img, dx, dy, dw, dh);

}

function draw_face_box(head) {
    // draws the boxes around the face etc
    // face box
    octx.strokeStyle = "rgba(210,50,240, 0.6)";
    octx.lineWidth = 2;
    octx.strokeRect(head.x, head.y, head.width, head.height);
    octx.fillStyle = "rgba(210, 50, 240, 0.3)";
    octx.fillRect(head.x, head.y, head.width, head.height);
}

function take_snapshot() {

    if (SNOW) {
        // we need to render an animation frame to make sure the frame buffer
        // is good then load it into an image and copy that to the canvas context
        animate();
        var img = new Image;
        img.src = renderer.domElement.toDataURL('image/png');;

        img.onload = function() {
            composite_canvases(img);
            update_image_list();
        };
    } else {
        composite_canvases();
        update_image_list();
    }
}

function composite_canvases(render_image) {
    // composites the images together as required
    // render image provided optionally
    outctx.drawImage(inputVideo, 0, 0);
    outctx.drawImage(overlayCanvas, 0, 0, 480, 360, 0, 0, 640, 480);

    if (SNOW) {
        outctx.drawImage(render_image, 0, 0, 480, 360, 0, 0, 640, 480);
    }

    data_uri = outputCanvas.toDataURL("image/jpeg", 1.0);
}

function initiate_video() {
    // sets up the video stream if we need it
    window.navigator.getUserMedia( {
        /**video: {
            width: 640, height: 480
        },**/
	video: true,
    },
    function(stream) {
	try {
            inputVideo.src = window.URL.createObjectURL(stream);
        } catch (err) {
            inputVideo.src = stream;
        }
        /**inputVideo.onloadedmetadata = function(e) {
            inputVideo.play();
        };**/
    },
    function(err) {
        console.log("couldn't initiate video stream");
        console.log(err);
    });

}

function photobooth_init() {
    // run this to initialise various callbacks etc.

    console.log("Setting up with, FACE REC: %s SNOW: %s", FACEREC, SNOW);

    var prop_holder = document.getElementById("prop-holder");
    // load the various images in.
    for (var prop in props) {
        if (props.hasOwnProperty(prop)) {

            var p = props[prop];
            p.img.src = p.file;

            p.onLoad = function(img) {
                // add any further handling in here

                var li = document.createElement("li");
                var i = document.createElement("img");
                i.setAttribute('onclick', 'toggle_prop("' + prop + '")');
                i.setAttribute('src', img.src);
                i.setAttribute('class', 'off');
                i.setAttribute('id', prop);

                li.appendChild(i);
                prop_holder.appendChild(li);
            }(p.img);
        }
    }

    // add the status update callback for when we get messages to display them
    messaging.status_notifier(status_update);

	inputVideo = document.getElementById('inputVideo');

	animationCanvas = document.getElementById('animationCanvas');

	overlayCanvas = document.getElementById('overlayCanvas');
	octx = overlayCanvas.getContext('2d');

	outputCanvas = document.getElementById('outputCanvas');
	outctx = outputCanvas.getContext('2d');

	// set the output to be flipped (this makes output like a mirror)
	outctx.translate(outputCanvas.width, 0);
	outctx.scale(-1, 1);

    if (FACEREC) {

        faces = new tracking.ObjectTracker(['face']);
        faces.setInitialScale(4);
        faces.setStepSize(2);
        faces.setEdgesDensity(0.1);

        faces.on('track', function(event) {
            if (event.data.length === 0) {
                // No objects were detected in this frame.
            } else {
                heads = event.data;
            }
        });

        tracking.track(inputVideo, faces, { camera: true });
    } else {
        initiate_video();
    }

	// start up the particle system if needed.
    if (SNOW) {
	    three_init();
    }

    // start any animation sequences that are needed
	animate();

}

<|endoftext|>