You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2017/11/24 16:35:24 UTC

[1/3] openmeetings git commit: [OPENMEETINGS-1771] minified files are removed from source tree

Repository: openmeetings
Updated Branches:
  refs/heads/4.0.x f25da38fb -> ae1b51a99


http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/Chat.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/Chat.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/Chat.java
index d875a31..6b9c3fe 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/Chat.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/Chat.java
@@ -56,7 +56,6 @@ import org.apache.openmeetings.web.common.ConfirmableAjaxBorder;
 import org.apache.openmeetings.web.common.MainPanel;
 import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.head.CssHeaderItem;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
@@ -65,9 +64,7 @@ import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.form.HiddenField;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.Model;
-import org.apache.wicket.request.resource.CssResourceReference;
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
-import org.apache.wicket.request.resource.ResourceReference;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
 
@@ -78,8 +75,6 @@ import com.googlecode.wicket.jquery.ui.plugins.wysiwyg.WysiwygEditor;
 public class Chat extends Panel {
 	private static final long serialVersionUID = 1L;
 	private static final Logger log = Red5LoggerFactory.getLogger(Chat.class, getWebAppRootKey());
-	public static final ResourceReference EMOTIONS_JS_REFERENCE = new JavaScriptResourceReference(Chat.class, "cssemoticons.js");
-	public static final ResourceReference EMOTIONS_CSS_REFERENCE = new CssResourceReference(Chat.class, "cssemoticons.css");
 	private static final String PARAM_MSG_ID = "msgid";
 	private static final String PARAM_ROOM_ID = "roomid";
 	private static final String PARAM_TYPE = "type";
@@ -156,9 +151,7 @@ public class Chat extends Panel {
 	@Override
 	public void renderHead(IHeaderResponse response) {
 		super.renderHead(response);
-		response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(EMOTIONS_JS_REFERENCE)));
 		response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(Chat.class, "chat.js"))));
-		response.render(CssHeaderItem.forReference(EMOTIONS_CSS_REFERENCE));
 		response.render(new PriorityHeaderItem(getNamedFunction("chatActivity", chatActivity, explicit(PARAM_TYPE), explicit(PARAM_ROOM_ID), explicit(PARAM_MSG_ID))));
 
 		if (showDashboardChat) {

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat-base.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat-base.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat-base.js
new file mode 100644
index 0000000..67665f4
--- /dev/null
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat-base.js
@@ -0,0 +1,373 @@
+/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
+var Chat = function() {
+	const align = Settings.isRtl ? 'align-right' : 'align-left'
+		, alignIco = Settings.isRtl ? 'align-left' : 'align-right'
+		, tabTemplate = "<li><a href='#{href}'>#{label}</a></li>"
+		, msgTemplate = "<div class='clear msg-row' id='chat-msg-id-#{id}'><img class='profile " + align + "' src='#{imgSrc}'/><span class='from " + align + "' data-user-id='#{userId}'>#{from}</span><span class='" + align + "'>#{msg}</span><span class='date " + alignIco + "'>#{sent}</span></div>"
+		, acceptTemplate = "<div class='tick om-icon " + alignIco + " clickable' data-msgid='#{msgid}' data-roomid='#{roomid}' onclick='const e=$(this);chatActivity('accept',e.data(\"roomid\"),e.data(\"msgid\"));e.parent().remove();'></div>"
+		, infoTemplate = "<div class='user om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);showUserInfo(e.data(\"userId\"));'></div>"
+		, addTemplate = "<div class='add om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);addContact(e.data(\"userId\"));'></div>"
+		, messageTemplate = "<div class='new-email om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);privateMessage(e.data(\"userId\"));'></div>"
+		, inviteTemplate = "<div class='invite om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);inviteUser(e.data(\"userId\"));'></div>"
+		, closeBlock = "<span class='ui-icon ui-icon-close' role='presentation'></span>"
+		, closedSize = 20
+		, closedSizePx = closedSize + "px"
+		, emoticon = new CSSEmoticon()
+		, doneTypingInterval = 5000 //time in ms, 5 second for example
+		, iconOpen = 'ui-icon-caret-1-n'
+		, iconOpenRoom = 'ui-icon-caret-1-' + (Settings.isRtl ? 'e' : 'w')
+		, iconClose = 'ui-icon-caret-1-s'
+		, iconCloseRoom = 'ui-icon-caret-1-' + (Settings.isRtl ? 'w' : 'e')
+		;
+	let p, pp, ctrl, icon, tabs, openedHeight = "345px", openedWidth = "300px", allPrefix = "All"
+		, roomPrefix = "Room ", typingTimer, audio, roomMode = false, globalWidth = 600
+		, editor = $('#chatMessage .wysiwyg-editor')
+		;
+
+	try {
+		audio = new Audio('./public/chat_message.mp3');
+	} catch (e) {
+		//not implemented in IE
+		audio = {
+			play: function() {}
+		};
+	}
+	function _load() {
+		const s = Settings.load();
+		if (typeof(s.chat) === 'undefined') {
+			s.chat = {};
+		}
+		return s;
+	}
+	function _updateBtn(s, a) {
+		const muted = s.chat.muted === true;
+		a.removeClass('sound' + (muted ? '' : '-mute')).addClass('sound' + (muted ? '-mute' : ''))
+				.attr('title', a.data(muted ? 'sound-enabled' : 'sound-muted'));
+	}
+	function doneTyping () {
+		typingTimer = null;
+		chatActivity('typing_stop', $('.room.box').data('room-id'));
+	}
+	function initToolbar() {
+		const emtBtn = $('#emoticons');
+		emtBtn.html('');
+		emtBtn.append(' ' + emoticon.emoticonize(':)') + ' <b class="caret"></b>');
+		const emots = [].concat.apply([], [emoticon.threeCharEmoticons, emoticon.twoCharEmoticons]);
+		for (let ei in emoticon.specialEmoticons) {
+			emots.push(ei);
+		}
+		const rowSize = 20, emotMenuList = $('#emotMenuList');
+		emotMenuList.html('');
+		let row = $('<tr></tr>');
+		for (let i = 0; i < emots.length; ++i) {
+			row.append('<td><div class="emt" onclick="Chat.emtClick(\'' + emots[i] + '\');">'
+				+ emoticon.emoticonize(emots[i]) + '</div></td>');
+			if (i !== 0 && i % rowSize === 0) {
+				emotMenuList.append(row);
+				row = $('<tr></tr>');
+			}
+		}
+		const a = $('#chat .audio');
+		_updateBtn(_load(), a);
+		$('#chat .chat-btn').hover(function(){ $(this).addClass('ui-state-hover') }, function(){ $(this).removeClass('ui-state-hover') });
+		a.off().click(function() {
+			const s = _load();
+			s.chat.muted = !s.chat.muted;
+			_updateBtn(s, a);
+			Settings.save(s);
+		});
+	}
+	function isClosed() {
+		return p.hasClass('closed');
+	}
+	function activateTab(id) {
+		tabs.tabs("option", "active", tabs.find('a[href="#' + id + '"]').parent().index());
+	}
+	function isInited() {
+		return !!$("#chatTabs").data("ui-tabs");
+	}
+	function _reinit(_allPrefix, _roomPrefix) {
+		allPrefix = _allPrefix;
+		roomPrefix = _roomPrefix;
+		p = $('#chatPanel');
+		pp = $('#chatPanel, #chatPopup');
+		ctrl = $('#chatPopup .control.block');
+		icon = $('#chatPopup .control.block .ui-icon');
+		editor = $('#chatMessage .wysiwyg-editor');
+		icon.removeClass(function(index, className) {
+			return (className.match (/(^|\s)ui-icon-caret-\S+/g) || []).join(' ');
+		});
+		initToolbar();
+		tabs = $("#chatTabs").tabs({
+			activate: function(event, ui) {
+				$('#activeChatTab').val(ui.newPanel[0].id);
+			}
+		});
+		// close icon: removing the tab on click
+		tabs.delegate("span.ui-icon-close", "click", function() {
+			const panelId = $(this).closest("li").remove().attr("aria-controls");
+			$("#" + panelId).remove();
+			tabs.tabs("refresh");
+		});
+		if (roomMode) {
+			icon.addClass(isClosed() ? iconOpenRoom : iconCloseRoom);
+			p.addClass('room').hover(_open, _close);
+			pp.width(closedSize);
+			_removeResize();
+		} else {
+			ctrl.attr('title', '');
+			icon.addClass(isClosed() ? iconOpen : iconClose);
+			ctrl.height(closedSize).width(globalWidth).off('click').click(Chat.toggle);
+			pp.width(globalWidth).height(closedSize);
+			p.removeClass('room opened').addClass('closed')
+				.off('mouseenter mouseleave')
+				.resizable({
+					handles: 'n, ' + (Settings.isRtl ? 'w' : 'e')
+					, disabled: isClosed()
+					, alsoResize: "#chatPopup, #chat .ui-tabs .ui-tabs-panel.messageArea"
+					, minHeight: 195
+					, minWidth: 260
+					, stop: function(event, ui) {
+						p.css({'top': '', 'left': ''});
+						openedHeight = ui.size.height + "px";
+						globalWidth = ui.size.width;
+					}
+				});
+		}
+		$('#chatMessage').off().on('input propertychange paste', function () {
+			const room = $('.room.box');
+			if (room.length) {
+				if (!!typingTimer) {
+					clearTimeout(typingTimer);
+				} else {
+					chatActivity('typing_start', room.data('room-id'));
+				}
+				typingTimer = setTimeout(doneTyping, doneTypingInterval);
+			}
+		});
+	}
+	function _removeTab(id) {
+		$('#chat li[aria-controls="' + id + '"]').remove();
+		$('#' + id).remove();
+		if (isInited()) {
+			tabs.tabs("refresh");
+		}
+	}
+	function _addTab(id, label) {
+		if (!isInited()) {
+			_reinit();
+		}
+		if ($('#chat').length < 1 || $('#' + id).length) {
+			return;
+		}
+		if (!label) {
+			label = id === "chatTab-all" ? allPrefix : roomPrefix + id.substr(9);
+		}
+		const li = $(tabTemplate.replace(/#\{href\}/g, "#" + id).replace(/#\{label\}/g, label));
+		if (id.indexOf("chatTab-r") !== 0) {
+			li.append(closeBlock);
+		}
+		tabs.find(".ui-tabs-nav").append(li);
+		tabs.append("<div class='messageArea' id='" + id + "'></div>");
+		tabs.tabs("refresh");
+		activateTab(id);
+	}
+	function _addMessage(m) {
+		if ($('#chat').length > 0 && m && m.type === "chat") {
+			if (isClosed()) {
+				ctrl.addClass('ui-state-highlight');
+				const s = _load();
+				if (p.is(':visible') && s.chat.muted !== true) {
+					const playPromise = audio.play();
+
+					// In browsers that don’t yet support this functionality,
+					// playPromise won’t be defined.
+					if (playPromise !== undefined) {
+						playPromise.then(function() {
+							// Automatic playback started!
+						}).catch(function() {
+							// Automatic playback failed.
+						});
+					}
+				}
+			}
+			let msg, cm;
+			while (!!(cm = m.msg.pop())) {
+				let area = $('#' + cm.scope);
+				msg = $(msgTemplate.replace(/#\{id\}/g, cm.id)
+						.replace(/#\{userId\}/g, cm.from.id)
+						.replace(/#\{imgSrc\}/g, !!cm.from.img ? cm.from.img : './profile/' + cm.from.id + '?anticache=' + Date.now())
+						.replace(/#\{from\}/g, cm.from.name)
+						.replace(/#\{sent\}/g, cm.sent)
+						.replace(/#\{msg\}/g, emoticon.emoticonize(!!cm.message ? cm.message : "")));
+				const date = msg.children('.date');
+				date.after(infoTemplate.replace(/#\{userId\}/g, cm.from.id));
+				if ("full" === cm.actions) {
+					date.after(addTemplate.replace(/#\{userId\}/g, cm.from.id));
+					date.after(messageTemplate.replace(/#\{userId\}/g, cm.from.id));
+					date.after(inviteTemplate.replace(/#\{userId\}/g, cm.from.id));
+				}
+				if (cm.needModeration) {
+					msg.append(acceptTemplate.replace(/#\{msgid\}/g, cm.id).replace(/#\{roomid\}/g, cm.scope.substring(9)));
+				}
+				if (!area.length) {
+					_addTab(cm.scope, cm.scopeName);
+					area = $('#' + cm.scope);
+				}
+				if (m.mode === "accept") {
+					$('#chat-msg-id-' + cm.id).remove();
+				}
+				const btm = area.scrollTop() + area.innerHeight() >= area[0].scrollHeight;
+				area.append(msg);
+				if (btm) {
+					area.animate({
+						scrollTop: area[0].scrollHeight
+					}, 300);
+				}
+			}
+		}
+	}
+	function _setOpened() {
+		p.addClass('opened').off('mouseenter mouseleave');
+		p.resizable({
+			handles: (Settings.isRtl ? 'e' : 'w')
+			, alsoResize: '#chatPopup'
+			, stop: function(event, ui) {
+				p.css({'left': ''});
+				openedWidth = ui.size.width + 'px';
+			}
+		});
+		Room.setSize();
+	}
+	function _removeResize() {
+		if (p.resizable('instance') !== undefined) {
+			p.resizable('destroy');
+		}
+	}
+	function _open(handler) {
+		if (isClosed()) {
+			icon.removeClass(roomMode ? iconOpenRoom : iconOpen).addClass(roomMode ? iconCloseRoom : iconClose);
+			ctrl.removeClass('ui-state-highlight');
+			let opts;
+			if (roomMode) {
+				opts = {width: openedWidth};
+				ctrl.height(closedSize);
+			} else {
+				opts = {height: openedHeight};
+				p.resizable("option", "disabled", false);
+			}
+			p.removeClass('closed');
+			pp.animate(opts, 1000, function() {
+				p.removeClass('closed');
+				$('#chat .ui-tabs .ui-tabs-panel.messageArea').height(p.height() - closedSize - $('#chat .ui-tabs-nav').height() - $('#chat form').height() - 5);
+				$('#chat .messageArea').each(function() {
+					$(this).scrollTop($(this)[0].scrollHeight);
+				});
+				if (typeof(handler) === 'function') {
+					handler();
+				}
+				if (roomMode) {
+					ctrl.off('click').click(function() {
+						if (p.hasClass('opened')) {
+							ctrl.attr('title', ctrl.data('ttl-dock'));
+							_close(Room.setSize);
+							p.removeClass('opened').hover(_open, _close);
+							_removeResize();
+						} else {
+							ctrl.attr('title', ctrl.data('ttl-undock'));
+							_setOpened();
+						}
+					}).attr('title', ctrl.data('ttl-dock'));
+				}
+			});
+		}
+	}
+	function _close(handler) {
+		if (!isClosed()) {
+			icon.removeClass(roomMode ? iconCloseRoom : iconClose).addClass(roomMode ? iconOpenRoom : iconOpen);
+			let opts;
+			if (roomMode) {
+				opts = {width: closedSizePx};
+				ctrl.off('click');
+			} else {
+				opts = {height: closedSizePx};
+				p.resizable("option", "disabled", true);
+			}
+			pp.animate(opts, 1000, function() {
+				p.addClass('closed');
+				if (roomMode) {
+					ctrl.height(p.height());
+				}
+				if (typeof(handler) === 'function') {
+					handler();
+				}
+			});
+		}
+	}
+	function _toggle() {
+		if (isClosed()) {
+			_open();
+		} else {
+			_close();
+		}
+	}
+	function _emtClick(emoticon) {
+		editor.html(editor.html() + ' ' + emoticon + ' ').trigger('change');
+	}
+	function _clean() {
+		editor.html('').trigger('change');
+	}
+	function _setRoomMode(_mode) {
+		roomMode = _mode;
+		_reinit(allPrefix, roomPrefix);
+	}
+	function _setHeight(h) {
+		pp.height(h);
+		if (isClosed()) {
+			ctrl.height(h);
+		}
+	}
+
+	return {
+		reinit: _reinit
+		, removeTab: _removeTab
+		, addTab: _addTab
+		, addMessage: _addMessage
+		, open: _open
+		, setOpened: function() {
+			_open(function() {
+				_setOpened();
+			});
+		}
+		, close: _close
+		, toggle: _toggle
+		, emtClick: _emtClick
+		, setRoomMode: _setRoomMode
+		, setHeight: _setHeight
+		, clean: _clean
+	};
+}();
+$(function() {
+	Wicket.Event.subscribe("/websocket/message", function(jqEvent, msg) {
+		try {
+			if (msg instanceof Blob) {
+				return; //ping
+			}
+			const m = jQuery.parseJSON(msg);
+			if (m) {
+				switch(m.type) {
+					case "chat":
+						Chat.addMessage(m);
+						break;
+					case "typing":
+						if (typeof(typingActivity) === "function") {
+							typingActivity(m.uid, m.active);
+						}
+						break;
+				}
+			}
+		} catch (err) {
+			//no-op
+		}
+	});
+});

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat.js
deleted file mode 100644
index cc66752..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/chat.js
+++ /dev/null
@@ -1,374 +0,0 @@
-/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
-var Chat = function() {
-	const align = Settings.isRtl ? 'align-right' : 'align-left'
-		, alignIco = Settings.isRtl ? 'align-left' : 'align-right'
-		, tabTemplate = "<li><a href='#{href}'>#{label}</a></li>"
-		, msgTemplate = "<div class='clear msg-row' id='chat-msg-id-#{id}'><img class='profile " + align + "' src='#{imgSrc}'/><span class='from " + align + "' data-user-id='#{userId}'>#{from}</span><span class='" + align + "'>#{msg}</span><span class='date " + alignIco + "'>#{sent}</span></div>"
-		, acceptTemplate = "<div class='tick om-icon " + alignIco + " clickable' data-msgid='#{msgid}' data-roomid='#{roomid}' onclick='const e=$(this);chatActivity('accept',e.data(\"roomid\"),e.data(\"msgid\"));e.parent().remove();'></div>"
-		, infoTemplate = "<div class='user om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);showUserInfo(e.data(\"userId\"));'></div>"
-		, addTemplate = "<div class='add om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);addContact(e.data(\"userId\"));'></div>"
-		, messageTemplate = "<div class='new-email om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);privateMessage(e.data(\"userId\"));'></div>"
-		, inviteTemplate = "<div class='invite om-icon " + alignIco + " clickable' data-user-id='#{userId}' onclick='const e=$(this);inviteUser(e.data(\"userId\"));'></div>"
-		, closeBlock = "<span class='ui-icon ui-icon-close' role='presentation'></span>"
-		, closedSize = 20
-		, closedSizePx = closedSize + "px"
-		, emoticon = new CSSEmoticon()
-		, doneTypingInterval = 5000 //time in ms, 5 second for example
-		, iconOpen = 'ui-icon-caret-1-n'
-		, iconOpenRoom = 'ui-icon-caret-1-' + (Settings.isRtl ? 'e' : 'w')
-		, iconClose = 'ui-icon-caret-1-s'
-		, iconCloseRoom = 'ui-icon-caret-1-' + (Settings.isRtl ? 'w' : 'e')
-		;
-	let p, pp, ctrl, icon, tabs, openedHeight = "345px", openedWidth = "300px", allPrefix = "All"
-		, roomPrefix = "Room ", typingTimer, audio, roomMode = false, globalWidth = 600
-		, editor = $('#chatMessage .wysiwyg-editor')
-		;
-
-	try {
-		audio = new Audio('./public/chat_message.mp3');
-	} catch (e) {
-		//not implemented in IE
-		audio = {
-			play: function() {}
-		};
-	}
-	function _load() {
-		const s = Settings.load();
-		if (typeof(s.chat) === 'undefined') {
-			s.chat = {};
-		}
-		return s;
-	}
-	function _updateBtn(s, a) {
-		const muted = s.chat.muted === true;
-		a.removeClass('sound' + (muted ? '' : '-mute')).addClass('sound' + (muted ? '-mute' : ''))
-				.attr('title', a.data(muted ? 'sound-enabled' : 'sound-muted'));
-	}
-	function doneTyping () {
-		typingTimer = null;
-		chatActivity('typing_stop', $('.room.box').data('room-id'));
-	}
-	function initToolbar() {
-		const emtBtn = $('#emoticons');
-		emtBtn.html('');
-		emtBtn.append(' ' + emoticon.emoticonize(':)') + ' <b class="caret"></b>');
-		const emots = [].concat.apply([], [emoticon.threeCharEmoticons, emoticon.twoCharEmoticons]);
-		for (let ei in emoticon.specialEmoticons) {
-			emots.push(ei);
-		}
-		const rowSize = 20, emotMenuList = $('#emotMenuList');
-		emotMenuList.html('');
-		let row = $('<tr></tr>');
-		for (let i = 0; i < emots.length; ++i) {
-			row.append('<td><div class="emt" onclick="Chat.emtClick(\'' + emots[i] + '\');">'
-				+ emoticon.emoticonize(emots[i]) + '</div></td>');
-			if (i !== 0 && i % rowSize === 0) {
-				emotMenuList.append(row);
-				row = $('<tr></tr>');
-			}
-		}
-		const a = $('#chat .audio');
-		_updateBtn(_load(), a);
-		$('#chat .chat-btn').hover(function(){ $(this).addClass('ui-state-hover') }, function(){ $(this).removeClass('ui-state-hover') });
-		a.off().click(function() {
-			const s = _load();
-			s.chat.muted = !s.chat.muted;
-			_updateBtn(s, a);
-			Settings.save(s);
-		});
-	}
-	function isClosed() {
-		return p.hasClass('closed');
-	}
-	function activateTab(id) {
-		tabs.tabs("option", "active", tabs.find('a[href="#' + id + '"]').parent().index());
-	}
-	function isInited() {
-		return !!$("#chatTabs").data("ui-tabs");
-	}
-	function _reinit(_allPrefix, _roomPrefix) {
-		allPrefix = _allPrefix;
-		roomPrefix = _roomPrefix;
-		p = $('#chatPanel');
-		pp = $('#chatPanel, #chatPopup');
-		ctrl = $('#chatPopup .control.block');
-		icon = $('#chatPopup .control.block .ui-icon');
-		editor = $('#chatMessage .wysiwyg-editor');
-		icon.removeClass(function(index, className) {
-			return (className.match (/(^|\s)ui-icon-caret-\S+/g) || []).join(' ');
-		});
-		initToolbar();
-		tabs = $("#chatTabs").tabs({
-			activate: function(event, ui) {
-				$('#activeChatTab').val(ui.newPanel[0].id);
-			}
-		});
-		// close icon: removing the tab on click
-		tabs.delegate("span.ui-icon-close", "click", function() {
-			const panelId = $(this).closest("li").remove().attr("aria-controls");
-			$("#" + panelId).remove();
-			tabs.tabs("refresh");
-		});
-		if (roomMode) {
-			icon.addClass(isClosed() ? iconOpenRoom : iconCloseRoom);
-			p.addClass('room').hover(_open, _close);
-			pp.width(closedSize);
-			_removeResize();
-		} else {
-			ctrl.attr('title', '');
-			icon.addClass(isClosed() ? iconOpen : iconClose);
-			ctrl.height(closedSize).width(globalWidth).off('click').click(Chat.toggle);
-			pp.width(globalWidth).height(closedSize);
-			p.removeClass('room opened').addClass('closed')
-				.off('mouseenter mouseleave')
-				.resizable({
-					handles: 'n, ' + (Settings.isRtl ? 'w' : 'e')
-					, disabled: isClosed()
-					, alsoResize: "#chatPopup, #chat .ui-tabs .ui-tabs-panel.messageArea"
-					, minHeight: 195
-					, minWidth: 260
-					, stop: function(event, ui) {
-						p.css({'top': '', 'left': ''});
-						openedHeight = ui.size.height + "px";
-						globalWidth = ui.size.width;
-					}
-				});
-		}
-		$('#chatMessage').off().on('input propertychange paste', function () {
-			const room = $('.room.box');
-			if (room.length) {
-				if (!!typingTimer) {
-					clearTimeout(typingTimer);
-				} else {
-					chatActivity('typing_start', room.data('room-id'));
-				}
-				typingTimer = setTimeout(doneTyping, doneTypingInterval);
-			}
-		});
-	}
-	function _removeTab(id) {
-		$('#chat li[aria-controls="' + id + '"]').remove();
-		$('#' + id).remove();
-		if (isInited()) {
-			tabs.tabs("refresh");
-		}
-	}
-	function _addTab(id, label) {
-		if (!isInited()) {
-			_reinit();
-		}
-		if ($('#chat').length < 1 || $('#' + id).length) {
-			return;
-		}
-		if (!label) {
-			label = id === "chatTab-all" ? allPrefix : roomPrefix + id.substr(9);
-		}
-		const li = $(tabTemplate.replace(/#\{href\}/g, "#" + id).replace(/#\{label\}/g, label));
-		if (id.indexOf("chatTab-r") !== 0) {
-			li.append(closeBlock);
-		}
-		tabs.find(".ui-tabs-nav").append(li);
-		tabs.append("<div class='messageArea' id='" + id + "'></div>");
-		tabs.tabs("refresh");
-		activateTab(id);
-	}
-	function _addMessage(m) {
-		if ($('#chat').length > 0 && m && m.type === "chat") {
-			if (isClosed()) {
-				ctrl.addClass('ui-state-highlight');
-				const s = _load();
-				if (p.is(':visible') && s.chat.muted !== true) {
-					const playPromise = audio.play();
-
-					// In browsers that don’t yet support this functionality,
-					// playPromise won’t be defined.
-					if (playPromise !== undefined) {
-						playPromise.then(function() {
-							// Automatic playback started!
-						}).catch(function() {
-							// Automatic playback failed.
-						});
-					}
-				}
-			}
-			let msg, cm;
-			while (!!(cm = m.msg.pop())) {
-				let area = $('#' + cm.scope);
-				msg = $(msgTemplate.replace(/#\{id\}/g, cm.id)
-						.replace(/#\{userId\}/g, cm.from.id)
-						.replace(/#\{imgSrc\}/g, !!cm.from.img ? cm.from.img : './profile/' + cm.from.id + '?anticache=' + Date.now())
-						.replace(/#\{from\}/g, cm.from.name)
-						.replace(/#\{sent\}/g, cm.sent)
-						.replace(/#\{msg\}/g, emoticon.emoticonize(!!cm.message ? cm.message : "")));
-				const date = msg.children('.date');
-				date.after(infoTemplate.replace(/#\{userId\}/g, cm.from.id));
-				if ("full" === cm.actions) {
-					date.after(addTemplate.replace(/#\{userId\}/g, cm.from.id));
-					date.after(messageTemplate.replace(/#\{userId\}/g, cm.from.id));
-					date.after(inviteTemplate.replace(/#\{userId\}/g, cm.from.id));
-				}
-				if (cm.needModeration) {
-					msg.append(acceptTemplate.replace(/#\{msgid\}/g, cm.id).replace(/#\{roomid\}/g, cm.scope.substring(9)));
-				}
-				if (!area.length) {
-					_addTab(cm.scope, cm.scopeName);
-					area = $('#' + cm.scope);
-				}
-				if (m.mode === "accept") {
-					$('#chat-msg-id-' + cm.id).remove();
-				}
-				const btm = area.scrollTop() + area.innerHeight() >= area[0].scrollHeight;
-				area.append(msg);
-				if (btm) {
-					area.animate({
-						scrollTop: area[0].scrollHeight
-					}, 300);
-				}
-			}
-		}
-	}
-	function _setOpened() {
-		p.addClass('opened').off('mouseenter mouseleave');
-		p.resizable({
-			handles: (Settings.isRtl ? 'e' : 'w')
-			, alsoResize: '#chatPopup'
-			, stop: function(event, ui) {
-				p.css({'left': ''});
-				openedWidth = ui.size.width + 'px';
-			}
-		});
-		Room.setSize();
-	}
-	function _removeResize() {
-		if (p.resizable('instance') !== undefined) {
-			p.resizable('destroy');
-		}
-	}
-	function _open(handler) {
-		if (isClosed()) {
-			icon.removeClass(roomMode ? iconOpenRoom : iconOpen).addClass(roomMode ? iconCloseRoom : iconClose);
-			ctrl.removeClass('ui-state-highlight');
-			let opts;
-			if (roomMode) {
-				opts = {width: openedWidth};
-				ctrl.height(closedSize);
-			} else {
-				opts = {height: openedHeight};
-				p.resizable("option", "disabled", false);
-			}
-			p.removeClass('closed');
-			pp.animate(opts, 1000, function() {
-				p.removeClass('closed');
-				$('#chat .ui-tabs .ui-tabs-panel.messageArea').height(p.height() - closedSize - $('#chat .ui-tabs-nav').height() - $('#chat form').height() - 5);
-				$('#chat .messageArea').each(function() {
-					$(this).scrollTop($(this)[0].scrollHeight);
-				});
-				if (typeof(handler) === 'function') {
-					handler();
-				}
-				if (roomMode) {
-					ctrl.off('click').click(function() {
-						if (p.hasClass('opened')) {
-							ctrl.attr('title', ctrl.data('ttl-dock'));
-							_close(Room.setSize);
-							p.removeClass('opened').hover(_open, _close);
-							_removeResize();
-						} else {
-							ctrl.attr('title', ctrl.data('ttl-undock'));
-							_setOpened();
-						}
-					}).attr('title', ctrl.data('ttl-dock'));
-				}
-			});
-		}
-	}
-	function _close(handler) {
-		if (!isClosed()) {
-			icon.removeClass(roomMode ? iconCloseRoom : iconClose).addClass(roomMode ? iconOpenRoom : iconOpen);
-			let opts;
-			if (roomMode) {
-				opts = {width: closedSizePx};
-				ctrl.off('click');
-			} else {
-				opts = {height: closedSizePx};
-				p.resizable("option", "disabled", true);
-			}
-			pp.animate(opts, 1000, function() {
-				p.addClass('closed');
-				if (roomMode) {
-					ctrl.height(p.height());
-				}
-				if (typeof(handler) === 'function') {
-					handler();
-				}
-			});
-		}
-	}
-	function _toggle() {
-		if (isClosed()) {
-			_open();
-		} else {
-			_close();
-		}
-	}
-	function _emtClick(emoticon) {
-		editor.html(editor.html() + ' ' + emoticon + ' ').trigger('change');
-	}
-	function _clean() {
-		editor.html('').trigger('change');
-	}
-	function _setRoomMode(_mode) {
-		roomMode = _mode;
-		_reinit(allPrefix, roomPrefix);
-	}
-	function _setHeight(h) {
-		pp.height(h);
-		if (isClosed()) {
-			ctrl.height(h);
-		}
-	}
-
-	return {
-		reinit: _reinit
-		, removeTab: _removeTab
-		, addTab: _addTab
-		, addMessage: _addMessage
-		, open: _open
-		, setOpened: function() {
-			_open(function() {
-				_setOpened();
-			});
-		}
-		, close: _close
-		, toggle: _toggle
-		, emtClick: _emtClick
-		, setRoomMode: _setRoomMode
-		, setHeight: _setHeight
-		, clean: _clean
-	};
-}();
-
-$(function() {
-	Wicket.Event.subscribe("/websocket/message", function(jqEvent, msg) {
-		try {
-			if (msg instanceof Blob) {
-				return; //ping
-			}
-			const m = jQuery.parseJSON(msg);
-			if (m) {
-				switch(m.type) {
-					case "chat":
-						Chat.addMessage(m);
-						break;
-					case "typing":
-						if (typeof(typingActivity) === "function") {
-							typingActivity(m.uid, m.active);
-						}
-						break;
-				}
-			}
-		} catch (err) {
-			//no-op
-		}
-	});
-});

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.css
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.css b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.css
deleted file mode 100644
index c14765c..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.css
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * jQuery CSSEmoticons plugin 0.2.9
- *
- * Copyright (c) 2010 Steve Schwartz (JangoSteve)
- *
- * Dual licensed under the MIT and GPL licenses:
- *   http://www.opensource.org/licenses/mit-license.php
- *   http://www.gnu.org/licenses/gpl.html
- *
- * Date: Sun Oct 22 1:00:00 2010 -0500
- */
- 
- /* Basic styles for emoticons */
-span.css-emoticon {
-  font-family: "Trebuchet MS"; /* seems to give the best and most consistent emoticon appearance */
-  font-size: 0.65em;
-  font-weight: bold;
-  color: #000000;
-  display: inline-block;
-  overflow: hidden;
-  vertical-align: middle;
-  transform: rotate(90deg);
-  -webkit-transform: rotate(90deg);
-  -moz-transform: rotate(90deg);
-  -o-transform: rotate(90deg);
-  width: 1.54em; /* note that this is a multiple of this span's font-size, not containing text font-size */
-  height: 1.54em; /* so, relative to containing text, width and height are 0.9 x 1.6 = 1.44em */
-  text-align: center;
-  padding: 0;
-  line-height: 1.34em;
-  -moz-border-radius: 1.54em;
-  -webkit-border-radius: 1.54em;
-  border-radius: 1.54em;
-  -moz-box-shadow: 1px -1px 2px rgba(0,0,0,0.5);
-  -webkit-box-shadow: 1px -1px 2px rgba(0,0,0,0.5);
-  box-shadow: 1px -1px 2px rgba(0,0,0,0.5);
-  border: 1px solid rgba(0,0,0,0.25);
-  background-color: #ffcc00;
-  background-image: -webkit-gradient(
-    linear,
-    right top,
-    left top,
-    color-stop(0.41, rgb(255,204,0)),
-    color-stop(0.56, rgb(255,221,85)),
-    color-stop(1, rgb(255,238,170))
-  );
-  background-image: -moz-linear-gradient(
-    center right,
-    rgb(255,204,0) 41%,
-    rgb(255,221,85) 56%,
-    rgb(255,238,170) 100%
-  );
-  -webkit-transition-property:color, background, transform;  
-  -webkit-transition-duration: 1s, 1s;  
-  -webkit-transition-timing-function: linear, ease-in;
-}
-
-/* Styles for two-character emoticons that need more letter-spacing for proportionality */
-span.css-emoticon.spaced-emoticon {
-  padding-left: 0.2em;
-  width: 1.34em;
-  letter-spacing: 0.2em;
-}
-
-/* This is a dirty dirty hack, because webkit doesn't properly do the padding+width=total-width as it should
-   I think the width of the border may be throwing things off, because it's more noticable for small icons */
-@media screen and (-webkit-min-device-pixel-ratio:0) {
-  span.css-emoticon.spaced-emoticon {
-    width: 1.4em;
-  }
-}
-
-/* Styles for emoticons that need to have smaller characters to fit inside the circle */
-span.css-emoticon.small-emoticon {
-  font-size: 0.55em;
-  width: 1.82em;
-  height: 1.82em;
-  line-height: 1.72em;
-  -moz-border-radius: 1.82em;
-  -webkit-border-radius: 1.82em;
-  border-radius: 1.82em;
-}
-
-span.css-emoticon.small-emoticon.spaced-emoticon {
-  padding-left: 0;
-  width: 1.82em;
-  letter-spacing: 0.1em;
-}
-
-/* Styles for additional colors */
-span.css-emoticon.red-emoticon {
-  background-color: #eb0542;
-  background-image: -webkit-gradient(
-    linear,
-    right top,
-    left top,
-    color-stop(0.41, rgb(235,5,66)),
-    color-stop(0.56, rgb(235,38,90)),
-    color-stop(1, rgb(250,55,110))
-  );
-  background-image: -moz-linear-gradient(
-    center right,
-    rgb(235,5,66) 41%,
-    rgb(235,38,90) 56%,
-    rgb(250,55,110) 100%
-  );
-}
-
-span.css-emoticon.pink-emoticon {
-  background-color: #ff8fd4;
-  background-image: -webkit-gradient(
-    linear,
-    right top,
-    left top,
-    color-stop(0.41, rgb(255,143,212)),
-    color-stop(0.56, rgb(255,153,216)),
-    color-stop(1,    rgb(255,173,225))
-  );
-  background-image: -moz-linear-gradient(
-    center right,
-    rgb(255,143,212) 41%,
-    rgb(255,153,216) 56%,
-    rgb(255,173,225) 100%
-  );
-}
-
-/* styles for emoticons that need no rotation, like O_o */
-span.css-emoticon.no-rotate { 
-  transform: rotate(0deg);
-  -webkit-transform: rotate(0deg);
-  -moz-transform: rotate(0deg);
-  -o-transform: rotate(0deg);
-  -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.5);
-  -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.5);
-  box-shadow: 1px 1px 2px rgba(0,0,0,0.5);
-  font-size: 0.45em;
-  width: 2.2em;
-  height: 2.2em;
-  line-height: 1.9em;
-  -moz-border-radius: 2.2em;
-  -webkit-border-radius: 2.2em;
-  border-radius: 2.2em;
-  background-image: -webkit-gradient(
-    linear,
-    right bottom,
-    right top,
-    color-stop(0.41, rgb(255,204,0)),
-    color-stop(0.56, rgb(255,221,85)),
-    color-stop(1, rgb(255,238,170))
-  );
-  background-image: -moz-linear-gradient(
-    center bottom,
-    rgb(255,204,0) 41%,
-    rgb(255,221,85) 56%,
-    rgb(255,238,170) 100%
-  );
-}
-
-span.css-emoticon.no-rotate.red-emoticon {
-  background-image: -webkit-gradient(
-    linear,
-    right bottom,
-    right top,
-    color-stop(0.41, rgb(235,5,66)),
-    color-stop(0.56, rgb(235,38,90)),
-    color-stop(1, rgb(250,55,110))
-  );
-  background-image: -moz-linear-gradient(
-    center bottom,
-    rgb(235,5,66) 41%,
-    rgb(235,38,90) 56%,
-    rgb(250,55,110) 100%
-  );
-}
-
-span.css-emoticon.no-rotate.pink-emoticon {
-  background-image: -webkit-gradient(
-    linear,
-    right bottom,
-    right top,
-    color-stop(0.41, rgb(255,143,212)),
-    color-stop(0.56, rgb(255,153,216)),
-    color-stop(1,    rgb(255,173,225))
-  );
-  background-image: -moz-linear-gradient(
-    center bottom,
-    rgb(255,143,212) 41%,
-    rgb(255,153,216) 56%,
-    rgb(255,173,225) 100%
-  );
-}
-
-/* Styles for emoticons that need to be rotated counter-clockwise, like <3 */
-span.css-emoticon.counter-rotated { 
-  transform: rotate(-90deg);
-  -webkit-transform: rotate(-90deg);
-  -moz-transform: rotate(-90deg);
-  -o-transform: rotate(-90deg);
-  -moz-box-shadow: -1px 1px 2px rgba(0,0,0,0.5);
-  -webkit-box-shadow: -1px 1px 2px rgba(0,0,0,0.5);
-  box-shadow: -1px 1px 2px rgba(0,0,0,0.5);
-  background-image: -webkit-gradient(
-    linear,
-    left top,
-    right top,
-    color-stop(0.41, rgb(255,204,0)),
-    color-stop(0.56, rgb(255,221,85)),
-    color-stop(1, rgb(255,238,170))
-  );
-  background-image: -moz-linear-gradient(
-    center left,
-    rgb(255,204,0) 41%,
-    rgb(255,221,85) 56%,
-    rgb(255,238,170) 100%
-  );
-}
-
-span.css-emoticon.counter-rotated.red-emoticon {
-  background-image: -webkit-gradient(
-    linear,
-    left top,
-    right top,
-    color-stop(0.41, rgb(235,5,66)),
-    color-stop(0.56, rgb(235,38,90)),
-    color-stop(1, rgb(250,55,110))
-  );
-  background-image: -moz-linear-gradient(
-    center left,
-    rgb(235,5,66) 41%,
-    rgb(235,38,90) 56%,
-    rgb(250,55,110) 100%
-  );
-}
-
-span.css-emoticon.counter-rotated.pink-emoticon {
-  background-image: -webkit-gradient(
-    linear,
-    left top,
-    right top,
-    color-stop(0.41, rgb(255,143,212)),
-    color-stop(0.56, rgb(255,153,216)),
-    color-stop(1,    rgb(255,173,225))
-  );
-  background-image: -moz-linear-gradient(
-    center left,
-    rgb(255,143,212) 41%,
-    rgb(255,153,216) 56%,
-    rgb(255,173,225) 100%
-  );
-}
-
-/* Styles for animated states */
-span.css-emoticon.un-transformed-emoticon, span.css-emoticon.animated-emoticon:hover {
-    /* font-size: inherit;
-    font-weight: inherit;
-    vertical-align: inherit;
-    line-height: inherit;
-    font-family: inherit; */
-    letter-spacing: inherit;
-    color: inherit;
-    overflow: visible;
-    transform: rotate(0deg);
-    -webkit-transform: rotate(0deg);
-    -moz-transform: rotate(0deg);
-    -o-transform: rotate(0deg);
-    background: none;
-    background-image: none;
-    box-shadow: none;
-    -moz-box-shadow: none;
-    -webkit-box-shadow: none;
-    border-color: transparent;
-}
-
-span.css-emoticon.nintendo-controller {
-  font-size: .8em;
-  height: 1.2em;
-  line-height: 1em;
-  width: 2.7em;
-  vertical-align: bottom;
-  border-radius: 0;
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  background: -webkit-gradient(
-      linear,
-      left bottom,
-      left top,
-      color-stop(0.09, rgb(116,121,140)),
-      color-stop(0.55, rgb(165,170,189))
-  );
-  background: -moz-linear-gradient(
-      center bottom,
-      rgb(116,121,140) 9%,
-      rgb(165,170,189) 55%
-  );
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.min.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.min.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.min.js
deleted file mode 100644
index 006989f..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/user/chat/cssemoticons.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Dual licensed under the MIT and GPL licenses */
-var CSSEmoticon=function(){this.escapeCharacters=[")","(","*","[","]","{","}","|","^","<",">","\\","?","+","=","."];this.threeCharacterEmoticons=[":-)",":o)",":c)",":^)",":-D",":-(",":-9",";-)",":-P",":-p",":-Þ",":-b",":-O",":-/",":-X",":-#",":'(","B-)","8-)",";*(",":-*",":-\\","?-)"];this.threeCharEmoticons=this.threeCharacterEmoticons.slice();this.twoCharacterEmoticons=[":)",":]","=]","=)","8)",":}",":D",":(",":[",":{","=(",";)",";]",";D",":P",":p","=P","=p",":b",":Þ",":O",":/","=/",":S",":#",":X","B)",":|",":\\","=\\",":*",":&gt;",":&lt;"];this.twoCharEmoticons=this.twoCharacterEmoticons.slice();this.specialEmoticons={"&gt;:)":{cssClass:"red-emoticon small-emoticon spaced-emoticon"},"&gt;;)":{cssClass:"red-emoticon small-emoticon spaced-emoticon"},"&gt;:(":{cssClass:"red-emoticon small-emoticon spaced-emoticon"},"&gt;: )":{cssClass:"red-emoticon small-emoticon"},"&gt;; )":{cssClass:"red-emoticon small-emoticon"},"&gt;: (":{cssClass:"red-emoticon small-emoticon"},";(":{cssClass:
 "red-emoticon spaced-emoticon"},"&lt;3":{cssClass:"pink-emoticon counter-rotated"},"O_O":{cssClass:"no-rotate"},"o_o":{cssClass:"no-rotate"},"0_o":{cssClass:"no-rotate"},"O_o":{cssClass:"no-rotate"},"T_T":{cssClass:"no-rotate"},"^_^":{cssClass:"no-rotate"},"O:)":{cssClass:"small-emoticon spaced-emoticon"},"O: )":{cssClass:"small-emoticon"},"8D":{cssClass:"small-emoticon spaced-emoticon"},"XD":{cssClass:"small-emoticon spaced-emoticon"},"xD":{cssClass:"small-emoticon spaced-emoticon"},"=D":{cssClass:"small-emoticon spaced-emoticon"},"8O":{cssClass:"small-emoticon spaced-emoticon"},"[+=..]":{cssClass:"no-rotate nintendo-controller"}};var a=new RegExp('(\\'+this.escapeCharacters.join('|\\')+')','g');var b='(^|[\\s\\0])';for(var c=this.threeCharacterEmoticons.length-1;c>=0;--c){this.threeCharacterEmoticons[c]=this.threeCharacterEmoticons[c].replace(a,'\\$1');this.threeCharacterEmoticons[c]=new RegExp(b+'('+this.threeCharacterEmoticons[c]+')','g');}for(var c=this.twoCharacterEmoticons.le
 ngth-1;c>=0;--c){this.twoCharacterEmoticons[c]=this.twoCharacterEmoticons[c].replace(a,'\\$1');this.twoCharacterEmoticons[c]=new RegExp(b+'('+this.twoCharacterEmoticons[c]+')','g');}for(var d in this.specialEmoticons){this.specialEmoticons[d].regexp=d.replace(a,'\\$1');this.specialEmoticons[d].regexp=new RegExp(b+'('+this.specialEmoticons[d].regexp+')','g');}this.defaults={animate:true,delay:500,exclude:'pre,code,.no-emoticons'};};CSSEmoticon.prototype.emoticonize=function(a,b){var c={};for(var d in this.defaults)c[d]=this.defaults[d];for(var d in b)c[d]=b[d];var e='span.css-emoticon';if(c.exclude)e+=','+c.exclude;var f=e.split(',');var g='css-emoticon';if(c.animate)g+=' un-transformed-emoticon animated-emoticon';for(var h in this.specialEmoticons){var i=g+" "+this.specialEmoticons[h].cssClass;a=a.replace(this.specialEmoticons[h].regexp,"$1<span class='"+i+"'>$2</span>");}for(var d in this.threeCharacterEmoticons){var j=this.threeCharacterEmoticons[d];a=a.replace(j,"$1<span class='"
 +g+"'>$2</span>");}for(var d in this.twoCharacterEmoticons){var j=this.twoCharacterEmoticons[d];a=a.replace(j,"$1<span class='"+g+" spaced-emoticon'>$2</span>");}if(c.animate)setTimeout(function(){var a=document.body.getElementsByClassName("un-transformed-emoticon");for(var b in a)if(typeof a[b]=="object")a[b].classList.remove("un-transformed-emoticon");},c.delay);return a;};

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.css
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.css b/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.css
deleted file mode 100644
index abdd62a..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * Jasny Bootstrap v3.1.0 (http://jasny.github.com/bootstrap)
- * Copyright 2011-2014 Arnold Daniels.
- * Licensed under the Apache License, Version 2.0 (the "License"); (https://github.com/jasny/bootstrap/blob/master/LICENSE)
- */
-
-.btn-labeled{padding-top:0;padding-bottom:0}.btn-label{position:relative;background:transparent;background:rgba(0,0,0,0.15);display:inline-block;padding:6px 12px;left:-12px;border-radius:3px 0 0 3px}.btn-label.btn-label-right{left:auto;right:-12px;border-radius:0 3px 3px 0}.btn-lg .btn-label{padding:10px 16px;left:-16px;border-radius:5px 0 0 5px}.btn-lg .btn-label.btn-label-right{left:auto;right:-16px;border-radius:0 5px 5px 0}.btn-sm .btn-label{padding:5px 10px;left:-10px;border-radius:2px 0 0 2px}.btn-sm .btn-label.btn-label-right{left:auto;right:-10px;border-radius:0 2px 2px 0}.btn-xs .btn-label{padding:1px 5px;left:-5px;border-radius:2px 0 0 2px}.btn-xs .btn-label.btn-label-right{left:auto;right:-5px;border-radius:0 2px 2px 0}.nav-tabs-bottom{border-bottom:0;border-top:1px solid #ddd}.nav-tabs-bottom>li{margin-bottom:0;margin-top:-1px}.nav-tabs-bottom>li>a{border-radius:0 0 4px 4px}.nav-tabs-bottom>li>a:hover,.nav-tabs-bottom>li>a:focus,.nav-tabs-bottom>li.active>a,.nav-tabs-bot
 tom>li.active>a:hover,.nav-tabs-bottom>li.active>a:focus{border:1px solid #ddd;border-top-color:transparent}.nav-tabs-left{border-bottom:0;border-right:1px solid #ddd}.nav-tabs-left>li{margin-bottom:0;margin-right:-1px;float:none}.nav-tabs-left>li>a{border-radius:4px 0 0 4px;margin-right:0;margin-bottom:2px}.nav-tabs-left>li>a:hover,.nav-tabs-left>li>a:focus,.nav-tabs-left>li.active>a,.nav-tabs-left>li.active>a:hover,.nav-tabs-left>li.active>a:focus{border:1px solid #ddd;border-right-color:transparent}.row>.nav-tabs-left{padding-right:0;padding-left:15px;margin-right:-1px;position:relative;z-index:1}.row>.nav-tabs-left+.tab-content{border-left:1px solid #ddd}.nav-tabs-right{border-bottom:0;border-left:1px solid #ddd}.nav-tabs-right>li{margin-bottom:0;margin-left:-1px;float:none}.nav-tabs-right>li>a{border-radius:0 4px 4px 0;margin-left:0;margin-bottom:2px}.nav-tabs-right>li>a:hover,.nav-tabs-right>li>a:focus,.nav-tabs-right>li.active>a,.nav-tabs-right>li.active>a:hover,.nav-tabs-rig
 ht>li.active>a:focus{border:1px solid #ddd;border-left-color:transparent}.row>.nav-tabs-right{padding-left:0;padding-right:15px}.btn-file{overflow:hidden;position:relative;vertical-align:middle}.btn-file>input{position:absolute;top:0;right:0;margin:0;opacity:0;filter:alpha(opacity=0);font-size:23px;height:100%;width:100%;direction:ltr;cursor:pointer}.fileinput{margin-bottom:9px;display:inline-block}.fileinput .form-control{padding-top:7px;padding-bottom:5px;display:inline-block;margin-bottom:0px;vertical-align:middle;cursor:text}.fileinput .thumbnail{overflow:hidden;display:inline-block;margin-bottom:5px;vertical-align:middle;text-align:center}.fileinput .thumbnail>img{max-height:100%}.fileinput .btn{vertical-align:middle}.fileinput-exists .fileinput-new,.fileinput-new .fileinput-exists{display:none}.fileinput-inline .fileinput-controls{display:inline}.fileinput-filename{vertical-align:middle;display:inline-block;overflow:hidden}.form-control .fileinput-filename{vertical-align:botto
 m}.fileinput.input-group{display:table}.fileinput.input-group>*{position:relative;z-index:2}.fileinput.input-group>.btn-file{z-index:1}.fileinput-new.input-group .btn-file,.fileinput-new .input-group .btn-file{border-radius:0 4px 4px 0}.fileinput-new.input-group .btn-file.btn-xs,.fileinput-new .input-group .btn-file.btn-xs,.fileinput-new.input-group .btn-file.btn-sm,.fileinput-new .input-group .btn-file.btn-sm{border-radius:0 3px 3px 0}.fileinput-new.input-group .btn-file.btn-lg,.fileinput-new .input-group .btn-file.btn-lg{border-radius:0 6px 6px 0}.form-group.has-warning .fileinput .fileinput-preview{color:#8a6d3b}.form-group.has-warning .fileinput .thumbnail{border-color:#faebcc}.form-group.has-error .fileinput .fileinput-preview{color:#a94442}.form-group.has-error .fileinput .thumbnail{border-color:#ebccd1}.form-group.has-success .fileinput .fileinput-preview{color:#3c763d}.form-group.has-success .fileinput .thumbnail{border-color:#d6e9c6}.input-group-addon:not(:first-child){bord
 er-left:0}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.js
deleted file mode 100644
index 5815e25..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/upload/fileinput.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * Jasny Bootstrap v3.1.0 (http://jasny.github.com/bootstrap)
- * Copyright 2011-2014 Arnold Daniels.
- * Licensed under the Apache License, Version 2.0 (the "License"); (https://github.com/jasny/bootstrap/blob/master/LICENSE)
- */
-
-+function(a){"use strict";var b=window.navigator.appName=="Microsoft Internet Explorer",c=function(b,c){this.$element=a(b),this.$input=this.$element.find(":file");if(this.$input.length===0)return;this.name=this.$input.attr("name")||c.name,this.$hidden=this.$element.find('input[type=hidden][name="'+this.name+'"]'),this.$hidden.length===0&&(this.$hidden=a('<input type="hidden">').insertBefore(this.$input)),this.$preview=this.$element.find(".fileinput-preview");var d=this.$preview.css("height");this.$preview.css("display")!=="inline"&&d!=="0px"&&d!=="none"&&this.$preview.css("line-height",d),this.original={exists:this.$element.hasClass("fileinput-exists"),preview:this.$preview.html(),hiddenVal:this.$hidden.val()},this.listen()};c.prototype.listen=function(){this.$input.on("change.bs.fileinput",a.proxy(this.change,this)),a(this.$input[0].form).on("reset.bs.fileinput",a.proxy(this.reset,this)),this.$element.find('[data-trigger="fileinput"]').on("click.bs.fileinput",a.proxy(this.trigger,t
 his)),this.$element.find('[data-dismiss="fileinput"]').on("click.bs.fileinput",a.proxy(this.clear,this))},c.prototype.change=function(b){var c=b.target.files===undefined?b.target&&b.target.value?[{name:b.target.value.replace(/^.+\\/,"")}]:[]:b.target.files;b.stopPropagation();if(c.length===0){this.clear();return}this.$hidden.val(""),this.$hidden.attr("name",""),this.$input.attr("name",this.name);var d=c[0];if(this.$preview.length>0&&(typeof d.type!="undefined"?d.type.match(/^image\/(gif|png|jpeg)$/):d.name.match(/\.(gif|png|jpe?g)$/i))&&typeof FileReader!="undefined"){var e=new FileReader,f=this.$preview,g=this.$element;e.onload=function(b){var e=a("<img>");e[0].src=b.target.result,c[0].result=b.target.result,g.find(".fileinput-filename").text(d.name),f.css("max-height")!="none"&&e.css("max-height",parseInt(f.css("max-height"),10)-parseInt(f.css("padding-top"),10)-parseInt(f.css("padding-bottom"),10)-parseInt(f.css("border-top"),10)-parseInt(f.css("border-bottom"),10)),f.html(e),g.a
 ddClass("fileinput-exists").removeClass("fileinput-new"),g.trigger("change.bs.fileinput",c)},e.readAsDataURL(d)}else this.$element.find(".fileinput-filename").text(d.name),this.$preview.text(d.name),this.$element.addClass("fileinput-exists").removeClass("fileinput-new"),this.$element.trigger("change.bs.fileinput")},c.prototype.clear=function(a){a&&a.preventDefault(),this.$hidden.val(""),this.$hidden.attr("name",this.name),this.$input.attr("name","");if(b){var c=this.$input.clone(!0);this.$input.after(c),this.$input.remove(),this.$input=c}else this.$input.val("");this.$preview.html(""),this.$element.find(".fileinput-filename").text(""),this.$element.addClass("fileinput-new").removeClass("fileinput-exists"),a!==undefined&&(this.$input.trigger("change"),this.$element.trigger("clear.bs.fileinput"))},c.prototype.reset=function(){this.clear(),this.$hidden.val(this.original.hiddenVal),this.$preview.html(this.original.preview),this.$element.find(".fileinput-filename").text(""),this.original
 .exists?this.$element.addClass("fileinput-exists").removeClass("fileinput-new"):this.$element.addClass("fileinput-new").removeClass("fileinput-exists"),this.$element.trigger("reset.bs.fileinput")},c.prototype.trigger=function(a){this.$input.trigger("click"),a.preventDefault()};var d=a.fn.fileinput;a.fn.fileinput=function(b){return this.each(function(){var d=a(this),e=d.data("bs.fileinput");e||d.data("bs.fileinput",e=new c(this,b)),typeof b=="string"&&e[b]()})},a.fn.fileinput.Constructor=c,a.fn.fileinput.noConflict=function(){return a.fn.fileinput=d,this},a(document).on("click.fileinput.data-api",'[data-provides="fileinput"]',function(b){var c=a(this);if(c.data("bs.fileinput"))return;c.fileinput(c.data());var d=a(b.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');d.length>0&&(b.preventDefault(),d.trigger("click.bs.fileinput"))})}(window.jQuery)

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/webapp/css/cssemoticons.css
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/webapp/css/cssemoticons.css b/openmeetings-web/src/main/webapp/css/cssemoticons.css
new file mode 100644
index 0000000..c14765c
--- /dev/null
+++ b/openmeetings-web/src/main/webapp/css/cssemoticons.css
@@ -0,0 +1,295 @@
+/*
+ * jQuery CSSEmoticons plugin 0.2.9
+ *
+ * Copyright (c) 2010 Steve Schwartz (JangoSteve)
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Date: Sun Oct 22 1:00:00 2010 -0500
+ */
+ 
+ /* Basic styles for emoticons */
+span.css-emoticon {
+  font-family: "Trebuchet MS"; /* seems to give the best and most consistent emoticon appearance */
+  font-size: 0.65em;
+  font-weight: bold;
+  color: #000000;
+  display: inline-block;
+  overflow: hidden;
+  vertical-align: middle;
+  transform: rotate(90deg);
+  -webkit-transform: rotate(90deg);
+  -moz-transform: rotate(90deg);
+  -o-transform: rotate(90deg);
+  width: 1.54em; /* note that this is a multiple of this span's font-size, not containing text font-size */
+  height: 1.54em; /* so, relative to containing text, width and height are 0.9 x 1.6 = 1.44em */
+  text-align: center;
+  padding: 0;
+  line-height: 1.34em;
+  -moz-border-radius: 1.54em;
+  -webkit-border-radius: 1.54em;
+  border-radius: 1.54em;
+  -moz-box-shadow: 1px -1px 2px rgba(0,0,0,0.5);
+  -webkit-box-shadow: 1px -1px 2px rgba(0,0,0,0.5);
+  box-shadow: 1px -1px 2px rgba(0,0,0,0.5);
+  border: 1px solid rgba(0,0,0,0.25);
+  background-color: #ffcc00;
+  background-image: -webkit-gradient(
+    linear,
+    right top,
+    left top,
+    color-stop(0.41, rgb(255,204,0)),
+    color-stop(0.56, rgb(255,221,85)),
+    color-stop(1, rgb(255,238,170))
+  );
+  background-image: -moz-linear-gradient(
+    center right,
+    rgb(255,204,0) 41%,
+    rgb(255,221,85) 56%,
+    rgb(255,238,170) 100%
+  );
+  -webkit-transition-property:color, background, transform;  
+  -webkit-transition-duration: 1s, 1s;  
+  -webkit-transition-timing-function: linear, ease-in;
+}
+
+/* Styles for two-character emoticons that need more letter-spacing for proportionality */
+span.css-emoticon.spaced-emoticon {
+  padding-left: 0.2em;
+  width: 1.34em;
+  letter-spacing: 0.2em;
+}
+
+/* This is a dirty dirty hack, because webkit doesn't properly do the padding+width=total-width as it should
+   I think the width of the border may be throwing things off, because it's more noticable for small icons */
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+  span.css-emoticon.spaced-emoticon {
+    width: 1.4em;
+  }
+}
+
+/* Styles for emoticons that need to have smaller characters to fit inside the circle */
+span.css-emoticon.small-emoticon {
+  font-size: 0.55em;
+  width: 1.82em;
+  height: 1.82em;
+  line-height: 1.72em;
+  -moz-border-radius: 1.82em;
+  -webkit-border-radius: 1.82em;
+  border-radius: 1.82em;
+}
+
+span.css-emoticon.small-emoticon.spaced-emoticon {
+  padding-left: 0;
+  width: 1.82em;
+  letter-spacing: 0.1em;
+}
+
+/* Styles for additional colors */
+span.css-emoticon.red-emoticon {
+  background-color: #eb0542;
+  background-image: -webkit-gradient(
+    linear,
+    right top,
+    left top,
+    color-stop(0.41, rgb(235,5,66)),
+    color-stop(0.56, rgb(235,38,90)),
+    color-stop(1, rgb(250,55,110))
+  );
+  background-image: -moz-linear-gradient(
+    center right,
+    rgb(235,5,66) 41%,
+    rgb(235,38,90) 56%,
+    rgb(250,55,110) 100%
+  );
+}
+
+span.css-emoticon.pink-emoticon {
+  background-color: #ff8fd4;
+  background-image: -webkit-gradient(
+    linear,
+    right top,
+    left top,
+    color-stop(0.41, rgb(255,143,212)),
+    color-stop(0.56, rgb(255,153,216)),
+    color-stop(1,    rgb(255,173,225))
+  );
+  background-image: -moz-linear-gradient(
+    center right,
+    rgb(255,143,212) 41%,
+    rgb(255,153,216) 56%,
+    rgb(255,173,225) 100%
+  );
+}
+
+/* styles for emoticons that need no rotation, like O_o */
+span.css-emoticon.no-rotate { 
+  transform: rotate(0deg);
+  -webkit-transform: rotate(0deg);
+  -moz-transform: rotate(0deg);
+  -o-transform: rotate(0deg);
+  -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.5);
+  -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.5);
+  box-shadow: 1px 1px 2px rgba(0,0,0,0.5);
+  font-size: 0.45em;
+  width: 2.2em;
+  height: 2.2em;
+  line-height: 1.9em;
+  -moz-border-radius: 2.2em;
+  -webkit-border-radius: 2.2em;
+  border-radius: 2.2em;
+  background-image: -webkit-gradient(
+    linear,
+    right bottom,
+    right top,
+    color-stop(0.41, rgb(255,204,0)),
+    color-stop(0.56, rgb(255,221,85)),
+    color-stop(1, rgb(255,238,170))
+  );
+  background-image: -moz-linear-gradient(
+    center bottom,
+    rgb(255,204,0) 41%,
+    rgb(255,221,85) 56%,
+    rgb(255,238,170) 100%
+  );
+}
+
+span.css-emoticon.no-rotate.red-emoticon {
+  background-image: -webkit-gradient(
+    linear,
+    right bottom,
+    right top,
+    color-stop(0.41, rgb(235,5,66)),
+    color-stop(0.56, rgb(235,38,90)),
+    color-stop(1, rgb(250,55,110))
+  );
+  background-image: -moz-linear-gradient(
+    center bottom,
+    rgb(235,5,66) 41%,
+    rgb(235,38,90) 56%,
+    rgb(250,55,110) 100%
+  );
+}
+
+span.css-emoticon.no-rotate.pink-emoticon {
+  background-image: -webkit-gradient(
+    linear,
+    right bottom,
+    right top,
+    color-stop(0.41, rgb(255,143,212)),
+    color-stop(0.56, rgb(255,153,216)),
+    color-stop(1,    rgb(255,173,225))
+  );
+  background-image: -moz-linear-gradient(
+    center bottom,
+    rgb(255,143,212) 41%,
+    rgb(255,153,216) 56%,
+    rgb(255,173,225) 100%
+  );
+}
+
+/* Styles for emoticons that need to be rotated counter-clockwise, like <3 */
+span.css-emoticon.counter-rotated { 
+  transform: rotate(-90deg);
+  -webkit-transform: rotate(-90deg);
+  -moz-transform: rotate(-90deg);
+  -o-transform: rotate(-90deg);
+  -moz-box-shadow: -1px 1px 2px rgba(0,0,0,0.5);
+  -webkit-box-shadow: -1px 1px 2px rgba(0,0,0,0.5);
+  box-shadow: -1px 1px 2px rgba(0,0,0,0.5);
+  background-image: -webkit-gradient(
+    linear,
+    left top,
+    right top,
+    color-stop(0.41, rgb(255,204,0)),
+    color-stop(0.56, rgb(255,221,85)),
+    color-stop(1, rgb(255,238,170))
+  );
+  background-image: -moz-linear-gradient(
+    center left,
+    rgb(255,204,0) 41%,
+    rgb(255,221,85) 56%,
+    rgb(255,238,170) 100%
+  );
+}
+
+span.css-emoticon.counter-rotated.red-emoticon {
+  background-image: -webkit-gradient(
+    linear,
+    left top,
+    right top,
+    color-stop(0.41, rgb(235,5,66)),
+    color-stop(0.56, rgb(235,38,90)),
+    color-stop(1, rgb(250,55,110))
+  );
+  background-image: -moz-linear-gradient(
+    center left,
+    rgb(235,5,66) 41%,
+    rgb(235,38,90) 56%,
+    rgb(250,55,110) 100%
+  );
+}
+
+span.css-emoticon.counter-rotated.pink-emoticon {
+  background-image: -webkit-gradient(
+    linear,
+    left top,
+    right top,
+    color-stop(0.41, rgb(255,143,212)),
+    color-stop(0.56, rgb(255,153,216)),
+    color-stop(1,    rgb(255,173,225))
+  );
+  background-image: -moz-linear-gradient(
+    center left,
+    rgb(255,143,212) 41%,
+    rgb(255,153,216) 56%,
+    rgb(255,173,225) 100%
+  );
+}
+
+/* Styles for animated states */
+span.css-emoticon.un-transformed-emoticon, span.css-emoticon.animated-emoticon:hover {
+    /* font-size: inherit;
+    font-weight: inherit;
+    vertical-align: inherit;
+    line-height: inherit;
+    font-family: inherit; */
+    letter-spacing: inherit;
+    color: inherit;
+    overflow: visible;
+    transform: rotate(0deg);
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    background: none;
+    background-image: none;
+    box-shadow: none;
+    -moz-box-shadow: none;
+    -webkit-box-shadow: none;
+    border-color: transparent;
+}
+
+span.css-emoticon.nintendo-controller {
+  font-size: .8em;
+  height: 1.2em;
+  line-height: 1em;
+  width: 2.7em;
+  vertical-align: bottom;
+  border-radius: 0;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  background: -webkit-gradient(
+      linear,
+      left bottom,
+      left top,
+      color-stop(0.09, rgb(116,121,140)),
+      color-stop(0.55, rgb(165,170,189))
+  );
+  background: -moz-linear-gradient(
+      center bottom,
+      rgb(116,121,140) 9%,
+      rgb(165,170,189) 55%
+  );
+}
\ No newline at end of file


[2/3] openmeetings git commit: [OPENMEETINGS-1771] minified files are removed from source tree

Posted by so...@apache.org.
http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.min.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.min.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.min.js
deleted file mode 100644
index 21a4783..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Licensed MIT https://github.com/kangax/fabric.js/blob/master/LICENSE */
-function resizeCanvasIfNeeded(t){var e=t.targetCanvas,i=e.width,r=e.height,n=t.destinationWidth,s=t.destinationHeight;i===n&&r===s||(e.width=n,e.height=s)}function copyGLTo2DDrawImage(t,e){var i=t.canvas,r=e.targetCanvas,n=r.getContext("2d");n.translate(0,r.height),n.scale(1,-1);var s=i.height-r.height;n.drawImage(i,0,s,r.width,r.height,0,0,r.width,r.height)}function copyGLTo2DPutImageData(t,e){var i=e.targetCanvas.getContext("2d"),r=e.destinationWidth,n=e.destinationHeight,s=r*n*4,o=new Uint8Array(this.imageBuffer,0,s),a=new Uint8ClampedArray(this.imageBuffer,0,s);t.readPixels(0,0,r,n,t.RGBA,t.UNSIGNED_BYTE,o);var h=new ImageData(a,r,n);i.putImageData(h,0,0)}var fabric=fabric||{version:"2.0.0-rc.1"};"undefined"!=typeof exports&&(exports.fabric=fabric),"undefined"!=typeof document&&"undefined"!=typeof window?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom(decodeURIComponent("%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2
 Fbody%3E%3C%2Fhtml%3E"),{features:{FetchExternalResources:["img"]}}),fabric.window=fabric.document.defaultView,DOMParser=require("xmldom").DOMParser),fabric.isTouchSupported="ontouchstart"in fabric.window,fabric.isLikelyNode="undefined"!=typeof Buffer&&"undefined"==typeof window,fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","id","paint-order","instantiated_by_use"],fabric.DPI=96,fabric.reNum="(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)",fabric.fontPaths={},fabric.iMatrix=[1,0,0,1,0,0],fabric.canvasModule="canvas",fabric.perfLimitSizeTotal=2097152,fabric.maxCacheSideLimit=4096,fabric.minCacheSideLimit=256,fabric.charWidthsCache={},fabric.textureSize=2048,fabric.enableGLFiltering=!0,fabric.devicePixelRatio=fabric.window.devicePixelRatio||fabric.window.webkitDevicePixelRatio||fabric.window.mozDevicePixelRatio||1,fabric.browser
 ShadowBlurConstant=1,fabric.initFilterBackend=function(){return fabric.enableGLFiltering&&fabric.isWebglSupported&&fabric.isWebglSupported(fabric.textureSize)?(console.log("max texture size: "+fabric.maxTextureSize),new fabric.WebglFilterBackend({tileSize:fabric.textureSize})):fabric.Canvas2dFilterBackend?new fabric.Canvas2dFilterBackend:void 0},"undefined"!=typeof document&&"undefined"!=typeof window&&(window.fabric=fabric),function(){function t(t,e){if(this.__eventListeners[t]){var i=this.__eventListeners[t];e?i[i.indexOf(e)]=!1:fabric.util.array.fill(i,!1)}}function e(t,e){if(this.__eventListeners||(this.__eventListeners={}),1===arguments.length)for(var i in t)this.on(i,t[i]);else this.__eventListeners[t]||(this.__eventListeners[t]=[]),this.__eventListeners[t].push(e);return this}function i(e,i){if(this.__eventListeners){if(0===arguments.length)for(e in this.__eventListeners)t.call(this,e);else if(1===arguments.length&&"object"==typeof arguments[0])for(var r in e)t.call(this,r,e[
 r]);else t.call(this,e,i);return this}}function r(t,e){if(this.__eventListeners){var i=this.__eventListeners[t];if(i){for(var r=0,n=i.length;r<n;r++)i[r]&&i[r].call(this,e||{});return this.__eventListeners[t]=i.filter(function(t){return!1!==t}),this}}}fabric.Observable={observe:e,stopObserving:i,fire:r,on:e,off:i,trigger:r}}(),fabric.Collection={_objects:[],add:function(){if(this._objects.push.apply(this._objects,arguments),this._onObjectAdded)for(var t=0,e=arguments.length;t<e;t++)this._onObjectAdded(arguments[t]);return this.renderOnAddRemove&&this.requestRenderAll(),this},insertAt:function(t,e,i){var r=this.getObjects();return i?r[e]=t:r.splice(e,0,t),this._onObjectAdded&&this._onObjectAdded(t),this.renderOnAddRemove&&this.requestRenderAll(),this},remove:function(){for(var t,e=this.getObjects(),i=!1,r=0,n=arguments.length;r<n;r++)-1!==(t=e.indexOf(arguments[r]))&&(i=!0,e.splice(t,1),this._onObjectRemoved&&this._onObjectRemoved(arguments[r]));return this.renderOnAddRemove&&i&&this
 .requestRenderAll(),this},forEachObject:function(t,e){for(var i=this.getObjects(),r=0,n=i.length;r<n;r++)t.call(e,i[r],r,i);return this},getObjects:function(t){return void 0===t?this._objects:this._objects.filter(function(e){return e.type===t})},item:function(t){return this.getObjects()[t]},isEmpty:function(){return 0===this.getObjects().length},size:function(){return this.getObjects().length},contains:function(t){return this.getObjects().indexOf(t)>-1},complexity:function(){return this.getObjects().reduce(function(t,e){return t+=e.complexity?e.complexity():0},0)}},fabric.CommonMethods={_setOptions:function(t){for(var e in t)this.set(e,t[e])},_initGradient:function(t,e){!t||!t.colorStops||t instanceof fabric.Gradient||this.set(e,new fabric.Gradient(t))},_initPattern:function(t,e,i){!t||!t.source||t instanceof fabric.Pattern?i&&i():this.set(e,new fabric.Pattern(t,i))},_initClipping:function(t){if(t.clipTo&&"string"==typeof t.clipTo){var e=fabric.util.getFunctionBody(t.clipTo);void 0!
 ==e&&(this.clipTo=new Function("ctx",e))}},_setObject:function(t){for(var e in t)this._set(e,t[e])},set:function(t,e){return"object"==typeof t?this._setObject(t):"function"==typeof e&&"clipTo"!==t?this._set(t,e(this.get(t))):this._set(t,e),this},_set:function(t,e){this[t]=e},toggle:function(t){var e=this.get(t);return"boolean"==typeof e&&this.set(t,!e),this},get:function(t){return this[t]}},function(t){var e=Math.sqrt,i=Math.atan2,r=Math.pow,n=Math.abs,s=Math.PI/180;fabric.util={removeFromArray:function(t,e){var i=t.indexOf(e);return-1!==i&&t.splice(i,1),t},getRandomInt:function(t,e){return Math.floor(Math.random()*(e-t+1))+t},degreesToRadians:function(t){return t*s},radiansToDegrees:function(t){return t/s},rotatePoint:function(t,e,i){t.subtractEquals(e);var r=fabric.util.rotateVector(t,i);return new fabric.Point(r.x,r.y).addEquals(e)},rotateVector:function(t,e){var i=Math.sin(e),r=Math.cos(e);return{x:t.x*r-t.y*i,y:t.x*i+t.y*r}},transformPoint:function(t,e,i){return i?new fabric.Po
 int(e[0]*t.x+e[2]*t.y,e[1]*t.x+e[3]*t.y):new fabric.Point(e[0]*t.x+e[2]*t.y+e[4],e[1]*t.x+e[3]*t.y+e[5])},makeBoundingBoxFromPoints:function(t){var e=[t[0].x,t[1].x,t[2].x,t[3].x],i=fabric.util.array.min(e),r=fabric.util.array.max(e)-i,n=[t[0].y,t[1].y,t[2].y,t[3].y],s=fabric.util.array.min(n);return{left:i,top:s,width:r,height:fabric.util.array.max(n)-s}},invertTransform:function(t){var e=1/(t[0]*t[3]-t[1]*t[2]),i=[e*t[3],-e*t[1],-e*t[2],e*t[0]],r=fabric.util.transformPoint({x:t[4],y:t[5]},i,!0);return i[4]=-r.x,i[5]=-r.y,i},toFixed:function(t,e){return parseFloat(Number(t).toFixed(e))},parseUnit:function(t,e){var i=/\D{0,2}$/.exec(t),r=parseFloat(t);switch(e||(e=fabric.Text.DEFAULT_SVG_FONT_SIZE),i[0]){case"mm":return r*fabric.DPI/25.4;case"cm":return r*fabric.DPI/2.54;case"in":return r*fabric.DPI;case"pt":return r*fabric.DPI/72;case"pc":return r*fabric.DPI/72*12;case"em":return r*e;default:return r}},falseFunction:function(){return!1},getKlass:function(t,e){return t=fabric.util.s
 tring.camelize(t.charAt(0).toUpperCase()+t.slice(1)),fabric.util.resolveNamespace(e)[t]},getSvgAttributes:function(t){var e=["instantiated_by_use","style","id","class"];switch(t){case"linearGradient":e=e.concat(["x1","y1","x2","y2","gradientUnits","gradientTransform"]);break;case"radialGradient":e=e.concat(["gradientUnits","gradientTransform","cx","cy","r","fx","fy","fr"]);break;case"stop":e=e.concat(["offset","stop-color","stop-opacity"])}return e},resolveNamespace:function(e){if(!e)return fabric;var i,r=e.split("."),n=r.length,s=t||fabric.window;for(i=0;i<n;++i)s=s[r[i]];return s},loadImage:function(t,e,i,r){if(t){var n=fabric.util.createImage(),s=function(){e&&e.call(i,n),n=n.onload=n.onerror=null};n.onload=s,n.onerror=function(){fabric.log("Error loading "+n.src),e&&e.call(i,null,!0),n=n.onload=n.onerror=null},0!==t.indexOf("data")&&r&&(n.crossOrigin=r),"data:image/svg"===t.substring(0,14)&&(n.onload=null,fabric.util.loadImageInDom(n,s)),n.src=t}else e&&e.call(i,t)},loadImageInD
 om:function(t,e){var i=fabric.document.createElement("div");i.style.width=i.style.height="1px",i.style.left=i.style.top="-100%",i.style.position="absolute",i.appendChild(t),fabric.document.querySelector("body").appendChild(i),t.onload=function(){e(),i.parentNode.removeChild(i),i=null}},enlivenObjects:function(t,e,i,r){function n(){++o===a&&e&&e(s)}var s=[],o=0,a=(t=t||[]).length;a?t.forEach(function(t,e){t&&t.type?fabric.util.getKlass(t.type,i).fromObject(t,function(i,o){o||(s[e]=i),r&&r(t,i,o),n()}):n()}):e&&e(s)},enlivenPatterns:function(t,e){function i(){++n===s&&e&&e(r)}var r=[],n=0,s=(t=t||[]).length;s?t.forEach(function(t,e){t&&t.source?new fabric.Pattern(t,function(t){r[e]=t,i()}):(r[e]=t,i())}):e&&e(r)},groupSVGElements:function(t,e,i){var r;return 1===t.length?t[0]:(e&&(e.width&&e.height?e.centerPoint={x:e.width/2,y:e.height/2}:(delete e.width,delete e.height)),r=new fabric.Group(t,e),void 0!==i&&(r.sourcePath=i),r)},populateWithProperties:function(t,e,i){if(i&&"[object Arr
 ay]"===Object.prototype.toString.call(i))for(var r=0,n=i.length;r<n;r++)i[r]in t&&(e[i[r]]=t[i[r]])},drawDashedLine:function(t,r,n,s,o,a){var h=s-r,c=o-n,l=e(h*h+c*c),u=i(c,h),f=a.length,d=0,g=!0;for(t.save(),t.translate(r,n),t.moveTo(0,0),t.rotate(u),r=0;l>r;)(r+=a[d++%f])>l&&(r=l),t[g?"lineTo":"moveTo"](r,0),g=!g;t.restore()},createCanvasElement:function(){return fabric.document.createElement("canvas")},createImage:function(){return fabric.document.createElement("img")},clipContext:function(t,e){e.save(),e.beginPath(),t.clipTo(e),e.clip()},multiplyTransformMatrices:function(t,e,i){return[t[0]*e[0]+t[2]*e[1],t[1]*e[0]+t[3]*e[1],t[0]*e[2]+t[2]*e[3],t[1]*e[2]+t[3]*e[3],i?0:t[0]*e[4]+t[2]*e[5]+t[4],i?0:t[1]*e[4]+t[3]*e[5]+t[5]]},qrDecompose:function(t){var n=i(t[1],t[0]),o=r(t[0],2)+r(t[1],2),a=e(o),h=(t[0]*t[3]-t[2]*t[1])/a,c=i(t[0]*t[2]+t[1]*t[3],o);return{angle:n/s,scaleX:a,scaleY:h,skewX:c/s,skewY:0,translateX:t[4],translateY:t[5]}},customTransformMatrix:function(t,e,i){var r=[1,0
 ,n(Math.tan(i*s)),1],o=[n(t),0,0,n(e)];return fabric.util.multiplyTransformMatrices(o,r,!0)},resetObjectTransform:function(t){t.scaleX=1,t.scaleY=1,t.skewX=0,t.skewY=0,t.flipX=!1,t.flipY=!1,t.rotate(0)},getFunctionBody:function(t){return(String(t).match(/function[^{]*\{([\s\S]*)\}/)||{})[1]},isTransparent:function(t,e,i,r){r>0&&(e>r?e-=r:e=0,i>r?i-=r:i=0);var n,s,o=!0,a=t.getImageData(e,i,2*r||1,2*r||1),h=a.data.length;for(n=3;n<h&&(s=a.data[n],!1!==(o=s<=0));n+=4);return a=null,o},parsePreserveAspectRatioAttribute:function(t){var e,i="meet",r="Mid",n="Mid",s=t.split(" ");return s&&s.length&&("meet"!==(i=s.pop())&&"slice"!==i?(e=i,i="meet"):s.length&&(e=s.pop())),r="none"!==e?e.slice(1,4):"none",n="none"!==e?e.slice(5,8):"none",{meetOrSlice:i,alignX:r,alignY:n}},clearFabricFontCache:function(t){t?fabric.charWidthsCache[t]&&delete fabric.charWidthsCache[t]:fabric.charWidthsCache={}},limitDimsByArea:function(t,e){var i=Math.sqrt(e*t),r=Math.floor(e/i);return{x:Math.floor(i),y:r}},capV
 alue:function(t,e,i){return Math.max(t,Math.min(e,i))},findScaleToFit:function(t,e){return Math.min(e.width/t.width,e.height/t.height)},findScaleToCover:function(t,e){return Math.max(e.width/t.width,e.height/t.height)}}}("undefined"!=typeof exports?exports:this),function(){function t(t,r,s,o,h,c,l){var u=a.call(arguments);if(n[u])return n[u];var f=Math.PI,d=l*f/180,g=Math.sin(d),p=Math.cos(d),v=0,m=0,b=-p*t*.5-g*r*.5,_=-p*r*.5+g*t*.5,y=(s=Math.abs(s))*s,x=(o=Math.abs(o))*o,C=_*_,S=b*b,w=y*x-y*C-x*S,T=0;if(w<0){var O=Math.sqrt(1-w/(y*x));s*=O,o*=O}else T=(h===c?-1:1)*Math.sqrt(w/(y*C+x*S));var k=T*s*_/o,D=-T*o*b/s,E=p*k-g*D+.5*t,j=g*k+p*D+.5*r,A=i(1,0,(b-k)/s,(_-D)/o),P=i((b-k)/s,(_-D)/o,(-b-k)/s,(-_-D)/o);0===c&&P>0?P-=2*f:1===c&&P<0&&(P+=2*f);for(var M=Math.ceil(Math.abs(P/f*2)),F=[],L=P/M,I=8/3*Math.sin(L/4)*Math.sin(L/4)/Math.sin(L/2),R=A+L,B=0;B<M;B++)F[B]=e(A,R,p,g,s,o,E,j,I,v,m),v=F[B][4],m=F[B][5],A=R,R+=L;return n[u]=F,F}function e(t,e,i,r,n,o,h,c,l,u,f){var d=a.call(argumen
 ts);if(s[d])return s[d];var g=Math.cos(t),p=Math.sin(t),v=Math.cos(e),m=Math.sin(e),b=i*n*v-r*o*m+h,_=r*n*v+i*o*m+c,y=u+l*(-i*n*p-r*o*g),x=f+l*(-r*n*p+i*o*g),C=b+l*(i*n*m+r*o*v),S=_+l*(r*n*m-i*o*v);return s[d]=[y,x,C,S,b,_],s[d]}function i(t,e,i,r){var n=Math.atan2(e,t),s=Math.atan2(r,i);return s>=n?s-n:2*Math.PI-(n-s)}function r(t,e,i,r,n,s,h,c){var l=a.call(arguments);if(o[l])return o[l];var u,f,d,g,p,v,m,b,_=Math.sqrt,y=Math.min,x=Math.max,C=Math.abs,S=[],w=[[],[]];f=6*t-12*i+6*n,u=-3*t+9*i-9*n+3*h,d=3*i-3*t;for(var T=0;T<2;++T)if(T>0&&(f=6*e-12*r+6*s,u=-3*e+9*r-9*s+3*c,d=3*r-3*e),C(u)<1e-12){if(C(f)<1e-12)continue;0<(g=-d/f)&&g<1&&S.push(g)}else(m=f*f-4*d*u)<0||(0<(p=(-f+(b=_(m)))/(2*u))&&p<1&&S.push(p),0<(v=(-f-b)/(2*u))&&v<1&&S.push(v));for(var O,k,D,E=S.length,j=E;E--;)O=(D=1-(g=S[E]))*D*D*t+3*D*D*g*i+3*D*g*g*n+g*g*g*h,w[0][E]=O,k=D*D*D*e+3*D*D*g*r+3*D*g*g*s+g*g*g*c,w[1][E]=k;w[0][j]=t,w[1][j]=e,w[0][j+1]=h,w[1][j+1]=c;var A=[{x:y.apply(null,w[0]),y:y.apply(null,w[1])},{x:x.a
 pply(null,w[0]),y:x.apply(null,w[1])}];return o[l]=A,A}var n={},s={},o={},a=Array.prototype.join;fabric.util.drawArc=function(e,i,r,n){for(var s=n[0],o=n[1],a=n[2],h=n[3],c=n[4],l=[[],[],[],[]],u=t(n[5]-i,n[6]-r,s,o,h,c,a),f=0,d=u.length;f<d;f++)l[f][0]=u[f][0]+i,l[f][1]=u[f][1]+r,l[f][2]=u[f][2]+i,l[f][3]=u[f][3]+r,l[f][4]=u[f][4]+i,l[f][5]=u[f][5]+r,e.bezierCurveTo.apply(e,l[f])},fabric.util.getBoundsOfArc=function(e,i,n,s,o,a,h,c,l){for(var u,f=0,d=0,g=[],p=t(c-e,l-i,n,s,a,h,o),v=0,m=p.length;v<m;v++)u=r(f,d,p[v][0],p[v][1],p[v][2],p[v][3],p[v][4],p[v][5]),g.push({x:u[0].x+e,y:u[0].y+i}),g.push({x:u[1].x+e,y:u[1].y+i}),f=p[v][4],d=p[v][5];return g},fabric.util.getBoundsOfCurve=r}(),function(){function t(t,e,i){if(t&&0!==t.length){var r=t.length-1,n=e?t[r][e]:t[r];if(e)for(;r--;)i(t[r][e],n)&&(n=t[r][e]);else for(;r--;)i(t[r],n)&&(n=t[r]);return n}}var e=Array.prototype.slice;fabric.util.array={fill:function(t,e){for(var i=t.length;i--;)t[i]=e;return t},invoke:function(t,i){for(va
 r r=e.call(arguments,2),n=[],s=0,o=t.length;s<o;s++)n[s]=r.length?t[s][i].apply(t[s],r):t[s][i].call(t[s]);return n},min:function(e,i){return t(e,i,function(t,e){return t<e})},max:function(e,i){return t(e,i,function(t,e){return t>=e})}}}(),function(){function t(e,i,r){if(r)if(!fabric.isLikelyNode&&i instanceof Element)e=i;else if(i instanceof Array){e=[];for(var n=0,s=i.length;n<s;n++)e[n]=t({},i[n],r)}else if(i&&"object"==typeof i)for(var o in i)i.hasOwnProperty(o)&&(e[o]=t({},i[o],r));else e=i;else for(var o in i)e[o]=i[o];return e}fabric.util.object={extend:t,clone:function(e,i){return t({},e,i)}},fabric.util.object.extend(fabric.util,fabric.Observable)}(),function(){function t(t,e){var i=t.charCodeAt(e);if(isNaN(i))return"";if(i<55296||i>57343)return t.charAt(e);if(55296<=i&&i<=56319){if(t.length<=e+1)throw"High surrogate without following low surrogate";var r=t.charCodeAt(e+1);if(56320>r||r>57343)throw"High surrogate without following low surrogate";return t.charAt(e)+t.charAt(
 e+1)}if(0===e)throw"Low surrogate without preceding high surrogate";var n=t.charCodeAt(e-1);if(55296>n||n>56319)throw"Low surrogate without preceding high surrogate";return!1}fabric.util.string={camelize:function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},capitalize:function(t,e){return t.charAt(0).toUpperCase()+(e?t.slice(1):t.slice(1).toLowerCase())},escapeXml:function(t){return t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&apos;").replace(/</g,"&lt;").replace(/>/g,"&gt;")},graphemeSplit:function(e){var i,r=0,n=[];for(r=0,i;r<e.length;r++)!1!==(i=t(e,r))&&n.push(i);return n}}}(),function(){function t(){}function e(t){for(var e=null,r=this;r.constructor.superclass;){var n=r.constructor.superclass.prototype[t];if(r[t]!==n){e=n;break}r=r.constructor.superclass.prototype}return e?arguments.length>1?e.apply(this,i.call(arguments,1)):e.call(this):console.log("tried to callSuper "+t+", method not found in prototype chain",this)}var i=Array.
 prototype.slice,r=function(){},n=function(){for(var t in{toString:1})if("toString"===t)return!1;return!0}(),s=function(t,e,i){for(var r in e)r in t.prototype&&"function"==typeof t.prototype[r]&&(e[r]+"").indexOf("callSuper")>-1?t.prototype[r]=function(t){return function(){var r=this.constructor.superclass;this.constructor.superclass=i;var n=e[t].apply(this,arguments);if(this.constructor.superclass=r,"initialize"!==t)return n}}(r):t.prototype[r]=e[r],n&&(e.toString!==Object.prototype.toString&&(t.prototype.toString=e.toString),e.valueOf!==Object.prototype.valueOf&&(t.prototype.valueOf=e.valueOf))};fabric.util.createClass=function(){function n(){this.initialize.apply(this,arguments)}var o=null,a=i.call(arguments,0);"function"==typeof a[0]&&(o=a.shift()),n.superclass=o,n.subclasses=[],o&&(t.prototype=o.prototype,n.prototype=new t,o.subclasses.push(n));for(var h=0,c=a.length;h<c;h++)s(n,a[h],o);return n.prototype.initialize||(n.prototype.initialize=r),n.prototype.constructor=n,n.prototy
 pe.callSuper=e,n}}(),function(){function t(t){var e,i,r=Array.prototype.slice.call(arguments,1),n=r.length;for(i=0;i<n;i++)if(e=typeof t[r[i]],!/^(?:function|object|unknown)$/.test(e))return!1;return!0}function e(t,e){return{handler:e,wrappedHandler:i(t,e)}}function i(t,e){return function(i){e.call(s(t),i||fabric.window.event)}}function r(t,e){return function(i){if(g[t]&&g[t][e])for(var r=g[t][e],n=0,s=r.length;n<s;n++)r[n].call(this,i||fabric.window.event)}}function n(t,e,i){var r="touchend"===t.type?"changedTouches":"touches";return t[r]&&t[r][0]?t[r][0][e]-(t[r][0][e]-t[r][0][i])||t[i]:t[i]}var s,o,a="unknown",h=function(){var t=0;return function(e){return e.__uniqueID||(e.__uniqueID="uniqueID__"+t++)}}();!function(){var t={};s=function(e){return t[e]},o=function(e,i){t[e]=i}}();var c,l,u=t(fabric.document.documentElement,"addEventListener","removeEventListener")&&t(fabric.window,"addEventListener","removeEventListener"),f=t(fabric.document.documentElement,"attachEvent","detachEv
 ent")&&t(fabric.window,"attachEvent","detachEvent"),d={},g={};u?(c=function(t,e,i,r){t&&t.addEventListener(e,i,!f&&r)},l=function(t,e,i,r){t&&t.removeEventListener(e,i,!f&&r)}):f?(c=function(t,i,r){if(t){var n=h(t);o(n,t),d[n]||(d[n]={}),d[n][i]||(d[n][i]=[]);var s=e(n,r);d[n][i].push(s),t.attachEvent("on"+i,s.wrappedHandler)}},l=function(t,e,i){if(t){var r,n=h(t);if(d[n]&&d[n][e])for(var s=0,o=d[n][e].length;s<o;s++)(r=d[n][e][s])&&r.handler===i&&(t.detachEvent("on"+e,r.wrappedHandler),d[n][e][s]=null)}}):(c=function(t,e,i){if(t){var n=h(t);if(g[n]||(g[n]={}),!g[n][e]){g[n][e]=[];var s=t["on"+e];s&&g[n][e].push(s),t["on"+e]=r(n,e)}g[n][e].push(i)}},l=function(t,e,i){if(t){var r=h(t);if(g[r]&&g[r][e])for(var n=g[r][e],s=0,o=n.length;s<o;s++)n[s]===i&&n.splice(s,1)}}),fabric.util.addListener=c,fabric.util.removeListener=l;var p=function(t){return t.clientX},v=function(t){return t.clientY};fabric.isTouchSupported&&(p=function(t){return n(t,"pageX","clientX")},v=function(t){return n(t,
 "pageY","clientY")}),fabric.util.getPointer=function(t){t||(t=fabric.window.event);var e=t.target||(typeof t.srcElement!==a?t.srcElement:null),i=fabric.util.getScrollLeftTop(e);return{x:p(t)+i.left,y:v(t)+i.top}}}(),function(){var t=fabric.document.createElement("div"),e="string"==typeof t.style.opacity,i="string"==typeof t.style.filter,r=/alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,n=function(t){return t};e?n=function(t,e){return t.style.opacity=e,t}:i&&(n=function(t,e){var i=t.style;return t.currentStyle&&!t.currentStyle.hasLayout&&(i.zoom=1),r.test(i.filter)?(e=e>=.9999?"":"alpha(opacity="+100*e+")",i.filter=i.filter.replace(r,e)):i.filter+=" alpha(opacity="+100*e+")",t}),fabric.util.setStyle=function(t,e){var i=t.style;if(!i)return t;if("string"==typeof e)return t.style.cssText+=";"+e,e.indexOf("opacity")>-1?n(t,e.match(/opacity:\s*(\d?\.?\d*)/)[1]):t;for(var r in e)"opacity"===r?n(t,e[r]):i["float"===r||"cssFloat"===r?void 0===i.styleFloat?"cssFloat":"styleFloat":r]=e[r];return t}}(
 ),function(){function t(t,e){var i=fabric.document.createElement(t);for(var r in e)"class"===r?i.className=e[r]:"for"===r?i.htmlFor=e[r]:i.setAttribute(r,e[r]);return i}function e(t){for(var e=0,i=0,r=fabric.document.documentElement,n=fabric.document.body||{scrollLeft:0,scrollTop:0};t&&(t.parentNode||t.host)&&((t=t.parentNode||t.host)===fabric.document?(e=n.scrollLeft||r.scrollLeft||0,i=n.scrollTop||r.scrollTop||0):(e+=t.scrollLeft||0,i+=t.scrollTop||0),1!==t.nodeType||"fixed"!==fabric.util.getElementStyle(t,"position")););return{left:e,top:i}}var i,r=Array.prototype.slice,n=function(t){return r.call(t,0)};try{i=n(fabric.document.childNodes)instanceof Array}catch(t){}i||(n=function(t){for(var e=new Array(t.length),i=t.length;i--;)e[i]=t[i];return e});var s;s=fabric.document.defaultView&&fabric.document.defaultView.getComputedStyle?function(t,e){var i=fabric.document.defaultView.getComputedStyle(t,null);return i?i[e]:void 0}:function(t,e){var i=t.style[e];return!i&&t.currentStyle&&(i
 =t.currentStyle[e]),i},function(){var t=fabric.document.documentElement.style,e="userSelect"in t?"userSelect":"MozUserSelect"in t?"MozUserSelect":"WebkitUserSelect"in t?"WebkitUserSelect":"KhtmlUserSelect"in t?"KhtmlUserSelect":"";fabric.util.makeElementUnselectable=function(t){return void 0!==t.onselectstart&&(t.onselectstart=fabric.util.falseFunction),e?t.style[e]="none":"string"==typeof t.unselectable&&(t.unselectable="on"),t},fabric.util.makeElementSelectable=function(t){return void 0!==t.onselectstart&&(t.onselectstart=null),e?t.style[e]="":"string"==typeof t.unselectable&&(t.unselectable=""),t}}(),function(){fabric.util.getScript=function(t,e){var i=fabric.document.getElementsByTagName("head")[0],r=fabric.document.createElement("script"),n=!0;r.onload=r.onreadystatechange=function(t){if(n){if("string"==typeof this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)return;n=!1,e(t||fabric.window.event),r=r.onload=r.onreadystatechange=null}},r.src=t,i.appendChi
 ld(r)}}(),fabric.util.getById=function(t){return"string"==typeof t?fabric.document.getElementById(t):t},fabric.util.toArray=n,fabric.util.makeElement=t,fabric.util.addClass=function(t,e){t&&-1===(" "+t.className+" ").indexOf(" "+e+" ")&&(t.className+=(t.className?" ":"")+e)},fabric.util.wrapElement=function(e,i,r){return"string"==typeof i&&(i=t(i,r)),e.parentNode&&e.parentNode.replaceChild(i,e),i.appendChild(e),i},fabric.util.getScrollLeftTop=e,fabric.util.getElementOffset=function(t){var i,r,n=t&&t.ownerDocument,o={left:0,top:0},a={left:0,top:0},h={borderLeftWidth:"left",borderTopWidth:"top",paddingLeft:"left",paddingTop:"top"};if(!n)return a;for(var c in h)a[h[c]]+=parseInt(s(t,c),10)||0;return i=n.documentElement,void 0!==t.getBoundingClientRect&&(o=t.getBoundingClientRect()),r=e(t),{left:o.left+r.left-(i.clientLeft||0)+a.left,top:o.top+r.top-(i.clientTop||0)+a.top}},fabric.util.getElementStyle=s}(),function(){function t(t,e){return t+(/\?/.test(t)?"&":"?")+e}function e(){}var i=
 function(){for(var t=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0")},function(){return new XMLHttpRequest}],e=t.length;e--;)try{if(t[e]())return t[e]}catch(t){}}();fabric.util.request=function(r,n){n||(n={});var s=n.method?n.method.toUpperCase():"GET",o=n.onComplete||function(){},a=i(),h=n.body||n.parameters;return a.onreadystatechange=function(){4===a.readyState&&(o(a),a.onreadystatechange=e)},"GET"===s&&(h=null,"string"==typeof n.parameters&&(r=t(r,n.parameters))),a.open(s,r,!0),"POST"!==s&&"PUT"!==s||a.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),a.send(h),a}}(),fabric.log=function(){},fabric.warn=function(){},"undefined"!=typeof console&&["log","warn"].forEach(function(t){void 0!==console[t]&&"function"==typeof console[t].apply&&(fabric[t]=function(){return console[t].apply(console,arguments)})}),function(){function t(){return!1}fun
 ction e(){return i.apply(fabric.window,arguments)}var i=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(t){return fabric.window.setTimeout(t,1e3/60)},r=fabric.window.cancelAnimationFrame||fabric.window.clearTimeout;fabric.util.animate=function(i){e(function(r){i||(i={});var n,s=r||+new Date,o=i.duration||500,a=s+o,h=i.onChange||t,c=i.abort||t,l=i.onComplete||t,u=i.easing||function(t,e,i,r){return-i*Math.cos(t/r*(Math.PI/2))+i+e},f="startValue"in i?i.startValue:0,d="endValue"in i?i.endValue:100,g=i.byValue||d-f;i.onStart&&i.onStart(),function t(r){if(c())l(d,1,1);else{var p=(n=r||+new Date)>a?o:n-s,v=p/o,m=u(p,f,g,o),b=Math.abs((m-f)/g);h(m,b,v),n>a?i.onComplete&&i.onComplete():e(t)}}(s)})},fabric.util.requestAnimFrame=e,fabric.util.cancelAnimFrame=function(){return r.apply(fabric.window,arguments)}}(),function(){function t(t,e,
 i){var r="rgba("+parseInt(t[0]+i*(e[0]-t[0]),10)+","+parseInt(t[1]+i*(e[1]-t[1]),10)+","+parseInt(t[2]+i*(e[2]-t[2]),10);return r+=","+(t&&e?parseFloat(t[3]+i*(e[3]-t[3])):1),r+=")"}fabric.util.animateColor=function(e,i,r,n){var s=new fabric.Color(e).getSource(),o=new fabric.Color(i).getSource();n=n||{},fabric.util.animate(fabric.util.object.extend(n,{duration:r||500,startValue:s,endValue:o,byValue:o,easing:function(e,i,r,s){return t(i,r,n.colorEasing?n.colorEasing(e,s):1-Math.cos(e/s*(Math.PI/2)))}}))}}(),function(){function t(t,e,i,r){return t<Math.abs(e)?(t=e,r=i/4):r=0===e&&0===t?i/(2*Math.PI)*Math.asin(1):i/(2*Math.PI)*Math.asin(e/t),{a:t,c:e,p:i,s:r}}function e(t,e,i){return t.a*Math.pow(2,10*(e-=1))*Math.sin((e*i-t.s)*(2*Math.PI)/t.p)}function i(t,e,i,n){return i-r(n-t,0,i,n)+e}function r(t,e,i,r){return(t/=r)<1/2.75?i*(7.5625*t*t)+e:t<2/2.75?i*(7.5625*(t-=1.5/2.75)*t+.75)+e:t<2.5/2.75?i*(7.5625*(t-=2.25/2.75)*t+.9375)+e:i*(7.5625*(t-=2.625/2.75)*t+.984375)+e}fabric.util.ease
 ={easeInQuad:function(t,e,i,r){return i*(t/=r)*t+e},easeOutQuad:function(t,e,i,r){return-i*(t/=r)*(t-2)+e},easeInOutQuad:function(t,e,i,r){return(t/=r/2)<1?i/2*t*t+e:-i/2*(--t*(t-2)-1)+e},easeInCubic:function(t,e,i,r){return i*(t/=r)*t*t+e},easeOutCubic:function(t,e,i,r){return i*((t=t/r-1)*t*t+1)+e},easeInOutCubic:function(t,e,i,r){return(t/=r/2)<1?i/2*t*t*t+e:i/2*((t-=2)*t*t+2)+e},easeInQuart:function(t,e,i,r){return i*(t/=r)*t*t*t+e},easeOutQuart:function(t,e,i,r){return-i*((t=t/r-1)*t*t*t-1)+e},easeInOutQuart:function(t,e,i,r){return(t/=r/2)<1?i/2*t*t*t*t+e:-i/2*((t-=2)*t*t*t-2)+e},easeInQuint:function(t,e,i,r){return i*(t/=r)*t*t*t*t+e},easeOutQuint:function(t,e,i,r){return i*((t=t/r-1)*t*t*t*t+1)+e},easeInOutQuint:function(t,e,i,r){return(t/=r/2)<1?i/2*t*t*t*t*t+e:i/2*((t-=2)*t*t*t*t+2)+e},easeInSine:function(t,e,i,r){return-i*Math.cos(t/r*(Math.PI/2))+i+e},easeOutSine:function(t,e,i,r){return i*Math.sin(t/r*(Math.PI/2))+e},easeInOutSine:function(t,e,i,r){return-i/2*(Math.cos(
 Math.PI*t/r)-1)+e},easeInExpo:function(t,e,i,r){return 0===t?e:i*Math.pow(2,10*(t/r-1))+e},easeOutExpo:function(t,e,i,r){return t===r?e+i:i*(1-Math.pow(2,-10*t/r))+e},easeInOutExpo:function(t,e,i,r){return 0===t?e:t===r?e+i:(t/=r/2)<1?i/2*Math.pow(2,10*(t-1))+e:i/2*(2-Math.pow(2,-10*--t))+e},easeInCirc:function(t,e,i,r){return-i*(Math.sqrt(1-(t/=r)*t)-1)+e},easeOutCirc:function(t,e,i,r){return i*Math.sqrt(1-(t=t/r-1)*t)+e},easeInOutCirc:function(t,e,i,r){return(t/=r/2)<1?-i/2*(Math.sqrt(1-t*t)-1)+e:i/2*(Math.sqrt(1-(t-=2)*t)+1)+e},easeInElastic:function(i,r,n,s){var o=0,a=n;return 0===i?r:1==(i/=s)?r+n:(o||(o=.3*s),-e(t(a,n,o,1.70158),i,s)+r)},easeOutElastic:function(e,i,r,n){var s=0,o=r;if(0===e)return i;if(1==(e/=n))return i+r;s||(s=.3*n);var a=t(o,r,s,1.70158);return a.a*Math.pow(2,-10*e)*Math.sin((e*n-a.s)*(2*Math.PI)/a.p)+a.c+i},easeInOutElastic:function(i,r,n,s){var o=0,a=n;if(0===i)return r;if(2==(i/=s/2))return r+n;o||(o=s*(.3*1.5));var h=t(a,n,o,1.70158);return i<1?-.5*e(h,
 i,s)+r:h.a*Math.pow(2,-10*(i-=1))*Math.sin((i*s-h.s)*(2*Math.PI)/h.p)*.5+h.c+r},easeInBack:function(t,e,i,r,n){return void 0===n&&(n=1.70158),i*(t/=r)*t*((n+1)*t-n)+e},easeOutBack:function(t,e,i,r,n){return void 0===n&&(n=1.70158),i*((t=t/r-1)*t*((n+1)*t+n)+1)+e},easeInOutBack:function(t,e,i,r,n){return void 0===n&&(n=1.70158),(t/=r/2)<1?i/2*(t*t*((1+(n*=1.525))*t-n))+e:i/2*((t-=2)*t*((1+(n*=1.525))*t+n)+2)+e},easeInBounce:i,easeOutBounce:r,easeInOutBounce:function(t,e,n,s){return t<s/2?.5*i(2*t,0,n,s)+e:.5*r(2*t-s,0,n,s)+.5*n+e}}}(),function(t){"use strict";function e(t){return t in O?O[t]:t}function i(t,e,i,r){var n,s="[object Array]"===Object.prototype.toString.call(e);if("fill"!==t&&"stroke"!==t||"none"!==e)if("strokeDashArray"===t)e="none"===e?null:e.replace(/,/g," ").split(/\s+/).map(function(t){return parseFloat(t)});else if("transformMatrix"===t)e=i&&i.transformMatrix?x(i.transformMatrix,v.parseTransformAttribute(e)):v.parseTransformAttribute(e);else if("visible"===t)e="none
 "!==e&&"hidden"!==e,i&&!1===i.visible&&(e=!1);else if("opacity"===t)e=parseFloat(e),i&&void 0!==i.opacity&&(e*=i.opacity);else if("textAnchor"===t)e="start"===e?"left":"end"===e?"right":"center";else if("paintFirst"===t){var o=e.indexOf("fill"),a=e.indexOf("stroke"),e="fill";o>-1&&a>-1&&a<o?e="stroke":-1===o&&a>-1&&(e="stroke")}else n=s?e.map(y):y(e,r);else e="";return!s&&isNaN(n)?e:n}function r(t){return new RegExp("^("+t.join("|")+")\\b","i")}function n(t){for(var e in k)if(void 0!==t[k[e]]&&""!==t[e]){if(void 0===t[e]){if(!v.Object.prototype[e])continue;t[e]=v.Object.prototype[e]}if(0!==t[e].indexOf("url(")){var i=new v.Color(t[e]);t[e]=i.setAlpha(_(i.getAlpha()*t[k[e]],2)).toRgba()}}return t}function s(t,e){var i,r,n,s,o=[];for(n=0,s=e.length;n<s;n++)i=e[n],r=t.getElementsByTagName(i),o=o.concat(Array.prototype.slice.call(r));return o}function o(t,e){var i,r;t.replace(/;\s*$/,"").split(";").forEach(function(t){var n=t.split(":");i=n[0].trim().toLowerCase(),r=n[1].trim(),e[i]=r})
 }function a(t,e){var i,r;for(var n in t)void 0!==t[n]&&(i=n.toLowerCase(),r=t[n],e[i]=r)}function h(t,e){var i={};for(var r in v.cssRules[e])if(c(t,r.split(" ")))for(var n in v.cssRules[e][r])i[n]=v.cssRules[e][r][n];return i}function c(t,e){var i,r=!0;return(i=u(t,e.pop()))&&e.length&&(r=l(t,e)),i&&r&&0===e.length}function l(t,e){for(var i,r=!0;t.parentNode&&1===t.parentNode.nodeType&&e.length;)r&&(i=e.pop()),r=u(t=t.parentNode,i);return 0===e.length}function u(t,e){var i,r,n=t.nodeName,s=t.getAttribute("class"),o=t.getAttribute("id");if(i=new RegExp("^"+n,"i"),e=e.replace(i,""),o&&e.length&&(i=new RegExp("#"+o+"(?![a-zA-Z\\-]+)","i"),e=e.replace(i,"")),s&&e.length)for(r=(s=s.split(" ")).length;r--;)i=new RegExp("\\."+s[r]+"(?![a-zA-Z\\-]+)","i"),e=e.replace(i,"");return 0===e.length}function f(t,e){var i;if(t.getElementById&&(i=t.getElementById(e)),i)return i;var r,n,s,o=t.getElementsByTagName("*");for(n=0,s=o.length;n<s;n++)if(r=o[n],e===r.getAttribute("id"))return r}function d(t
 ){for(var e=s(t,["use","svg:use"]),i=0;e.length&&i<e.length;){var r,n,o,a,h=e[i],c=h.getAttribute("xlink:href").substr(1),l=h.getAttribute("x")||0,u=h.getAttribute("y")||0,d=f(t,c).cloneNode(!0),p=(d.getAttribute("transform")||"")+" translate("+l+", "+u+")",v=e.length;if(g(d),/^svg$/i.test(d.nodeName)){var m=d.ownerDocument.createElement("g");for(n=0,a=(o=d.attributes).length;n<a;n++)r=o.item(n),m.setAttribute(r.nodeName,r.nodeValue);for(;d.firstChild;)m.appendChild(d.firstChild);d=m}for(n=0,a=(o=h.attributes).length;n<a;n++)"x"!==(r=o.item(n)).nodeName&&"y"!==r.nodeName&&"xlink:href"!==r.nodeName&&("transform"===r.nodeName?p=r.nodeValue+" "+p:d.setAttribute(r.nodeName,r.nodeValue));d.setAttribute("transform",p),d.setAttribute("instantiated_by_use","1"),d.removeAttribute("id"),h.parentNode.replaceChild(d,h),e.length===v&&i++}}function g(t){var e,i,r,n,s=t.getAttribute("viewBox"),o=1,a=1,h=0,c=0,l=t.getAttribute("width"),u=t.getAttribute("height"),f=t.getAttribute("x")||0,d=t.getAttr
 ibute("y")||0,g=t.getAttribute("preserveAspectRatio")||"",p=!s||!v.svgViewBoxElementsRegEx.test(t.nodeName)||!(s=s.match(D)),m=!l||!u||"100%"===l||"100%"===u,b=p&&m,_={},x="";if(_.width=0,_.height=0,_.toBeParsed=b,b)return _;if(p)return _.width=y(l),_.height=y(u),_;if(h=-parseFloat(s[1]),c=-parseFloat(s[2]),e=parseFloat(s[3]),i=parseFloat(s[4]),m?(_.width=e,_.height=i):(_.width=y(l),_.height=y(u),o=_.width/e,a=_.height/i),"none"!==(g=v.util.parsePreserveAspectRatioAttribute(g)).alignX&&(a=o=o>a?a:o),1===o&&1===a&&0===h&&0===c&&0===f&&0===d)return _;if((f||d)&&(x=" translate("+y(f)+" "+y(d)+") "),r=x+" matrix("+o+" 0 0 "+a+" "+h*o+" "+c*a+") ","svg"===t.nodeName){for(n=t.ownerDocument.createElement("g");t.firstChild;)n.appendChild(t.firstChild);t.appendChild(n)}else r=(n=t).getAttribute("transform")+r;return n.setAttribute("transform",r),_}function p(t,e){for(;t&&(t=t.parentNode);)if(t.nodeName&&e.test(t.nodeName.replace("svg:",""))&&!t.getAttribute("instantiated_by_use"))return!0;re
 turn!1}var v=t.fabric||(t.fabric={}),m=v.util.object.extend,b=v.util.object.clone,_=v.util.toFixed,y=v.util.parseUnit,x=v.util.multiplyTransformMatrices,C=["path","circle","polygon","polyline","ellipse","rect","line","image","text","linearGradient","radialGradient","stop"],S=["symbol","image","marker","pattern","view","svg"],w=["pattern","defs","symbol","metadata","clipPath","mask","desc"],T=["symbol","g","a","svg"],O={cx:"left",x:"left",r:"radius",cy:"top",y:"top",display:"visible",visibility:"visible",transform:"transformMatrix","fill-opacity":"fillOpacity","fill-rule":"fillRule","font-family":"fontFamily","font-size":"fontSize","font-style":"fontStyle","font-weight":"fontWeight","paint-order":"paintFirst","stroke-dasharray":"strokeDashArray","stroke-linecap":"strokeLineCap","stroke-linejoin":"strokeLineJoin","stroke-miterlimit":"strokeMiterLimit","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","text-decoration":"textDecoration","text-anchor":"textAnchor",opacity:"op
 acity"},k={stroke:"strokeOpacity",fill:"fillOpacity"};v.svgValidTagNamesRegEx=r(C),v.svgViewBoxElementsRegEx=r(S),v.svgInvalidAncestorsRegEx=r(w),v.svgValidParentsRegEx=r(T),v.cssRules={},v.gradientDefs={},v.parseTransformAttribute=function(){function t(t,e){var i=Math.cos(e[0]),r=Math.sin(e[0]),n=0,s=0;3===e.length&&(n=e[1],s=e[2]),t[0]=i,t[1]=r,t[2]=-r,t[3]=i,t[4]=n-(i*n-r*s),t[5]=s-(r*n+i*s)}function e(t,e){var i=e[0],r=2===e.length?e[1]:e[0];t[0]=i,t[3]=r}function i(t,e,i){t[i]=Math.tan(v.util.degreesToRadians(e[0]))}function r(t,e){t[4]=e[0],2===e.length&&(t[5]=e[1])}var n=[1,0,0,1,0,0],s=v.reNum,o="(?:\\s+,?\\s*|,\\s*)",a="(?:"+("(?:(matrix)\\s*\\(\\s*("+s+")"+o+"("+s+")"+o+"("+s+")"+o+"("+s+")"+o+"("+s+")"+o+"("+s+")\\s*\\))")+"|"+("(?:(translate)\\s*\\(\\s*("+s+")(?:"+o+"("+s+"))?\\s*\\))")+"|"+("(?:(scale)\\s*\\(\\s*("+s+")(?:"+o+"("+s+"))?\\s*\\))")+"|"+("(?:(rotate)\\s*\\(\\s*("+s+")(?:"+o+"("+s+")"+o+"("+s+"))?\\s*\\))")+"|"+("(?:(skewX)\\s*\\(\\s*("+s+")\\s*\\))")+"|"+(
 "(?:(skewY)\\s*\\(\\s*("+s+")\\s*\\))")+")",h="^\\s*(?:"+("(?:"+a+"(?:"+o+"*"+a+")*)")+"?)\\s*$",c=new RegExp(h),l=new RegExp(a,"g");return function(s){var o=n.concat(),h=[];if(!s||s&&!c.test(s))return o;s.replace(l,function(s){var c=new RegExp(a).exec(s).filter(function(t){return!!t}),l=c[1],u=c.slice(2).map(parseFloat);switch(l){case"translate":r(o,u);break;case"rotate":u[0]=v.util.degreesToRadians(u[0]),t(o,u);break;case"scale":e(o,u);break;case"skewX":i(o,u,2);break;case"skewY":i(o,u,1);break;case"matrix":o=u}h.push(o.concat()),o=n.concat()});for(var u=h[0];h.length>1;)h.shift(),u=v.util.multiplyTransformMatrices(u,h[0]);return u}}();var D=new RegExp("^\\s*("+v.reNum+"+)\\s*,?\\s*("+v.reNum+"+)\\s*,?\\s*("+v.reNum+"+)\\s*,?\\s*("+v.reNum+"+)\\s*$");v.parseSVGDocument=function(t,e,i,r){if(t){d(t);var n,s,o=v.Object.__uid++,a=g(t),h=v.util.toArray(t.getElementsByTagName("*"));if(a.crossOrigin=r&&r.crossOrigin,a.svgUid=o,0===h.length&&v.isLikelyNode){var c=[];for(n=0,s=(h=t.selectN
 odes('//*[name(.)!="svg"]')).length;n<s;n++)c[n]=h[n];h=c}var l=h.filter(function(t){return g(t),v.svgValidTagNamesRegEx.test(t.nodeName.replace("svg:",""))&&!p(t,v.svgInvalidAncestorsRegEx)});!l||l&&!l.length?e&&e([],{}):(v.gradientDefs[o]=v.getGradientDefs(t),v.cssRules[o]=v.getCSSRules(t),v.parseElements(l,function(t,i){e&&e(t,a,i,h)},b(a),i,r))}};var E=new RegExp("(normal|italic)?\\s*(normal|small-caps)?\\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*("+v.reNum+"(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|"+v.reNum+"))?\\s+(.*)");m(v,{parseFontDeclaration:function(t,e){var i=t.match(E);if(i){var r=i[1],n=i[3],s=i[4],o=i[5],a=i[6];r&&(e.fontStyle=r),n&&(e.fontWeight=isNaN(parseFloat(n))?n:parseFloat(n)),s&&(e.fontSize=y(s)),a&&(e.fontFamily=a),o&&(e.lineHeight="normal"===o?1:o)}},getGradientDefs:function(t){var e,i,r,n=s(t,["linearGradient","radialGradient","svg:linearGradient","svg:radialGradient"]),o=0,a={},h={};for(o=n.length;o--;)r=(e=n[o]).getAttribute("
 xlink:href"),i=e.getAttribute("id"),r&&(h[i]=r.substr(1)),a[i]=e;for(i in h){var c=a[h[i]].cloneNode(!0);for(e=a[i];c.firstChild;)e.appendChild(c.firstChild)}return a},parseAttributes:function(t,r,s){if(t){var o,a,c={};void 0===s&&(s=t.getAttribute("svgUid")),t.parentNode&&v.svgValidParentsRegEx.test(t.parentNode.nodeName)&&(c=v.parseAttributes(t.parentNode,r,s)),a=c&&c.fontSize||t.getAttribute("font-size")||v.Text.DEFAULT_SVG_FONT_SIZE;var l=r.reduce(function(e,i){return(o=t.getAttribute(i))&&(e[i]=o),e},{});l=m(l,m(h(t,s),v.parseStyleAttribute(t)));var u,f,d={};for(var g in l)f=i(u=e(g),l[g],c,a),d[u]=f;d&&d.font&&v.parseFontDeclaration(d.font,d);var p=m(c,d);return v.svgValidParentsRegEx.test(t.nodeName)?p:n(p)}},parseElements:function(t,e,i,r,n){new v.ElementsParser(t,e,i,r,n).parse()},parseStyleAttribute:function(t){var e={},i=t.getAttribute("style");return i?("string"==typeof i?o(i,e):a(i,e),e):e},parsePointsAttribute:function(t){if(!t)return null;var e,i,r=[];for(e=0,i=(t=(t=
 t.replace(/,/g," ").trim()).split(/\s+/)).length;e<i;e+=2)r.push({x:parseFloat(t[e]),y:parseFloat(t[e+1])});return r},getCSSRules:function(t){var e,i,r=t.getElementsByTagName("style"),n={};for(e=0,i=r.length;e<i;e++){var s=r[e].textContent||r[e].text;""!==(s=s.replace(/\/\*[\s\S]*?\*\//g,"")).trim()&&s.match(/[^{]*\{[\s\S]*?\}/g).map(function(t){return t.trim()}).forEach(function(t){var r=t.match(/([\s\S]*?)\s*\{([^}]*)\}/),s={},o=r[2].trim().replace(/;$/,"").split(/\s*;\s*/);for(e=0,i=o.length;e<i;e++){var a=o[e].split(/\s*:\s*/),h=a[0],c=a[1];s[h]=c}(t=r[1]).split(",").forEach(function(t){""!==(t=t.replace(/^svg/i,"").trim())&&(n[t]?v.util.object.extend(n[t],s):n[t]=v.util.object.clone(s))})})}return n},loadSVGFromURL:function(t,e,i,r){t=t.replace(/^\n\s*/,"").trim(),new v.util.request(t,{method:"get",onComplete:function(t){var n=t.responseXML;n&&!n.documentElement&&v.window.ActiveXObject&&t.responseText&&((n=new ActiveXObject("Microsoft.XMLDOM")).async="false",n.loadXML(t.respons
 eText.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i,""))),n&&n.documentElement||e&&e(null),v.parseSVGDocument(n.documentElement,function(t,i,r,n){e&&e(t,i,r,n)},i,r)}})},loadSVGFromString:function(t,e,i,r){t=t.trim();var n;if("undefined"!=typeof DOMParser){var s=new DOMParser;s&&s.parseFromString&&(n=s.parseFromString(t,"text/xml"))}else v.window.ActiveXObject&&((n=new ActiveXObject("Microsoft.XMLDOM")).async="false",n.loadXML(t.replace(/<!DOCTYPE[\s\S]*?(\[[\s\S]*\])*?>/i,"")));v.parseSVGDocument(n.documentElement,function(t,i,r,n){e(t,i,r,n)},i,r)}})}("undefined"!=typeof exports?exports:this),fabric.ElementsParser=function(t,e,i,r,n){this.elements=t,this.callback=e,this.options=i,this.reviver=r,this.svgUid=i&&i.svgUid||0,this.parsingOptions=n},fabric.ElementsParser.prototype.parse=function(){this.instances=new Array(this.elements.length),this.numElements=this.elements.length,this.createObjects()},fabric.ElementsParser.prototype.createObjects=function(){for(var t=0,e=this.elements.l
 ength;t<e;t++)this.elements[t].setAttribute("svgUid",this.svgUid),function(t,e){setTimeout(function(){t.createObject(t.elements[e],e)},0)}(this,t)},fabric.ElementsParser.prototype.createObject=function(t,e){var i=fabric[fabric.util.string.capitalize(t.tagName.replace("svg:",""))];if(i&&i.fromElement)try{this._createObject(i,t,e)}catch(t){fabric.log(t)}else this.checkIfDone()},fabric.ElementsParser.prototype._createObject=function(t,e,i){t.fromElement(e,this.createCallback(i,e),this.options)},fabric.ElementsParser.prototype.createCallback=function(t,e){var i=this;return function(r){var n;i.resolveGradient(r,"fill"),i.resolveGradient(r,"stroke"),r instanceof fabric.Image&&(n=r.parsePreserveAspectRatioAttribute(e)),r._removeTransformMatrix(n),i.reviver&&i.reviver(e,r),i.instances[t]=r,i.checkIfDone()}},fabric.ElementsParser.prototype.resolveGradient=function(t,e){var i=t.get(e);if(/^url\(/.test(i)){var r=i.slice(5,i.length-1);fabric.gradientDefs[this.svgUid][r]&&t.set(e,fabric.Gradient
 .fromElement(fabric.gradientDefs[this.svgUid][r],t))}},fabric.ElementsParser.prototype.checkIfDone=function(){0==--this.numElements&&(this.instances=this.instances.filter(function(t){return null!=t}),this.callback(this.instances,this.elements))},function(t){"use strict";function e(t,e){this.x=t,this.y=e}var i=t.fabric||(t.fabric={});i.Point?i.warn("fabric.Point is already defined"):(i.Point=e,e.prototype={type:"point",constructor:e,add:function(t){return new e(this.x+t.x,this.y+t.y)},addEquals:function(t){return this.x+=t.x,this.y+=t.y,this},scalarAdd:function(t){return new e(this.x+t,this.y+t)},scalarAddEquals:function(t){return this.x+=t,this.y+=t,this},subtract:function(t){return new e(this.x-t.x,this.y-t.y)},subtractEquals:function(t){return this.x-=t.x,this.y-=t.y,this},scalarSubtract:function(t){return new e(this.x-t,this.y-t)},scalarSubtractEquals:function(t){return this.x-=t,this.y-=t,this},multiply:function(t){return new e(this.x*t,this.y*t)},multiplyEquals:function(t){retu
 rn this.x*=t,this.y*=t,this},divide:function(t){return new e(this.x/t,this.y/t)},divideEquals:function(t){return this.x/=t,this.y/=t,this},eq:function(t){return this.x===t.x&&this.y===t.y},lt:function(t){return this.x<t.x&&this.y<t.y},lte:function(t){return this.x<=t.x&&this.y<=t.y},gt:function(t){return this.x>t.x&&this.y>t.y},gte:function(t){return this.x>=t.x&&this.y>=t.y},lerp:function(t,i){return void 0===i&&(i=.5),i=Math.max(Math.min(1,i),0),new e(this.x+(t.x-this.x)*i,this.y+(t.y-this.y)*i)},distanceFrom:function(t){var e=this.x-t.x,i=this.y-t.y;return Math.sqrt(e*e+i*i)},midPointFrom:function(t){return this.lerp(t)},min:function(t){return new e(Math.min(this.x,t.x),Math.min(this.y,t.y))},max:function(t){return new e(Math.max(this.x,t.x),Math.max(this.y,t.y))},toString:function(){return this.x+","+this.y},setXY:function(t,e){return this.x=t,this.y=e,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setFromPoint:function(t){return this.x=t.x,t
 his.y=t.y,this},swap:function(t){var e=this.x,i=this.y;this.x=t.x,this.y=t.y,t.x=e,t.y=i},clone:function(){return new e(this.x,this.y)}})}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){this.status=t,this.points=[]}var i=t.fabric||(t.fabric={});i.Intersection?i.warn("fabric.Intersection is already defined"):(i.Intersection=e,i.Intersection.prototype={constructor:e,appendPoint:function(t){return this.points.push(t),this},appendPoints:function(t){return this.points=this.points.concat(t),this}},i.Intersection.intersectLineLine=function(t,r,n,s){var o,a=(s.x-n.x)*(t.y-n.y)-(s.y-n.y)*(t.x-n.x),h=(r.x-t.x)*(t.y-n.y)-(r.y-t.y)*(t.x-n.x),c=(s.y-n.y)*(r.x-t.x)-(s.x-n.x)*(r.y-t.y);if(0!==c){var l=a/c,u=h/c;0<=l&&l<=1&&0<=u&&u<=1?(o=new e("Intersection")).appendPoint(new i.Point(t.x+l*(r.x-t.x),t.y+l*(r.y-t.y))):o=new e}else o=new e(0===a||0===h?"Coincident":"Parallel");return o},i.Intersection.intersectLinePolygon=function(t,i,r){var n,s,o,a,h=new e,c=r.lengt
 h;for(a=0;a<c;a++)n=r[a],s=r[(a+1)%c],o=e.intersectLineLine(t,i,n,s),h.appendPoints(o.points);return h.points.length>0&&(h.status="Intersection"),h},i.Intersection.intersectPolygonPolygon=function(t,i){var r,n=new e,s=t.length;for(r=0;r<s;r++){var o=t[r],a=t[(r+1)%s],h=e.intersectLinePolygon(o,a,i);n.appendPoints(h.points)}return n.points.length>0&&(n.status="Intersection"),n},i.Intersection.intersectPolygonRectangle=function(t,r,n){var s=r.min(n),o=r.max(n),a=new i.Point(o.x,s.y),h=new i.Point(s.x,o.y),c=e.intersectLinePolygon(s,a,t),l=e.intersectLinePolygon(a,o,t),u=e.intersectLinePolygon(o,h,t),f=e.intersectLinePolygon(h,s,t),d=new e;return d.appendPoints(c.points),d.appendPoints(l.points),d.appendPoints(u.points),d.appendPoints(f.points),d.points.length>0&&(d.status="Intersection"),d})}("undefined"!=typeof exports?exports:this),function(t){"use strict";function e(t){t?this._tryParsingColor(t):this.setSource([0,0,0,1])}function i(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e
 -t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t}var r=t.fabric||(t.fabric={});r.Color?r.warn("fabric.Color is already defined."):(r.Color=e,r.Color.prototype={_tryParsingColor:function(t){var i;t in e.colorNameMap&&(t=e.colorNameMap[t]),"transparent"===t&&(i=[255,255,255,0]),i||(i=e.sourceFromHex(t)),i||(i=e.sourceFromRgb(t)),i||(i=e.sourceFromHsl(t)),i||(i=[0,0,0,1]),i&&this.setSource(i)},_rgbToHsl:function(t,e,i){t/=255,e/=255,i/=255;var n,s,o,a=r.util.array.max([t,e,i]),h=r.util.array.min([t,e,i]);if(o=(a+h)/2,a===h)n=s=0;else{var c=a-h;switch(s=o>.5?c/(2-a-h):c/(a+h),a){case t:n=(e-i)/c+(e<i?6:0);break;case e:n=(i-t)/c+2;break;case i:n=(t-e)/c+4}n/=6}return[Math.round(360*n),Math.round(100*s),Math.round(100*o)]},getSource:function(){return this._source},setSource:function(t){this._source=t},toRgb:function(){var t=this.getSource();return"rgb("+t[0]+","+t[1]+","+t[2]+")"},toRgba:function(){var t=this.getSource();return"rgba("+t[0]+","+t[1]+","+t[2]+","+t[3]+")"},toHsl:function(){var t=this
 .getSource(),e=this._rgbToHsl(t[0],t[1],t[2]);return"hsl("+e[0]+","+e[1]+"%,"+e[2]+"%)"},toHsla:function(){var t=this.getSource(),e=this._rgbToHsl(t[0],t[1],t[2]);return"hsla("+e[0]+","+e[1]+"%,"+e[2]+"%,"+t[3]+")"},toHex:function(){var t,e,i,r=this.getSource();return t=r[0].toString(16),t=1===t.length?"0"+t:t,e=r[1].toString(16),e=1===e.length?"0"+e:e,i=r[2].toString(16),i=1===i.length?"0"+i:i,t.toUpperCase()+e.toUpperCase()+i.toUpperCase()},toHexa:function(){var t;return t=255*this.getSource()[3],t=t.toString(16),t=1===t.length?"0"+t:t,this.toHex()+t.toUpperCase()},getAlpha:function(){return this.getSource()[3]},setAlpha:function(t){var e=this.getSource();return e[3]=t,this.setSource(e),this},toGrayscale:function(){var t=this.getSource(),e=parseInt((.3*t[0]+.59*t[1]+.11*t[2]).toFixed(0),10),i=t[3];return this.setSource([e,e,e,i]),this},toBlackWhite:function(t){var e=this.getSource(),i=(.3*e[0]+.59*e[1]+.11*e[2]).toFixed(0),r=e[3];return t=t||127,i=Number(i)<Number(t)?0:255,this.se
 tSource([i,i,i,r]),this},overlayWith:function(t){t instanceof e||(t=new e(t));var i,r=[],n=this.getAlpha(),s=this.getSource(),o=t.getSource();for(i=0;i<3;i++)r.push(Math.round(.5*s[i]+.5*o[i]));return r[3]=n,this.setSource(r),this}},r.Color.reRGBa=/^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*((?:\d*\.?\d+)?)\s*)?\)$/,r.Color.reHSLa=/^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/,r.Color.reHex=/^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i,r.Color.colorNameMap={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aqua:"#00FFFF",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blue:"#0000FF",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",d
 arkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgrey:"#A9A9A9",darkgreen:"#006400",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",fuchsia:"#FF00FF",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",l
 ightgray:"#D3D3D3",lightgrey:"#D3D3D3",lightgreen:"#90EE90",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",lime:"#00FF00",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",maroon:"#800000",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",navy:"#000080",oldlace:"#FDF5E6",olive:"#808000",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",purple:"#80008
 0",rebeccapurple:"#663399",red:"#FF0000",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",silver:"#C0C0C0",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",teal:"#008080",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",white:"#FFFFFF",whitesmoke:"#F5F5F5",yellow:"#FFFF00",yellowgreen:"#9ACD32"},r.Color.fromRgb=function(t){return e.fromSource(e.sourceFromRgb(t))},r.Color.sourceFromRgb=function(t){var i=t.match(e.reRGBa);if(i){var r=parseInt(i[1],10)/(/%$/.test(i[1])?100:1)*(/%$/.test(i[1])?255:1),n=parseInt(i[2],10)/(/%$/.test(i[2])?100:1)*(/%$/.test(i[2])?255:1),s=parseInt(i[3],10)/(/%$/.test(i[3])?100:1)*(/%$/.test(i[3])?255:1);return[parseInt(r,10),parseInt(n,10),parseInt(s,10),i[4]?parseFloat(i[4]):1]}},r.Color.fromRgba=e.fromRgb,r.Color.
 fromHsl=function(t){return e.fromSource(e.sourceFromHsl(t))},r.Color.sourceFromHsl=function(t){var r=t.match(e.reHSLa);if(r){var n,s,o,a=(parseFloat(r[1])%360+360)%360/360,h=parseFloat(r[2])/(/%$/.test(r[2])?100:1),c=parseFloat(r[3])/(/%$/.test(r[3])?100:1);if(0===h)n=s=o=c;else{var l=c<=.5?c*(h+1):c+h-c*h,u=2*c-l;n=i(u,l,a+1/3),s=i(u,l,a),o=i(u,l,a-1/3)}return[Math.round(255*n),Math.round(255*s),Math.round(255*o),r[4]?parseFloat(r[4]):1]}},r.Color.fromHsla=e.fromHsl,r.Color.fromHex=function(t){return e.fromSource(e.sourceFromHex(t))},r.Color.sourceFromHex=function(t){if(t.match(e.reHex)){var i=t.slice(t.indexOf("#")+1),r=3===i.length||4===i.length,n=8===i.length||4===i.length,s=r?i.charAt(0)+i.charAt(0):i.substring(0,2),o=r?i.charAt(1)+i.charAt(1):i.substring(2,4),a=r?i.charAt(2)+i.charAt(2):i.substring(4,6),h=n?r?i.charAt(3)+i.charAt(3):i.substring(6,8):"FF";return[parseInt(s,16),parseInt(o,16),parseInt(a,16),parseFloat((parseInt(h,16)/255).toFixed(2))]}},r.Color.fromSource=functi
 on(t){var i=new e;return i.setSource(t),i})}("undefined"!=typeof exports?exports:this),function(){function t(t){var e,i,r,n,s=t.getAttribute("style"),o=t.getAttribute("offset")||0;if(o=parseFloat(o)/(/%$/.test(o)?100:1),o=o<0?0:o>1?1:o,s){var a=s.split(/\s*;\s*/);for(""===a[a.length-1]&&a.pop(),n=a.length;n--;){var h=a[n].split(/\s*:\s*/),c=h[0].trim(),l=h[1].trim();"stop-color"===c?e=l:"stop-opacity"===c&&(r=l)}}return e||(e=t.getAttribute("stop-color")||"rgb(0,0,0)"),r||(r=t.getAttribute("stop-opacity")),e=new fabric.Color(e),i=e.getAlpha(),r=isNaN(parseFloat(r))?1:parseFloat(r),r*=i,{offset:o,color:e.toRgb(),opacity:r}}function e(t){return{x1:t.getAttribute("x1")||0,y1:t.getAttribute("y1")||0,x2:t.getAttribute("x2")||"100%",y2:t.getAttribute("y2")||0}}function i(t){return{x1:t.getAttribute("fx")||t.getAttribute("cx")||"50%",y1:t.getAttribute("fy")||t.getAttribute("cy")||"50%",r1:0,x2:t.getAttribute("cx")||"50%",y2:t.getAttribute("cy")||"50%",r2:t.getAttribute("r")||"50%"}}functio
 n r(t,e,i){var r,n=0,s=1,o="";for(var a in e)"Infinity"===e[a]?e[a]=1:"-Infinity"===e[a]&&(e[a]=0),r=parseFloat(e[a],10),s="string"==typeof e[a]&&/^\d+%$/.test(e[a])?.01:1,"x1"===a||"x2"===a||"r2"===a?(s*="objectBoundingBox"===i?t.width:1,n="objectBoundingBox"===i?t.left||0:0):"y1"!==a&&"y2"!==a||(s*="objectBoundingBox"===i?t.height:1,n="objectBoundingBox"===i?t.top||0:0),e[a]=r*s+n;if("ellipse"===t.type&&null!==e.r2&&"objectBoundingBox"===i&&t.rx!==t.ry){var h=t.ry/t.rx;o=" scale(1, "+h+")",e.y1&&(e.y1/=h),e.y2&&(e.y2/=h)}return o}var n=fabric.util.object.clone;fabric.Gradient=fabric.util.createClass({offsetX:0,offsetY:0,initialize:function(t){t||(t={});var e={};this.id=fabric.Object.__uid++,this.type=t.type||"linear",e={x1:t.coords.x1||0,y1:t.coords.y1||0,x2:t.coords.x2||0,y2:t.coords.y2||0},"radial"===this.type&&(e.r1=t.coords.r1||0,e.r2=t.coords.r2||0),this.coords=e,this.colorStops=t.colorStops.slice(),t.gradientTransform&&(this.gradientTransform=t.gradientTransform),this.offset
 X=t.offsetX||this.offsetX,this.offsetY=t.offsetY||this.offsetY},addColorStop:function(t){for(var e in t){var i=new fabric.Color(t[e]);this.colorStops.push({offset:parseFloat(e),color:i.toRgb(),opacity:i.getAlpha()})}return this},toObject:function(t){var e={type:this.type,coords:this.coords,colorStops:this.colorStops,offsetX:this.offsetX,offsetY:this.offsetY,gradientTransform:this.gradientTransform?this.gradientTransform.concat():this.gradientTransform};return fabric.util.populateWithProperties(this,e,t),e},toSVG:function(t){var e,i,r,s,o=n(this.coords,!0),a=n(this.colorStops,!0),h=o.r1>o.r2,c=t.width/2,l=t.height/2;a.sort(function(t,e){return t.offset-e.offset}),"path"===t.type&&(c-=t.pathOffset.x,l-=t.pathOffset.y);for(var u in o)"x1"===u||"x2"===u?o[u]+=this.offsetX-c:"y1"!==u&&"y2"!==u||(o[u]+=this.offsetY-l);if(s='id="SVGID_'+this.id+'" gradientUnits="userSpaceOnUse"',this.gradientTransform&&(s+=' gradientTransform="matrix('+this.gradientTransform.join(" ")+')" '),"linear"===thi
 s.type?r=["<linearGradient ",s,' x1="',o.x1,'" y1="',o.y1,'" x2="',o.x2,'" y2="',o.y2,'">\n']:"radial"===this.type&&(r=["<radialGradient ",s,' cx="',h?o.x1:o.x2,'" cy="',h?o.y1:o.y2,'" r="',h?o.r1:o.r2,'" fx="',h?o.x2:o.x1,'" fy="',h?o.y2:o.y1,'">\n']),"radial"===this.type){if(h)for((a=a.concat()).reverse(),e=0,i=a.length;e<i;e++)a[e].offset=1-a[e].offset;var f=Math.min(o.r1,o.r2);if(f>0){var d=f/Math.max(o.r1,o.r2);for(e=0,i=a.length;e<i;e++)a[e].offset+=d*(1-a[e].offset)}}for(e=0,i=a.length;e<i;e++){var g=a[e];r.push("<stop ",'offset="',100*g.offset+"%",'" style="stop-color:',g.color,null!==g.opacity?";stop-opacity: "+g.opacity:";",'"/>\n')}return r.push("linear"===this.type?"</linearGradient>\n":"</radialGradient>\n"),r.join("")},toLive:function(t){var e,i,r,n=fabric.util.object.clone(this.coords);if(this.type){for("linear"===this.type?e=t.createLinearGradient(n.x1,n.y1,n.x2,n.y2):"radial"===this.type&&(e=t.createRadialGradient(n.x1,n.y1,n.r1,n.x2,n.y2,n.r2)),i=0,r=this.colorStop
 s.length;i<r;i++){var s=this.colorStops[i].color,o=this.colorStops[i].opacity,a=this.colorStops[i].offset;void 0!==o&&(s=new fabric.Color(s).setAlpha(o).toRgba()),e.addColorStop(a,s)}return e}}}),fabric.util.object.extend(fabric.Gradient,{fromElement:function(n,s){var o,a,h,c,l=n.getElementsByTagName("stop"),u=n.getAttribute("gradientUnits")||"objectBoundingBox",f=n.getAttribute("gradientTransform"),d=[];for("linear"===(o="linearGradient"===n.nodeName||"LINEARGRADIENT"===n.nodeName?"linear":"radial")?a=e(n):"radial"===o&&(a=i(n)),c=l.length;c--;)d.push(t(l[c]));h=r(s,a,u);var g=new fabric.Gradient({type:o,coords:a,colorStops:d,offsetX:-s.left,offsetY:-s.top});return(f||""!==h)&&(g.gradientTransform=fabric.parseTransformAttribute((f||"")+h)),g},forObject:function(t,e){return e||(e={}),r(t,e.coords,"userSpaceOnUse"),new fabric.Gradient(e)}})}(),function(){"use strict";var t=fabric.util.toFixed;fabric.Pattern=fabric.util.createClass({repeat:"repeat",offsetX:0,offsetY:0,initialize:funct
 ion(t,e){if(t||(t={}),this.id=fabric.Object.__uid++,this.setOptions(t),!t.source||t.source&&"string"!=typeof t.source)e&&e(this);else if(void 0!==fabric.util.getFunctionBody(t.source))this.source=new Function(fabric.util.getFunctionBody(t.source)),e&&e(this);else{var i=this;this.source=fabric.util.createImage(),fabric.util.loadImage(t.source,function(t){i.source=t,e&&e(i)})}},toObject:function(e){var i,r,n=fabric.Object.NUM_FRACTION_DIGITS;return"function"==typeof this.source?i=String(this.source):"string"==typeof this.source.src?i=this.source.src:"object"==typeof this.source&&this.source.toDataURL&&(i=this.source.toDataURL()),r={type:"pattern",source:i,repeat:this.repeat,offsetX:t(this.offsetX,n),offsetY:t(this.offsetY,n)},fabric.util.populateWithProperties(this,r,e),r},toSVG:function(t){var e="function"==typeof this.source?this.source():this.source,i=e.width/t.width,r=e.height/t.height,n=this.offsetX/t.width,s=this.offsetY/t.height,o="";return"repeat-x"!==this.repeat&&"no-repeat"!
 ==this.repeat||(r=1),"repeat-y"!==this.repeat&&"no-repeat"!==this.repeat||(i=1),e.src?o=e.src:e.toDataURL&&(o=e.toDataURL()),'<pattern id="SVGID_'+this.id+'" x="'+n+'" y="'+s+'" width="'+i+'" height="'+r+'">\n<image x="0" y="0" width="'+e.width+'" height="'+e.height+'" xlink:href="'+o+'"></image>\n</pattern>\n'},setOptions:function(t){for(var e in t)this[e]=t[e]},toLive:function(t){var e="function"==typeof this.source?this.source():this.source;if(!e)return"";if(void 0!==e.src){if(!e.complete)return"";if(0===e.naturalWidth||0===e.naturalHeight)return""}return t.createPattern(e,this.repeat)}})}(),function(t){"use strict";var e=t.fabric||(t.fabric={}),i=e.util.toFixed;e.Shadow?e.warn("fabric.Shadow is already defined."):(e.Shadow=e.util.createClass({color:"rgb(0,0,0)",blur:0,offsetX:0,offsetY:0,affectStroke:!1,includeDefaultValues:!0,initialize:function(t){"string"==typeof t&&(t=this._parseShadow(t));for(var i in t)this[i]=t[i];this.id=e.Object.__uid++},_parseShadow:function(t){var i=t
 .trim(),r=e.Shadow.reOffsetsAndBlur.exec(i)||[];return{color:(i.replace(e.Shadow.reOffsetsAndBlur,"")||"rgb(0,0,0)").trim(),offsetX:parseInt(r[1],10)||0,offsetY:parseInt(r[2],10)||0,blur:parseInt(r[3],10)||0}},toString:function(){return[this.offsetX,this.offsetY,this.blur,this.color].join("px ")},toSVG:function(t){var r=40,n=40,s=e.Object.NUM_FRACTION_DIGITS,o=e.util.rotateVector({x:this.offsetX,y:this.offsetY},e.util.degreesToRadians(-t.angle));return t.width&&t.height&&(r=100*i((Math.abs(o.x)+this.blur)/t.width,s)+20,n=100*i((Math.abs(o.y)+this.blur)/t.height,s)+20),t.flipX&&(o.x*=-1),t.flipY&&(o.y*=-1),'<filter id="SVGID_'+this.id+'" y="-'+n+'%" height="'+(100+2*n)+'%" x="-'+r+'%" width="'+(100+2*r)+'%" >\n\t<feGaussianBlur in="SourceAlpha" stdDeviation="'+i(this.blur?this.blur/2:0,s)+'"></feGaussianBlur>\n\t<feOffset dx="'+i(o.x,s)+'" dy="'+i(o.y,s)+'" result="oBlur" ></feOffset>\n\t<feFlood flood-color="'+this.color+'"/>\n\t<feComposite in2="oBlur" operator="in" />\n\t<feMerge>
 \n\t\t<feMergeNode></feMergeNode>\n\t\t<feMergeNode in="SourceGraphic"></feMergeNode>\n\t</feMerge>\n</filter>\n'},toObject:function(){if(this.includeDefaultValues)return{color:this.color,blur:this.blur,offsetX:this.offsetX,offsetY:this.offsetY,affectStroke:this.affectStroke};var t={},i=e.Shadow.prototype;return["color","blur","offsetX","offsetY","affectStroke"].forEach(function(e){this[e]!==i[e]&&(t[e]=this[e])},this),t}}),e.Shadow.reOffsetsAndBlur=/(?:\s|^)(-?\d+(?:px)?(?:\s?|$))?(-?\d+(?:px)?(?:\s?|$))?(\d+(?:px)?)?(?:\s?|$)(?:$|\s)/)}("undefined"!=typeof exports?exports:this),function(){"use strict";if(fabric.StaticCanvas)fabric.warn("fabric.StaticCanvas is already defined.");else{var t=fabric.util.object.extend,e=fabric.util.getElementOffset,i=fabric.util.removeFromArray,r=fabric.util.toFixed,n=fabric.util.transformPoint,s=fabric.util.invertTransform,o=new Error("Could not initialize `canvas` element");fabric.StaticCanvas=fabric.util.createClass(fabric.CommonMethods,{initialize
 :function(t,e){e||(e={}),this.renderAndResetBound=this.renderAndReset.bind(this),this.requestRenderAllBound=this.requestRenderAll.bind(this),this._initStatic(t,e)},backgroundColor:"",backgroundImage:null,overlayColor:"",overlayImage:null,includeDefaultValues:!0,stateful:!1,renderOnAddRemove:!0,clipTo:null,controlsAboveOverlay:!1,allowTouchScrolling:!1,imageSmoothingEnabled:!0,viewportTransform:fabric.iMatrix.concat(),backgroundVpt:!0,overlayVpt:!0,onBeforeScaleRotate:function(){},enableRetinaScaling:!0,vptCoords:{},skipOffscreen:!0,_initStatic:function(t,e){var i=this.requestRenderAllBound;this._objects=[],this._createLowerCanvas(t),this._initOptions(e),this._setImageSmoothing(),this.interactive||this._initRetinaScaling(),e.overlayImage&&this.setOverlayImage(e.overlayImage,i),e.backgroundImage&&this.setBackgroundImage(e.backgroundImage,i),e.backgroundColor&&this.setBackgroundColor(e.backgroundColor,i),e.overlayColor&&this.setOverlayColor(e.overlayColor,i),this.calcOffset()},_isRetin
 aScaling:function(){return 1!==fabric.devicePixelRatio&&this.enableRetinaScaling},getRetinaScaling:function(){return this._isRetinaScaling()?fabric.devicePixelRatio:1},_initRetinaScaling:function(){this._isRetinaScaling()&&(this.lowerCanvasEl.setAttribute("width",this.width*fabric.devicePixelRatio),this.lowerCanvasEl.setAttribute("height",this.height*fabric.devicePixelRatio),this.contextContainer.scale(fabric.devicePixelRatio,fabric.devicePixelRatio))},calcOffset:function(){return this._offset=e(this.lowerCanvasEl),this},setOverlayImage:function(t,e,i){return this.__setBgOverlayImage("overlayImage",t,e,i)},setBackgroundImage:function(t,e,i){return this.__setBgOverlayImage("backgroundImage",t,e,i)},setOverlayColor:function(t,e){return this.__setBgOverlayColor("overlayColor",t,e)},setBackgroundColor:function(t,e){return this.__setBgOverlayColor("backgroundColor",t,e)},_setImageSmoothing:function(){var t=this.getContext();t.imageSmoothingEnabled=t.imageSmoothingEnabled||t.webkitImageSm
 oothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled||t.oImageSmoothingEnabled,t.imageSmoothingEnabled=this.imageSmoothingEnabled},__setBgOverlayImage:function(t,e,i,r){return"string"==typeof e?fabric.util.loadImage(e,function(e){e&&(this[t]=new fabric.Image(e,r)),i&&i(e)},this,r&&r.crossOrigin):(r&&e.setOptions(r),this[t]=e,i&&i(e)),this},__setBgOverlayColor:function(t,e,i){return this[t]=e,this._initGradient(e,t),this._initPattern(e,t,i),this},_createCanvasElement:function(){var t=fabric.util.createCanvasElement();if(!t)throw o;if(t.style||(t.style={}),void 0===t.getContext)throw o;return t},_initOptions:function(t){this._setOptions(t),this.width=this.width||parseInt(this.lowerCanvasEl.width,10)||0,this.height=this.height||parseInt(this.lowerCanvasEl.height,10)||0,this.lowerCanvasEl.style&&(this.lowerCanvasEl.width=this.width,this.lowerCanvasEl.height=this.height,this.lowerCanvasEl.style.width=this.width+"px",this.lowerCanvasEl.style.height=this.height+"px",this.v
 iewportTransform=this.viewportTransform.slice())},_createLowerCanvas:function(t){t&&t.getContext?this.lowerCanvasEl=t:this.lowerCanvasEl=fabric.util.getById(t)||this._createCanvasElement(),fabric.util.addClass(this.lowerCanvasEl,"lower-canvas"),this.interactive&&this._applyCanvasStyle(this.lowerCanvasEl),this.contextContainer=this.lowerCanvasEl.getContext("2d")},getWidth:function(){return this.width},getHeight:function(){return this.height},setWidth:function(t,e){return this.setDimensions({width:t},e)},setHeight:function(t,e){return this.setDimensions({height:t},e)},setDimensions:function(t,e){var i;e=e||{};for(var r in t)i=t[r],e.cssOnly||(this._setBackstoreDimension(r,t[r]),i+="px"),e.backstoreOnly||this._setCssDimension(r,i);return this._initRetinaScaling(),this._setImageSmoothing(),this.calcOffset(),e.cssOnly||this.requestRenderAll(),this},_setBackstoreDimension:function(t,e){return this.lowerCanvasEl[t]=e,this.upperCanvasEl&&(this.upperCanvasEl[t]=e),this.cacheCanvasEl&&(this.c
 acheCanvasEl[t]=e),this[t]=e,this},_setCssDimension:function(t,e){return this.lowerCanvasEl.style[t]=e,this.upperCanvasEl&&(this.upperCanvasEl.style[t]=e),this.wrapperEl&&(this.wrapperEl.style[t]=e),this},getZoom:function(){return this.viewportTransform[0]},setViewportTransform:function(t){var e,i,r,n=this._activeObject;for(this.viewportTransform=t,i=0,r=this._objects.length;i<r;i++)(e=this._objects[i]).group||e.setCoords(!1,!0);return n&&"activeSelection"===n.type&&n.setCoords(!1,!0),this.calcViewportBoundaries(),this.renderOnAddRemove&&this.requestRenderAll(),this},zoomToPoint:function(t,e){var i=t,r=this.viewportTransform.slice(0);t=n(t,s(this.viewportTransform)),r[0]=e,r[3]=e;var o=n(t,r);return r[4]+=i.x-o.x,r[5]+=i.y-o.y,this.setViewportTransform(r)},setZoom:function(t){return this.zoomToPoint(new fabric.Point(0,0),t),this},absolutePan:function(t){var e=this.viewportTransform.slice(0);return e[4]=-t.x,e[5]=-t.y,this.setViewportTransform(e)},relativePan:function(t){return this.
 absolutePan(new fabric.Point(-t.x-this.viewportTransform[4],-t.y-this.viewportTransform[5]))},getElement:function(){return this.lowerCanvasEl},_onObjectAdded:function(t){this.stateful&&t.setupState(),t._set("canvas",this),t.setCoords(),this.fire("object:added",{target:t}),t.fire("added")},_onObjectRemoved:function(t){this.fire("object:removed",{target:t}),t.fire("removed"),delete t.canvas},clearContext:function(t){return t.clearRect(0,0,this.width,this.height),this},getContext:function(){return this.contextContainer},clear:function(){return this._objects.length=0,this.backgroundImage=null,this.overlayImage=null,this.backgroundColor="",this.overlayColor="",this._hasITextHandlers&&(this.off("mouse:up",this._mouseUpITextHandler),this._iTextInstances=null,this._hasITextHandlers=!1),this.clearContext(this.contextContainer),this.fire("canvas:cleared"),this.renderOnAddRemove&&this.requestRenderAll(),this},renderAll:function(){var t=this.contextContainer;return this.renderCanvas(t,this._obj
 ects),this},renderAndReset:function(){this.isRendering=0,this.renderAll()},requestRenderAll:function(){return this.isRendering||(this.isRendering=fabric.util.requestAnimFrame(this.renderAndResetBound)),this},calcViewportBoundaries:function(){var t={},e=this.width,i=this.height,r=s(this.viewportTransform);return t.tl=n({x:0,y:0},r),t.br=n({x:e,y:i},r),t.tr=new fabric.Point(t.br.x,t.tl.y),t.bl=new fabric.Point(t.tl.x,t.br.y),this.vptCoords=t,t},renderCanvas:function(t,e){var i=this.viewportTransform;this.isRendering&&(fabric.util.cancelAnimFrame(this.isRendering),this.isRendering=0),this.calcViewportBoundaries(),this.clearContext(t),this.fire("before:render"),this.clipTo&&fabric.util.clipContext(this,t),this._renderBackground(t),t.save(),t.transform(i[0],i[1],i[2],i[3],i[4],i[5]),this._renderObjects(t,e),t.restore(),!this.controlsAboveOverlay&&this.interactive&&this.drawControls(t),this.clipTo&&t.restore(),this._renderOverlay(t),this.controlsAboveOverlay&&this.interactive&&this.drawCo
 ntrols(t),this.fire("after:render")},_renderObjects:function(t,e){var i,r;for(i=0,r=e.length;i<r;++i)e[i]&&e[i].render(t)},_renderBackgroundOrOverlay:function(t,e){var i,r=this[e+"Color"];r&&(t.fillStyle=r.toLive?r.toLive(t,this):r,t.fillRect(r.offsetX||0,r.offsetY||0,this.width,this.height)),(r=this[e+"Image"])&&(this[e+"Vpt"]&&(i=this.viewportTransform,t.save(),t.transform(i[0],i[1],i[2],i[3],i[4],i[5])),r.render(t),this[e+"Vpt"]&&t.restore())},_renderBackground:function(t){this._renderBackgroundOrOverlay(t,"background")},_renderOverlay:function(t){this._renderBackgroundOrOverlay(t,"overlay")},getCenter:function(){return{top:this.height/2,left:this.width/2}},centerObjectH:function(t){return this._centerObject(t,new fabric.Point(this.getCenter().left,t.getCenterPoint().y))},centerObjectV:function(t){return this._centerObject(t,new fabric.Point(t.getCenterPoint().x,this.getCenter().top))},centerObject:function(t){var e=this.getCenter();return this._centerObject(t,new fabric.Point(e.
 left,e.top))},viewportCenterObject:function(t){var e=this.getVpCenter();return this._centerObject(t,e)},viewportCenterObjectH:function(t){var e=this.getVpCenter();return this._centerObject(t,new fabric.Point(e.x,t.getCenterPoint().y)),this},viewportCenterObjectV:function(t){var e=this.getVpCenter();return this._centerObject(t,new fabric.Point(t.getCenterPoint().x,e.y))},getVpCenter:function(){var t=this.getCenter(),e=s(this.viewportTransform);return n({x:t.left,y:t.top},e)},_centerObject:function(t,e){return t.setPositionByOrigin(e,"center","center"),this.renderOnAddRemove&&this.requestRenderAll(),this},toDatalessJSON:function(t){return this.toDatalessObject(t)},toObject:function(t){return this._toObjectMethod("toObject",t)},toDatalessObject:function(t){return this._toObjectMethod("toDatalessObject",t)},_toObjectMethod:function(e,i){var r={version:fabric.version,objects:this._toObjects(e,i)};return t(r,this.__serializeBgOverlay(e,i)),fabric.util.populateWithProperties(this,r,i),r},_
 toObjects:function(t,e){return this.getObjects().filter(function(t){return!t.excludeFromExport}).map(function(i){return this._toObject(i,t,e)},this)},_toObject:function(t,e,i){var r;this.includeDefaultValues||(r=t.includeDefaultValues,t.includeDefaultValues=!1);var n=t[e](i);return this.includeDefaultValues||(t.includeDefaultValues=r),n},__serializeBgOverlay:function(t,e){var i={},r=this.backgroundImage,n=this.overlayImage;return this.backgroundColor&&(i.background=this.backgroundColor.toObject?this.backgroundColor.toObject(e):this.backgroundColor),this.overlayColor&&(i.overlay=this.overlayColor.toObject?this.overlayColor.toObject(e):this.overlayColor),r&&!r.excludeFromExport&&(i.backgroundImage=this._toObject(r,t,e)),n&&!n.excludeFromExport&&(i.overlayImage=this._toObject(n,t,e)),i},svgViewportTransformation:!0,toSVG:function(t,e){t||(t={});var i=[];return this._setSVGPreamble(i,t),this._setSVGHeader(i,t),this._setSVGBgOverlayColor(i,"backgroundColor"),this._setSVGBgOverlayImage(i,
 "backgroundImage",e),this._setSVGObjects(i,e),this._setSVGBgOverlayColor(i,"overlayColor"),this._setSVGBgOverlayImage(i,"overlayImage",e),i.push("</svg>"),i.join("")},_setSVGPreamble:function(t,e){e.suppressPreamble||t.push('<?xml version="1.0" encoding="',e.encoding||"UTF-8",'" standalone="no" ?>\n','<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ','"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n')},_setSVGHeader:function(t,e){var i,n=e.width||this.width,s=e.height||this.height,o='viewBox="0 0 '+this.width+" "+this.height+'" ',a=fabric.Object.NUM_FRACTION_DIGITS;e.viewBox?o='viewBox="'+e.viewBox.x+" "+e.viewBox.y+" "+e.viewBox.width+" "+e.viewBox.height+'" ':this.svgViewportTransformation&&(i=this.viewportTransform,o='viewBox="'+r(-i[4]/i[0],a)+" "+r(-i[5]/i[3],a)+" "+r(this.width/i[0],a)+" "+r(this.height/i[3],a)+'" '),t.push("<svg ",'xmlns="http://www.w3.org/2000/svg" ','xmlns:xlink="http://www.w3.org/1999/xlink" ','version="1.1" ','width="',n,'" ','height="',s,'" ',o,'xml:
 space="preserve">\n',"<desc>Created with Fabric.js ",fabric.version,"</desc>\n","<defs>\n",this.createSVGFontFacesMarkup(),this.createSVGRefElementsMarkup(),"</defs>\n")},createSVGRefElementsMarkup:function(){var t=this;return["backgroundColor","overlayColor"].map(function(e){var i=t[e];if(i&&i.toLive)return i.toSVG(t,!1)}).join("")},createSVGFontFacesMarkup:function(){var t,e,i,r,n,s,o,a,h="",c={},l=fabric.fontPaths,u=this.getObjects();for(o=0,a=u.length;o<a;o++)if(t=u[o],e=t.fontFamily,-1!==t.type.indexOf("text")&&!c[e]&&l[e]&&(c[e]=!0,t.styles)){i=t.styles;for(n in i){r=i[n];for(s in r)!c[e=r[s].fontFamily]&&l[e]&&(c[e]=!0)}}for(var f in c)h+=["\t\t@font-face {\n","\t\t\tfont-family: '",f,"';\n","\t\t\tsrc: url('",l[f],"');\n","\t\t}\n"].join("");return h&&(h=['\t<style type="text/css">',"<![CDATA[\n",h,"]]>","</style>\n"].join("")),h},_setSVGObjects:function(t,e){var i,r,n,s=this.getObjects();for(r=0,n=s.length;r<n;r++)(i=s[r]).excludeFromExport||this._setSVGObject(t,i,e)},_setS
 VGObject:function(t,e,i){t.push(e.toSVG(i))},_setSVGBgOverlayImage:function(t,e,i){this[e]&&this[e].toSVG&&t.push(this[e].toSVG(i))},_setSVGBgOverlayColor:function(t,e){var i=this[e];if(i)if(i.toLive){var r=i.repeat;t.push('<rect transform="translate(',this.width/2,",",this.height/2,')"',' x="',i.offsetX-this.width/2,'" y="',i.offsetY-this.height/2,'" ','width="',"repeat-y"===r||"no-repeat"===r?i.source.width:this.width,'" height="',"repeat-x"===r||"no-repeat"===r?i.source.height:this.height,'" fill="url(#SVGID_'+i.id+')"',"></rect>\n")}else t.push('<rect x="0" y="0" ','width="',this.width,'" height="',this.height,'" fill="',this[e],'"',"></rect>\n")},sendToBack:function(t){if(!t)return this;var e,r,n,s=this._activeObject;if(t===s&&"activeSelection"===t.type)for(e=(n=s._objects).length;e--;)r=n[e],i(this._objects,r),this._objects.unshift(r);else i(this._objects,t),this._objects.unshift(t);return this.renderOnAddRemove&&this.requestRenderAll(),this},bringToFront:function(t){if(!t)ret
 urn this;var e,r,n,s=this._activeObject;if(t===s&&"activeSelection"===t.type)for(n=s._objects,e=0;e<n.length;e++)r=n[e],i(this._objects,r),this._objects.push(r);else i(this._objects,t),this._objects.push(t);return this.renderOnAddRemove&&this.requestRenderAll(),this},sendBackwards:function(t,e){if(!t)return this;var r,n,s,o,a,h=this._activeObject,c=0;if(t===h&&"activeSelection"===t.type)for(a=h._objects,r=0;r<a.length;r++)n=a[r],(s=this._objects.indexOf(n))>0+c&&(o=s-1,i(this._objects,n),this._objects.splice(o,0,n)),c++;else 0!==(s=this._objects.indexOf(t))&&(o=this._findNewLowerIndex(t,s,e),i(this._objects,t),this._objects.splice(o,0,t));return this.renderOnAddRemove&&this.requestRenderAll(),this},_findNewLowerIndex:function(t,e,i){var r,n;if(i){for(r=e,n=e-1;n>=0;--n)if(t.intersectsWithObject(this._objects[n])||t.isContainedWithinObject(this._objects[n])||this._objects[n].isContainedWithinObject(t)){r=n;break}}else r=e-1;return r},bringForward:function(t,e){if(!t)return this;var r
 ,n,s,o,a,h=this._activeObject,c=0;if(t===h&&"activeSelection"===t.type)for(r=(a=h._objects).length;r--;)n=a[r],(s=this._objects.indexOf(n))<this._objects.length-1-c&&(o=s+1,i(this._objects,n),this._objects.splice(o,0,n)),c++;else(s=this._objects.indexOf(t))!==this._objects.length-1&&(o=this._findNewUpperIndex(t,s,e),i(this._objects,t),this._objects.splice(o,0,t));return this.renderOnAddRemove&&this.requestRenderAll(),this},_findNewUpperIndex:function(t,e,i){var r,n,s;if(i){for(r=e,n=e+1,s=this._objects.length;n<s;++n)if(t.intersectsWithObject(this._objects[n])||t.isContainedWithinObject(this._objects[n])||this._objects[n].isContainedWithinObject(t)){r=n;break}}else r=e+1;return r},moveTo:function(t,e){return i(this._objects,t),this._objects.splice(e,0,t),this.renderOnAddRemove&&this.requestRenderAll()},dispose:function(){return this._objects.length=0,this.backgroundImage=null,this.overlayImage=null,this._iTextInstances=null,this.lowerCanvasEl=null,this.cacheCanvasEl=null,this},toStr
 ing:function(){return"#<fabric.Canvas ("+this.complexity()+"): { objects: "+this.getObjects().length+" }>"}}),t(fabric.StaticCanvas.prototype,fabric.Observable),t(fabric.StaticCanvas.prototype,fabric.Collection),t(fabric.StaticCanvas.prototype,fabric.DataURLExporter),t(fabric.StaticCanvas,{EMPTY_JSON:'{"objects": [], "background": "white"}',supports:function(t){var e=fabric.util.createCanvasElement();if(!e||!e.getContext)return null;var i=e.getContext("2d");if(!i)return null;switch(t){case"getImageData":return void 0!==i.getImageData;case"setLineDash":return void 0!==i.setLineDash;case"toDataURL":return void 0!==e.toDataURL;case"toDataURLWithQuality":try{return e.toDataURL("image/jpeg",0),!0}catch(t){}return!1;default:return null}}}),fabric.StaticCanvas.prototype.toJSON=fabric.StaticCanvas.prototype.toObject}}(),fabric.BaseBrush=fabric.util.createClass({color:"rgb(0, 0, 0)",width:1,shadow:null,strokeLineCap:"round",strokeLineJoin:"round",strokeMiterLimit:10,strokeDashArray:null,setS
 hadow:function(t){return this.shadow=new fabric.Shadow(t),this},_setBrushStyles:function(){var t=this.canvas.contextTop;t.strokeStyle=this.color,t.lineWidth=this.width,t.lineCap=this.strokeLineCap,t.miterLimit=this.strokeMiterLimit,t.lineJoin=this.strokeLineJoin,this.strokeDashArray&&fabric.StaticCanvas.supports("setLineDash")&&t.setLineDash(this.strokeDashArray)},_setShadow:function(){if(this.shadow){var t=this.canvas.contextTop,e=this.canvas.getZoom();t.shadowColor=this.shadow.color,t.shadowBlur=this.shadow.blur*e,t.shadowOffsetX=this.shadow.offsetX*e,t.shadowOffsetY=this.shadow.offsetY*e}},_resetShadow:function(){var t=this.canvas.contextTop;t.shadowColor="",t.shadowBlur=t.shadowOffsetX=t.shadowOffsetY=0}}),fabric.PencilBrush=fabric.util.createClass(fabric.BaseBrush,{initialize:function(t){this.canvas=t,this._points=[]},onMouseDown:function(t){this._prepareForDrawing(t),this._captureDrawingPath(t),this._render()},onMouseMove:function(t){this._captureDrawingPath(t),this.canvas.cle
 arContext(this.canvas.contextTop),this._render()},onMouseUp:function(){this._finalizeAndAddPath()},_prepareForDrawing:function(t){var e=new fabric.Point(t.x,t.y);this._reset(),this._addPoint(e),this.canvas.contextTop.moveTo(e.x,e.y)},_addPoint:function(t){this._points.length>1&&t.eq(this._points[this._points.length-1])||this._points.push(t)},_reset:function(){this._points.length=0,this._setBrushStyles(),this._setShadow()},_captureDrawingPath:function(t){var e=new fabric.Point(t.x,t.y);this._addPoint(e)},_render:function(){var t,e,i=this.canvas.contextTop,r=this.canvas.viewportTransform,n=this._points[0],s=this._points[1];if(i.save(),i.transform(r[0],r[1],r[2],r[3],r[4],r[5]),i.beginPath(),2===this._points.length&&n.x===s.x&&n.y===s.y){var o=this.width/1e3;n=new fabric.Point(n.x,n.y),s=new fabric.Point(s.x,s.y),n.x-=o,s.x+=o}for(i.moveTo(n.x,n.y),t=1,e=this._points.length;t<e;t++){var a=n.midPointFrom(s);i.quadraticCurveTo(n.x,n.y,a.x,a.y),n=this._points[t],s=this._points[t+1]}i.line
 To(n.x,n.y),i.stroke(),i.restore()},convertPointsToSVGPath:function(t){var e,i,r,n=[],s=this.width/1e3,o=new fabric.Point(t[0].x,t[0].y),a=new fabric.Point(t[1].x,t[1].y),h=t.length,c=h>2;for(c&&(i=t[2].x<a.x?-1:t[2].x===a.x?0:1,r=t[2].y<a.y?-1:t[2].y===a.y?0:1),n.push("M ",o.x-i*s," ",o.y-r*s," "),e=1;e<h;e++){if(!o.eq(a)){var l=o.midPointFrom(a);n.push("Q ",o.x," ",o.y," ",l.x," ",l.y," ")}o=t[e],e+1<t.length&&(a=t[e+1])}return c&&(i=o.x>t[e-2].x?1:o.x===t[e-2].x?0:-1,r=o.y>t[e-2].y?1:o.y===t[e-2].y?0:-1),n.push("L ",o.x+i*s," ",o.y+r*s),n},createPath:function(t){var e=new fabric.Path(t,{fill:null,stroke:this.color,strokeWidth:this.width,strokeLineCap:this.strokeLineCap,strokeMiterLimit:this.strokeMiterLimit,strokeLineJoin:this.strokeLineJoin,strokeDashArray:this.strokeDashArray}),i=new fabric.Point(e.left+e.width/2,e.top+e.height/2);return i=e.translateToGivenOrigin(i,"center","center",e.originX,e.originY),e.top=i.y,e.left=i.x,this.shadow&&(this.shadow.affectStroke=!0,e.setShadow
 (this.shadow)),e},_finalizeAndAddPath:function(){this.canvas.contextTop.closePath();var t=this.convertPointsToSVGPath(this._points).join("");if("M 0 0 Q 0 0 0 0 L 0 0"!==t){var e=this.createPath(t);this.canvas.clearContext(this.canvas.contextTop),this.canvas.add(e),this.canvas.renderAll(),e.setCoords(),this._resetShadow(),this.canvas.fire("path:created",{path:e})}else this.canvas.requestRenderAll()}}),fabric.CircleBrush=fabric.util.createClass(fabric.BaseBrush,{width:10,initialize:function(t){this.canvas=t,this.points=[]},drawDot:function(t){var e=this.addPoint(t),i=this.canvas.contextTop,r=this.canvas.viewportTransform;i.save(),i.transform(r[0],r[1],r[2],r[3],r[4],r[5]),i.fillStyle=e.fill,i.beginPath(),i.arc(e.x,e.y,e.radius,0,2*Math.PI,!1),i.closePath(),i.fill(),i.restore()},onMouseDown:function(t){this.points.length=0,this.canvas.clearContext(this.canvas.contextTop),this._setShadow(),this.drawDot(t)},onMouseMove:function(t){this.drawDot(t)},onMouseUp:function(){var t,e,i=this.can
 vas.renderOnAddRemove;this.canvas.renderOnAddRemove=!1;var r=[];for(t=0,e=this.points.length;t<e;t++){var n=this.points[t],s=new fabric.Circle({radius:n.radius,left:n.x,top:n.y,originX:"center",originY:"center",fill:n.fill});this.shadow&&s.setShadow(this.shadow),r.push(s)}var o=new fabric.Group(r,{originX:"center",originY:"center"});o.canvas=this.canvas,this.canvas.add(o),this.canvas.fire("path:created",{path:o}),this.canvas.clearContext(this.canvas.contextTop),this._resetShadow(),this.canvas.renderOnAddRemove=i,this.canvas.requestRenderAll()},addPoint:function(t){var e=new fabric.Point(t.x,t.y),i=fabric.util.getRandomInt(Math.max(0,this.width-20),this.width+20)/2,r=new fabric.Color(this.color).setAlpha(fabric.util.getRandomInt(0,100)/100).toRgba();return e.radius=i,e.fill=r,this.points.push(e),e}}),fabric.SprayBrush=fabric.util.createClass(fabric.BaseBrush,{width:10,density:20,dotWidth:1,dotWidthVariance:1,randomOpacity:!1,optimizeOverlapping:!0,initialize:function(t){this.canvas=t
 ,this.sprayChunks=[]},onMouseDown:function(t){this.sprayChunks.length=0,this.canvas.clearContext(this.canvas.contextTop),this._setShadow(),this.addSprayChunk(t),this.render()},onMouseMove:function(t){this.addSprayChunk(t),this.render()},onMouseUp:function(){var t=this.canvas.renderOnAddRemove;this.canvas.renderOnAddRemove=!1;for(var e=[],i=0,r=this.sprayChunks.length;i<r;i++)for(var n=this.sprayChunks[i],s=0,o=n.length;s<o;s++){var a=new fabric.Rect({width:n[s].width,height:n[s].width,left:n[s].x+1,top:n[s].y+1,originX:"center",originY:"center",fill:this.color});this.shadow&&a.setShadow(this.shadow),e.push(a)}this.optimizeOverlapping&&(e=this._getOptimizedRects(e));var h=new fabric.Group(e,{originX:"center",originY:"center"});h.canvas=this.canvas,this.canvas.add(h),this.canvas.fire("path:created",{path:h}),this.canvas.clearContext(this.canvas.contextTop),this._resetShadow(),this.canvas.renderOnAddRemove=t,this.canvas.requestRenderAll()},_getOptimizedRects:function(t){var e,i,r,n={};
 for(i=0,r=t.length;i<r;i++)n[e=t[i].left+""+t[i].top]||(n[e]=t[i]);var s=[];for(e in n)s.push(n[e]);return s},render:function(){var t=this.canvas.contextTop;t.fillStyle=this.color;var e,i,r=this.canvas.viewportTransform;for(t.save(),t.transform(r[0],r[1],r[2],r[3],r[4],r[5]),e=0,i=this.sprayChunkPoints.length;e<i;e++){var n=this.sprayChunkPoints[e];void 0!==n.opacity&&(t.globalAlpha=n.opacity),t.fillRect(n.x,n.y,n.width,n.width)}t.restore()},addSprayChunk:function(t){this.sprayChunkPoints=[];var e,i,r,n,s=this.width/2;for(n=0;n<this.density;n++){e=fabric.util.getRandomInt(t.x-s,t.x+s),i=fabric.util.getRandomInt(t.y-s,t.y+s),r=this.dotWidthVariance?fabric.util.getRandomInt(Math.max(1,this.dotWidth-this.dotWidthVariance),this.dotWidth+this.dotWidthVariance):this.dotWidth;var o=new fabric.Point(e,i);o.width=r,this.randomOpacity&&(o.opacity=fabric.util.getRandomInt(0,100)/100),this.sprayChunkPoints.push(o)}this.sprayChunks.push(this.sprayChunkPoints)}}),fabric.PatternBrush=fabric.util.c
 reateClass(fabric.PencilBrush,{getPatternSrc:function(){var t=fabric.document.createElement("canvas"),e=t.getContext("2d");return t.width=t.height=25,e.fillStyle=this.color,e.beginPath(),e.arc(10,10,10,0,2*Math.PI,!1),e.closePath(),e.fill(),t},getPatternSrcFunction:function(){return String(this.getPatternSrc).replace("this.color",'"'+this.color+'"')},getPattern:function(){return this.canvas.contextTop.createPattern(this.source||this.getPatternSrc(),"repeat")},_setBrushStyles:function(){this.callSuper("_setBrushStyles"),this.canvas.contextTop.strokeStyle=this.getPattern()},createPath:function(t){var e=this.callSuper("createPath",t),i=e._getLeftTopCoords().scalarAdd(e.strokeWidth/2);return e.stroke=new fabric.Pattern({source:this.source||this.getPatternSrcFunction(),offsetX:-i.x,offsetY:-i.y}),e}}),function(){var t=fabric.util.getPointer,e=fabric.util.degreesToRadians,i=fabric.util.radiansToDegrees,r=Math.atan2,n=Math.abs,s=fabric.StaticCanvas.supports("setLineDash");fabric.Canvas=fab
 ric.util.createClass(fabric.StaticCanvas,{initialize:function(t,e){e||(e={}),this.renderAndResetBound=this.renderAndReset.bind(this),this._initStatic(t,e),this._initInteractive(),this._createCacheCanvas()},uniScaleTransform:!1,uniScaleKey:"shiftKey",centeredScaling:!1,centeredRotation:!1,centeredKey:"altKey",altActionKey:"shiftKey",interactive:!0,selection:!0,selectionKey:"shiftKey",altSelectionKey:null,selectionColor:"rgba(100, 100, 255, 0.3)",selectionDashArray:[],selectionBorderColor:"rgba(255, 255, 255, 0.3)",selectionLineWidth:1,hoverCursor:"move",moveCursor:"move",defaultCursor:"default",freeDrawingCursor:"crosshair",rotationCursor:"crosshair",notAllowedCursor:"not-allowed",containerClass:"canvas-container",perPixelTargetFind:!1,targetFindTolerance:0,skipTargetFind:!1,isDrawingMode:!1,preserveObjectStacking:!1,snapAngle:0,snapThreshold:null,stopContextMenu:!1,fireRightClick:!1,fireMiddleClick:!1,_initInteractive:function(){this._currentTransform=null,this._groupSelector=null,t
 his._initWrapperElement(),this._createUpperCanvas(),this._initEventListeners(),this._initRetinaScaling(),this.freeDrawingBrush=fabric.PencilBrush&&new fabric.PencilBrush(this),this.calcOffset()},_chooseObjectsToRender:function(){var t,e,i,r=this.getActiveObjects();if(r.length>0&&!this.preserveObjectStacking){e=[],i=[];for(var n=0,s=this._objects.length;n<s;n++)t=this._objects[n],-1===r.indexOf(t)?e.push(t):i.push(t);r.length>1&&(this._activeObject._objects=i),e.push.apply(e,i)}else e=this._objects;return e},renderAll:function(){!this.contextTopDirty||this._groupSelector||this.isDrawingMode||(this.clearContext(this.contextTop),this.contextTopDirty=!1);var t=this.contextContainer;return this.renderCanvas(t,this._chooseObjectsToRender()),this},renderTop:function(){var t=this.contextTop;return this.clearContext(t),this.selection&&this._groupSelector&&this._drawSelection(t),this.fire("after:render"),this.contextTopDirty=!0,this},_resetCurrentTransform:function(){var t=this._currentTransf
 orm;t.target.set({scaleX:t.original.scaleX,scaleY:t.original.scaleY,skewX:t.original.skewX,skewY:t.original.skewY,left:t.original.left,top:t.original.top}),this._shouldCenterTransform(t.target)?"rotate"===t.action?this._setOriginToCenter(t.target):("center"!==t.originX&&("right"===t.originX?t.mouseXSign=-1:t.mouseXSign=1),"center"!==t.originY&&("bottom"===t.originY?t.mouseYSign=-1:t.mouseYSign=1),t.originX="center",t.originY="center"):(t.originX=t.original.originX,t.originY=t.original.originY)},containsPoint:function(t,e,i){var r,n=i||this.getPointer(t,!0);return r=e.group&&e.group===this._activeObject&&"activeSelection"===e.group.type?this._normalizePointer(e.group,n):{x:n.x,y:n.y},e.containsPoint(r)||e._findTargetCorner(n)},_normalizePointer:function(t,e){var i=t.calcTransformMatrix(),r=fabric.util.invertTransform(i),n=this.restorePointerVpt(e);return fabric.util.transformPoint(n,r)},isTargetTransparent:function(t,e,i){var r=this.contextCache,n=t.selectionBackgroundColor,s=this.vi
 ewportTransform;return t.selectionBackgroundColor="",this.clearContext(r),r.save(),r.transform(s[0],s[1],s[2],s[3],s[4],s[5]),t.render(r),r.restore(),t===this._activeObject&&t._renderControls(r,{hasBorders:!1,transparentCorners:!1},{hasBorders:!1}),t.selectionBackgroundColor=n,fabric.util.isTransparent(r,e,i,this.targetFindTolerance)},_isSelectionKeyPressed:function(t){return"[object Array]"===Object.prototype.toString.call(this.selectionKey)?!!this.selectionKey.find(function(e){return!0===t[e]}):t[this.selectionKey]},_shouldClearSelection:function(t,e){var i=this.getActiveObjects(),r=this._activeObject;return!e||e&&r&&i.length>1&&-1===i.indexOf(e)&&r!==e&&!this._isSelectionKeyPressed(t)||e&&!e.evented||e&&!e.selectable&&r&&r!==e},_shouldCenterTransform:function(t){if(t){var e,i=this._currentTransform;return"scale"===i.action||"scaleX"===i.action||"scaleY"===i.action?e=this.centeredScaling||t.centeredScaling:"rotate"===i.action&&(e=this.centeredRotation||t.centeredRotation),e?!i.alt
 Key:i.altKey}},_getOriginFromCorner:function(t,e){var i={x:t.originX,y:t.originY};return"ml"===e||"tl"===e||"bl"===e?i

<TRUNCATED>

[3/3] openmeetings git commit: [OPENMEETINGS-1771] minified files are removed from source tree

Posted by so...@apache.org.
[OPENMEETINGS-1771] minified files are removed from source tree


Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo
Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/ae1b51a9
Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/ae1b51a9
Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/ae1b51a9

Branch: refs/heads/4.0.x
Commit: ae1b51a99a52ed679e2862656e0054018d11545c
Parents: f25da38
Author: Maxim Solodovnik <so...@gmail.com>
Authored: Fri Nov 24 23:35:04 2017 +0700
Committer: Maxim Solodovnik <so...@gmail.com>
Committed: Fri Nov 24 23:35:04 2017 +0700

----------------------------------------------------------------------
 .../src/main/assembly/components/templates.xml  |   1 +
 openmeetings-web/pom.xml                        |  59 ++
 .../web/room/activities/activities.js           |  19 +
 .../web/room/jquery.dialogextend.min.js         |   3 -
 .../apache/openmeetings/web/room/room-base.js   | 818 +++++++++++++++++++
 .../org/apache/openmeetings/web/room/room.js    | 818 -------------------
 .../openmeetings/web/room/wb/WbPanel.java       |   9 -
 .../apache/openmeetings/web/room/wb/fabric.js   |  15 +-
 .../openmeetings/web/room/wb/fabric.min.js      |   2 -
 .../apache/openmeetings/web/user/chat/Chat.java |   7 -
 .../openmeetings/web/user/chat/chat-base.js     | 373 +++++++++
 .../apache/openmeetings/web/user/chat/chat.js   | 374 ---------
 .../openmeetings/web/user/chat/cssemoticons.css | 295 -------
 .../web/user/chat/cssemoticons.min.js           |   2 -
 .../web/util/upload/fileinput.min.css           |   7 -
 .../web/util/upload/fileinput.min.js            |   7 -
 .../src/main/webapp/css/cssemoticons.css        | 295 +++++++
 17 files changed, 1570 insertions(+), 1534 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-server/src/main/assembly/components/templates.xml
----------------------------------------------------------------------
diff --git a/openmeetings-server/src/main/assembly/components/templates.xml b/openmeetings-server/src/main/assembly/components/templates.xml
index 25cadf2..681f76c 100644
--- a/openmeetings-server/src/main/assembly/components/templates.xml
+++ b/openmeetings-server/src/main/assembly/components/templates.xml
@@ -36,6 +36,7 @@
 			<outputDirectory>${om.webapp}/WEB-INF/classes</outputDirectory>
 			<includes>
 				<include>**/*.js</include>
+				<include>**/*.css</include>
 			</includes>
 		</fileSet>
 		<fileSet>

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/pom.xml
----------------------------------------------------------------------
diff --git a/openmeetings-web/pom.xml b/openmeetings-web/pom.xml
index 505bebd..fdfd2bd 100644
--- a/openmeetings-web/pom.xml
+++ b/openmeetings-web/pom.xml
@@ -102,6 +102,7 @@
 								<cssSourceFile>activities.css</cssSourceFile>
 								<cssSourceFile>admin.css</cssSourceFile>
 								<cssSourceFile>calendar.css</cssSourceFile>
+								<cssSourceFile>cssemoticons.css</cssSourceFile>
 								<cssSourceFile>chat.css</cssSourceFile>
 								<cssSourceFile>menu.css</cssSourceFile>
 								<cssSourceFile>room.css</cssSourceFile>
@@ -150,6 +151,7 @@
 							<charset>UTF-8</charset>
 							<jsSourceDir>../java/org/apache/openmeetings/web/room/wb</jsSourceDir>
 							<jsSourceFiles>
+								<jsSourceFile>fabric.js</jsSourceFile>
 								<jsSourceFile>wb-all.js</jsSourceFile>
 								<jsSourceFile>uuid.js</jsSourceFile>
 								<jsSourceFile>player.js</jsSourceFile>
@@ -175,6 +177,63 @@
 							<jsEngine>CLOSURE</jsEngine>
 						</configuration>
 					</execution>
+					<execution>
+						<id>fileinput-js</id>
+						<goals>
+							<goal>minify</goal>
+						</goals>
+						<configuration>
+							<charset>UTF-8</charset>
+							<jsSourceDir>../java/org/apache/openmeetings/web/util/upload</jsSourceDir>
+							<jsSourceFiles>
+								<jsSourceFile>fileinput.js</jsSourceFile>
+							</jsSourceFiles>
+							<jsFinalFile>fileinput.js</jsFinalFile>
+							<jsTargetDir>../generated-sources/main/java/org/apache/openmeetings/web/util/upload</jsTargetDir>
+							<jsEngine>CLOSURE</jsEngine>
+							<cssSourceDir>../java/org/apache/openmeetings/web/util/upload</cssSourceDir>
+							<cssSourceFiles>
+								<cssSourceFile>fileinput.css</cssSourceFile>
+							</cssSourceFiles>
+							<skipMerge>true</skipMerge>
+							<cssFinalFile>fileinput.css</cssFinalFile>
+							<cssTargetDir>../generated-sources/main/java/org/apache/openmeetings/web/util/upload</cssTargetDir>
+						</configuration>
+					</execution>
+					<execution>
+						<id>room-js</id>
+						<goals>
+							<goal>minify</goal>
+						</goals>
+						<configuration>
+							<charset>UTF-8</charset>
+							<jsSourceDir>../java/org/apache/openmeetings/web/room</jsSourceDir>
+							<jsSourceFiles>
+								<jsSourceFile>jquery.dialogextend.js</jsSourceFile>
+								<jsSourceFile>room-base.js</jsSourceFile>
+							</jsSourceFiles>
+							<jsFinalFile>room.js</jsFinalFile>
+							<jsEngine>CLOSURE</jsEngine>
+							<jsTargetDir>../generated-sources/main/java/org/apache/openmeetings/web/room</jsTargetDir>
+						</configuration>
+					</execution>
+					<execution>
+						<id>chat-js</id>
+						<goals>
+							<goal>minify</goal>
+						</goals>
+						<configuration>
+							<charset>UTF-8</charset>
+							<jsSourceDir>../java/org/apache/openmeetings/web/user/chat</jsSourceDir>
+							<jsSourceFiles>
+								<jsSourceFile>cssemoticons.js</jsSourceFile>
+								<jsSourceFile>chat-base.js</jsSourceFile>
+							</jsSourceFiles>
+							<jsFinalFile>chat.js</jsFinalFile>
+							<jsEngine>CLOSURE</jsEngine>
+							<jsTargetDir>../generated-sources/main/java/org/apache/openmeetings/web/user/chat</jsTargetDir>
+						</configuration>
+					</execution>
 				</executions>
 			</plugin>
 			<plugin>

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js
index 635f51f..ddd0450 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/activities/activities.js
@@ -87,3 +87,22 @@ var Activities = function() {
 		}
 	};
 }();
+$(function() {
+	Wicket.Event.subscribe("/websocket/message", function(jqEvent, msg) {
+		try {
+			if (msg instanceof Blob) {
+				return; //ping
+			}
+			const m = jQuery.parseJSON(msg);
+			if (m) {
+				switch(m.type) {
+					case "activity":
+						Activities.addMessage(m);
+						break;
+				}
+			}
+		} catch (err) {
+			//no-op
+		}
+	});
+});

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/jquery.dialogextend.min.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/jquery.dialogextend.min.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/jquery.dialogextend.min.js
deleted file mode 100644
index 293458c..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/jquery.dialogextend.min.js
+++ /dev/null
@@ -1,3 +0,0 @@
-/* Licensed MIT */
-/*! jquery-dialogextend 2.0.4 2014-07-08 */
-(function(){var i;i=jQuery,i.widget("ui.dialogExtend",{version:"2.0.4",modes:{},options:{closable:!0,dblclick:!1,titlebar:!1,icons:{close:"ui-icon-closethick",restore:"ui-icon-newwin"},load:null,beforeRestore:null,restore:null},_create:function(){return this._state="normal",i(this.element[0]).data("ui-dialog")||i.error("jQuery.dialogExtend Error : Only jQuery UI Dialog element is accepted"),this._verifyOptions(),this._initStyles(),this._initButtons(),this._initTitleBar(),this._setState("normal"),this._on("load",function(i){return console.log("test",i)}),this._trigger("load")},_setState:function(t){return i(this.element[0]).removeClass("ui-dialog-"+this._state).addClass("ui-dialog-"+t),this._state=t},_verifyOptions:function(){var t,e,o;!this.options.dblclick||this.options.dblclick in this.modes||(i.error("jQuery.dialogExtend Error : Invalid <dblclick> value '"+this.options.dblclick+"'"),this.options.dblclick=!1),this.options.titlebar&&"none"!==(e=this.options.titlebar)&&"transparent"
 !==e&&(i.error("jQuery.dialogExtend Error : Invalid <titlebar> value '"+this.options.titlebar+"'"),this.options.titlebar=!1),o=[];for(t in this.modes)this["_verifyOptions_"+t]?o.push(this["_verifyOptions_"+t]()):o.push(void 0);return o},_initStyles:function(){var t,e,o;i(".dialog-extend-css").length||(e="",e+='<style class="dialog-extend-css" type="text/css">',e+=".ui-dialog .ui-dialog-titlebar-buttonpane>a { float: right; }",e+=".ui-dialog .ui-dialog-titlebar-restore { width: 19px; height: 18px; }",e+=".ui-dialog .ui-dialog-titlebar-restore span { display: block; margin: 1px; }",e+=".ui-dialog .ui-dialog-titlebar-restore:hover,",e+=".ui-dialog .ui-dialog-titlebar-restore:focus { padding: 0; }",e+=".ui-dialog .ui-dialog-titlebar ::selection { background-color: transparent; }",e+="</style>",i(e).appendTo("body")),o=[];for(t in this.modes)o.push(this["_initStyles_"+t]());return o},_initButtons:function(){var t,e,o,n,a,l=this;n=i(this.element[0]).dialog("widget").find(".ui-dialog-title
 bar"),t=i('<div class="ui-dialog-titlebar-buttonpane"></div>').appendTo(n),t.css({position:"absolute",top:"50%",right:"0.3em","margin-top":"-10px",height:"18px"}),n.find(".ui-dialog-titlebar-close").css({position:"relative","float":"right",top:"auto",right:"auto",margin:0}).find(".ui-icon").removeClass("ui-icon-closethick").addClass(this.options.icons.close).end().appendTo(t).end(),t.append('<a class="ui-dialog-titlebar-restore ui-corner-all ui-state-default" href="#"><span class="ui-icon '+this.options.icons.restore+'" title="restore">restore</span></a>').find(".ui-dialog-titlebar-restore").attr("role","button").mouseover(function(){return i(this).addClass("ui-state-hover")}).mouseout(function(){return i(this).removeClass("ui-state-hover")}).focus(function(){return i(this).addClass("ui-state-focus")}).blur(function(){return i(this).removeClass("ui-state-focus")}).end().find(".ui-dialog-titlebar-close").toggle(this.options.closable).end().find(".ui-dialog-titlebar-restore").hide().c
 lick(function(i){return i.preventDefault(),l.restore()}).end(),a=this.modes;for(o in a)e=a[o],this._initModuleButton(o,e);return n.dblclick(function(){return l.options.dblclick?"normal"!==l._state?l.restore():l[l.options.dblclick]():void 0}).select(function(){return!1})},_initModuleButton:function(t,e){var o,n=this;return o=i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar-buttonpane"),o.append('<a class="ui-dialog-titlebar-'+t+' ui-corner-all ui-state-default" href="#" title="'+t+'"><span class="ui-icon '+this.options.icons[t]+'">'+t+"</span></a>").find(".ui-dialog-titlebar-"+t).attr("role","button").mouseover(function(){return i(this).addClass("ui-state-hover")}).mouseout(function(){return i(this).removeClass("ui-state-hover")}).focus(function(){return i(this).addClass("ui-state-focus")}).blur(function(){return i(this).removeClass("ui-state-focus")}).end().find(".ui-dialog-titlebar-"+t).toggle(this.options[e.option]).click(function(i){return i.preventDefault(),n[t]()})
 .end()},_initTitleBar:function(){var t;switch(this.options.titlebar){case!1:return 0;case"none":return i(this.element[0]).dialog("option","draggable")&&(t=i("<div />").addClass("ui-dialog-draggable-handle").css("cursor","move").height(5),i(this.element[0]).dialog("widget").prepend(t).draggable("option","handle",t)),i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar").find(".ui-dialog-title").html("&nbsp;").end().css({"background-color":"transparent","background-image":"none",border:0,position:"absolute",right:0,top:0,"z-index":9999}).end();case"transparent":return i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar").css({"background-color":"transparent","background-image":"none",border:0});default:return i.error("jQuery.dialogExtend Error : Invalid <titlebar> value '"+this.options.titlebar+"'")}},state:function(){return this._state},restore:function(){return this._trigger("beforeRestore"),this._restore(),this._toggleButtons(),this._trigger("restore")},_restore:
 function(){return"normal"!==this._state?(this["_restore_"+this._state](),this._setState("normal"),i(this.element[0]).dialog("widget").focus()):void 0},_saveSnapshot:function(){return"normal"===this._state?(this.original_config_resizable=i(this.element[0]).dialog("option","resizable"),this.original_config_draggable=i(this.element[0]).dialog("option","draggable"),this.original_size_height=i(this.element[0]).dialog("widget").outerHeight(),this.original_size_width=i(this.element[0]).dialog("option","width"),this.original_size_maxHeight=i(this.element[0]).dialog("option","maxHeight"),this.original_position_mode=i(this.element[0]).dialog("widget").css("position"),this.original_position_left=i(this.element[0]).dialog("widget").offset().left-i("body").scrollLeft(),this.original_position_top=i(this.element[0]).dialog("widget").offset().top-i("body").scrollTop(),this.original_titlebar_wrap=i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar").css("white-space")):void 0},_loadSnapsho
 t:function(){return{config:{resizable:this.original_config_resizable,draggable:this.original_config_draggable},size:{height:this.original_size_height,width:this.original_size_width,maxHeight:this.original_size_maxHeight},position:{mode:this.original_position_mode,left:this.original_position_left,top:this.original_position_top},titlebar:{wrap:this.original_titlebar_wrap}}},_toggleButtons:function(t){var e,o,n,a,l,s;n=t||this._state,i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar-restore").toggle("normal"!==n).css({right:"1.4em"}).end(),a=this.modes;for(o in a)e=a[o],i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar-"+o).toggle(n!==e.state&&this.options[e.option]);l=this.modes,s=[];for(o in l)e=l[o],e.state===n?s.push(i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar-restore").insertAfter(i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar-"+o)).end()):s.push(void 0);return s}})}).call(this),function(){var i;i=jQuery,i.extend(!0,i.ui.dia
 logExtend.prototype,{modes:{collapse:{option:"collapsable",state:"collapsed"}},options:{collapsable:!1,icons:{collapse:"ui-icon-triangle-1-s"},beforeCollapse:null,collapse:null},collapse:function(){var t,e;return t=i(this.element[0]).dialog("widget").find(".ui-dialog-titlebar").height()+2,this._trigger("beforeCollapse"),"normal"!==this._state&&this._restore(),this._saveSnapshot(),e=i(this.element[0]).dialog("widget").position(),i(this.element[0]).dialog("option",{resizable:!1,height:t,maxHeight:t,position:[e.left-i(document).scrollLeft(),e.top-i(document).scrollTop()]}).on("dialogclose",this._collapse_restore).dialog("widget").find(".ui-dialog-buttonpane:visible").hide().end().find(".ui-dialog-titlebar").css("white-space","nowrap").end().find(".ui-dialog-content"),this._setState("collapsed"),this._toggleButtons(),this._trigger("collapse")},_restore_collapsed:function(){var t;return t=this._loadSnapshot(),i(this.element[0]).show().dialog("widget").find(".ui-dialog-buttonpane:hidden")
 .show().end().find(".ui-dialog-titlebar").css("white-space",t.titlebar.wrap).end().find(".ui-dialog-content").dialog("option",{resizable:t.config.resizable,height:t.size.height,maxHeight:t.size.maxHeight}).off("dialogclose",this._collapse_restore)},_initStyles_collapse:function(){var t;return i(".dialog-extend-collapse-css").length?void 0:(t="",t+='<style class="dialog-extend-collapse-css" type="text/css">',t+=".ui-dialog .ui-dialog-titlebar-collapse { width: 19px; height: 18px; }",t+=".ui-dialog .ui-dialog-titlebar-collapse span { display: block; margin: 1px; }",t+=".ui-dialog .ui-dialog-titlebar-collapse:hover,",t+=".ui-dialog .ui-dialog-titlebar-collapse:focus { padding: 0; }",t+="</style>",i(t).appendTo("body"))},_collapse_restore:function(){return i(this).dialogExtend("restore")}})}.call(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room-base.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room-base.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room-base.js
new file mode 100644
index 0000000..edafe4c
--- /dev/null
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room-base.js
@@ -0,0 +1,818 @@
+/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
+const WB_AREA_SEL = '.room.wb.area';
+const WBA_WB_SEL = '.room.wb.area .ui-tabs-panel.ui-corner-bottom.ui-widget-content:visible';
+var WBA_SEL = WB_AREA_SEL;
+const VID_SEL = '.video.user-video';
+var RoomUtil = (function() {
+	const self = {};
+	function _confirmDlg(_id, okHandler) {
+		const confirm = $('#' + _id);
+		confirm.dialog({
+			modal: true
+			, buttons: [
+				{
+					text: confirm.data('btn-ok')
+					, click: function() {
+						okHandler();
+						$(this).dialog('close');
+					}
+				}
+				, {
+					text: confirm.data('btn-cancel')
+					, click: function() {
+						$(this).dialog('close');
+					}
+				}
+			]
+		});
+		return confirm;
+	}
+
+	self.confirmDlg = _confirmDlg;
+	return self;
+})();
+var VideoUtil = (function() {
+	const self = {};
+	function _getVid(uid) {
+		return "video" + uid;
+	}
+	function _isSharing(c) {
+		return 'sharing' === c.type && c.screenActivities.indexOf('sharing') > -1;
+	}
+	function _isRecording(c) {
+		return 'sharing' === c.type
+			&& c.screenActivities.indexOf('recording') > -1
+			&& c.screenActivities.indexOf('sharing') < 0;
+	}
+	function _hasAudio(c) {
+		return c.activities.indexOf('broadcastA') > -1;
+	}
+	function _hasVideo(c) {
+		return c.activities.indexOf('broadcastV') > -1;
+	}
+	function _getRects(sel, excl) {
+		const list = [], elems = $(sel);
+		for (let i = 0; i < elems.length; ++i) {
+			if (excl !== $(elems[i]).attr('aria-describedby')) {
+				list.push(_getRect(elems[i]));
+			}
+		}
+		return list;
+	}
+	function _getRect(e) {
+		const win = $(e), winoff = win.offset();
+		return {left: winoff.left
+			, top: winoff.top
+			, right: winoff.left + win.width()
+			, bottom: winoff.top + win.height()};
+	}
+	function _getPos(list, w, h) {
+		if (Room.getOptions().interview) {
+			return {left: 0, top: 0};
+		}
+		const wba = $(WBA_SEL), woffset = wba.offset()
+			, offsetX = 20, offsetY = 10
+			, area = {left: woffset.left, top: woffset.top, right: woffset.left + wba.width(), bottom: woffset.top + wba.height()};
+		const rectNew = {
+				_left: area.left
+				, _top: area.top
+				, right: area.left + w
+				, bottom: area.top + h
+				, get left() {
+					return this._left
+				}
+				, set left(l) {
+					this._left = l;
+					this.right = l + w;
+				}
+				, get top() {
+					return this._top
+				}
+				, set top(t) {
+					this._top = t;
+					this.bottom = t + h;
+				}
+			};
+		let minY = area.bottom, posFound;
+		do {
+			posFound = true
+			for (let i = 0; i < list.length; ++i) {
+				const rect = list[i];
+				minY = Math.min(minY, rect.bottom);
+
+				if (rectNew.left < rect.right && rectNew.right > rect.left && rectNew.top < rect.bottom && rectNew.bottom > rect.top) {
+					rectNew.left = rect.right + offsetX;
+					posFound = false;
+				}
+				if (rectNew.right >= area.right) {
+					rectNew.left = area.left;
+					rectNew.top = minY + offsetY;
+					posFound = false;
+				}
+				if (rectNew.bottom >= area.bottom) {
+					rectNew.top = area.top;
+					posFound = true;
+					break;
+				}
+			}
+		} while (!posFound);
+		return {left: rectNew.left, top: rectNew.top};
+	}
+	function _arrange() {
+		const list = [], elems = $(VID_SEL);
+		for (let i = 0; i < elems.length; ++i) {
+			const v = $(elems[i]);
+			v.css(_getPos(list, v.width(), v.height()));
+			list.push(_getRect(v));
+		}
+	}
+
+	self.getVid = _getVid;
+	self.isSharing = _isSharing;
+	self.isRecording = _isRecording;
+	self.hasAudio = _hasAudio;
+	self.hasVideo = _hasVideo;
+	self.getRects = _getRects;
+	self.getPos = _getPos;
+	self.arrange = _arrange;
+	return self;
+})();
+var Video = (function() {
+	const self = {};
+	let c, v, vc, t, f, swf, size, vol, slider, handle
+		, lastVolume = 50;
+
+	function _getName() {
+		return c.user.firstName + ' ' + c.user.lastName;
+	}
+	function _resizeDlg(_ww, _hh) {
+		const interview = Room.getOptions().interview;
+		const _w = interview ? 320 : _ww, _h = interview ? 260 : _hh;
+		const h = _h + t.height() + 2 + (f.is(":visible") ? f.height() : 0);
+		v.dialog("option", "width", _w).dialog("option", "height", h);
+		_resize(_w, _h);
+		return h;
+	}
+	function _securityMode(on) {
+		if (Room.getOptions().interview) {
+			return;
+		}
+		if (on) {
+			//TODO buttons
+			v.dialog("option", "position", {my: "center", at: "center", of: WBA_SEL});
+		} else {
+			const h = _resizeDlg(size.width, size.height);
+			v.dialog("widget").css(VideoUtil.getPos(VideoUtil.getRects(VID_SEL, VideoUtil.getVid(c.uid)), c.width, h));
+		}
+	}
+	function _resize(w, h) {
+		vc.width(w).height(h);
+		swf.attr('width', w).attr('height', h);
+	}
+	function _handleMicStatus(state) {
+		if (!f.is(":visible")) {
+			return;
+		}
+		if (state) {
+			f.find('.off').hide();
+			f.find('.on').show();
+			f.addClass('ui-state-highlight');
+			t.addClass('ui-state-highlight');
+		} else {
+			f.find('.off').show();
+			f.find('.on').hide();
+			f.removeClass('ui-state-highlight');
+			t.removeClass('ui-state-highlight');
+		}
+	}
+	function _handleVolume(val) {
+		handle.text(val);
+		const ico = vol.find('.ui-icon');
+		if (val > 0 && ico.hasClass('ui-icon-volume-off')) {
+			ico.toggleClass('ui-icon-volume-off ui-icon-volume-on');
+			vol.removeClass('ui-state-error');
+			_handleMicStatus(true);
+		} else if (val === 0 && ico.hasClass('ui-icon-volume-on')) {
+			ico.toggleClass('ui-icon-volume-on ui-icon-volume-off');
+			vol.addClass('ui-state-error');
+			_handleMicStatus(false);
+		}
+		if (swf[0].setVolume !== undefined) {
+			swf[0].setVolume(val);
+		}
+	}
+	function _mute(mute) {
+		if (!slider) {
+			return;
+		}
+		if (mute) {
+			const val = slider.slider("option", "value");
+			if (val > 0) {
+				lastVolume = val;
+			}
+			slider.slider("option", "value", 0);
+			_handleVolume(0);
+		} else {
+			slider.slider("option", "value", lastVolume);
+			_handleVolume(lastVolume);
+		}
+	}
+	function _init(_c, _pos) {
+		c = _c;
+		size = {width: c.width, height: c.height};
+		const _id = VideoUtil.getVid(c.uid)
+			, name = _getName()
+			, _w = c.self ? Math.max(300, c.width) : c.width
+			, _h = c.self ? Math.max(200, c.height) : c.height
+			, opts = Room.getOptions();
+		{ //scope
+			const cont = opts.interview ? $('.pod.pod-' + c.pod) : $('.room.box');
+			cont.append($('#user-video').clone().attr('id', _id).attr('title', name)
+					.attr('data-client-uid', c.type + c.cuid).data(self));
+		}
+		v = $('#' + _id);
+		v.dialog({
+			classes: {
+				'ui-dialog': 'ui-corner-all video user-video' + (opts.showMicStatus ? ' mic-status' : '')
+				, 'ui-dialog-titlebar': 'ui-corner-all' + (opts.showMicStatus ? ' ui-state-highlight' : '')
+			}
+			, width: _w
+			, minWidth: 40
+			, minHeight: 50
+			, autoOpen: true
+			, appendTo: opts.interview ? '.pod.pod-' + c.pod : '.room.box'
+			, draggable: !opts.interview
+			, resizable: !opts.interview
+			, modal: false
+			, resizeStop: function(event, ui) {
+				const w = ui.size.width - 2
+					, h = ui.size.height - t.height() - 4 - (f.is(":visible") ? f.height() : 0);
+				_resize(w, h);
+				swf[0].vidResize(w, h);
+			}
+			, close: function() {
+				VideoManager.close(c.uid, true);
+			}
+		}).dialogExtend({
+			icons: {
+				'collapse': 'ui-icon-minus'
+			}
+			, closable: VideoUtil.isSharing(c)
+			, collapsable: true
+			, dblclick: "collapse"
+		});
+		t = v.parent().find('.ui-dialog-titlebar').attr('title', name);
+		f = v.find('.footer');
+		if (!VideoUtil.isSharing(c)) {
+			v.parent().find('.ui-dialog-titlebar-buttonpane')
+				.append($('#video-volume-btn').children().clone())
+				.append($('#video-refresh-btn').children().clone());
+			const volume = v.parent().find('.dropdown-menu.video.volume');
+			slider = v.parent().find('.slider');
+			if (opts.interview) {
+				v.parent().find('.ui-dialog-titlebar-collapse').hide();
+			}
+			vol = v.parent().find('.ui-dialog-titlebar-volume')
+				.on('mouseenter', function(e) {
+					e.stopImmediatePropagation();
+					volume.toggle();
+				})
+				.click(function(e) {
+					e.stopImmediatePropagation();
+					const muted = $(this).find('.ui-icon').hasClass('ui-icon-volume-off');
+					roomAction('mute', JSON.stringify({uid: c.cuid, mute: !muted}));
+					_mute(!muted);
+					volume.hide();
+					return false;
+				}).dblclick(function(e) {
+					e.stopImmediatePropagation();
+					return false;
+				});
+			v.parent().find('.ui-dialog-titlebar-refresh')
+				.click(function(e) {
+					e.stopImmediatePropagation();
+					_refresh();
+					return false;
+				}).dblclick(function(e) {
+					e.stopImmediatePropagation();
+					return false;
+				});
+			volume.on('mouseleave', function() {
+				$(this).hide();
+			});
+			handle = v.parent().find('.slider .handle');
+			slider.slider({
+				orientation: 'vertical'
+				, range: 'min'
+				, min: 0
+				, max: 100
+				, value: lastVolume
+				, create: function() {
+					handle.text($(this).slider("value"));
+				}
+				, slide: function(event, ui) {
+					_handleVolume(ui.value);
+				}
+			});
+			const hasAudio = VideoUtil.hasAudio(c);
+			_handleMicStatus(hasAudio);
+			if (!hasAudio) {
+				vol.hide();
+			}
+		}
+		vc = v.find('.video');
+		vc.width(_w).height(_h);
+		//broadcast
+		const o = Room.getOptions();
+		if (c.self) {
+			o.cam = c.cam;
+			o.mic = c.mic;
+			o.mode = 'broadcast';
+		} else {
+			o.mode = 'play';
+		}
+		o.av = c.activities.join();
+		o.rights = o.rights.join();
+		o.width = c.width;
+		o.height = c.height;
+		o.sid = c.sid;
+		o.uid = c.uid;
+		o.cuid = c.cuid;
+		o.userId = c.user.id;
+		o.broadcastId = c.broadcastId;
+		o.type = c.type;
+		delete o.keycode;
+		swf = initSwf(vc, 'main.swf', _id + '-swf', o);
+		swf.attr('width', _w).attr('height', _h);
+		v.dialog("widget").css(_pos);
+	}
+	function _update(_c) {
+		const opts = Room.getOptions();
+		c.screenActivities = _c.screenActivities;
+		c.activities = _c.activities;
+		c.user.firstName = _c.user.firstName;
+		c.user.lastName = _c.user.lastName;
+		const hasAudio = VideoUtil.hasAudio(c);
+		_handleMicStatus(hasAudio);
+		if (hasAudio) {
+			vol.show();
+		} else {
+			vol.hide();
+			v.parent().find('.dropdown-menu.video.volume').hide();
+		}
+		if (opts.interview && c.pod !== _c.pod) {
+			c.pod = _c.pod;
+			v.dialog('option', 'appendTo', '.pod.pod-' + c.pod);
+		}
+		const name = _getName();
+		v.dialog('option', 'title', name).parent().find('.ui-dialog-titlebar').attr('title', name);
+		if (swf[0].update !== undefined) {
+			c.self ? swf[0].update() : swf[0].update(c);
+		}
+	}
+	function _refresh(_opts) {
+		if (swf[0].refresh !== undefined) {
+			const opts = _opts || {};
+			if (!Room.getOptions().interview && !isNaN(opts.width)) {
+				_resizeDlg(opts.width, opts.height);
+			}
+			swf[0].refresh(opts);
+		}
+	}
+	function _setRights(_r) {
+		if (swf[0].setRights !== undefined) {
+			swf[0].setRights(_r);
+		}
+	}
+
+	self.update = _update;
+	self.refresh = _refresh;
+	self.mute = _mute;
+	self.isMuted = function() { return 0 === slider.slider("option", "value"); };
+	self.init = _init;
+	self.securityMode = _securityMode;
+	self.client = function() { return c; };
+	self.setRights = _setRights;
+	return self;
+});
+var VideoManager = (function() {
+	const self = {};
+	let share, inited = false;
+
+	function _init() {
+		if ($(WB_AREA_SEL + ' .wb-area .tabs').length > 0) {
+			WBA_SEL = WBA_WB_SEL;
+		}
+		VideoSettings.init(Room.getOptions());
+		share = $('.room.box').find('.icon.shared.ui-button');
+		inited = true;
+	}
+	function _update(c) {
+		if (!inited) {
+			return;
+		}
+		for (let i = 0; i < c.streams.length; ++i) {
+			const cl = JSON.parse(JSON.stringify(c)), s = c.streams[i];
+			delete cl.streams;
+			$.extend(cl, s);
+			if (cl.self && VideoUtil.isSharing(cl) || VideoUtil.isRecording(cl)) {
+				continue;
+			}
+			const _id = VideoUtil.getVid(cl.uid)
+				, av = VideoUtil.hasAudio(cl) || VideoUtil.hasVideo(cl)
+				, v = $('#' + _id);
+			if (av && v.length !== 1 && !!cl.self) {
+				Video().init(cl, VideoUtil.getPos(VideoUtil.getRects(VID_SEL), cl.width, cl.height + 25));
+			} else if (av && v.length === 1) {
+				v.data().update(cl);
+			} else if (!av && v.length === 1) {
+				_closeV(v);
+			}
+		}
+		if (c.uid === Room.getOptions().uid) {
+			Room.setRights(c.rights);
+			const windows = $(VID_SEL + ' .ui-dialog-content');
+			for (let i = 0; i < windows.length; ++i) {
+				const w = $(windows[i]);
+				w.data().setRights(c.rights);
+			}
+
+		}
+		if (c.streams.length === 0) {
+			// check for non inited video window
+			const v = $('#' + VideoUtil.getVid(c.uid));
+			if (v.length === 1) {
+				_closeV(v);
+			}
+		}
+	}
+	function _closeV(v) {
+		if (v.dialog('instance') !== undefined) {
+			v.dialog('destroy');
+		}
+		v.remove();
+	}
+	function _play(c) {
+		if (!inited) {
+			return;
+		}
+		if (VideoUtil.isSharing(c)) {
+			_highlight(share
+					.attr('title', share.data('user') + ' ' + c.user.firstName + ' ' + c.user.lastName + ' ' + share.data('text'))
+					.data('uid', c.uid)
+					.show(), 10);
+			share.tooltip().off('click').click(function() {
+				const v = $('#' + VideoUtil.getVid(c.uid))
+				if (v.length !== 1) {
+					Video().init(c, $(WBA_SEL).offset());
+				} else {
+					v.dialog('open');
+				}
+			});
+		} else if ('sharing' !== c.type) {
+			Video().init(c, VideoUtil.getPos(VideoUtil.getRects(VID_SEL), c.width, c.height + 25));
+		}
+	}
+	function _close(uid, showShareBtn) {
+		const _id = VideoUtil.getVid(uid), v = $('#' + _id);
+		if (v.length === 1) {
+			_closeV(v);
+		}
+		if (!showShareBtn && uid === share.data('uid')) {
+			share.off('click').hide();
+		}
+	}
+	function _highlight(el, count) {
+		if (count < 0) {
+			return;
+		}
+		el.addClass('ui-state-highlight', 2000, function() {
+			el.removeClass('ui-state-highlight', 2000, function() {
+				_highlight(el, --count);
+			});
+		});
+	}
+	function _find(uid) {
+		return $(VID_SEL + ' div[data-client-uid="room' + uid + '"]');
+	}
+	function _micActivity(uid, active) {
+		const u = $('#user' + uid + ' .audio-activity.ui-icon')
+			, v = _find(uid).parent();
+		if (active) {
+			u.addClass("speaking");
+			v.addClass('user-speaks')
+		} else {
+			u.removeClass("speaking");
+			v.removeClass('user-speaks')
+		}
+	}
+	function _refresh(uid, opts) {
+		const v = _find(uid);
+		if (v.length > 0) {
+			v.data().refresh(opts);
+		}
+	}
+	function _mute(uid, mute) {
+		const v = _find(uid);
+		if (v.length > 0) {
+			v.data().mute(mute);
+		}
+	}
+	function _clickExclusive(uid) {
+		const s = VideoSettings.load();
+		if (false !== s.video.confirmExclusive) {
+			const dlg = $('#exclusive-confirm');
+			dlg.dialog({
+				buttons: [
+					{
+						text: dlg.data('btn-ok')
+						, click: function() {
+							s.video.confirmExclusive = !$('#exclusive-confirm-dont-show').prop('checked');
+							VideoSettings.save();
+							roomAction('exclusive', uid);
+							$(this).dialog('close');
+						}
+					}
+					, {
+						text: dlg.data('btn-cancel')
+						, click: function() {
+							$(this).dialog('close');
+						}
+					}
+				]
+			})
+		}
+	}
+	function _exclusive(uid) {
+		const windows = $(VID_SEL + ' .ui-dialog-content');
+		for (let i = 0; i < windows.length; ++i) {
+			const w = $(windows[i]);
+			w.data().mute('room' + uid !== w.data('client-uid'));
+		}
+	}
+
+	self.init = _init;
+	self.update = _update;
+	self.play = _play;
+	self.close = _close;
+	self.securityMode = function(uid, on) { $('#' + VideoUtil.getVid(uid)).data().securityMode(on); };
+	self.micActivity = _micActivity;
+	self.refresh = _refresh;
+	self.mute = _mute;
+	self.clickExclusive = _clickExclusive;
+	self.exclusive = _exclusive;
+	return self;
+})();
+var Room = (function() {
+	const self = {}, sbSide = Settings.isRtl ? 'right' : 'left';
+	let options, menuHeight, chat, sb, dock;
+
+	function _init(_options) {
+		options = _options;
+		window.WbArea = options.interview ? InterviewWbArea() : DrawWbArea();
+		const menu = $('.room.box .room.menu');
+		chat = $('#chatPanel');
+		sb = $('.room.sidebar').css(sbSide, '0px');
+		dock = sb.find('.btn-dock').button({
+			icon: "ui-icon icon-undock"
+			, showLabel: false
+		}).click(function() {
+			const offset = parseInt(sb.css(sbSide));
+			if (offset < 0) {
+				sb.removeClass('closed');
+			}
+			dock.button('option', 'disabled', true);
+			const props = {};
+			props[sbSide] = offset < 0 ? '0px' : (-sb.width() + 45) + 'px';
+			sb.animate(props, 1500
+				, function() {
+					dock.button('option', 'disabled', false)
+						.button('option', 'icon', 'ui-icon ' + (offset < 0 ? 'icon-undock' : 'icon-dock'));
+					if (offset < 0) {
+						dock.attr('title', dock.data('ttl-undock'));
+						_sbAddResizable();
+					} else {
+						dock.attr('title', dock.data('ttl-dock'));
+						sb.addClass('closed').resizable('destroy');
+					}
+					_setSize();
+				});
+		});
+		dock.addClass(Settings.isRtl ? 'align-left' : 'align-right').attr('title', dock.data('ttl-undock'))
+			.button('option', 'label', dock.data('ttl-undock'))
+			.button('refresh');
+		menuHeight = menu.length === 0 ? 0 : menu.height();
+		VideoManager.init();
+		Activities.init();
+	}
+	function _getSelfAudioClient() {
+		const vw = $('#video' + Room.getOptions().uid);
+		if (vw.length > 0) {
+			const v = vw.data();
+			if (VideoUtil.hasAudio(v.client())) {
+				return v;
+			}
+		}
+		return null;
+	}
+	function _keyHandler(e) {
+		if (e.shiftKey) {
+			switch (e.which) {
+				case options.keycode.arrange: // Shift+F8 by default
+					VideoUtil.arrange();
+					break;
+				case options.keycode.exclusive: // Shift+F12 by default
+				{
+					const v = _getSelfAudioClient();
+					if (v !== null) {
+						VideoManager.clickExclusive(Room.getOptions().uid);
+					}
+				}
+					break;
+				case options.keycode.mute: // Shift+F7 by default
+				{
+					const v = _getSelfAudioClient();
+					if (v !== null) {
+						v.mute(!v.isMuted());
+					}
+				}
+					break;
+			}
+		}
+		if (e.which === 27) {
+			$('#wb-rename-menu').hide();
+		}
+	}
+	function _mouseHandler(e) {
+		if (e.which === 1) {
+			$('#wb-rename-menu').hide();
+		}
+	}
+	function _sbWidth() {
+		if (sb === undefined) {
+			sb = $('.room.sidebar');
+		}
+		return sb === undefined ? 0 : sb.width() + parseInt(sb.css(sbSide));
+	}
+	function _setSize() {
+		const sbW = _sbWidth()
+			, w = $(window).width() - sbW - 8
+			, h = $(window).height() - menuHeight - 3
+			, p = sb.find('.tabs')
+			, holder = $('.room.holder');
+		sb.height(h);
+		const hh = h - 5;
+		p.height(hh);
+		$(".user.list", p).height(hh - $("ul", p).height() - $(".user.header", p).height() - 5);
+		if (sbW > 255) {
+			holder.addClass('big').removeClass('small');
+		} else {
+			holder.removeClass('big').addClass('small');
+		}
+		Chat.setHeight(h);
+		if (typeof(WbArea) !== 'undefined') {
+			const chW = chat.width();
+			WbArea.resize(sbW + 5, chW + 5, w - chW, h);
+		}
+	}
+	function _reload() {
+		if (!!options && !!options.reloadUrl) {
+			window.location.href = options.reloadUrl;
+		} else {
+			window.location.reload();
+		}
+	}
+	function _close() {
+		_unload();
+		$(".room.holder").remove();
+		$("#chatPanel").remove();
+		const dlg = $('#disconnected-dlg');
+		dlg.dialog({
+			modal: true
+			, close: _reload
+			, buttons: [
+				{
+					text: dlg.data('reload')
+					, icons: {primary: "ui-icon-refresh"}
+					, click: function() {
+						$(this).dialog("close");
+					}
+				}
+			]
+		});
+	}
+	function _sbAddResizable() {
+		sb.resizable({
+			handles: Settings.isRtl ? 'w' : 'e'
+			, stop: function() {
+				_setSize();
+			}
+		});
+	}
+	function _load() {
+		if (sb !== undefined) {
+			sb.ready(function() {
+				_setSize();
+			});
+			_sbAddResizable();
+		}
+		$(window).on('resize.openmeetings', function() {
+			_setSize();
+		});
+		Wicket.Event.subscribe("/websocket/closed", _close);
+		Wicket.Event.subscribe("/websocket/error", _close);
+		$(window).keyup(_keyHandler);
+		$(document).click(_mouseHandler);
+	}
+	function _unload() {
+		$(window).off('resize.openmeetings');
+		Wicket.Event.unsubscribe("/websocket/closed", _close);
+		Wicket.Event.unsubscribe("/websocket/error", _close);
+		if (typeof(WbArea) !== 'undefined') {
+			WbArea.destroy();
+			WbArea = undefined;
+		}
+		if (typeof(VideoSettings) !== 'undefined') {
+			VideoSettings.close();
+		}
+		$('.ui-dialog.user-video').remove();
+		$(window).off('keyup', _keyHandler);
+		$(document).off('click', _mouseHandler);
+	}
+	function _showClipboard(txt) {
+		const dlg = $('#clipboard-dialog');
+		dlg.find('p .text').text(txt);
+		dlg.dialog({
+			resizable: false
+			, height: "auto"
+			, width: 400
+			, modal: true
+			, buttons: [
+				{
+					text: dlg.data('btn-ok')
+					, click: function() {
+						$(this).dialog('close');
+					}
+				}
+			]
+		});
+	}
+
+	self.init = _init;
+	self.getMenuHeight = function() { return menuHeight; };
+	self.getOptions = function() { return typeof(options) === 'object' ? JSON.parse(JSON.stringify(options)) : {}; };
+	self.setRights = function(_r) { return options.rights = _r; };
+	self.setSize = _setSize;
+	self.load = _load;
+	self.unload = _unload;
+	self.showClipboard = _showClipboard;
+	return self;
+})();
+function startPrivateChat(el) {
+	Chat.addTab('chatTab-u' + el.parent().parent().data("userid"), el.parent().parent().find('.user.name').text());
+	Chat.open();
+	$('#chatMessage .wysiwyg-editor').click();
+}
+/***** functions required by SIP   ******/
+function sipBtnClick() {
+	const txt = $('.sip-number');
+	txt.val(txt.val() + $(this).data('value'));
+}
+function sipBtnEraseClick() {
+	const txt = $('.sip-number')
+		, t = txt.val();
+	if (!!t) {
+		txt.val(t.substring(0, t.length -1));
+	}
+}
+function sipGetKey(evt) {
+	let k = -1;
+	if (evt.keyCode > 47 && evt.keyCode < 58) {
+		k = evt.keyCode - 48;
+	}
+	if (evt.keyCode > 95 && evt.keyCode < 106) {
+		k = evt.keyCode - 96;
+	}
+	return k;
+}
+function sipKeyDown(evt) {
+	const k = sipGetKey(evt);
+	if (k > 0) {
+		$('#sip-dialer-btn-' + k).addClass('ui-state-active');
+	}
+}
+function sipKeyUp(evt) {
+	const k = sipGetKey(evt);
+	if (k > 0) {
+		$('#sip-dialer-btn-' + k).removeClass('ui-state-active');
+	}
+}
+/***** functions required by SWF   ******/
+function typingActivity(uid, active) {
+	const u = $('#user' + uid + ' .typing-activity.ui-icon');
+	if (active) {
+		u.addClass("typing");
+	} else {
+		u.removeClass("typing");
+	}
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js
deleted file mode 100644
index edafe4c..0000000
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js
+++ /dev/null
@@ -1,818 +0,0 @@
-/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
-const WB_AREA_SEL = '.room.wb.area';
-const WBA_WB_SEL = '.room.wb.area .ui-tabs-panel.ui-corner-bottom.ui-widget-content:visible';
-var WBA_SEL = WB_AREA_SEL;
-const VID_SEL = '.video.user-video';
-var RoomUtil = (function() {
-	const self = {};
-	function _confirmDlg(_id, okHandler) {
-		const confirm = $('#' + _id);
-		confirm.dialog({
-			modal: true
-			, buttons: [
-				{
-					text: confirm.data('btn-ok')
-					, click: function() {
-						okHandler();
-						$(this).dialog('close');
-					}
-				}
-				, {
-					text: confirm.data('btn-cancel')
-					, click: function() {
-						$(this).dialog('close');
-					}
-				}
-			]
-		});
-		return confirm;
-	}
-
-	self.confirmDlg = _confirmDlg;
-	return self;
-})();
-var VideoUtil = (function() {
-	const self = {};
-	function _getVid(uid) {
-		return "video" + uid;
-	}
-	function _isSharing(c) {
-		return 'sharing' === c.type && c.screenActivities.indexOf('sharing') > -1;
-	}
-	function _isRecording(c) {
-		return 'sharing' === c.type
-			&& c.screenActivities.indexOf('recording') > -1
-			&& c.screenActivities.indexOf('sharing') < 0;
-	}
-	function _hasAudio(c) {
-		return c.activities.indexOf('broadcastA') > -1;
-	}
-	function _hasVideo(c) {
-		return c.activities.indexOf('broadcastV') > -1;
-	}
-	function _getRects(sel, excl) {
-		const list = [], elems = $(sel);
-		for (let i = 0; i < elems.length; ++i) {
-			if (excl !== $(elems[i]).attr('aria-describedby')) {
-				list.push(_getRect(elems[i]));
-			}
-		}
-		return list;
-	}
-	function _getRect(e) {
-		const win = $(e), winoff = win.offset();
-		return {left: winoff.left
-			, top: winoff.top
-			, right: winoff.left + win.width()
-			, bottom: winoff.top + win.height()};
-	}
-	function _getPos(list, w, h) {
-		if (Room.getOptions().interview) {
-			return {left: 0, top: 0};
-		}
-		const wba = $(WBA_SEL), woffset = wba.offset()
-			, offsetX = 20, offsetY = 10
-			, area = {left: woffset.left, top: woffset.top, right: woffset.left + wba.width(), bottom: woffset.top + wba.height()};
-		const rectNew = {
-				_left: area.left
-				, _top: area.top
-				, right: area.left + w
-				, bottom: area.top + h
-				, get left() {
-					return this._left
-				}
-				, set left(l) {
-					this._left = l;
-					this.right = l + w;
-				}
-				, get top() {
-					return this._top
-				}
-				, set top(t) {
-					this._top = t;
-					this.bottom = t + h;
-				}
-			};
-		let minY = area.bottom, posFound;
-		do {
-			posFound = true
-			for (let i = 0; i < list.length; ++i) {
-				const rect = list[i];
-				minY = Math.min(minY, rect.bottom);
-
-				if (rectNew.left < rect.right && rectNew.right > rect.left && rectNew.top < rect.bottom && rectNew.bottom > rect.top) {
-					rectNew.left = rect.right + offsetX;
-					posFound = false;
-				}
-				if (rectNew.right >= area.right) {
-					rectNew.left = area.left;
-					rectNew.top = minY + offsetY;
-					posFound = false;
-				}
-				if (rectNew.bottom >= area.bottom) {
-					rectNew.top = area.top;
-					posFound = true;
-					break;
-				}
-			}
-		} while (!posFound);
-		return {left: rectNew.left, top: rectNew.top};
-	}
-	function _arrange() {
-		const list = [], elems = $(VID_SEL);
-		for (let i = 0; i < elems.length; ++i) {
-			const v = $(elems[i]);
-			v.css(_getPos(list, v.width(), v.height()));
-			list.push(_getRect(v));
-		}
-	}
-
-	self.getVid = _getVid;
-	self.isSharing = _isSharing;
-	self.isRecording = _isRecording;
-	self.hasAudio = _hasAudio;
-	self.hasVideo = _hasVideo;
-	self.getRects = _getRects;
-	self.getPos = _getPos;
-	self.arrange = _arrange;
-	return self;
-})();
-var Video = (function() {
-	const self = {};
-	let c, v, vc, t, f, swf, size, vol, slider, handle
-		, lastVolume = 50;
-
-	function _getName() {
-		return c.user.firstName + ' ' + c.user.lastName;
-	}
-	function _resizeDlg(_ww, _hh) {
-		const interview = Room.getOptions().interview;
-		const _w = interview ? 320 : _ww, _h = interview ? 260 : _hh;
-		const h = _h + t.height() + 2 + (f.is(":visible") ? f.height() : 0);
-		v.dialog("option", "width", _w).dialog("option", "height", h);
-		_resize(_w, _h);
-		return h;
-	}
-	function _securityMode(on) {
-		if (Room.getOptions().interview) {
-			return;
-		}
-		if (on) {
-			//TODO buttons
-			v.dialog("option", "position", {my: "center", at: "center", of: WBA_SEL});
-		} else {
-			const h = _resizeDlg(size.width, size.height);
-			v.dialog("widget").css(VideoUtil.getPos(VideoUtil.getRects(VID_SEL, VideoUtil.getVid(c.uid)), c.width, h));
-		}
-	}
-	function _resize(w, h) {
-		vc.width(w).height(h);
-		swf.attr('width', w).attr('height', h);
-	}
-	function _handleMicStatus(state) {
-		if (!f.is(":visible")) {
-			return;
-		}
-		if (state) {
-			f.find('.off').hide();
-			f.find('.on').show();
-			f.addClass('ui-state-highlight');
-			t.addClass('ui-state-highlight');
-		} else {
-			f.find('.off').show();
-			f.find('.on').hide();
-			f.removeClass('ui-state-highlight');
-			t.removeClass('ui-state-highlight');
-		}
-	}
-	function _handleVolume(val) {
-		handle.text(val);
-		const ico = vol.find('.ui-icon');
-		if (val > 0 && ico.hasClass('ui-icon-volume-off')) {
-			ico.toggleClass('ui-icon-volume-off ui-icon-volume-on');
-			vol.removeClass('ui-state-error');
-			_handleMicStatus(true);
-		} else if (val === 0 && ico.hasClass('ui-icon-volume-on')) {
-			ico.toggleClass('ui-icon-volume-on ui-icon-volume-off');
-			vol.addClass('ui-state-error');
-			_handleMicStatus(false);
-		}
-		if (swf[0].setVolume !== undefined) {
-			swf[0].setVolume(val);
-		}
-	}
-	function _mute(mute) {
-		if (!slider) {
-			return;
-		}
-		if (mute) {
-			const val = slider.slider("option", "value");
-			if (val > 0) {
-				lastVolume = val;
-			}
-			slider.slider("option", "value", 0);
-			_handleVolume(0);
-		} else {
-			slider.slider("option", "value", lastVolume);
-			_handleVolume(lastVolume);
-		}
-	}
-	function _init(_c, _pos) {
-		c = _c;
-		size = {width: c.width, height: c.height};
-		const _id = VideoUtil.getVid(c.uid)
-			, name = _getName()
-			, _w = c.self ? Math.max(300, c.width) : c.width
-			, _h = c.self ? Math.max(200, c.height) : c.height
-			, opts = Room.getOptions();
-		{ //scope
-			const cont = opts.interview ? $('.pod.pod-' + c.pod) : $('.room.box');
-			cont.append($('#user-video').clone().attr('id', _id).attr('title', name)
-					.attr('data-client-uid', c.type + c.cuid).data(self));
-		}
-		v = $('#' + _id);
-		v.dialog({
-			classes: {
-				'ui-dialog': 'ui-corner-all video user-video' + (opts.showMicStatus ? ' mic-status' : '')
-				, 'ui-dialog-titlebar': 'ui-corner-all' + (opts.showMicStatus ? ' ui-state-highlight' : '')
-			}
-			, width: _w
-			, minWidth: 40
-			, minHeight: 50
-			, autoOpen: true
-			, appendTo: opts.interview ? '.pod.pod-' + c.pod : '.room.box'
-			, draggable: !opts.interview
-			, resizable: !opts.interview
-			, modal: false
-			, resizeStop: function(event, ui) {
-				const w = ui.size.width - 2
-					, h = ui.size.height - t.height() - 4 - (f.is(":visible") ? f.height() : 0);
-				_resize(w, h);
-				swf[0].vidResize(w, h);
-			}
-			, close: function() {
-				VideoManager.close(c.uid, true);
-			}
-		}).dialogExtend({
-			icons: {
-				'collapse': 'ui-icon-minus'
-			}
-			, closable: VideoUtil.isSharing(c)
-			, collapsable: true
-			, dblclick: "collapse"
-		});
-		t = v.parent().find('.ui-dialog-titlebar').attr('title', name);
-		f = v.find('.footer');
-		if (!VideoUtil.isSharing(c)) {
-			v.parent().find('.ui-dialog-titlebar-buttonpane')
-				.append($('#video-volume-btn').children().clone())
-				.append($('#video-refresh-btn').children().clone());
-			const volume = v.parent().find('.dropdown-menu.video.volume');
-			slider = v.parent().find('.slider');
-			if (opts.interview) {
-				v.parent().find('.ui-dialog-titlebar-collapse').hide();
-			}
-			vol = v.parent().find('.ui-dialog-titlebar-volume')
-				.on('mouseenter', function(e) {
-					e.stopImmediatePropagation();
-					volume.toggle();
-				})
-				.click(function(e) {
-					e.stopImmediatePropagation();
-					const muted = $(this).find('.ui-icon').hasClass('ui-icon-volume-off');
-					roomAction('mute', JSON.stringify({uid: c.cuid, mute: !muted}));
-					_mute(!muted);
-					volume.hide();
-					return false;
-				}).dblclick(function(e) {
-					e.stopImmediatePropagation();
-					return false;
-				});
-			v.parent().find('.ui-dialog-titlebar-refresh')
-				.click(function(e) {
-					e.stopImmediatePropagation();
-					_refresh();
-					return false;
-				}).dblclick(function(e) {
-					e.stopImmediatePropagation();
-					return false;
-				});
-			volume.on('mouseleave', function() {
-				$(this).hide();
-			});
-			handle = v.parent().find('.slider .handle');
-			slider.slider({
-				orientation: 'vertical'
-				, range: 'min'
-				, min: 0
-				, max: 100
-				, value: lastVolume
-				, create: function() {
-					handle.text($(this).slider("value"));
-				}
-				, slide: function(event, ui) {
-					_handleVolume(ui.value);
-				}
-			});
-			const hasAudio = VideoUtil.hasAudio(c);
-			_handleMicStatus(hasAudio);
-			if (!hasAudio) {
-				vol.hide();
-			}
-		}
-		vc = v.find('.video');
-		vc.width(_w).height(_h);
-		//broadcast
-		const o = Room.getOptions();
-		if (c.self) {
-			o.cam = c.cam;
-			o.mic = c.mic;
-			o.mode = 'broadcast';
-		} else {
-			o.mode = 'play';
-		}
-		o.av = c.activities.join();
-		o.rights = o.rights.join();
-		o.width = c.width;
-		o.height = c.height;
-		o.sid = c.sid;
-		o.uid = c.uid;
-		o.cuid = c.cuid;
-		o.userId = c.user.id;
-		o.broadcastId = c.broadcastId;
-		o.type = c.type;
-		delete o.keycode;
-		swf = initSwf(vc, 'main.swf', _id + '-swf', o);
-		swf.attr('width', _w).attr('height', _h);
-		v.dialog("widget").css(_pos);
-	}
-	function _update(_c) {
-		const opts = Room.getOptions();
-		c.screenActivities = _c.screenActivities;
-		c.activities = _c.activities;
-		c.user.firstName = _c.user.firstName;
-		c.user.lastName = _c.user.lastName;
-		const hasAudio = VideoUtil.hasAudio(c);
-		_handleMicStatus(hasAudio);
-		if (hasAudio) {
-			vol.show();
-		} else {
-			vol.hide();
-			v.parent().find('.dropdown-menu.video.volume').hide();
-		}
-		if (opts.interview && c.pod !== _c.pod) {
-			c.pod = _c.pod;
-			v.dialog('option', 'appendTo', '.pod.pod-' + c.pod);
-		}
-		const name = _getName();
-		v.dialog('option', 'title', name).parent().find('.ui-dialog-titlebar').attr('title', name);
-		if (swf[0].update !== undefined) {
-			c.self ? swf[0].update() : swf[0].update(c);
-		}
-	}
-	function _refresh(_opts) {
-		if (swf[0].refresh !== undefined) {
-			const opts = _opts || {};
-			if (!Room.getOptions().interview && !isNaN(opts.width)) {
-				_resizeDlg(opts.width, opts.height);
-			}
-			swf[0].refresh(opts);
-		}
-	}
-	function _setRights(_r) {
-		if (swf[0].setRights !== undefined) {
-			swf[0].setRights(_r);
-		}
-	}
-
-	self.update = _update;
-	self.refresh = _refresh;
-	self.mute = _mute;
-	self.isMuted = function() { return 0 === slider.slider("option", "value"); };
-	self.init = _init;
-	self.securityMode = _securityMode;
-	self.client = function() { return c; };
-	self.setRights = _setRights;
-	return self;
-});
-var VideoManager = (function() {
-	const self = {};
-	let share, inited = false;
-
-	function _init() {
-		if ($(WB_AREA_SEL + ' .wb-area .tabs').length > 0) {
-			WBA_SEL = WBA_WB_SEL;
-		}
-		VideoSettings.init(Room.getOptions());
-		share = $('.room.box').find('.icon.shared.ui-button');
-		inited = true;
-	}
-	function _update(c) {
-		if (!inited) {
-			return;
-		}
-		for (let i = 0; i < c.streams.length; ++i) {
-			const cl = JSON.parse(JSON.stringify(c)), s = c.streams[i];
-			delete cl.streams;
-			$.extend(cl, s);
-			if (cl.self && VideoUtil.isSharing(cl) || VideoUtil.isRecording(cl)) {
-				continue;
-			}
-			const _id = VideoUtil.getVid(cl.uid)
-				, av = VideoUtil.hasAudio(cl) || VideoUtil.hasVideo(cl)
-				, v = $('#' + _id);
-			if (av && v.length !== 1 && !!cl.self) {
-				Video().init(cl, VideoUtil.getPos(VideoUtil.getRects(VID_SEL), cl.width, cl.height + 25));
-			} else if (av && v.length === 1) {
-				v.data().update(cl);
-			} else if (!av && v.length === 1) {
-				_closeV(v);
-			}
-		}
-		if (c.uid === Room.getOptions().uid) {
-			Room.setRights(c.rights);
-			const windows = $(VID_SEL + ' .ui-dialog-content');
-			for (let i = 0; i < windows.length; ++i) {
-				const w = $(windows[i]);
-				w.data().setRights(c.rights);
-			}
-
-		}
-		if (c.streams.length === 0) {
-			// check for non inited video window
-			const v = $('#' + VideoUtil.getVid(c.uid));
-			if (v.length === 1) {
-				_closeV(v);
-			}
-		}
-	}
-	function _closeV(v) {
-		if (v.dialog('instance') !== undefined) {
-			v.dialog('destroy');
-		}
-		v.remove();
-	}
-	function _play(c) {
-		if (!inited) {
-			return;
-		}
-		if (VideoUtil.isSharing(c)) {
-			_highlight(share
-					.attr('title', share.data('user') + ' ' + c.user.firstName + ' ' + c.user.lastName + ' ' + share.data('text'))
-					.data('uid', c.uid)
-					.show(), 10);
-			share.tooltip().off('click').click(function() {
-				const v = $('#' + VideoUtil.getVid(c.uid))
-				if (v.length !== 1) {
-					Video().init(c, $(WBA_SEL).offset());
-				} else {
-					v.dialog('open');
-				}
-			});
-		} else if ('sharing' !== c.type) {
-			Video().init(c, VideoUtil.getPos(VideoUtil.getRects(VID_SEL), c.width, c.height + 25));
-		}
-	}
-	function _close(uid, showShareBtn) {
-		const _id = VideoUtil.getVid(uid), v = $('#' + _id);
-		if (v.length === 1) {
-			_closeV(v);
-		}
-		if (!showShareBtn && uid === share.data('uid')) {
-			share.off('click').hide();
-		}
-	}
-	function _highlight(el, count) {
-		if (count < 0) {
-			return;
-		}
-		el.addClass('ui-state-highlight', 2000, function() {
-			el.removeClass('ui-state-highlight', 2000, function() {
-				_highlight(el, --count);
-			});
-		});
-	}
-	function _find(uid) {
-		return $(VID_SEL + ' div[data-client-uid="room' + uid + '"]');
-	}
-	function _micActivity(uid, active) {
-		const u = $('#user' + uid + ' .audio-activity.ui-icon')
-			, v = _find(uid).parent();
-		if (active) {
-			u.addClass("speaking");
-			v.addClass('user-speaks')
-		} else {
-			u.removeClass("speaking");
-			v.removeClass('user-speaks')
-		}
-	}
-	function _refresh(uid, opts) {
-		const v = _find(uid);
-		if (v.length > 0) {
-			v.data().refresh(opts);
-		}
-	}
-	function _mute(uid, mute) {
-		const v = _find(uid);
-		if (v.length > 0) {
-			v.data().mute(mute);
-		}
-	}
-	function _clickExclusive(uid) {
-		const s = VideoSettings.load();
-		if (false !== s.video.confirmExclusive) {
-			const dlg = $('#exclusive-confirm');
-			dlg.dialog({
-				buttons: [
-					{
-						text: dlg.data('btn-ok')
-						, click: function() {
-							s.video.confirmExclusive = !$('#exclusive-confirm-dont-show').prop('checked');
-							VideoSettings.save();
-							roomAction('exclusive', uid);
-							$(this).dialog('close');
-						}
-					}
-					, {
-						text: dlg.data('btn-cancel')
-						, click: function() {
-							$(this).dialog('close');
-						}
-					}
-				]
-			})
-		}
-	}
-	function _exclusive(uid) {
-		const windows = $(VID_SEL + ' .ui-dialog-content');
-		for (let i = 0; i < windows.length; ++i) {
-			const w = $(windows[i]);
-			w.data().mute('room' + uid !== w.data('client-uid'));
-		}
-	}
-
-	self.init = _init;
-	self.update = _update;
-	self.play = _play;
-	self.close = _close;
-	self.securityMode = function(uid, on) { $('#' + VideoUtil.getVid(uid)).data().securityMode(on); };
-	self.micActivity = _micActivity;
-	self.refresh = _refresh;
-	self.mute = _mute;
-	self.clickExclusive = _clickExclusive;
-	self.exclusive = _exclusive;
-	return self;
-})();
-var Room = (function() {
-	const self = {}, sbSide = Settings.isRtl ? 'right' : 'left';
-	let options, menuHeight, chat, sb, dock;
-
-	function _init(_options) {
-		options = _options;
-		window.WbArea = options.interview ? InterviewWbArea() : DrawWbArea();
-		const menu = $('.room.box .room.menu');
-		chat = $('#chatPanel');
-		sb = $('.room.sidebar').css(sbSide, '0px');
-		dock = sb.find('.btn-dock').button({
-			icon: "ui-icon icon-undock"
-			, showLabel: false
-		}).click(function() {
-			const offset = parseInt(sb.css(sbSide));
-			if (offset < 0) {
-				sb.removeClass('closed');
-			}
-			dock.button('option', 'disabled', true);
-			const props = {};
-			props[sbSide] = offset < 0 ? '0px' : (-sb.width() + 45) + 'px';
-			sb.animate(props, 1500
-				, function() {
-					dock.button('option', 'disabled', false)
-						.button('option', 'icon', 'ui-icon ' + (offset < 0 ? 'icon-undock' : 'icon-dock'));
-					if (offset < 0) {
-						dock.attr('title', dock.data('ttl-undock'));
-						_sbAddResizable();
-					} else {
-						dock.attr('title', dock.data('ttl-dock'));
-						sb.addClass('closed').resizable('destroy');
-					}
-					_setSize();
-				});
-		});
-		dock.addClass(Settings.isRtl ? 'align-left' : 'align-right').attr('title', dock.data('ttl-undock'))
-			.button('option', 'label', dock.data('ttl-undock'))
-			.button('refresh');
-		menuHeight = menu.length === 0 ? 0 : menu.height();
-		VideoManager.init();
-		Activities.init();
-	}
-	function _getSelfAudioClient() {
-		const vw = $('#video' + Room.getOptions().uid);
-		if (vw.length > 0) {
-			const v = vw.data();
-			if (VideoUtil.hasAudio(v.client())) {
-				return v;
-			}
-		}
-		return null;
-	}
-	function _keyHandler(e) {
-		if (e.shiftKey) {
-			switch (e.which) {
-				case options.keycode.arrange: // Shift+F8 by default
-					VideoUtil.arrange();
-					break;
-				case options.keycode.exclusive: // Shift+F12 by default
-				{
-					const v = _getSelfAudioClient();
-					if (v !== null) {
-						VideoManager.clickExclusive(Room.getOptions().uid);
-					}
-				}
-					break;
-				case options.keycode.mute: // Shift+F7 by default
-				{
-					const v = _getSelfAudioClient();
-					if (v !== null) {
-						v.mute(!v.isMuted());
-					}
-				}
-					break;
-			}
-		}
-		if (e.which === 27) {
-			$('#wb-rename-menu').hide();
-		}
-	}
-	function _mouseHandler(e) {
-		if (e.which === 1) {
-			$('#wb-rename-menu').hide();
-		}
-	}
-	function _sbWidth() {
-		if (sb === undefined) {
-			sb = $('.room.sidebar');
-		}
-		return sb === undefined ? 0 : sb.width() + parseInt(sb.css(sbSide));
-	}
-	function _setSize() {
-		const sbW = _sbWidth()
-			, w = $(window).width() - sbW - 8
-			, h = $(window).height() - menuHeight - 3
-			, p = sb.find('.tabs')
-			, holder = $('.room.holder');
-		sb.height(h);
-		const hh = h - 5;
-		p.height(hh);
-		$(".user.list", p).height(hh - $("ul", p).height() - $(".user.header", p).height() - 5);
-		if (sbW > 255) {
-			holder.addClass('big').removeClass('small');
-		} else {
-			holder.removeClass('big').addClass('small');
-		}
-		Chat.setHeight(h);
-		if (typeof(WbArea) !== 'undefined') {
-			const chW = chat.width();
-			WbArea.resize(sbW + 5, chW + 5, w - chW, h);
-		}
-	}
-	function _reload() {
-		if (!!options && !!options.reloadUrl) {
-			window.location.href = options.reloadUrl;
-		} else {
-			window.location.reload();
-		}
-	}
-	function _close() {
-		_unload();
-		$(".room.holder").remove();
-		$("#chatPanel").remove();
-		const dlg = $('#disconnected-dlg');
-		dlg.dialog({
-			modal: true
-			, close: _reload
-			, buttons: [
-				{
-					text: dlg.data('reload')
-					, icons: {primary: "ui-icon-refresh"}
-					, click: function() {
-						$(this).dialog("close");
-					}
-				}
-			]
-		});
-	}
-	function _sbAddResizable() {
-		sb.resizable({
-			handles: Settings.isRtl ? 'w' : 'e'
-			, stop: function() {
-				_setSize();
-			}
-		});
-	}
-	function _load() {
-		if (sb !== undefined) {
-			sb.ready(function() {
-				_setSize();
-			});
-			_sbAddResizable();
-		}
-		$(window).on('resize.openmeetings', function() {
-			_setSize();
-		});
-		Wicket.Event.subscribe("/websocket/closed", _close);
-		Wicket.Event.subscribe("/websocket/error", _close);
-		$(window).keyup(_keyHandler);
-		$(document).click(_mouseHandler);
-	}
-	function _unload() {
-		$(window).off('resize.openmeetings');
-		Wicket.Event.unsubscribe("/websocket/closed", _close);
-		Wicket.Event.unsubscribe("/websocket/error", _close);
-		if (typeof(WbArea) !== 'undefined') {
-			WbArea.destroy();
-			WbArea = undefined;
-		}
-		if (typeof(VideoSettings) !== 'undefined') {
-			VideoSettings.close();
-		}
-		$('.ui-dialog.user-video').remove();
-		$(window).off('keyup', _keyHandler);
-		$(document).off('click', _mouseHandler);
-	}
-	function _showClipboard(txt) {
-		const dlg = $('#clipboard-dialog');
-		dlg.find('p .text').text(txt);
-		dlg.dialog({
-			resizable: false
-			, height: "auto"
-			, width: 400
-			, modal: true
-			, buttons: [
-				{
-					text: dlg.data('btn-ok')
-					, click: function() {
-						$(this).dialog('close');
-					}
-				}
-			]
-		});
-	}
-
-	self.init = _init;
-	self.getMenuHeight = function() { return menuHeight; };
-	self.getOptions = function() { return typeof(options) === 'object' ? JSON.parse(JSON.stringify(options)) : {}; };
-	self.setRights = function(_r) { return options.rights = _r; };
-	self.setSize = _setSize;
-	self.load = _load;
-	self.unload = _unload;
-	self.showClipboard = _showClipboard;
-	return self;
-})();
-function startPrivateChat(el) {
-	Chat.addTab('chatTab-u' + el.parent().parent().data("userid"), el.parent().parent().find('.user.name').text());
-	Chat.open();
-	$('#chatMessage .wysiwyg-editor').click();
-}
-/***** functions required by SIP   ******/
-function sipBtnClick() {
-	const txt = $('.sip-number');
-	txt.val(txt.val() + $(this).data('value'));
-}
-function sipBtnEraseClick() {
-	const txt = $('.sip-number')
-		, t = txt.val();
-	if (!!t) {
-		txt.val(t.substring(0, t.length -1));
-	}
-}
-function sipGetKey(evt) {
-	let k = -1;
-	if (evt.keyCode > 47 && evt.keyCode < 58) {
-		k = evt.keyCode - 48;
-	}
-	if (evt.keyCode > 95 && evt.keyCode < 106) {
-		k = evt.keyCode - 96;
-	}
-	return k;
-}
-function sipKeyDown(evt) {
-	const k = sipGetKey(evt);
-	if (k > 0) {
-		$('#sip-dialer-btn-' + k).addClass('ui-state-active');
-	}
-}
-function sipKeyUp(evt) {
-	const k = sipGetKey(evt);
-	if (k > 0) {
-		$('#sip-dialer-btn-' + k).removeClass('ui-state-active');
-	}
-}
-/***** functions required by SWF   ******/
-function typingActivity(uid, active) {
-	const u = $('#user' + uid + ' .typing-activity.ui-icon');
-	if (active) {
-		u.addClass("typing");
-	} else {
-		u.removeClass("typing");
-	}
-}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
index 9a8ed19..c09a68b 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/WbPanel.java
@@ -82,8 +82,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
@@ -104,7 +102,6 @@ public class WbPanel extends AbstractWbPanel {
 	private static final int DEFAULT_HEIGHT = 480;
 	private static final int UNDO_SIZE = 20;
 	public static final ResourceReference WB_JS_REFERENCE = new JavaScriptResourceReference(WbPanel.class, "wb.js");
-	private static final ResourceReference FABRIC_JS_REFERENCE = new JavaScriptResourceReference(WbPanel.class, "fabric.js");
 	private final Long roomId;
 	private long wb2save = -1;
 	private final Map<Long, Deque<UndoObject>> undoList = new HashMap<>();
@@ -156,12 +153,6 @@ public class WbPanel extends AbstractWbPanel {
 	}
 
 	@Override
-	public void renderHead(IHeaderResponse response) {
-		super.renderHead(response);
-		response.render(JavaScriptHeaderItem.forReference(FABRIC_JS_REFERENCE));
-	}
-
-	@Override
 	void internalWbLoad(StringBuilder sb) {
 		Long langId = rp.getClient().getUser().getLanguageId();
 		if (!WhiteboardCache.contains(roomId) && rp.getRoom().getFiles() != null && !rp.getRoom().getFiles().isEmpty()) {

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/ae1b51a9/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js
index 236a9ce..af55bf1 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/fabric.js
@@ -8307,7 +8307,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
       var path = [], i, width = this.width / 1000,
           p1 = new fabric.Point(points[0].x, points[0].y),
           p2 = new fabric.Point(points[1].x, points[1].y),
-          len = points.length, multSignX, multSignY, manyPoints = len > 2;
+          len = points.length, multSignX = 1, multSignY = 1, manyPoints = len > 2;
 
       if (manyPoints) {
         multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1;
@@ -14345,7 +14345,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
         prefix = this.group.transformMatrixKey(skipGroup) + sep;
       };
       return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY +
-        sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.flipX + sep + this.flipY;
+        sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.flipX + sep + this.flipY +
+        sep + this.width + sep + this.height;
     },
 
     /**
@@ -18660,12 +18661,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
     return;
   }
 
-  var stateProperties = fabric.Object.prototype.stateProperties.concat();
-  stateProperties.push(
-    'cropX',
-    'cropY'
-  );
-
   /**
    * Image class
    * @class fabric.Image
@@ -18742,7 +18737,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
      * as well as for history (undo/redo) purposes
      * @type Array
      */
-    stateProperties: stateProperties,
+    stateProperties: fabric.Object.prototype.stateProperties.concat('cropX', 'cropY'),
 
     /**
      * When `true`, object is cached on an additional canvas.
@@ -26189,7 +26184,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
         return;
       }
 
-      this.hoverCursor = this._savedProps.overCursor;
+      this.hoverCursor = this._savedProps.hoverCursor;
       this.hasControls = this._savedProps.hasControls;
       this.borderColor = this._savedProps.borderColor;
       this.lockMovementX = this._savedProps.lockMovementX;