summaryrefslogtreecommitdiffstats
path: root/modules-available
diff options
context:
space:
mode:
authorChristian Klinger2016-08-05 12:06:50 +0200
committerChristian Klinger2016-08-05 12:06:50 +0200
commit5773e599f142ea1b1106dbdbda219dfb14986878 (patch)
tree8986f3cba65b12cbd5450d5dcd34b32ffea735d1 /modules-available
parentadded jqueryui module (diff)
downloadslx-admin-5773e599f142ea1b1106dbdbda219dfb14986878.tar.gz
slx-admin-5773e599f142ea1b1106dbdbda219dfb14986878.tar.xz
slx-admin-5773e599f142ea1b1106dbdbda219dfb14986878.zip
grobe Integration vom Raumplaner.
Diffstat (limited to 'modules-available')
-rw-r--r--modules-available/roomplanner/clientscript.js125
-rw-r--r--modules-available/roomplanner/config.json4
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/copier.pngbin0 -> 35255 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/pc.pngbin0 -> 45209 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/pc_east.pngbin0 -> 29729 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/pc_north.pngbin0 -> 24902 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/pc_south.pngbin0 -> 24789 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/pc_west.pngbin0 -> 29724 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/printer.pngbin0 -> 9472 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_wIP/telephone.pngbin0 -> 31658 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_woIP/flatscreen.pngbin0 -> 23508 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_woIP/lamp.pngbin0 -> 59715 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_woIP/plasmapanel.pngbin0 -> 108588 bytes
-rw-r--r--modules-available/roomplanner/images/electricalDevices_woIP/tvcamera.pngbin0 -> 6066 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/4chairs1squaretable.pngbin0 -> 38455 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/6chairs1table.pngbin0 -> 69935 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/6chairs1table_horizontal.pngbin0 -> 68181 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/6chairs1table_vertical.pngbin0 -> 69935 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/8chairs1conferencetable.pngbin0 -> 96558 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/8chairs1conferencetable_horizontal.pngbin0 -> 96558 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/8chairs1conferencetable_vertical.pngbin0 -> 100157 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/armchair.pngbin0 -> 71397 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/armchair_east.pngbin0 -> 72212 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/armchair_north.pngbin0 -> 70843 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/armchair_south.pngbin0 -> 71397 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/armchair_west.pngbin0 -> 71509 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair.pngbin0 -> 50354 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair2.pngbin0 -> 57539 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair2_east.pngbin0 -> 60159 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair2_north.pngbin0 -> 57047 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair2_south.pngbin0 -> 57539 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair2_west.pngbin0 -> 59577 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair_east.pngbin0 -> 50780 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair_north.pngbin0 -> 50873 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair_south.pngbin0 -> 50354 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/chair_west.pngbin0 -> 51038 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdesk.pngbin0 -> 203830 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdesk_east.pngbin0 -> 195670 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdesk_north.pngbin0 -> 203830 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdesk_south.pngbin0 -> 203863 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdesk_west.pngbin0 -> 195570 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdeskchair.pngbin0 -> 104752 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdeskchair_east.pngbin0 -> 107825 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdeskchair_north.pngbin0 -> 104752 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdeskchair_south.pngbin0 -> 105023 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomdeskchair_west.pngbin0 -> 108205 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtable.pngbin0 -> 86667 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtable_east.pngbin0 -> 86667 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtable_north.pngbin0 -> 87138 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtable_south.pngbin0 -> 86876 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtable_west.pngbin0 -> 86527 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtablechair.pngbin0 -> 62367 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtablechair_east.pngbin0 -> 62418 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtablechair_north.pngbin0 -> 62367 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtablechair_south.pngbin0 -> 61541 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/classroomtablechair_west.pngbin0 -> 62454 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/coatrack.pngbin0 -> 50598 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/coatrack_east.pngbin0 -> 58243 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/coatrack_north.pngbin0 -> 50383 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/coatrack_south.pngbin0 -> 50598 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/coatrack_west.pngbin0 -> 57728 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/conferencetable.pngbin0 -> 101802 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/conferencetable_horizontal.pngbin0 -> 100512 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/conferencetable_vertical.pngbin0 -> 107335 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/couch.pngbin0 -> 75142 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/couch_east.pngbin0 -> 77496 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/couch_north.pngbin0 -> 74771 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/couch_south.pngbin0 -> 75142 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/couch_west.pngbin0 -> 77220 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/greenchair.pngbin0 -> 270980 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/greenchair_east.pngbin0 -> 281772 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/greenchair_north.pngbin0 -> 265248 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/greenchair_south.pngbin0 -> 270980 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/greenchair_west.pngbin0 -> 280625 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/lecturetheaterrow.pngbin0 -> 203617 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/lecturetheaterrowseats.pngbin0 -> 574843 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/locker.pngbin0 -> 69483 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/locker_east.pngbin0 -> 68728 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/locker_north.pngbin0 -> 69483 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/locker_south.pngbin0 -> 69369 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/locker_west.pngbin0 -> 68896 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/podium.pngbin0 -> 97614 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/podium_east.pngbin0 -> 100568 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/podium_north.pngbin0 -> 97887 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/podium_south.pngbin0 -> 97614 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/podium_west.pngbin0 -> 101167 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/roundeddesk.pngbin0 -> 6669 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/roundeddesk_east.pngbin0 -> 6669 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/roundeddesk_north.pngbin0 -> 6528 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/roundeddesk_south.pngbin0 -> 6491 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/roundeddesk_west.pngbin0 -> 6789 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/roundtable.pngbin0 -> 56701 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/semicirculartable.pngbin0 -> 55548 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/semicirculartable_east.pngbin0 -> 54251 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/semicirculartable_north.pngbin0 -> 55548 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/semicirculartable_south.pngbin0 -> 53122 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/semicirculartable_west.pngbin0 -> 54235 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/squaretable.pngbin0 -> 49063 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdesk.pngbin0 -> 112509 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdesk_east.pngbin0 -> 113232 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdesk_north.pngbin0 -> 111532 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdesk_south.pngbin0 -> 112509 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdesk_west.pngbin0 -> 112252 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdeskchair.pngbin0 -> 43647 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdeskchair_east.pngbin0 -> 47300 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdeskchair_north.pngbin0 -> 43647 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdeskchair_south.pngbin0 -> 42966 bytes
-rw-r--r--modules-available/roomplanner/images/furniture/studentdeskchair_west.pngbin0 -> 47779 bytes
-rw-r--r--modules-available/roomplanner/images/grid.pngbin0 -> 748 bytes
-rw-r--r--modules-available/roomplanner/images/grid2.pngbin0 -> 1112 bytes
-rw-r--r--modules-available/roomplanner/images/grid3.pngbin0 -> 1113 bytes
-rw-r--r--modules-available/roomplanner/images/grid_100_sep.pngbin0 -> 1211 bytes
-rw-r--r--modules-available/roomplanner/images/misc/projectionscreen.pngbin0 -> 49367 bytes
-rw-r--r--modules-available/roomplanner/images/officeSupply/papertray.pngbin0 -> 4763 bytes
-rw-r--r--modules-available/roomplanner/images/officeSupply/wastecan.pngbin0 -> 24087 bytes
-rw-r--r--modules-available/roomplanner/images/plants/plant.pngbin0 -> 107165 bytes
-rw-r--r--modules-available/roomplanner/images/plants/plant2.pngbin0 -> 95427 bytes
-rw-r--r--modules-available/roomplanner/images/plants/plant3.pngbin0 -> 82054 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-en.pngbin0 -> 6064 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-es.pngbin0 -> 6507 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-ne.pngbin0 -> 6448 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-nw.pngbin0 -> 6529 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-se.pngbin0 -> 6078 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-sw.pngbin0 -> 6558 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-wn.pngbin0 -> 6379 bytes
-rw-r--r--modules-available/roomplanner/images/wall/door-ws.pngbin0 -> 5930 bytes
-rw-r--r--modules-available/roomplanner/images/wall/wall-horizontal.gif73
-rw-r--r--modules-available/roomplanner/images/wall/wall-horizontal.pngbin0 -> 344 bytes
-rw-r--r--modules-available/roomplanner/images/wall/wall-vertical.pngbin0 -> 375 bytes
-rw-r--r--modules-available/roomplanner/js/grid.js518
-rw-r--r--modules-available/roomplanner/js/init.js163
-rw-r--r--modules-available/roomplanner/js/lib/jquery-collision.js394
-rw-r--r--modules-available/roomplanner/js/lib/jquery-ui-draggable-collision.js826
-rw-r--r--modules-available/roomplanner/page.inc.php53
-rw-r--r--modules-available/roomplanner/style.css763
-rw-r--r--modules-available/roomplanner/templates/page.html350
136 files changed, 3269 insertions, 0 deletions
diff --git a/modules-available/roomplanner/clientscript.js b/modules-available/roomplanner/clientscript.js
new file mode 100644
index 00000000..ed91c9fd
--- /dev/null
+++ b/modules-available/roomplanner/clientscript.js
@@ -0,0 +1,125 @@
+/**
+ * Pop-Up to select a machine
+ *
+ * Copyright 2016 Christian Klinger
+ * */
+
+/* uuid -> obj */
+machineCache = {};
+
+
+
+function renderMachineEntry(item, escape) {
+ machineCache[item.machineuuid] = item;
+ return '<div class="machine-entry">'
+ //+ ' <div class="machine-logo"><i class="glyphicon glyphicon-hdd"></i></div>'
+ + ' <div class="machine-body">'
+ + ' <div class="machine-entry-header"> ' + escape(item.hostname) + '</div>'
+ + ' <table class="table table-sm">'
+ + '<tr><td>UUID:</td> <td>' + escape(item.machineuuid) + '</td></tr>'
+ + '<tr><td>MAC:</td> <td>' + escape(item.macaddr) + '</td></tr>'
+ + '<tr><td>IP: </td> <td>' + escape(item.clientip) + '</td></tr>'
+ + ' </table>'
+ + ' </div>'
+ + '</div>';
+}
+
+function loadMachines(query, callback) {
+ console.log('queryMachines(' + query + ')');
+ if (query.length < 2) return callback();
+ $.ajax({
+ url: '?do=roomplanner&action=getmachines&query=' + encodeURIComponent(query),
+ type: 'GET',
+ error: function() {
+ console.log('error while doing ajax call');
+ callback();
+ },
+ success: function(res) {
+ console.log('success ajax call');
+ var json = JSON.parse(res);
+ json.machines.forEach(function (v,i,a){
+ a[i].combined = v.machineuuid + " " + v.hostname + " " + v.clientip + " " + v.macaddr;
+ });
+ return callback(json.machines);
+ }
+ });
+}
+
+
+var searchSettings = {
+ plugins : ["remove_button"],
+ valueField: 'machineuuid',
+ searchField: "combined",
+ //labelField: "combined",
+ openOnFocus: false,
+ create: false,
+ render : { option : renderMachineEntry, item: renderMachineEntry},
+ load: loadMachines,
+ maxItems: 1,
+ sortField: 'clientip',
+ sortDirection: 'asc',
+ onChange: clearSubnetBox
+
+}
+
+var subnetSettings = {
+ plugins : ["remove_button"],
+ valueField: 'machineuuid',
+ searchField: "combined",
+ //labelField: "combined",
+ openOnFocus: false,
+ create: false,
+ render : { option : renderMachineEntry, item: renderMachineEntry},
+ load: loadMachines,
+ maxItems: 1,
+ sortField: 'clientip',
+ sortDirection: 'asc',
+ onChange: clearSearchBox
+
+}
+
+function clearSearchBox() {
+ console.log("clearSearchBox()");
+ $selectizeSearch[0].selectize.clear(false);
+}
+function clearSubnetBox() {
+ console.log("clearSubnetBox()");
+ $selectizeSubnet[0].selectize.clear(false);
+}
+
+function selectMachine(usedUuids, callback) {
+ /* show a popup */
+ $modal = $('#selectMachineModal');
+ $selectizeSearch = $('#machineSearchBox').selectize(searchSettings);
+ $selectizeSubnet = $('#subnetBox').selectize(subnetSettings);
+
+ /* connect subnet tab and search tab such that on change of one the other gets emptied */
+
+
+ $modal.modal('show');
+
+ $('#selectMachineButton').on('click', function() {
+
+ /* check which one has a value */
+ var bySubnet = machineCache[$selectizeSubnet[0].selectize.getValue()];
+ var bySearch = machineCache[$selectizeSearch[0].selectize.getValue()];
+
+ var selected = bySubnet; // (bySubnet === undefined || bySubnet == "")? bySearch : bySubnet;
+
+ console.log('value is ');
+ console.log($selectizeSubnet[0].selectize.getValue());
+ console.log(machineCache);
+ console.log('selected is ');
+ console.log(selected);
+
+ var result = {muuid: selected.machineuuid, ip: selected.clientip, mac_address : selected.macaddr, hostname: selected.hostname};
+ $modal.modal('hide');
+ clearSubnetBox();
+ clearSearchBox();
+ callback(result);
+ });
+
+ var result = {muuid: "blabla", ip: "blabla", mac_address: "blub", hostname: "lalala"};
+
+ callback(result);
+}
diff --git a/modules-available/roomplanner/config.json b/modules-available/roomplanner/config.json
new file mode 100644
index 00000000..83e4ca30
--- /dev/null
+++ b/modules-available/roomplanner/config.json
@@ -0,0 +1,4 @@
+{
+ "category":"main.content",
+ "dependencies": ["js_jqueryui", "js_selectize"]
+}
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/copier.png b/modules-available/roomplanner/images/electricalDevices_wIP/copier.png
new file mode 100644
index 00000000..24cdc2ae
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/copier.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/pc.png b/modules-available/roomplanner/images/electricalDevices_wIP/pc.png
new file mode 100644
index 00000000..d1c9417d
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/pc.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/pc_east.png b/modules-available/roomplanner/images/electricalDevices_wIP/pc_east.png
new file mode 100644
index 00000000..6ac2fb0e
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/pc_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/pc_north.png b/modules-available/roomplanner/images/electricalDevices_wIP/pc_north.png
new file mode 100644
index 00000000..c564a2d3
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/pc_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/pc_south.png b/modules-available/roomplanner/images/electricalDevices_wIP/pc_south.png
new file mode 100644
index 00000000..6359234b
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/pc_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/pc_west.png b/modules-available/roomplanner/images/electricalDevices_wIP/pc_west.png
new file mode 100644
index 00000000..539a1bf1
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/pc_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/printer.png b/modules-available/roomplanner/images/electricalDevices_wIP/printer.png
new file mode 100644
index 00000000..ec851e04
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/printer.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_wIP/telephone.png b/modules-available/roomplanner/images/electricalDevices_wIP/telephone.png
new file mode 100644
index 00000000..207bfe56
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_wIP/telephone.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_woIP/flatscreen.png b/modules-available/roomplanner/images/electricalDevices_woIP/flatscreen.png
new file mode 100644
index 00000000..de05797c
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_woIP/flatscreen.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_woIP/lamp.png b/modules-available/roomplanner/images/electricalDevices_woIP/lamp.png
new file mode 100644
index 00000000..584ea1d9
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_woIP/lamp.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_woIP/plasmapanel.png b/modules-available/roomplanner/images/electricalDevices_woIP/plasmapanel.png
new file mode 100644
index 00000000..5f6bd40e
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_woIP/plasmapanel.png
Binary files differ
diff --git a/modules-available/roomplanner/images/electricalDevices_woIP/tvcamera.png b/modules-available/roomplanner/images/electricalDevices_woIP/tvcamera.png
new file mode 100644
index 00000000..c57833b2
--- /dev/null
+++ b/modules-available/roomplanner/images/electricalDevices_woIP/tvcamera.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/4chairs1squaretable.png b/modules-available/roomplanner/images/furniture/4chairs1squaretable.png
new file mode 100644
index 00000000..4e48225e
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/4chairs1squaretable.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/6chairs1table.png b/modules-available/roomplanner/images/furniture/6chairs1table.png
new file mode 100644
index 00000000..fa9cd791
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/6chairs1table.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/6chairs1table_horizontal.png b/modules-available/roomplanner/images/furniture/6chairs1table_horizontal.png
new file mode 100644
index 00000000..e6c9a7cb
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/6chairs1table_horizontal.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/6chairs1table_vertical.png b/modules-available/roomplanner/images/furniture/6chairs1table_vertical.png
new file mode 100644
index 00000000..1daaf67b
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/6chairs1table_vertical.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/8chairs1conferencetable.png b/modules-available/roomplanner/images/furniture/8chairs1conferencetable.png
new file mode 100644
index 00000000..1e9b2d84
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/8chairs1conferencetable.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/8chairs1conferencetable_horizontal.png b/modules-available/roomplanner/images/furniture/8chairs1conferencetable_horizontal.png
new file mode 100644
index 00000000..12a5a36c
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/8chairs1conferencetable_horizontal.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/8chairs1conferencetable_vertical.png b/modules-available/roomplanner/images/furniture/8chairs1conferencetable_vertical.png
new file mode 100644
index 00000000..8615777e
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/8chairs1conferencetable_vertical.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/armchair.png b/modules-available/roomplanner/images/furniture/armchair.png
new file mode 100644
index 00000000..7185ac87
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/armchair.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/armchair_east.png b/modules-available/roomplanner/images/furniture/armchair_east.png
new file mode 100644
index 00000000..aea3a7b3
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/armchair_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/armchair_north.png b/modules-available/roomplanner/images/furniture/armchair_north.png
new file mode 100644
index 00000000..cb2ba1ca
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/armchair_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/armchair_south.png b/modules-available/roomplanner/images/furniture/armchair_south.png
new file mode 100644
index 00000000..61da516a
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/armchair_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/armchair_west.png b/modules-available/roomplanner/images/furniture/armchair_west.png
new file mode 100644
index 00000000..98ef47cc
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/armchair_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair.png b/modules-available/roomplanner/images/furniture/chair.png
new file mode 100644
index 00000000..f7a023d4
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair2.png b/modules-available/roomplanner/images/furniture/chair2.png
new file mode 100644
index 00000000..b4afa66f
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair2.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair2_east.png b/modules-available/roomplanner/images/furniture/chair2_east.png
new file mode 100644
index 00000000..68ad3cfe
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair2_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair2_north.png b/modules-available/roomplanner/images/furniture/chair2_north.png
new file mode 100644
index 00000000..fc9790f4
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair2_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair2_south.png b/modules-available/roomplanner/images/furniture/chair2_south.png
new file mode 100644
index 00000000..cc8a31fe
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair2_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair2_west.png b/modules-available/roomplanner/images/furniture/chair2_west.png
new file mode 100644
index 00000000..8167372f
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair2_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair_east.png b/modules-available/roomplanner/images/furniture/chair_east.png
new file mode 100644
index 00000000..729a0d2c
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair_north.png b/modules-available/roomplanner/images/furniture/chair_north.png
new file mode 100644
index 00000000..3a1a6ea9
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair_south.png b/modules-available/roomplanner/images/furniture/chair_south.png
new file mode 100644
index 00000000..2b01a4f5
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/chair_west.png b/modules-available/roomplanner/images/furniture/chair_west.png
new file mode 100644
index 00000000..25fbbb2d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/chair_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdesk.png b/modules-available/roomplanner/images/furniture/classroomdesk.png
new file mode 100644
index 00000000..e303f00d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdesk.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdesk_east.png b/modules-available/roomplanner/images/furniture/classroomdesk_east.png
new file mode 100644
index 00000000..3fead9d7
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdesk_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdesk_north.png b/modules-available/roomplanner/images/furniture/classroomdesk_north.png
new file mode 100644
index 00000000..9e7c5d33
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdesk_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdesk_south.png b/modules-available/roomplanner/images/furniture/classroomdesk_south.png
new file mode 100644
index 00000000..43e5a80e
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdesk_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdesk_west.png b/modules-available/roomplanner/images/furniture/classroomdesk_west.png
new file mode 100644
index 00000000..b694fff6
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdesk_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdeskchair.png b/modules-available/roomplanner/images/furniture/classroomdeskchair.png
new file mode 100644
index 00000000..2f6e4c30
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdeskchair.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdeskchair_east.png b/modules-available/roomplanner/images/furniture/classroomdeskchair_east.png
new file mode 100644
index 00000000..525cce5a
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdeskchair_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdeskchair_north.png b/modules-available/roomplanner/images/furniture/classroomdeskchair_north.png
new file mode 100644
index 00000000..86587808
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdeskchair_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdeskchair_south.png b/modules-available/roomplanner/images/furniture/classroomdeskchair_south.png
new file mode 100644
index 00000000..fddb9f3b
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdeskchair_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomdeskchair_west.png b/modules-available/roomplanner/images/furniture/classroomdeskchair_west.png
new file mode 100644
index 00000000..399ff3eb
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomdeskchair_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtable.png b/modules-available/roomplanner/images/furniture/classroomtable.png
new file mode 100644
index 00000000..0e7884eb
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtable.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtable_east.png b/modules-available/roomplanner/images/furniture/classroomtable_east.png
new file mode 100644
index 00000000..2c34b321
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtable_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtable_north.png b/modules-available/roomplanner/images/furniture/classroomtable_north.png
new file mode 100644
index 00000000..f355f5f2
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtable_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtable_south.png b/modules-available/roomplanner/images/furniture/classroomtable_south.png
new file mode 100644
index 00000000..fce91e44
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtable_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtable_west.png b/modules-available/roomplanner/images/furniture/classroomtable_west.png
new file mode 100644
index 00000000..7ca2a926
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtable_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtablechair.png b/modules-available/roomplanner/images/furniture/classroomtablechair.png
new file mode 100644
index 00000000..2d5055ba
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtablechair.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtablechair_east.png b/modules-available/roomplanner/images/furniture/classroomtablechair_east.png
new file mode 100644
index 00000000..6bebcccc
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtablechair_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtablechair_north.png b/modules-available/roomplanner/images/furniture/classroomtablechair_north.png
new file mode 100644
index 00000000..5c4ab84c
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtablechair_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtablechair_south.png b/modules-available/roomplanner/images/furniture/classroomtablechair_south.png
new file mode 100644
index 00000000..374712b0
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtablechair_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/classroomtablechair_west.png b/modules-available/roomplanner/images/furniture/classroomtablechair_west.png
new file mode 100644
index 00000000..c78b646b
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/classroomtablechair_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/coatrack.png b/modules-available/roomplanner/images/furniture/coatrack.png
new file mode 100644
index 00000000..c46e83c4
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/coatrack.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/coatrack_east.png b/modules-available/roomplanner/images/furniture/coatrack_east.png
new file mode 100644
index 00000000..f20ac7e7
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/coatrack_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/coatrack_north.png b/modules-available/roomplanner/images/furniture/coatrack_north.png
new file mode 100644
index 00000000..c4171978
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/coatrack_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/coatrack_south.png b/modules-available/roomplanner/images/furniture/coatrack_south.png
new file mode 100644
index 00000000..f8eb05ec
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/coatrack_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/coatrack_west.png b/modules-available/roomplanner/images/furniture/coatrack_west.png
new file mode 100644
index 00000000..1c2ef6b6
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/coatrack_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/conferencetable.png b/modules-available/roomplanner/images/furniture/conferencetable.png
new file mode 100644
index 00000000..0a802d02
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/conferencetable.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/conferencetable_horizontal.png b/modules-available/roomplanner/images/furniture/conferencetable_horizontal.png
new file mode 100644
index 00000000..9755f281
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/conferencetable_horizontal.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/conferencetable_vertical.png b/modules-available/roomplanner/images/furniture/conferencetable_vertical.png
new file mode 100644
index 00000000..40d814f1
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/conferencetable_vertical.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/couch.png b/modules-available/roomplanner/images/furniture/couch.png
new file mode 100644
index 00000000..5722dec1
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/couch.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/couch_east.png b/modules-available/roomplanner/images/furniture/couch_east.png
new file mode 100644
index 00000000..723a3373
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/couch_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/couch_north.png b/modules-available/roomplanner/images/furniture/couch_north.png
new file mode 100644
index 00000000..87b9905a
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/couch_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/couch_south.png b/modules-available/roomplanner/images/furniture/couch_south.png
new file mode 100644
index 00000000..3c8292cb
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/couch_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/couch_west.png b/modules-available/roomplanner/images/furniture/couch_west.png
new file mode 100644
index 00000000..9e89e288
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/couch_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/greenchair.png b/modules-available/roomplanner/images/furniture/greenchair.png
new file mode 100644
index 00000000..c79db1e8
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/greenchair.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/greenchair_east.png b/modules-available/roomplanner/images/furniture/greenchair_east.png
new file mode 100644
index 00000000..71fb0335
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/greenchair_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/greenchair_north.png b/modules-available/roomplanner/images/furniture/greenchair_north.png
new file mode 100644
index 00000000..07581f8d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/greenchair_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/greenchair_south.png b/modules-available/roomplanner/images/furniture/greenchair_south.png
new file mode 100644
index 00000000..10d7452c
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/greenchair_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/greenchair_west.png b/modules-available/roomplanner/images/furniture/greenchair_west.png
new file mode 100644
index 00000000..3ebf702f
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/greenchair_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/lecturetheaterrow.png b/modules-available/roomplanner/images/furniture/lecturetheaterrow.png
new file mode 100644
index 00000000..007f4428
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/lecturetheaterrow.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/lecturetheaterrowseats.png b/modules-available/roomplanner/images/furniture/lecturetheaterrowseats.png
new file mode 100644
index 00000000..eb20f8df
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/lecturetheaterrowseats.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/locker.png b/modules-available/roomplanner/images/furniture/locker.png
new file mode 100644
index 00000000..2b958a48
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/locker.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/locker_east.png b/modules-available/roomplanner/images/furniture/locker_east.png
new file mode 100644
index 00000000..b63abd5c
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/locker_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/locker_north.png b/modules-available/roomplanner/images/furniture/locker_north.png
new file mode 100644
index 00000000..b360b47f
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/locker_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/locker_south.png b/modules-available/roomplanner/images/furniture/locker_south.png
new file mode 100644
index 00000000..e2c7ab7f
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/locker_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/locker_west.png b/modules-available/roomplanner/images/furniture/locker_west.png
new file mode 100644
index 00000000..04d69e4f
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/locker_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/podium.png b/modules-available/roomplanner/images/furniture/podium.png
new file mode 100644
index 00000000..661c7c3a
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/podium.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/podium_east.png b/modules-available/roomplanner/images/furniture/podium_east.png
new file mode 100644
index 00000000..9fddfedb
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/podium_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/podium_north.png b/modules-available/roomplanner/images/furniture/podium_north.png
new file mode 100644
index 00000000..cef475ed
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/podium_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/podium_south.png b/modules-available/roomplanner/images/furniture/podium_south.png
new file mode 100644
index 00000000..015c4c7a
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/podium_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/podium_west.png b/modules-available/roomplanner/images/furniture/podium_west.png
new file mode 100644
index 00000000..b076ad6d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/podium_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/roundeddesk.png b/modules-available/roomplanner/images/furniture/roundeddesk.png
new file mode 100644
index 00000000..c2e17884
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/roundeddesk.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/roundeddesk_east.png b/modules-available/roomplanner/images/furniture/roundeddesk_east.png
new file mode 100644
index 00000000..5c87d408
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/roundeddesk_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/roundeddesk_north.png b/modules-available/roomplanner/images/furniture/roundeddesk_north.png
new file mode 100644
index 00000000..3952d2cb
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/roundeddesk_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/roundeddesk_south.png b/modules-available/roomplanner/images/furniture/roundeddesk_south.png
new file mode 100644
index 00000000..2d608431
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/roundeddesk_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/roundeddesk_west.png b/modules-available/roomplanner/images/furniture/roundeddesk_west.png
new file mode 100644
index 00000000..78afee3d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/roundeddesk_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/roundtable.png b/modules-available/roomplanner/images/furniture/roundtable.png
new file mode 100644
index 00000000..aecebe9d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/roundtable.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/semicirculartable.png b/modules-available/roomplanner/images/furniture/semicirculartable.png
new file mode 100644
index 00000000..4c160d5a
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/semicirculartable.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/semicirculartable_east.png b/modules-available/roomplanner/images/furniture/semicirculartable_east.png
new file mode 100644
index 00000000..c286e88e
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/semicirculartable_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/semicirculartable_north.png b/modules-available/roomplanner/images/furniture/semicirculartable_north.png
new file mode 100644
index 00000000..befce8a4
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/semicirculartable_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/semicirculartable_south.png b/modules-available/roomplanner/images/furniture/semicirculartable_south.png
new file mode 100644
index 00000000..e02f0283
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/semicirculartable_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/semicirculartable_west.png b/modules-available/roomplanner/images/furniture/semicirculartable_west.png
new file mode 100644
index 00000000..9bae2915
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/semicirculartable_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/squaretable.png b/modules-available/roomplanner/images/furniture/squaretable.png
new file mode 100644
index 00000000..a71246ca
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/squaretable.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdesk.png b/modules-available/roomplanner/images/furniture/studentdesk.png
new file mode 100644
index 00000000..29e155c7
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdesk.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdesk_east.png b/modules-available/roomplanner/images/furniture/studentdesk_east.png
new file mode 100644
index 00000000..979ae7b5
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdesk_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdesk_north.png b/modules-available/roomplanner/images/furniture/studentdesk_north.png
new file mode 100644
index 00000000..998ad6ef
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdesk_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdesk_south.png b/modules-available/roomplanner/images/furniture/studentdesk_south.png
new file mode 100644
index 00000000..2c0ae3ca
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdesk_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdesk_west.png b/modules-available/roomplanner/images/furniture/studentdesk_west.png
new file mode 100644
index 00000000..e09101ce
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdesk_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdeskchair.png b/modules-available/roomplanner/images/furniture/studentdeskchair.png
new file mode 100644
index 00000000..26f6410e
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdeskchair.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdeskchair_east.png b/modules-available/roomplanner/images/furniture/studentdeskchair_east.png
new file mode 100644
index 00000000..70260dfc
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdeskchair_east.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdeskchair_north.png b/modules-available/roomplanner/images/furniture/studentdeskchair_north.png
new file mode 100644
index 00000000..26955e2d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdeskchair_north.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdeskchair_south.png b/modules-available/roomplanner/images/furniture/studentdeskchair_south.png
new file mode 100644
index 00000000..cc1c576d
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdeskchair_south.png
Binary files differ
diff --git a/modules-available/roomplanner/images/furniture/studentdeskchair_west.png b/modules-available/roomplanner/images/furniture/studentdeskchair_west.png
new file mode 100644
index 00000000..7704a5e6
--- /dev/null
+++ b/modules-available/roomplanner/images/furniture/studentdeskchair_west.png
Binary files differ
diff --git a/modules-available/roomplanner/images/grid.png b/modules-available/roomplanner/images/grid.png
new file mode 100644
index 00000000..18c3d98d
--- /dev/null
+++ b/modules-available/roomplanner/images/grid.png
Binary files differ
diff --git a/modules-available/roomplanner/images/grid2.png b/modules-available/roomplanner/images/grid2.png
new file mode 100644
index 00000000..7f2b4ce4
--- /dev/null
+++ b/modules-available/roomplanner/images/grid2.png
Binary files differ
diff --git a/modules-available/roomplanner/images/grid3.png b/modules-available/roomplanner/images/grid3.png
new file mode 100644
index 00000000..ea8dc98e
--- /dev/null
+++ b/modules-available/roomplanner/images/grid3.png
Binary files differ
diff --git a/modules-available/roomplanner/images/grid_100_sep.png b/modules-available/roomplanner/images/grid_100_sep.png
new file mode 100644
index 00000000..128d5ca6
--- /dev/null
+++ b/modules-available/roomplanner/images/grid_100_sep.png
Binary files differ
diff --git a/modules-available/roomplanner/images/misc/projectionscreen.png b/modules-available/roomplanner/images/misc/projectionscreen.png
new file mode 100644
index 00000000..4d7ba7b1
--- /dev/null
+++ b/modules-available/roomplanner/images/misc/projectionscreen.png
Binary files differ
diff --git a/modules-available/roomplanner/images/officeSupply/papertray.png b/modules-available/roomplanner/images/officeSupply/papertray.png
new file mode 100644
index 00000000..2ee473ee
--- /dev/null
+++ b/modules-available/roomplanner/images/officeSupply/papertray.png
Binary files differ
diff --git a/modules-available/roomplanner/images/officeSupply/wastecan.png b/modules-available/roomplanner/images/officeSupply/wastecan.png
new file mode 100644
index 00000000..48b7338d
--- /dev/null
+++ b/modules-available/roomplanner/images/officeSupply/wastecan.png
Binary files differ
diff --git a/modules-available/roomplanner/images/plants/plant.png b/modules-available/roomplanner/images/plants/plant.png
new file mode 100644
index 00000000..d83bcfe5
--- /dev/null
+++ b/modules-available/roomplanner/images/plants/plant.png
Binary files differ
diff --git a/modules-available/roomplanner/images/plants/plant2.png b/modules-available/roomplanner/images/plants/plant2.png
new file mode 100644
index 00000000..680b6ad8
--- /dev/null
+++ b/modules-available/roomplanner/images/plants/plant2.png
Binary files differ
diff --git a/modules-available/roomplanner/images/plants/plant3.png b/modules-available/roomplanner/images/plants/plant3.png
new file mode 100644
index 00000000..2cc5fa06
--- /dev/null
+++ b/modules-available/roomplanner/images/plants/plant3.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-en.png b/modules-available/roomplanner/images/wall/door-en.png
new file mode 100644
index 00000000..3dfcc525
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-en.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-es.png b/modules-available/roomplanner/images/wall/door-es.png
new file mode 100644
index 00000000..6d1d37a4
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-es.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-ne.png b/modules-available/roomplanner/images/wall/door-ne.png
new file mode 100644
index 00000000..1acc4083
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-ne.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-nw.png b/modules-available/roomplanner/images/wall/door-nw.png
new file mode 100644
index 00000000..de9626bc
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-nw.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-se.png b/modules-available/roomplanner/images/wall/door-se.png
new file mode 100644
index 00000000..ad27fa4f
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-se.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-sw.png b/modules-available/roomplanner/images/wall/door-sw.png
new file mode 100644
index 00000000..36d7e004
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-sw.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-wn.png b/modules-available/roomplanner/images/wall/door-wn.png
new file mode 100644
index 00000000..43e4e8fd
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-wn.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/door-ws.png b/modules-available/roomplanner/images/wall/door-ws.png
new file mode 100644
index 00000000..f6da550d
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/door-ws.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/wall-horizontal.gif b/modules-available/roomplanner/images/wall/wall-horizontal.gif
new file mode 100644
index 00000000..12b3f6b6
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/wall-horizontal.gif
@@ -0,0 +1,73 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <title>404 Not Found</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <style type="text/css">
+ body {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ background-color:#367E8E;
+ scrollbar-base-color: #005B70;
+ scrollbar-arrow-color: #F3960B;
+ scrollbar-DarkShadow-Color: #000000;
+ color: #FFFFFF;
+ margin:0;
+ }
+ a { color:#021f25; text-decoration:none}
+ h1 {
+ font-size: 18px;
+ color: #FB9802;
+ padding-bottom: 10px;
+ background-image: url(sys_cpanel/images/bottombody.jpg);
+ background-repeat: repeat-x;
+ padding:5px 0 10px 15px;
+ margin:0;
+ }
+ #body-content p {
+ padding-left: 25px;
+ padding-right: 25px;
+ line-height: 18px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ }
+ h2 {
+ font-size: 14px;
+ font-weight: bold;
+ color: #FF9900;
+ padding-left: 15px;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="body-content">
+<!-- start content-->
+
+<!--
+ instead of REQUEST_URI, we could show absolute URL via:
+ http://HTTP_HOST/REQUEST_URI
+ but what if its https:// or other protocol?
+
+ SERVER_PORT_SECURE doesn't seem to be used
+ SERVER_PORT logic would break if they use alternate ports
+-->
+
+<h1>404 Not Found</h1>
+<p>The server can not find the requested page:</p>
+ <blockquote>
+ www.stripemania.com/transparent/25-25-45-1-53AC18-1-C2C2C2-DDEE1E-DDEE1E-DDEE1E-DDEE1E-C2C2C2-78D316-78D316-78D316-78D316-yes-yes-yes-yes-yes-.gif (port 80)
+ </blockquote>
+<p>
+ Please forward this error screen to www.stripemania.com's
+ <a href="mailto:webmaster@stripemania.alpha.co.hu?subject=Error message [404] 404 Not Found for www.stripemania.com/transparent/25-25-45-1-53AC18-1-C2C2C2-DDEE1E-DDEE1E-DDEE1E-DDEE1E-C2C2C2-78D316-78D316-78D316-78D316-yes-yes-yes-yes-yes-.gif port 80 on Wednesday, 10-Feb-2016 17:57:37 CET">
+ WebMaster</a>.
+</p>
+<hr />
+
+
+<!-- end content -->
+ </div>
+ </body>
+</html>
diff --git a/modules-available/roomplanner/images/wall/wall-horizontal.png b/modules-available/roomplanner/images/wall/wall-horizontal.png
new file mode 100644
index 00000000..02d7aa91
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/wall-horizontal.png
Binary files differ
diff --git a/modules-available/roomplanner/images/wall/wall-vertical.png b/modules-available/roomplanner/images/wall/wall-vertical.png
new file mode 100644
index 00000000..ac374b3f
--- /dev/null
+++ b/modules-available/roomplanner/images/wall/wall-vertical.png
Binary files differ
diff --git a/modules-available/roomplanner/js/grid.js b/modules-available/roomplanner/js/grid.js
new file mode 100644
index 00000000..1b82f772
--- /dev/null
+++ b/modules-available/roomplanner/js/grid.js
@@ -0,0 +1,518 @@
+if (!roomplanner) var roomplanner = {
+
+ getScaleFactor: function() {
+ return this.settings.scale/100;
+ },
+ getCellPositionFromPixels: function(left,top) {
+ var n = this.settings.scale / this.settings.cellsep;
+ return [ parseInt(left) - ((parseInt(left)%n)+n)%n , parseInt(top) - ((parseInt(top)%n)+n)%n];
+ },
+ getCellPositionFromGrid: function(row,col) {
+ var n = this.settings.scale / this.settings.cellsep;
+ return [ parseInt(col*n), parseInt(row*n) ]
+ },
+ getGridFromPixels: function(left,top) {
+ var n = this.settings.scale / this.settings.cellsep;
+ return [Math.round(top/n), Math.round(left/n)];
+ },
+ settings: {
+ cellsep: 4,
+ scale: 100,
+ room: {
+ width: 1000,
+ height: 1000
+ }
+ },
+ selectFromServer: selectMachine,
+ isElementResizable: function(el) {
+ return (!$(el).attr('noresize') && $(el).attr('itemtype') != 'pc');
+ },
+ initRotation: function(el) {
+ if (!(new RegExp(".*(east|south|west|north)$").test($(el).attr('itemlook')))) {
+ return;
+ }
+
+ $(el).append('<div class="rotationHandle glyphicon glyphicon-repeat"></div>');
+ $(el).find('.rotationHandle').click(function () {
+ var str = $(el).attr('itemlook');
+ if (str.indexOf('-') > -1){
+ var values =str.split('-');
+ var name = values[0];
+ var direction = values[1];
+
+ var re = new RegExp("east|south|west|north");
+ if (re.test(direction)) {
+ var newdirection;
+ switch(direction) {
+ case "east":
+ newdirection = "south";
+ break;
+ case "south":
+ newdirection = "west";
+ break;
+ case "west":
+ newdirection = "north";
+ break;
+ case "north":
+ newdirection = "east";
+ break;
+ }
+ var result = name + "-" + newdirection;
+ $(el).attr('itemlook', result);
+ }
+ }
+ });
+ },
+ initDelete: function(el) {
+ $(el).append('<div class="deleteHandle glyphicon glyphicon-remove-sign"></div>');
+ $(el).find('.deleteHandle').click(function() {
+ if ($(this).parent().attr('itemtype') == "pc") {
+ var self = this;
+ BootstrapDialog.confirm(__('are you sure'),function(result) {
+ if (result) {
+ $(self).parent().remove();
+ }
+ });
+ } else {
+ $(this).parent().remove();
+ }
+ });
+ },
+ initTooltip: function(el) {
+ if ($(el).attr('itemtype') == 'pc') {
+ var tip = "<b>Rechnerdaten</b><br>";
+ $(roomplanner.computerAttributes).each(function(i,key){
+ tip += __(key)+": "+$(el).attr(key)+"<br>";
+ });
+
+ $(el).attr('data-togle','tooltip');
+ $(el).attr('title',tip);
+ $(el).tooltip({html: true});
+ }
+ },
+
+ initDraggable: function(el) {
+ $(el).draggable();
+ var options = {
+ "containment" : "#draw-element-area",
+ "helper" : false,
+ "grid" : [(roomplanner.settings.scale / 4), (roomplanner.settings.scale / 4)],
+ "stop": function(ev,ui) {
+ if ($(this).attr("obstacle") == "true") {
+ $(this).addClass("obstacle");
+ }
+
+ if ($(this).attr('itemtype') == "pc_drag") {
+ $(this).attr('itemtype','pc');
+ }
+
+ },
+ "preventCollision" : true,
+ "restraint": "#draw-element-area",
+ "obstacle" : ".obstacle",
+ "start": function(ev,ui) {
+ if (roomplanner.isElementResizable(this)) {
+ $(this).resizable("option","maxHeight",null);
+ $(this).resizable("option","maxWidth",null);
+ }
+
+ if ($(this).attr('itemtype') == "pc") {
+ $(this).attr('itemtype','pc_drag');
+ }
+
+ $(this).removeClass("obstacle");
+ }
+ };
+
+ // pcs can be placed everywhere
+ if ($(el).attr('itemtype') == "pc") {
+ options.obstacle = '[itemtype="pc"]';
+ }
+
+ for (var o in options) {
+ $(el).draggable("option",o,options[o]);
+ }
+ },
+ initResizable: function(el) {
+ if (!roomplanner.isElementResizable(el)) { return; }
+
+ $(el).resizable({
+ containment : "#draw-element-area",
+ obstacle: ".obstacle",
+ handles: "se",
+ autoHide: true,
+ grid: [(roomplanner.settings.scale / 4), (roomplanner.settings.scale / 4)],
+ resize: function(ev,ui) {
+ var gridSteps = $(this).resizable("option","grid");
+
+
+ var collides = $(this).collision(".obstacle");
+ var pos = $(this).offset();
+ var self = this;
+
+ var mw = $(this).resizable("option","maxWidth");
+ var mh = $(this).resizable("option","maxHeight");
+
+ var hLimit = ($(this).attr('scalable') == 'v');
+ var vLimit = ($(this).attr('scalable') == 'h');
+
+ if(collides.length) {
+ $(collides).each(function(idx,item) {
+ var itempos = $(item).offset();
+
+ if (!hLimit) {
+ if (pos.left < itempos.left && (pos.left + $(self).width()) > itempos.left) {
+ $(self).resizable("option","maxWidth",parseInt(itempos.left - pos.left));
+
+ } else {
+ $(self).resizable("option","maxWidth",null);
+ }
+ }
+
+ if (!vLimit) {
+ if (pos.top < itempos.top && pos.top + $(self).height() > itempos.top) {
+ $(self).resizable("option","maxHeight",parseInt(itempos.top - pos.top));
+ } else {
+ $(self).resizable("option","maxHeight",null);
+ }
+ }
+ });
+ } else {
+ if (!hLimit && (mw == null || mw > $(this).width())) {
+ $(this).resizable("option","maxWidth",null);
+ }
+ if (!vLimit && (mh == null || mh > $(this).height())) {
+ $(this).resizable("option","maxHeight",null);
+ }
+ }
+ },
+ start: function(ev,ui) {
+ $(this).removeClass("obstacle");
+ $(this).css('opacity',0.8);
+
+ var gridSteps = $(this).resizable("option","grid");
+
+ $(this).resizable("option",{
+ minHeight: gridSteps[1]*roomplanner.getScaleFactor(),
+ minWidth: gridSteps[0]*roomplanner.getScaleFactor()
+ });
+
+ if ($(this).attr('scalable')) {
+ switch ($(this).attr('scalable')) {
+ case 'h':
+ $(this).resizable("option",{
+ minHeight: $(this).height(),
+ maxHeight: $(this).height()
+ });
+ break;
+ case 'v':
+ $(this).resizable("option",{
+ minWidth: $(this).width(),
+ maxWidth: $(this).width()
+ });
+ break;
+ }
+ }
+
+ },
+ stop: function(ev,ui) {
+ if ($(this).attr("obstacle") == "true") {
+ $(this).addClass("obstacle");
+ }
+
+ var gridSteps = $(this).resizable("option","grid");
+ var mw = $(this).resizable("option","maxWidth");
+ if (mw) {
+ $(this).width(mw);
+ } else {
+ $(this).width($(this).outerWidth() - $(this).outerWidth()%(gridSteps[0]));
+ }
+
+ var mh = $(this).resizable("option","maxHeight");
+ if (mh) {
+ $(this).height(mh);
+ } else {
+ $(this).height($(this).outerHeight() - $(this).outerHeight()%(gridSteps[1]));
+ }
+
+
+ $(this).attr('data-width', $(this).outerWidth()/roomplanner.getScaleFactor() - (($(this).outerWidth()%gridSteps[0])/roomplanner.getScaleFactor()));
+ $(this).attr('data-height', $(this).outerHeight()/roomplanner.getScaleFactor() - (($(this).outerHeight()%gridSteps[1])/roomplanner.getScaleFactor()));
+
+
+ $(this).css('opacity',1);
+ }
+ });
+ },
+ serialize: function() {
+
+ var objects = {
+ "furniture": [],
+ "computers": []
+ };
+
+ var furniture = $('#draw-element-area div[itemtype="furniture"]');
+ furniture.each(function(idx,el) {
+ objects.furniture.push({
+ "gridRow" : $(el).attr('gridRow'),
+ "gridCol" : $(el).attr('gridCol'),
+ "data-width": $(el).attr('data-width'),
+ "data-height": $(el).attr('data-height'),
+ "itemlook": $(el).attr('itemlook'),
+ });
+ });
+
+ var computers = $('#draw-element-area div[itemtype="pc"]');
+ computers.each(function(idx,el) {
+
+ var object = {
+ "gridRow" : $(el).attr('gridRow'),
+ "gridCol" : $(el).attr('gridCol'),
+ "data-width": $(el).attr('data-width'),
+ "data-height": $(el).attr('data-height'),
+ "itemlook": $(el).attr('itemlook'),
+ "muuid": $(el).attr('muuid')
+ };
+
+ objects.computers.push(object)
+ });
+
+
+ return JSON.stringify(objects);
+ },
+ load: function(object) {
+ try {
+ var objects = JSON.parse(object);
+ } catch(e) {
+ alert('invalid JSON format');
+ return false;
+ }
+
+ $('#draw-element-area').html('');
+
+ function itemToHtml(item, itemtype, obstacle) {
+ var html = '<div itemtype="'+itemtype+'" style="position:absolute;" ';
+ for (var prop in item) {
+ if (!item.hasOwnProperty(prop)) continue;
+ html += prop+'="'+item[prop]+'" ';
+ }
+ html += 'class="draggable ui-draggable';
+
+ if (obstacle) {
+ html += " obstacle";
+ }
+
+ html+= '"></div>';
+ return html;
+ }
+
+ if (objects.furniture) {
+ var furniture = objects.furniture;
+ for (var piece in furniture) {
+ var item = itemToHtml(furniture[piece], "furniture", true);
+ $('#draw-element-area').append(item);
+
+ }
+ }
+
+
+ if (objects.computers) {
+ var computers = objects.computers;
+ for (var piece in computers) {
+ var item = itemToHtml(computers[piece], "pc", false);
+ $('#draw-element-area').append(item);
+ }
+ }
+
+ $('#draw-element-area .draggable').each(function(idx,el) {
+ roomplanner.initDraggable(el);
+ roomplanner.initResizable(el);
+ roomplanner.initTooltip(el);
+ roomplanner.initRotation(el);
+ roomplanner.initDelete(el);
+ });
+
+ roomplanner.grid.scale(roomplanner.settings.scale);
+ },
+ clear: function() {
+ $('#draw-element-area').html('');
+ }
+};
+
+roomplanner.grid = (function() {
+ var grid = {
+ resize: function() {
+ var w = Math.max($('#drawpanel .panel-body').width(),roomplanner.settings.room.width*roomplanner.settings.scale)
+ var h = Math.max($('#drawpanel .panel-body').height(),roomplanner.settings.room.height*roomplanner.settings.scale)
+ $('#drawarea').width(w);
+ $('#drawarea').height(h);
+ },
+ scale: function(num) {
+ $('#drawarea').css('background-size',num);
+ roomplanner.settings.scale = num;
+ $('#draw-element-area .ui-draggable').each(function(idx,item) {
+ var h = $(item).attr('data-height') * roomplanner.getScaleFactor();
+ var w = $(item).attr('data-width') * roomplanner.getScaleFactor();
+ //var pos = roomplanner.getCelloffset()
+
+ var l = parseInt($(item).css('left')) * roomplanner.getScaleFactor();
+ var t = parseInt($(item).css('top')) * roomplanner.getScaleFactor();
+
+ var pos = roomplanner.getCellPositionFromGrid($(item).attr('gridRow'),$(item).attr('gridCol'));
+
+ $(item).css({width: w+"px", height: h+"px", left: pos[0]+"px", top: pos[1]+"px"});
+ $(item).draggable("option","grid",[(roomplanner.settings.scale / 4), (roomplanner.settings.scale / 4)]);
+
+ if (roomplanner.isElementResizable(item)) {
+ $(item).resizable("option","grid",[(roomplanner.settings.scale / 4), (roomplanner.settings.scale / 4)]);
+ }
+ });
+ this.resize();
+ },
+ init: function() {
+ this.resize();
+ $(window).resize($.proxy(function(){
+ this.resize();
+ },this));
+ }
+ }
+
+ return grid;
+}
+)();
+
+$(document).ready(function(){
+ roomplanner.grid.init();
+
+ $('#scaleslider').slider({
+ orientation: "horizontal",
+ range: "min",
+ min: 20,
+ max: 200,
+ value: 100,
+ slide: function(event,ui) {
+ roomplanner.grid.scale(ui.value);
+ },
+ stop: function(e, ui) {
+ $('#drawarea').trigger('checkposition');
+ }
+
+ });
+
+ $('#drawarea').bind('checkposition', function() {
+ if ($(this).offset().left > 0) {
+ $(this).css('left',0);
+ }
+ if (parseInt($(this).css('top')) > 0) {
+ $(this).css('top',0);
+ }
+
+ if (($(this).width() + parseInt($(this).css('left'))) < $(this).parent().width()) {
+ $(this).css('left', ($(this).parent().width() - $(this).width()));
+ }
+
+ if (($(this).height() + parseInt($(this).css('top'))) < $(this).parent().height()) {
+ $(this).css('top', ($(this).parent().height() - $(this).height()));
+ }
+ });
+
+ $('#drawarea').draggable({
+ stop: function() {
+ $(this).trigger('checkposition');
+ }
+ });
+
+ $('#draw-element-area').droppable({
+ accept: ".draggable",
+ drop: function(event, ui) {
+
+ // the element is already in drawing area
+ var el = (ui.helper == ui.draggable) ? ui.draggable : $(ui.helper.clone());
+ var collidingSelector = ($(el).attr('itemtype') =="pc_drag") ? '[itemtype="pc"]' : '.obstacle';
+
+ if ($(el).collision(collidingSelector).length) {
+ return;
+ }
+
+ var itemtype = $(el).attr('itemtype');
+ $(el).attr('itemtype',itemtype.replace('_drag',''));
+
+ $(el).removeClass('collides');
+ $(el).css('opacity',1);
+
+ if (ui.helper != ui.draggable) {
+ var l = parseInt($(el).css('left'))-parseInt($('#drawarea').css('left'))-$('#drawpanel').offset().left;
+ var t = parseInt($(el).css('top'))-parseInt($('#drawarea').css('top'))-($('#drawpanel').offset().top + $('#drawpanel .panel-heading').height());
+ var cp = roomplanner.getCellPositionFromPixels(l,t);
+ $(el).css('left',cp[0]);
+ $(el).css('top',cp[1]);
+ }
+
+ var gridPositions = roomplanner.getGridFromPixels(parseInt($(el).css('left')),parseInt($(el).css('top')));
+ $(el).attr('gridRow',gridPositions[0]);
+ $(el).attr('gridCol',gridPositions[1]);
+
+ if ($(el).attr("obstacle") == "true") {
+ $(el).addClass("obstacle");
+ }
+
+ roomplanner.initResizable(el);
+ roomplanner.initDraggable(el);
+
+ if (ui.helper != ui.draggable) {
+ $(this).append(el);
+
+ if ($(el).attr('itemtype') == "pc") {
+
+ var uuids = [];
+ var computers = $('#draw-element-area div[itemtype="pc"]');
+ computers.each(function(idx,el) {
+ if ($(el).attr('muuid')) {
+ uuids.push($(el).attr('muuid'));
+ }
+ });
+
+ roomplanner.selectFromServer(uuids, function (result) {
+ if (!result) {
+ $(el).remove();
+ } else {
+ for (var key in result) {
+ $(el).attr(key,result[key]);
+ }
+ roomplanner.initTooltip(el);
+ }
+ });
+ }
+ roomplanner.initDelete(el);
+ roomplanner.initRotation(el);
+
+ }
+
+ }
+ });
+
+ $('.draggable').draggable({
+ helper: "clone",
+ //grid : [(roomplanner.settings.scale / 4), (roomplanner.settings.scale / 4)],
+ preventCollision: true,
+ restraint: "#draw-element-area",
+ obstacle: ".obstacle",
+ cursorAt: {left:5,top:5},
+ start: function(ev,ui) {
+ $(ui.helper).css('opacity',0.8);
+ $(ui.helper).height($(this).attr('data-height')*roomplanner.getScaleFactor());
+ $(ui.helper).width($(this).attr('data-width')*roomplanner.getScaleFactor());
+ var type = $(ui.helper).attr('itemtype');
+ $(ui.helper).attr('itemtype',type+"_drag");
+ },
+ drag: function(ev,ui) {
+ var collidingSelector = ($(ui.helper).attr('itemtype') =="pc_drag") ? '[itemtype="pc"]' : '.obstacle';
+ if ($(ui.helper).collision(collidingSelector).length) {
+ $(ui.helper).addClass('collides');
+ } else {
+ $(ui.helper).removeClass('collides');
+ }
+ }
+ })
+
+});
diff --git a/modules-available/roomplanner/js/init.js b/modules-available/roomplanner/js/init.js
new file mode 100644
index 00000000..e1a619aa
--- /dev/null
+++ b/modules-available/roomplanner/js/init.js
@@ -0,0 +1,163 @@
+/* */
+
+function initRoomplanner() {
+
+ console.log('initRoomplanner');
+ $('#drawarea').css('top',(-roomplanner.settings.scale*10)+'px');
+ $('#drawarea').css('left',(-roomplanner.settings.scale*10)+'px');
+
+ roomplanner.computerAttributes = [
+ "muuid",
+ "mac_address",
+ "ip",
+ "hostname"
+ ];
+
+ $("#loadButton").click(function() {
+ roomplanner.load($('#serializedRoom').val());
+ });
+
+ $("#serializeButton").click(function() {
+ $('#serializedRoom').val(roomplanner.serialize());
+ });
+}
+
+var translation = {
+ "muuid" : "Machine UUID",
+ "mac_address" : "MAC Adresse",
+ "ip" : "IP Adresse",
+ "hostname": "Rechnername",
+
+ "wall-horizontal" : "Wand (horizontal)",
+ "wall-vertical" : "Mauer (vertikal)",
+ "window-horizontal" : "Fenster",
+ "window-vertical" : "Fenster",
+ "door-nw" : "Tür",
+ "door-ne" : "Tür",
+ "door-sw" : "Tür",
+ "door-se" : "Tür",
+ "door-wn" : "Tür",
+ "door-ws" : "Tür",
+ "door-en" : "Tür",
+ "door-es" : "Tür",
+ //"pc" : "PC",
+ "pc-east" : "PC",
+ "pc-south" : "PC",
+ "pc-west" : "PC",
+ "pc-north" : "PC",
+ "copier" : "Kopierer",
+ "printer" : "Drucker",
+ "telephone" : "Telefon",
+ "flatscreen" : "Flatscreen",
+ "lamp" : "Schreibtischlampe",
+ "tvcamera" : "Projektor",
+ "4chairs1squaretable" : "4 Stühle und ein quadratischer Tisch",
+ //"6chairs1table" : "6 Stühle und ein Tisch",
+ "6chairs1table-horizontal" : "6 Stühle und ein Tisch",
+ "6chairs1table-vertical" : "6 Stühle und ein Tisch",
+ //"8chairs1conferencetable" : "8 Stühle und 1 Konferenztisch",
+ "8chairs1conferencetable-horizontal" : "8 Stühle und 1 Konferenztisch",
+ "8chairs1conferencetable-vertical" : "8 Stühle und 1 Konferenztisch",
+ //"armchair" : "Sessel",
+ "armchair-east" : "Sessel",
+ "armchair-south" : "Sessel",
+ "armchair-west" : "Sessel",
+ "armchair-north" : "Sessel",
+ //"chair" : "Stuhl",
+ "chair-east" : "Stuhl",
+ "chair-south" : "Stuhl",
+ "chair-west" : "Stuhl",
+ "chair-north" : "Stuhl",
+ //"chair2" : "Stuhl",
+ "chair2-east" : "Stuhl",
+ "chair2-south" : "Stuhl",
+ "chair2-west" : "Stuhl",
+ "chair2-north" : "Stuhl",
+ //"classroomdesk" : "Klassenzimmerpult",
+ "classroomdesk-east" : "Klassenzimmerpult",
+ "classroomdesk-south" : "Klassenzimmerpult",
+ "classroomdesk-west" : "Klassenzimmerpult",
+ "classroomdesk-north" : "Klassenzimmerpult",
+ //"classroomdeskchair" : "Klassenzimmerpult mit Stuhl",
+ "classroomdeskchair-east" : "Klassenzimmerpult mit Stuhl",
+ "classroomdeskchair-south" : "Klassenzimmerpult mit Stuhl",
+ "classroomdeskchair-west" : "Klassenzimmerpult mit Stuhl",
+ "classroomdeskchair-north" : "Klassenzimmerpult mit Stuhl",
+ //"classroomtable" : "Klassenzimmertisch",
+ "classroomtable-east" : "Klassenzimmertisch",
+ "classroomtable-south" : "Klassenzimmertisch",
+ "classroomtable-west" : "Klassenzimmertisch",
+ "classroomtable-north" : "Klassenzimmertisch",
+ //"classroomtablechair" : "Klassenzimmertisch mit Stuhl",
+ "classroomtablechair-east" : "Klassenzimmertisch mit Stuhl",
+ "classroomtablechair-south" : "Klassenzimmertisch mit Stuhl",
+ "classroomtablechair-west" : "Klassenzimmertisch mit Stuhl",
+ "classroomtablechair-north" : "Klassenzimmertisch mit Stuhl",
+ //"coatrack" : "Garderobe",
+ "coatrack-east" : "Garderobe",
+ "coatrack-south" : "Garderobe",
+ "coatrack-west" : "Garderobe",
+ "coatrack-north" : "Garderobe",
+ //"conferencetable" : "Konferenztisch",
+ "conferencetable-horizontal" : "Konferenztisch",
+ "conferencetable-vertical" : "Konferenztisch",
+ //"couch" : "Couch",
+ "couch-east" : "Couch",
+ "couch-south" : "Couch",
+ "couch-west" : "Couch",
+ "couch-north" : "Couch",
+ //"greenchair" : "Stuhl",
+ "greenchair-east" : "Stuhl",
+ "greenchair-south" : "Stuhl",
+ "greenchair-west" : "Stuhl",
+ "greenchair-north" : "Stuhl",
+ "lecturetheaterrow" : "Vorlesungssaalreihe mit Stühlen",
+ "lecturetheaterrowseats" : "Vorlesungssaalstuhlreihe",
+ //"locker" : "Schließfach",
+ "locker-east" : "Schließfach",
+ "locker-south" : "Schließfach",
+ "locker-west" : "Schließfach",
+ "locker-north" : "Schließfach",
+ //"podium" : "Podium",
+ "podium-east" : "Podium",
+ "podium-south" : "Podium",
+ "podium-west" : "Podium",
+ "podium-north" : "Podium",
+ //"roundeddesk" : "Eckschreibtisch",
+ "roundeddesk-east" : "Eckschreibtisch",
+ "roundeddesk-south" : "Eckschreibtisch",
+ "roundeddesk-west" : "Eckschreibtisch",
+ "roundeddesk-north" : "Eckschreibtisch",
+ "roundtable" : "Runder Tisch",
+ //"semicirculartable" : "Nierentisch",
+ "semicirculartable-east" : "Nierentisch",
+ "semicirculartable-south" : "Nierentisch",
+ "semicirculartable-west" : "Nierentisch",
+ "semicirculartable-north" : "Nierentisch",
+ "squaretable" : "Quadratischer Tisch",
+ //"studentdesk" : "Schülerpult",
+ "studentdesk-east" : "Schülerpult",
+ "studentdesk-south" : "Schülerpult",
+ "studentdesk-west" : "Schülerpult",
+ "studentdesk-north" : "Schülerpult",
+ //"studentdeskchair" : "Schülerpult mit Stuhl",
+ "studentdeskchair-east" : "Schülerpult mit Stuhl",
+ "studentdeskchair-south" : "Schülerpult mit Stuhl",
+ "studentdeskchair-west" : "Schülerpult mit Stuhl",
+ "studentdeskchair-north" : "Schülerpult mit Stuhl",
+ "papertray" : "Papierfach",
+ "wastecan" : "Papierkorb",
+ "plant" : "Pflanze",
+ "plant2" : "Pflanze",
+ "plant3" : "Pflanze",
+ "projectionscreen" : "Projektionswand",
+ "are you sure" : "Sind Sie sicher?"
+};
+
+function __(key) {
+ if (translation[key]) {
+ return translation[key];
+ }
+
+ return key;
+}
diff --git a/modules-available/roomplanner/js/lib/jquery-collision.js b/modules-available/roomplanner/js/lib/jquery-collision.js
new file mode 100644
index 00000000..98e37882
--- /dev/null
+++ b/modules-available/roomplanner/js/lib/jquery-collision.js
@@ -0,0 +1,394 @@
+/*
+Copyright (c) 2011 Sean Cusack
+
+MIT-LICENSE:
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+(function($){
+
+ //
+ // Private classes
+ //
+
+ function CollisionCoords( proto, containment )
+ {
+ if( ! proto )
+ {
+ // default if nothing else:
+ this.x1 = this.y1 = this.x2 = this.y2 = 0;
+ this.proto = null;
+ }
+ else if( "offset" in proto )
+ {
+ // used to grab stuff from a jquery object
+ // if it has collision-coordinates data, use that
+ // otherwise just pull in the offset
+
+ var d = proto.data("jquery-collision-coordinates");
+ if( d )
+ {
+ this.x1 = d.x1;
+ this.y1 = d.y1;
+ this.x2 = d.x2;
+ this.y2 = d.y2;
+ }
+ else if( containment && containment.length && containment.length >= 4 )
+ {
+ this.x1 = containment[0];
+ this.y1 = containment[1];
+ this.x2 = containment[2]+proto.outerWidth(true);
+ this.y2 = containment[3]+proto.outerHeight(true);
+ }
+ else if( proto.parent().length <= 0 )
+ {
+ this.x1 = parseInt(proto.css("left" )) || 0;
+ this.y1 = parseInt(proto.css("top" )) || 0;
+ this.x2 = parseInt(proto.css("width" )) || 0;
+ this.y2 = parseInt(proto.css("height")) || 0;
+ this.x2 += this.x1;
+ this.x2 += (parseInt(proto.css("margin-left"))||0) + (parseInt(proto.css("border-left"))||0) + (parseInt(proto.css("padding-left"))||0) +
+ (parseInt(proto.css("padding-right"))||0) + (parseInt(proto.css("border-right"))||0) + (parseInt(proto.css("margin-right"))||0);
+ this.y2 += this.y1;
+ this.y2 += (parseInt(proto.css("margin-top"))||0) + (parseInt(proto.css("border-top"))||0) + (parseInt(proto.css("padding-top"))||0) +
+ (parseInt(proto.css("padding-bottom"))||0) + (parseInt(proto.css("border-bottom"))||0) + (parseInt(proto.css("margin-bottom"))||0);
+ }
+ else
+ {
+ var o = proto.offset();
+ this.x1 = o.left - (parseInt(proto.css("margin-left"))||0); // not also border -- offset starts from inside margin but outside border
+ this.y1 = o.top - (parseInt(proto.css("margin-top" ))||0); // not also border -- offset starts from inside margin but outside border
+ this.x2 = this.x1 + proto.outerWidth(true);
+ this.y2 = this.y1 + proto.outerHeight(true);
+ }
+ this.proto = proto;
+ }
+ else if( "x1" in proto )
+ {
+ // used to effectively "clone"
+ this.x1 = proto.x1;
+ this.y1 = proto.y1;
+ this.x2 = proto.x2;
+ this.y2 = proto.y2;
+ this.proto = proto;
+ }
+
+ if( "dir" in proto )
+ {
+ this.dir = proto.dir;
+ }
+ }
+
+ CollisionCoords.prototype.innerContainer = function()
+ {
+ var clone = new CollisionCoords( this );
+ if( this.proto["css"] )
+ {
+ clone.x1 += parseInt( this.proto.css( "margin-left" ) ) || 0;
+ clone.x1 += parseInt( this.proto.css( "border-left" ) ) || 0;
+ clone.x1 += parseInt( this.proto.css("padding-left" ) ) || 0;
+ clone.x2 -= parseInt( this.proto.css("padding-right" ) ) || 0;
+ clone.x2 -= parseInt( this.proto.css( "border-right" ) ) || 0;
+ clone.x2 -= parseInt( this.proto.css( "margin-right" ) ) || 0;
+ clone.y1 += parseInt( this.proto.css( "margin-top" ) ) || 0;
+ clone.y1 += parseInt( this.proto.css( "border-top" ) ) || 0;
+ clone.y1 += parseInt( this.proto.css("padding-top" ) ) || 0;
+ clone.y2 -= parseInt( this.proto.css("padding-bottom") ) || 0;
+ clone.y2 -= parseInt( this.proto.css( "border-bottom") ) || 0;
+ clone.y2 -= parseInt( this.proto.css( "margin-bottom") ) || 0;
+ }
+ return clone;
+ }
+
+ CollisionCoords.prototype.move = function( dx, dy )
+ {
+ this.x1 += dx;
+ this.x2 += dx;
+ this.y1 += dy;
+ this.y2 += dy;
+ return this;
+ };
+
+ CollisionCoords.prototype.update = function( obj )
+ {
+ if( "x1" in obj ) this.x1 = obj["x1"];
+ if( "x2" in obj ) this.x1 = obj["x2"];
+ if( "y1" in obj ) this.x1 = obj["y1"];
+ if( "y2" in obj ) this.x1 = obj["y2"];
+ if( "left" in obj )
+ {
+ var w = this.x2-this.x1;
+ this.x1 = obj["left"];
+ this.x2 = this.x1 + w;
+ }
+ if( "top" in obj )
+ {
+ var h = this.y2-this.y1;
+ this.y1 = obj["top"];
+ this.y2 = this.y1 + h;
+ }
+ if( "offset" in obj )
+ {
+ var o = obj.offset();
+ this.update( o );
+ this.x2 = this.x1 + obj.width();
+ this.y2 = this.y1 + obj.height();
+ }
+ if( "dir" in obj ) this.x1 = obj["dir"];
+ return this;
+ };
+
+ CollisionCoords.prototype.width = function() { return ( this.x2 - this.x1 ); };
+ CollisionCoords.prototype.height = function() { return ( this.y2 - this.y1 ); };
+ CollisionCoords.prototype.centerx = function() { return ( this.x1 + this.x2 ) / 2; };
+ CollisionCoords.prototype.centery = function() { return ( this.y1 + this.y2 ) / 2; };
+
+
+ CollisionCoords.prototype.toString = function()
+ {
+ return ( this.proto["get"] ? "#"+this.proto.get(0).id : "" ) + "["+[this.x1,this.y1,this.x2,this.y2].join(",")+"]";
+ };
+
+ // the big mistake in a lot of collision-detectors,
+ // make floating-point arithmetic work for you, not against you:
+ CollisionCoords.EPSILON = 0.001;
+
+ CollisionCoords.prototype.containsPoint = function( x, y, inclusive )
+ {
+ if( ! inclusive ) inclusive = false;
+ var epsilon = ( inclusive ? -1 : +1 ) * CollisionCoords.EPSILON;
+ if( ( x > ( this.x1 + epsilon ) && x < ( this.x2 - epsilon ) ) &&
+ ( y > ( this.y1 + epsilon ) && y < ( this.y2 - epsilon ) ) )
+ return true;
+ else
+ return false;
+ };
+
+ CollisionCoords.prototype.overlaps = function( other, inclusive )
+ {
+ var hit = this._overlaps( other, inclusive );
+ if( hit.length > 0 ) return hit;
+ hit = other._overlaps( this, inclusive );
+ if( hit.length > 0 )
+ {
+ hit[0].dir = hit[0].dir == "Inside" ? "Outside" :
+ hit[0].dir == "Outside" ? "Inside" :
+ hit[0].dir == "N" ? "S" :
+ hit[0].dir == "S" ? "N" :
+ hit[0].dir == "W" ? "E" :
+ hit[0].dir == "E" ? "W" :
+ hit[0].dir == "NE" ? "SW" :
+ hit[0].dir == "SW" ? "NE" :
+ hit[0].dir == "SE" ? "NW" :
+ hit[0].dir == "NW" ? "SE" :
+ undefined;
+ }
+ return hit || [];
+ }
+
+ CollisionCoords.prototype._overlaps = function( other, inclusive )
+ {
+ var c1 = other;
+ var c2 = this;
+ if( ! inclusive ) inclusive = false;
+ var ax = c1.centerx();
+ var ay = c1.centery();
+ // nine points to check whether they're in e2: e1's four corners, e1's center-sides, and e1's center
+ // if center of e1 is within e2, there's some kind of total inclusion
+ var points = [ [c1.x1,c1.y1,"SE"], [c1.x2,c1.y1,"SW"], [c1.x2,c1.y2,"NW"], [c1.x1,c1.y2,"NE"], [ax,c1.y1,"S"], [c1.x2,ay,"W"], [ax,c1.y2,"N"], [c1.x1,ay,"E"], [ax,ay,undefined] ];
+ var hit = null;
+ var dirs = { NW:false, N:false, NE:false, E:false, SE:false, S:false, SW:false, W:false };
+ for( var i=0; i<points.length; i++ )
+ {
+ if( this.containsPoint( points[i][0], points[i][1], inclusive ) )
+ {
+ if( points[i][2] ) dirs[points[i][2]] = true;
+ if( hit ) continue; // don't need to make another one - it'll be the same anyways //
+ hit = [ new CollisionCoords( { x1: Math.max(c1.x1,c2.x1), y1: Math.max(c1.y1,c2.y1),
+ x2: Math.min(c1.x2,c2.x2), y2: Math.min(c1.y2,c2.y2), dir: points[i][2] } ) ];
+ }
+ }
+ if( hit )
+ {
+ if( dirs["NW"] && dirs["NE"] ) hit[0].dir = "N";
+ if( dirs["NE"] && dirs["SE"] ) hit[0].dir = "E";
+ if( dirs["SE"] && dirs["SW"] ) hit[0].dir = "S";
+ if( dirs["SW"] && dirs["NW"] ) hit[0].dir = "W";
+ if( dirs["NW"] && dirs["NE"] &&
+ dirs["SE"] && dirs["SW"] ) hit[0].dir = "Outside";
+ if( !dirs["NW"] && !dirs["NE"] &&
+ !dirs["SE"] && !dirs["SW"] &&
+ !dirs["N"] && !dirs["E"] &&
+ !dirs["S"] && !dirs["W"] ) hit[0].dir = "Inside";
+ }
+ return hit || [];
+ };
+
+ CollisionCoords.prototype._protrusion = function( area, dir, list )
+ {
+ var o = this.overlaps( new CollisionCoords( area ), false );
+ if( o.length <= 0 ) return list;
+ o[0].dir = dir;
+ list.push( o[0] );
+ return list;
+ };
+
+ CollisionCoords.prototype.protrusions = function( container )
+ {
+ var list = [];
+ var n = Number.NEGATIVE_INFINITY;
+ var p = Number.POSITIVE_INFINITY;
+ var l = container.x1;
+ var r = container.x2;
+ var t = container.y1;
+ var b = container.y2;
+ list = this._protrusion( { x1:l, y1:n, x2:r, y2:t }, "N" , list );
+ list = this._protrusion( { x1:r, y1:n, x2:p, y2:t }, "NE", list );
+ list = this._protrusion( { x1:r, y1:t, x2:p, y2:b }, "E" , list );
+ list = this._protrusion( { x1:r, y1:b, x2:p, y2:p }, "SE", list );
+ list = this._protrusion( { x1:l, y1:b, x2:r, y2:p }, "S" , list );
+ list = this._protrusion( { x1:n, y1:b, x2:l, y2:p }, "SW", list );
+ list = this._protrusion( { x1:n, y1:t, x2:l, y2:b }, "W" , list );
+ list = this._protrusion( { x1:n, y1:n, x2:l, y2:t }, "NW", list );
+ return list;
+ };
+
+ function Collision( targetNode, obstacleNode, overlapCoords, overlapType )
+ {
+ this.target = targetNode;
+ this.obstacle = obstacleNode;
+ this.overlap = overlapCoords;
+ this.overlapType = overlapType;
+ }
+
+ Collision.prototype.distance = function( other )
+ {
+ var tc = c.target;
+ var oc = c.overlap;
+ return Math.sqrt( (tc.centerx()-oc.centerx())*(tc.centerx()-oc.centerx()) +
+ (tc.centery()-oc.centery())*(tc.centery()-oc.centery()) );
+ }
+
+ function CollisionFactory( targets, obstacles, containment )
+ {
+ this.targets = targets;
+ this.obstacles = obstacles;
+ this.collisions = null;
+ this.cache = null;
+ if( containment ) this.containment = containment;
+ else this.containment = null;
+ }
+
+ CollisionFactory.prototype.getCollisions = function( overlapType )
+ {
+ if( this.collisions !== null ) return this.collisions;
+ this.cache = {};
+ this.collisions = [];
+ // note: doesn't do any dup-detection, so if you ask if something collides with
+ // itself, it will!
+ if( ! overlapType ) overlapType = "collision";
+ if( overlapType != "collision" && overlapType != "protrusion" ) return [];
+ var c = [];
+ var t = this.targets;
+ var o = this.obstacles;
+ for( var ti=0; ti<t.length; ti++ )
+ {
+ var tc = t[ti];
+ for( var oi=0; oi<o.length; oi++ )
+ {
+ var oc = o[oi];
+ var ol = ( (overlapType=="collision") ? tc.overlaps( oc ) : tc.protrusions( oc.innerContainer() ) );
+ for( var oli=0; oli<ol.length; oli++ )
+ {
+ c.push( new Collision( t[ti], o[oi], ol[oli], overlapType ) );
+ }
+ }
+ }
+ this.collisions = c;
+ return c;
+ };
+
+ //
+ // Setup
+ //
+
+ function makeCoordsArray( j )
+ {
+ return $(j).get().map(function(e,i,a){ return new CollisionCoords( $(e) ); });
+ }
+
+ function combineQueries( array )
+ {
+ var j = $();
+ for( var i=0; i<array.length; i++ )
+ {
+ j=j.add( array[i] );
+ }
+ return j;
+ }
+
+ $.fn.collision = function( selector, options )
+ {
+ if( ! options ) options = {};
+ var mode = "collision";
+ var as = null;
+ var cd = null;
+ var od = null;
+ var dd = null;
+ var rel = "body"; // can be "body" (default), "collider", "obstacle", or a selector
+ if( options.mode == "protrusion" ) mode = options.mode;
+ if( options.as ) as = options.as;
+ if( options.colliderData ) cd = options.colliderData;
+ if( options.obstacleData ) od = options.obstacleData;
+ if( options.directionData ) dd = options.directionData;
+ if( options.relative ) rel = options.relative;
+ var cf = new CollisionFactory( makeCoordsArray(this), makeCoordsArray(selector) );
+ var ov = cf.getCollisions( mode );
+ var array;
+ // if no "as", then just the jquery object that we collided with
+ // but if there's as="<div/>", then make div's out of the overlaps
+ if( ! as ) array = $.map( ov, function(e,i,a){ return e.obstacle.proto; } );
+ else array = $.map( ov, function(e,i,a){ var xoff = e.overlap.x1;
+ var yoff = e.overlap.y1;
+ if( rel && rel != "body" )
+ {
+ var r = rel == "collider" ? $(e.target.proto) :
+ rel == "obstacle" ? $(e.obstacle.proto) :
+ $(rel);
+ if( r.length>0 )
+ {
+ var roff = r.offset();
+ xoff -= roff.left;
+ yoff -= roff.top;
+ }
+ }
+ var c = $(as).offset( { left: xoff, top: yoff } )
+ .width( e.overlap.width() )
+ .height( e.overlap.height() );
+ if( cd ) c.data(cd, $(e.target.proto));
+ if( od ) c.data(od, $(e.obstacle.proto));
+ if( dd && e.overlap.dir ) c.data(dd, e.overlap.dir);
+ return c;
+ } );
+ return combineQueries( array );
+ };
+
+})(jQuery);
diff --git a/modules-available/roomplanner/js/lib/jquery-ui-draggable-collision.js b/modules-available/roomplanner/js/lib/jquery-ui-draggable-collision.js
new file mode 100644
index 00000000..3ef553b1
--- /dev/null
+++ b/modules-available/roomplanner/js/lib/jquery-ui-draggable-collision.js
@@ -0,0 +1,826 @@
+/*
+Copyright (c) 2014 Djuri Baars
+Copyright (c) 2011 Sean Cusack
+
+MIT-LICENSE:
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+(function($){
+ // Default settings
+ var DEBUG = false;
+ var VISUAL_DEBUG = DEBUG;
+
+ $.ui.draggable.prototype.options.obstacle = ".ui-draggable-collision-obstacle";
+ $.ui.draggable.prototype.options.restraint = ".ui-draggable-collision-restraint";
+ $.ui.draggable.prototype.options.collider = ".ui-draggable-dragging";
+ $.ui.draggable.prototype.options.colliderData = null;
+ $.ui.draggable.prototype.options.obstacleData = null;
+ $.ui.draggable.prototype.options.directionData = null;
+ $.ui.draggable.prototype.options.relative = "body";
+ $.ui.draggable.prototype.options.preventCollision = false;
+ $.ui.draggable.prototype.options.preventProtrusion = false;
+ $.ui.draggable.prototype.options.collisionVisualDebug = false;
+ $.ui.draggable.prototype.options.multipleCollisionInteractions = [];
+
+ // Plugin setup
+ $.ui.plugin.add( "draggable", "obstacle", {
+ create: function(event,ui){ handleInit .call( this, event, ui ); },
+ start: function(event,ui){ handleStart .call( this, event, ui ); } ,
+ drag: function(event,ui){ return handleCollide.call( this, event, ui ); } ,
+ stop: function(event,ui){ handleCollide.call( this, event, ui );
+ handleStop .call( this, event, ui ); }
+ });
+
+ // NOTE: the "handleCollide" function must do all collision and protrusion detection at once, in order for the
+ // simultaneous prevention cases to work properly, so basically, if you ask for both, the obstacle events
+ // will occur first (and do both), and then these will trigger, see that they have an obstacle, and not
+ // do anything a second time
+ $.ui.plugin.add( "draggable", "restraint", {
+ create: function(event,ui){ handleInit .call( this, event, ui ); },
+ start: function(event,ui){ if( ! $(this).data("ui-draggable").options.obstacle ) // if there are obstacles, we already handled both
+ {
+ handleStart .call( this, event, ui );
+ }
+ } ,
+ drag: function(event,ui){ if( ! $(this).data("ui-draggable").options.obstacle ) // if there are obstacles, we already handled both
+ {
+ return handleCollide.call( this, event, ui );
+ }
+ } ,
+ stop: function(event,ui){ if( ! $(this).data("ui-draggable").options.obstacle ) // if there are obstacles, we already handled both
+ {
+ handleCollide.call( this, event, ui );
+ handleStop .call( this, event, ui );
+ }
+ }
+ });
+
+ // Likewise, if we already have an obstacle or restraint, we've done it all, so don't repeat
+ $.ui.plugin.add( "draggable", "multipleCollisionInteractions", {
+ create: function(event,ui){ handleInit .call( this, event, ui ); },
+ start: function(event,ui){ if( ! $(this).data("ui-draggable").options.obstacle &&
+ ! $(this).data("ui-draggable").options.restraint )
+ {
+ handleStart .call( this, event, ui );
+ }
+ } ,
+ drag: function(event,ui){ if( ! $(this).data("ui-draggable").options.obstacle &&
+ ! $(this).data("ui-draggable").options.restraint )
+ {
+ return handleCollide.call( this, event, ui );
+ }
+ } ,
+ stop: function(event,ui){ if( ! $(this).data("ui-draggable").options.obstacle &&
+ ! $(this).data("ui-draggable").options.restraint )
+ {
+ handleCollide.call( this, event, ui );
+ handleStop .call( this, event, ui );
+ }
+ }
+ });
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Private Classes
+ //
+
+ ////////////
+ // EVENTS //
+ ////////////
+
+ function CollisionEvent( eventType, collider, obstacle, collisionType, collision )
+ {
+ jQuery.Event.call( this, eventType );
+ this.collider = collider;
+ this.obstacle = obstacle;
+ this.collisionType = collisionType;
+ this.collision = collision;
+ }
+
+ CollisionEvent.prototype = new $.Event( "" );
+
+ function CollisionCheckEvent( eventType, collider, obstacle, collisionType )
+ {
+ jQuery.Event.call( this, eventType );
+ this.collider = collider;
+ this.obstacle = obstacle;
+ this.collisionType = collisionType;
+ }
+
+ CollisionCheckEvent.prototype = new $.Event( "" );
+
+ //////////////////////
+ // COORDINATE CLASS //
+ //////////////////////
+
+ function Coords( x1, y1, x2, y2 )
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ Coords.prototype.width = function() { return (this.x2-this.x1); };
+ Coords.prototype.height = function() { return (this.y2+this.y1); };
+ Coords.prototype.centerx = function() { return (this.x1+this.x2)/2; };
+ Coords.prototype.centery = function() { return (this.y1+this.y2)/2; };
+ Coords.prototype.area = function() { return this.width()*this.height(); };
+ Coords.prototype.hash = function() { return "["+[this.x1,this.y1,this.x2,this.y2].join(",")+"]"; };
+ Coords.prototype.distance = function(c)
+ {
+ return this.distanceTo( c.centerx(), c.centery() );
+ };
+
+ Coords.prototype.distanceTo = function(x,y)
+ {
+ var dx = this.centerx()-x;
+ var dy = this.centerx()-y;
+ return Math.sqrt( dx*dx + dy*dy );
+ };
+
+ /////////////////////////////////
+ // COORDINATE HELPER FUNCTIONS //
+ /////////////////////////////////
+
+ // create a box with the same total area, centered at center of gravity
+ function centerGravity( coordsList )
+ {
+ if( coordsList.length <= 0 ) return null;
+ var wsumx = 0;
+ var wsumy = 0;
+ var suma = 0;
+ for( var i = 0; i < coordsList.length; i++ )
+ {
+ suma += coordsList[i].area();
+ wsumx += coordsList[i].centerx() * coordsList[i].area();
+ wsumy += coordsList[i].centery() * coordsList[i].area();
+ }
+ var d = Math.sqrt( suma ); // dimension of square (both w and h)
+ return new Coords( (wsumx/suma) - d/2, (wsumy/suma) - d/2, (wsumx/suma) + d/2, (wsumy/suma) + d/2 );
+ }
+
+ // convert a jq object into a Coords object, handling all the nice-n-messy offsets and margins and crud
+ function jq2Coords( jq, dx, dy )
+ {
+ var x1,y1, x2, y2;
+
+ if( !dx ) dx=0;
+ if( !dy ) dy=0;
+ if( jq.parent().length > 0 )
+ {
+ x1 = dx + jq.offset().left - (parseInt(jq.css("margin-left"))||0);
+ y1 = dy + jq.offset().top - (parseInt(jq.css("margin-top" ))||0);
+ x2 = x1 + jq.outerWidth( true);
+ y2 = y1 + jq.outerHeight(true);
+ } else {
+ x1 = dx + parseInt(jq.css("left" )) || 0;
+ y1 = dy + parseInt(jq.css("top" )) || 0;
+ x2 = x1 + parseInt(jq.css("width" )) || 0;
+ y2 = y1 + parseInt(jq.css("height")) || 0;
+ x2 += (parseInt(jq.css("margin-left"))||0) + (parseInt(jq.css("border-left"))||0) + (parseInt(jq.css("padding-left"))||0) +
+ (parseInt(jq.css("padding-right"))||0) + (parseInt(jq.css("border-right"))||0) + (parseInt(jq.css("margin-right"))||0);
+ y2 += (parseInt(jq.css("margin-top"))||0) + (parseInt(jq.css("border-top"))||0) + (parseInt(jq.css("padding-top"))||0) +
+ (parseInt(jq.css("padding-bottom"))||0) + (parseInt(jq.css("border-bottom"))||0) + (parseInt(jq.css("margin-bottom"))||0);
+
+ }
+ return new Coords( x1, y1, x2, y2 );
+ }
+
+ function jqList2CenterGravity( jqList, dx, dy )
+ {
+ return centerGravity( jqList.toArray().map( function(e,i,a){ return jq2Coords($(e),dx,dy); } ) );
+ }
+
+ /////////////////////
+ // COLLISION CLASS //
+ /////////////////////
+
+ function Collision( jq, cdata, odata, type, dx, dy, ddata, recentCenterOfGravity, mousex, mousey )
+ {
+ if(!recentCenterOfGravity) recentCenterOfGravity=jqList2CenterGravity($(this.collider), dx, dy);
+ if(!dx) dx = 0;
+ if(!dy) dy = 0;
+ this.collision = $(jq );
+ this.collider = $(jq.data(cdata));
+ this.obstacle = $(jq.data(odata));
+ this.direction = jq.data(ddata);
+ this.type = type;
+ this.dx = dx;
+ this.dy = dy;
+ this.centerOfMass = recentCenterOfGravity;
+ this.collisionCoords = jq2Coords( this.collision );
+ this.colliderCoords = jq2Coords( this.collider, dx, dy );
+ this.obstacleCoords = jq2Coords( this.obstacle );
+ if(!mousex) mousex = this.colliderCoords.centerx();
+ if(!mousey) mousex = this.colliderCoords.centery();
+ this.mousex = mousex;
+ this.mousey = mousey;
+ }
+
+ // amount "embedded" into obstacle in x-direction
+ // might be negative or zero if it doesn't make sense
+ // this is used with the delta calculation - if its <= 0, it'll get skipped
+ // dirx is -1 or +1, depending on which way we are orienting things (which way we want to move it)
+ // NOTE: originally, we were taking the collision area into account, but it's easier to recalc embed value
+ Collision.prototype.embedx = function( dirx )
+ {
+ if( this.type == "collision" )
+ {
+ if( dirx < 0 ) /* want to move left */ return this.colliderCoords.x2 - this.obstacleCoords.x1;
+ if( dirx > 0 ) /* want to move right */ return this.obstacleCoords.x2 - this.colliderCoords.x1;
+ }
+ else if( this.type == "protrusion" )
+ {
+ // if we're embedded in a top/bottom edge, don't move left or right, silly:
+ if( ( this.direction == "N" ) || ( this.direction == "S" ) ) return 0;
+
+ if( dirx < 0 ) /* want to move left */ return this.colliderCoords.x2 - this.obstacleCoords.x2;
+ if( dirx > 0 ) /* want to move right */ return this.obstacleCoords.x1 - this.colliderCoords.x1;
+ }
+ return 0;
+ };
+
+ // and ditto for y-direction
+ Collision.prototype.embedy = function( diry )
+ {
+ if( this.type == "collision" )
+ {
+ if( diry < 0 ) /* want to move up */ return this.colliderCoords.y2 - this.obstacleCoords.y1;
+ if( diry > 0 ) /* want to move down */ return this.obstacleCoords.y2 - this.colliderCoords.y1;
+ }
+ else if( this.type == "protrusion" )
+ {
+ // if we're embedded in a left/right edge, don't move up or down, silly:
+ if( ( this.direction == "E" ) || ( this.direction == "W" ) ) return 0;
+
+ if( diry < 0 ) /* want to move up */ return this.colliderCoords.y2 - this.obstacleCoords.y2;
+ if( diry > 0 ) /* want to move down */ return this.obstacleCoords.y1 - this.colliderCoords.y1;
+ }
+ return 0;
+ };
+
+ // distance from collision to recent center of mass, i.e. it used to be in one place, and we're dragging it
+ // to another, so the "overlap" of some collider happens a certain "distance" from the center of where stuff
+ // used to be...
+ Collision.prototype.distance = function()
+ {
+ var cx1 = this.centerOfMass.centerx();
+ var cy1 = this.centerOfMass.centery();
+ var cx2 = this.collisionCoords.centerx();
+ var cy2 = this.collisionCoords.centery();
+ return Math.sqrt( (cx2-cx1)*(cx2-cx1) + (cy2-cy1)*(cy2-cy1) );
+ };
+
+ Collision.prototype.hash = function(){ return this.type+"["+this.colliderCoords.hash()+","+this.obstacleCoords.hash()+"]"; };
+
+ ////////////////////////////////
+ // COLLISION HELPER FUNCTIONS //
+ ////////////////////////////////
+
+ // sort so that collisions closest to recent center of mass come first -- we need to resolve them in order
+ function collisionComparison(c1,c2)
+ {
+ var cd1 = c1.distance();
+ var cd2 = c2.distance();
+ return ( ( cd1 < cd2 ) ? -1 : ( cd1 > cd2 ) ? +1 : 0 );
+ }
+
+ ///////////////////////
+ // INTERACTION CLASS //
+ ///////////////////////
+
+ function Interaction( draggable, options )
+ {
+ this.draggable = $(draggable);
+ this.obstacleSelector = options.obstacle || ".ui-draggable-collision-obstacle" ;
+ this.restraintSelector = options.restraint || ".ui-draggable-collision-restraint" ;
+ this.obstacle = $(options.obstacle || ".ui-draggable-collision-obstacle" );
+ this.restraint = $(options.restraint || ".ui-draggable-collision-restraint" );
+ var collider = options.collider || ".ui-draggable-dragging" ;
+ this.collider = draggable.find( collider ).andSelf().filter( collider );
+ this.colliderData = options.colliderData || null;
+ this.obstacleData = options.obstacleData || null;
+ this.directionData = options.directionData || null;
+ this.relative = options.relative || "body";
+ this.preventCollision = options.preventCollision || false;
+ this.preventProtrusion = options.preventProtrusion || false;
+ this.collisions = $();
+ this.protrusions = $();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Main handler functions
+ //
+
+ function uiTrigger( _this, widget, eventName, event, ui )
+ {
+ $.ui.plugin.call( widget, eventName, event, ui );
+ _this.trigger( event, ui );
+ }
+
+ function handleInit( event, ui, type )
+ {
+ var w = $(this).data("ui-draggable");
+ var o = w.options;
+ }
+
+ function handleStart(event,ui)
+ {
+ VISUAL_DEBUG = $(this).data("ui-draggable").options.collisionVisualDebug;
+ $(this).data( "jquery-ui-draggable-collision-recent-position", ui.originalPosition );
+ }
+
+ function handleStop (event,ui)
+ {
+ $(this).removeData("jquery-ui-draggable-collision-recent-position");
+ if( VISUAL_DEBUG ) $(".testdebug").remove();
+ VISUAL_DEBUG = DEBUG;
+ }
+
+ // This is the monolithic workhorse of the plugin:
+ // * At the beginning and end, it sends out all the pre/post-collision/protrusion events
+ // * In the middle, it both calculates collisions, and prevents them if requested
+ // * When it's either tried its best, or found a fit, or wasn't required to avoid obstacles, it sends out actual collision events
+ //
+ // Inside the first big loop is the actual "prevention" logic
+ // * It calculates the "intended position" of everything, checks all the collision logic, and if it needs to,
+ // then calculates a delta movement to see if that fits, and the loop continues until it either works,
+ // or an arbitrary iteration limit is reached, just in case it gets in a loop
+ // * The delta function is described in more detail below
+ //
+ // During all the "trying a new position" and "determining collisions" calculations, it's not using purely the
+ // current position of the colliders -- it can't because the draggable is now in a new "intended position",
+ // and with it, all its children, including any collider children
+ // * So, it keeps track of a dx and dy from known position, and populates a "jquery-collision-coordinates" data value
+ // that the jquery-collision plugin takes into account during the calculations
+ // * Also, the Coords() values get populated with these offsets at various times, so that they reflect "intended position"
+ //
+ // Note also that the collider, obstacle, and direction data fields are temporarily overriden (because we need them here,
+ // and the user may not have asked for them), and then erased and placed where the user wants them, right before
+ // sending out the collision events
+ //
+ // Note also that the collisions and protrusions requested are "relative" to "body". If the use asked for
+ // something relative, it has to get translated right before sending out the events...
+ function handleCollide( event, ui )
+ {
+ // Note that $(this) is the draggable that's moving - it has a ui.position that moves acording to where
+ // the draggable is "about to move". However, our "collidable" objects might not be the same as $(this) -
+ // they might be child elements. So we need to keep track of recent and present position so we can apply the
+ // "intended" dx and dy to all the moving elements:
+ var rp = $(this).data("jquery-ui-draggable-collision-recent-position");
+
+ if( DEBUG ) { console.log( "handleCollision ******************************************************************" ); }
+
+ if( VISUAL_DEBUG ) $(".testdebug").remove();
+
+ var ctyp = "collision";
+ var prec = "precollision";
+ var postc = "postcollision";
+ var ptyp = "protrusion";
+ var prep = "preprotrusion";
+ var postp = "postprotrusion";
+
+ // NOTE: widget is used for uiTrigger, otherwise event-binders don't get a "ui" variable
+ var widget = $(this).data("ui-draggable");
+ var o = widget.options;
+
+ // List of Interactions -- first one is the main set of args from the .draggable() setup call, rest are multipleCollisionInteractions:[...]
+ var ilist = [];
+
+ if( o.obstacle || o.restraint ) ilist.push( new Interaction( $(this), o ) );
+ if( o.multipleCollisionInteractions && o.multipleCollisionInteractions['length'] )
+ {
+ var mci = o.multipleCollisionInteractions;
+ for( var i=0; i<mci.length; i++ )
+ ilist.push( new Interaction( $(this), mci[i] ) );
+ }
+
+ if( ilist.length <= 0 )
+ {
+ // Just forget the whole stpuid business - why are we in here, anyways - no interactions to check
+ // Cache the current position anyways, and jump out:
+ $(this).data( "jquery-ui-draggable-collision-recent-position", ui.position );
+ return;
+ }
+
+ var d1 = "ui-draggable-collision-collider-temp";
+ var d2 = "ui-draggable-collision-obstacle-temp";
+ var d3 = "ui-draggable-collision-direction-temp";
+ var di = "ui-draggable-collision-interaction-temp";
+ var d = event.data;
+ var as = "<div />";
+ if( d && d.as ) as = d.as;
+
+ var e;
+
+ // Try moving things twice the number of colliders times obstacles+restraints, plus 1 original attempt
+ // We need to calculate maxiter here because there may be several levels of interactions
+ // (Honestly, anything will do, just need a reasonable cutoff)
+ var maxiter = 1;
+
+ // Global just-about-to-check-collisions event:
+ for( var i=0; i<ilist.length; i++ )
+ {
+ maxiter += 2 * ilist[i].collider.length * ( ilist[i].obstacle.length + ilist[i].restraint.length );
+
+ if( VISUAL_DEBUG )
+ {
+ ilist[i].obstacle .each(function(){$(this).clone().removeClass().empty().addClass("testdebug").css("pointer-events","none")
+ .css("background","transparent").css("padding","0px")
+ .css("border","1px solid black" ).css("margin","-1px")
+ .appendTo($(this).parent());});
+ ilist[i].restraint.each(function(){$(this).clone().removeClass().empty().addClass("testdebug").css("pointer-events","none")
+ .css("background","transparent").css("padding","0px")
+ .css("border","1px solid magenta").css("margin","-1px")
+ .appendTo($(this).parent());});
+ }
+
+ if( ilist[i].obstacleSelector )
+ {
+ e = new CollisionCheckEvent( prec, $(this), ilist[i].obstacle, ctyp )
+ uiTrigger( ilist[i].collider, widget, prec, e, ui );
+ }
+
+ if( ilist[i].restraintSelector )
+ {
+ e = new CollisionCheckEvent( prep, $(this), ilist[i].restraint, ptyp )
+ uiTrigger( ilist[i].collider, widget, prep, e, ui );
+ }
+ }
+
+ var origleft = rp.left;
+ var origtop = rp.top;
+ var origdx = ui.position.left - rp.left;
+ var origdy = ui.position.top - rp.top;
+ var dx;
+ var dy;
+ var ocl = []; // list of Collision()'s total
+ var cocl = []; // list of Collision()'s just from collisions
+ var pocl = []; // list of Collision()'s just from protrusions
+ var ccl = []; // list of Collision()'s just from containment (also a protrusion)
+
+ // Check if there's containment for the draggable:
+ var $cont = $();
+ if( widget.containment )
+ {
+ maxiter += 2; // the main draggable container times twice the number of containers (1)
+
+ var cn = widget.containment;
+ $cont = $("<div />").offset( { left: cn[0], top: cn[1] } )
+ .width( cn[2]-cn[0]+$(this).width( ) ) // because it had the draggable's size chopped out :-P
+ .height( cn[3]-cn[1]+$(this).height() ); // because it had the draggable's size chopped out :-P
+
+ if( VISUAL_DEBUG )
+ $cont.clone()
+ .css("background","transparent")
+ .css("border","1px solid blue")
+ .css("margin","-1px").css("padding","0px")
+ .addClass("testdebug")
+ .appendTo();
+ }
+
+ var deltaCache = {};
+ var iter = 0;
+ while( iter < maxiter )
+ {
+ iter++;
+
+ // Calc offset from recent move, so we can move the objects that are "coming along for the ride" before calculating their
+ // collisions. Otherwise the ui variable only keeps track of the main draggable, not its contents, which may contain
+ // the actual things that collide
+ dx = ui.position.left - rp.left;
+ dy = ui.position.top - rp.top;
+
+ // Empty the collision containers outside the interaction loop:
+ ocl = [];
+ cocl = [];
+ pocl = [];
+
+ for( var i=0; i<ilist.length; i++ )
+ {
+ ilist[i].collisions = $();
+ ilist[i].protrusions = $();
+
+ var $c = ilist[i].collider;
+ var $o = ilist[i].obstacle;
+ var $r = ilist[i].restraint;
+ if( DEBUG ) console.log( "trying inter,c,o,r=",ilist[i],$c,$o,$r)
+
+ // Add offset to coordinates before figuring out collisions, because we're basing it on "where its about to go", not "where it is":
+ // (Don't do this for anything but colliders! Applying to obstacles or restrictions or containment screws things up!!)
+ $c.each( function(){ $(this).data( "jquery-collision-coordinates", jq2Coords($(this),dx,dy) ); } );
+
+ var cog = jqList2CenterGravity($c);
+ for( var ci=0; ci<$c.length; ci++ )
+ {
+ // Calculate collisions separately from protrusions, as we might only prevent one or the other:
+ var oc = $($c[ci]).collision( $o, { mode: "collision", as: "<div />", colliderData: d1, obstacleData: d2, directionData: d3, relative: "body" } );
+ if( DEBUG ) { console.log( "collisions", oc ); }
+
+ // Add the interaction settings to their data, so we can pick it apart later:
+ oc.data( di, ilist[i] );
+
+ // And add the collisions to the interaction:
+ ilist[i].collisions = ilist[i].collisions.add(oc);
+
+ // And if there are any, make the appropriate Collision() objects and add them to the list
+ if( oc.length > 0 )
+ {
+ cocl = oc.toArray().map( function(e,i,a){ return new Collision($(e), d1, d2, "collision" , dx, dy, d3, cog, event.pageX, event.pageY ); } );
+ ocl = ocl.concat( cocl );
+ if(VISUAL_DEBUG) $("<span>c"+iter+"</span>").appendTo(oc.addClass("testdebug").css("position","absolute").css("padding","0px")
+ .css("border","1px solid black").css("margin","-1").appendTo("body"));
+ }
+
+ // Calculate protrusions likewise:
+ oc = $($c[ci]).collision( $r, { mode: "protrusion", as: "<div />", colliderData: d1, obstacleData: d2, directionData: d3, relative: "body" } );
+ if( DEBUG ) { console.log( "protrusions", oc ); }
+
+ // Add the interaction settings to their data, so we can pick it apart later:
+ oc.data( di, ilist[i] );
+
+ // And add the protrusions to the interaction:
+ ilist[i].protrusions = ilist[i].protrusions.add( oc );
+
+ // And if there are any, make the appropriate Collision() objects and add them to the list
+ if( oc.length > 0 )
+ {
+ pocl = oc.toArray().map( function(e,i,a){ return new Collision($(e), d1, d2, "protrusion", dx, dy, d3, cog, event.pageX, event.pageY ); } );
+ ocl = ocl.concat( pocl );
+ if(VISUAL_DEBUG) $("<span>p"+iter+"</span>").appendTo(oc.addClass("testdebug").css("position","absolute").css("padding","0px")
+ .css("border","1px solid magenta").css("margin","-1").appendTo("body"));
+ }
+ }
+
+ // Now remove coordinate offsets before sending events, otherwise event results might futz with em:
+ $c.each( function(){ $(this).removeData( "jquery-collision-coordinates" ); } );
+ }
+
+ if( widget.containment )
+ {
+ // Add offset to coordinates before figuring out collisions, because we're basing it on "where its about to go", not "where it is":
+ // (Don't do this for anything but colliders! Applying to obstacles or restrictions or containment screws things up!!)
+ $(this).each( function(){ $(this).data( "jquery-collision-coordinates", jq2Coords($(this),dx,dy) ); } );
+
+ // Check protrusion from container as well
+ // NOTE: since draggable plugin has already applied containment, if we accidentally move it outside, it won't fix it for us
+ var $cc = $(this).collision( $cont, { mode: "protrusion", as: "<div />", colliderData: d1, obstacleData: d2, directionData: d3, relative: "body" } );
+ ccl = $cc.toArray().map( function(e,i,a){ return new Collision($(e), d1, d2, "protrusion", dx, dy, d3, jqList2CenterGravity($c), event.pageX, event.pageY ); } );
+ if(VISUAL_DEBUG) $("<span>x"+iter+"</span>").appendTo($cc.addClass("testdebug").css("position","absolute")
+ .css("padding","0px").css("border","1px solid blue").css("margin","-1").appendTo("body"));
+
+ // Now remove coordinate offsets before sending events, otherwise event results might futz with em:
+ $(this).each( function(){ $(this).removeData( "jquery-collision-coordinates" ); } );
+ }
+
+ if( DEBUG ) console.log("checking if we have any collisions at all...");
+ // If there's no collisions, INCLUDING the container, stop now, don't keep doing stuff
+ if( ( cocl.length <= 0 ) && ( pocl.length <= 0 ) && ( ccl.length <= 0 ) ) break;
+
+ var doneAdjusting = true;
+
+ // Go through each interaction -- if any of them break the prevention rule, we aren't done adjusting yet
+ for( var i=0; i<ilist.length; i++ )
+ {
+ if( DEBUG ) console.log("checking adjustments for",ilist[i],"ccl=",ccl,
+ "pc,cl,pp,pl=",ilist[i].preventCollision, ilist[i].collisions.length, ilist[i].preventProtrusion, ilist[i].protrusions.length);
+
+ if( DEBUG ) console.log("checking if we overstepped our containment...");
+ // If we aren't trying to prevent anything yet we SOMEHOW jumped our containment, stop - this shouldn't ever happen, DANGER, WILL ROBINSON!
+ if( ( ! ilist[i].preventCollision ) && ( ! ilist[i].preventProtrusion ) && ( ccl.length > 0 ) )
+ {
+ if( DEBUG ) { console.log( "not trying to prevent anything, but jumped our containment", ilist[i] ); }
+ doneAdjusting = false;
+ }
+
+ if( DEBUG ) console.log("checking if we want to block something we have collided with...");
+ // More specifically, if aren't any collisions that we actually want to prevent, stop -- though we have to think of this in the opposite sense:
+ // if we DO either
+ // want to prevent collisions yet have a collision or containment failure, OR
+ // want to prevent protrusions yet have a protrusion or a containment failure,
+ // then DON'T STOP
+ if( ( ilist[i].preventCollision && ( ( ilist[i].collisions .length > 0 ) || ( ccl.length > 0 ) ) ) ||
+ ( ilist[i].preventProtrusion && ( ( ilist[i].protrusions.length > 0 ) || ( ccl.length > 0 ) ) ) )
+ {
+ if( DEBUG ) { console.log( "trying to prevent something that we're still hitting", ilist[i] ); }
+ doneAdjusting = false;
+ }
+ }
+
+ if( doneAdjusting )
+ {
+ if( DEBUG ) { console.log( "done adjusting" ); }
+ break;
+ }
+
+ if( DEBUG ) console.log("calculating delta with ocl,ccl=",ocl,ccl);
+ // Calculate a delta to move, based on collisions+protrusions and containment
+ var d = delta( ocl.concat(), ccl, deltaCache );
+
+ if( DEBUG ) console.log("dx=",d.dx,"dy=",d.dy);
+ // If there's nothing to do, stop -- it shouldn't happen if we had collisions, but...
+ if( d.dx == 0 && d.dy == 0 ) break;
+
+ // Apply the movement, and let the loop run again, to see if our proposed delta movement was any good
+ ui.position.left += d.dx;
+ ui.position.top += d.dy;
+ }
+
+ dx = ui.position.left - rp.left;
+ dy = ui.position.top - rp.top;
+ /* deactivated for now - doesn't seem to be needed - may revisit later:
+ // if our new center of gravity is further from the mouse position than the last one, revert
+ var origd = jqList2CenterGravity($c,origdx,origdy).distanceTo( event.pageX, event.pageY );
+ var newd = jqList2CenterGravity($c, dx, dy).distanceTo( event.pageX, event.pageY );
+ if( newd > origd ) { console.log("center of gravity issue: ",origd,newd); } // add this to revert
+ */
+
+ // If we failed to find a fit, revert to the previous position
+ if( ( iter > maxiter ) || // if we ran out of iterations, tough, revert
+ ( ccl.length > 0 ) || // if we ran outside out containment, also revert
+ ( o.preventProtrusion && ( pocl.length > 0 ) ) || // if we have a protrusion and are trying to prevent protrusions, revert
+ ( o.preventCollision && ( cocl.length > 0 ) ) ) // if we have a collision and are trying to prevent collisions, revert
+ {
+ if( DEBUG ) console.log("reverting, i=",iter,"maxiter=",maxiter,"cocl=",cocl,"cocl.len=",cocl.length,"pocl=",
+ pocl,"pocl.len=",pocl.length,"ccl=",ccl,"ccl.len=",ccl.length,
+ //"newd=",newd,"origd=",origd,
+ "origdx=",origdx,"origdy=",origdy,"dx=",dx,"dy=",dy);
+ ui.position.left = origleft;
+ ui.position.top = origtop;
+ }
+
+ // NOW we can go through and actually send out the events -- we couldn't before, because we might have hit
+ // collisions multiple times during the course of trying to prevent them
+ for( var ci=0; ci<ocl.length; ci++ )
+ {
+ var oc = ocl[ci]; // each ocl[n] is a Collision()
+ for( var oci=0; oci<oc.collision.length; oci++ )
+ {
+ var $occ = $( oc.collision[oci] );
+
+ // Remove our custom data elements that guaranteed us getting the data we needed
+ var $coll = $( $occ.data(d1) );
+ var $obs = $( $occ.data(d2) );
+ var dir = $occ.data(d3);
+ var inter = $occ.data(di);
+ $occ.removeData(d1).removeData(d2).removeData(d3).removeData(di);
+
+ // And add them back in if the user really wanted them after all
+ if( inter.colliderData ) $occ.data( inter.colliderData, $coll ); // not that useful, since event gets it, but meh
+ if( inter.obstacleData ) $occ.data( inter.obstacleData, $obs ); // not that useful, since event gets it, but meh
+ if( dir && inter.directionData ) $occ.data( inter.directionData, dir );
+
+ if( inter.relative && inter.relative != "body" )
+ {
+ var off = $occ.offset();
+ var rel = inter.relative == "collider" ? $coll :
+ inter.relative == "obstacle" ? $obs :
+ $(inter.relative);
+ var ro = rel.offset();
+ $occ.offset( { left: off.left-ro.left, top: off.top-ro.top } );
+ }
+
+ // Send actual collision event - one per collision, i.e. per collider per collided:
+ if( inter.obstacleSelector && ( oc.type == "collision" ) )
+ {
+ e = new CollisionEvent( ctyp, $coll, $obs, ctyp, $occ );
+ uiTrigger( $coll, widget, ctyp, e, ui );
+ }
+ if( inter.restraintSelector && ( oc.type == "protrusion" ) )
+ {
+ e = new CollisionEvent( ptyp, $coll, $obs, ptyp, $occ );
+ uiTrigger( $coll, widget, ptyp, e, ui );
+ }
+ }
+ }
+
+ // Global just-checked-collisions event:
+ for( var i=0; i<ilist.length; i++ )
+ {
+ if( ilist[i].obstacleSelector )
+ {
+ e = new CollisionCheckEvent( postc, $(this), ilist[i].obstacle, ctyp )
+ uiTrigger( ilist[i].collider, widget, postc, e, ui );
+ }
+ if( ilist[i].restraintSelector )
+ {
+ e = new CollisionCheckEvent( postp, $(this), ilist[i].restraint, ptyp )
+ uiTrigger( ilist[i].collider, widget, postp, e, ui );
+ }
+ }
+
+ // And put the resulting ui position in our cache, so that if we keep dragging, we'll know how far stuff moved since this time
+ $(this).data( "jquery-ui-draggable-collision-recent-position", ui.position );
+ }
+
+ // This is the inner-loop collision-prevention function, called maxiter times inside handleCollide()
+ // Its purpose is to determine a single [dx,dy] to move the whole list of colliders and draggable,
+ // in an attempt to fit them properly. Only one of dx or dy will be non-zero at a time.
+ // The cache argument is a simple object passed in from handleCollide, and is used to store previously-
+ // -tried movements, so that it doesn't repeat itself.
+ // * The most common repeat case is if a collider is stuck inbetween two obstacles, and the space isn't big
+ // enough -- one iteration will have it clear obstacle A, but embed into obstacle B, and the next iteration
+ // will reverse it, and it will get nowhere quickly.
+ // * The key for the hash is collider+obstacle coordinates, so the same collider won't avoid the same obstacle
+ // in the same way twice. (Actually three times, see below.)
+ // * Note that the value of the hash is either nothing, "tried normal", or "tried reverse"
+ // * Nothing means it hasn't been tried yet
+ // * Tried normal means it was tried once
+ // * Tried reverse means it was tried a second time
+ // How does it determine how to move things around?
+ // * It calculates an "embed" value, i.e. how far the collider is "embedded" into the obstacle
+ // * And a direction, either towards center of gravity or away, depending on if it's a collision or protrusion
+ // * And it returns that
+ // How does it choose what obstacle to avoid?
+ // * It first sorts all the "collisions" (remember, these are the actual overlapping regions) based on how
+ // far their centers of gravity are from the last known center of gravity of the draggable itself,
+ // which was passed in during the creation of the Collision objects
+ // * It looks at the last one first, so the furthest from the object -- that way, it's going to always reign
+ // it in towards the last known good value, otherwise "closer" obstacles might keep shoving it away forever
+ // * Next, it calculates the embed values in the x and y direction, and picks the smallest one -- so if it's
+ // embedded heavily in the x-direction and only a little in the y, it'll pick the y first (small changes are
+ // more likely to succeed)
+ // * If it's a negative value, it tries again, because the embed function does the sanity-checking if we
+ // tried to move it in a strange or useless way
+ // * Finally, this is why it tries each "position" twice -- because for each starting position, it tries the
+ // smaller movement first, but then it tries the larger one. That's why the cache keeps track of the
+ // "tried reverse" value
+ // In the end, it returns a { dx:_, dy:_ } object, the handleCollision tries moving everything around, recalculates
+ // all the collisions, and calls this again to see what to do next
+ // NOTE: you can't easily re-calc "real position" from the jquery objects, because they're tagged with data that has
+ // offsets that are used internally by the jquery-collision plugin, so only use the thisc.*Coords values
+ function delta( collisions, containments, cache )
+ {
+ var c = collisions.concat(containments).sort( collisionComparison );
+ if( VISUAL_DEBUG ) { if(!cache.deltanum){ cache.deltanum = 1; } }
+ if( DEBUG ) { console.log( "collisions, in order: ", c.map(function(e,i,a){return e.collisionCoords.hash();}).join(",") ); }
+ while( c.length > 0 )
+ {
+ // note _pop_ not _shift_. we want to grab furthest collision from center of mass first...
+ // this one is likely the one causing the most problems, because something is embedded deeply into
+ // some obstacle:
+ var thisc = c.pop();
+ var co = thisc.obstacleCoords;
+ var cc = thisc.colliderCoords;
+ var cv = thisc.collisionCoords;
+ var ct = thisc.type;
+ var cd = thisc.direction;
+ var key = thisc.hash();
+ var dirx = ( thisc.type=="protrusion" ? ( cc.centerx() > co.centerx() ? -1 : +1 )
+ : ( cc.centerx() > co.centerx() ? +1 : -1 ) );
+ var diry = ( thisc.type=="protrusion" ? ( cc.centery() > co.centery() ? -1 : +1 )
+ : ( cc.centery() > co.centery() ? +1 : -1 ) );
+ var dx = thisc.embedx( dirx );
+ var dy = thisc.embedy( diry );
+ if( DEBUG ) console.log("cv,cc,co,ct,dx,dy,thisc.dx,thisc.dy,dirx,diry,co.centerx,co.centery,cc.centerx,cc.centery,key=",
+ cv.hash(),cc.hash(),co.hash(),ct,dx,dy,thisc.dx,thisc.dy,dirx,diry,co.centerx(),co.centery(),cc.centerx(),cc.centery(),key);
+ var tryToAdjustDX = ( dx < dy );
+ if( key in cache && cache[key] == "tried reverse" ) { if( DEBUG ) console.log("but already tried reverse too...");
+ continue; }
+ else if( key in cache && cache[key] == "tried normal" ) { if( DEBUG ) console.log("but already tried this...");
+ tryToAdjustDX=!tryToAdjustDX; cache[key]="tried reverse";
+ }
+ else { cache[key]="tried normal"; }
+ if( tryToAdjustDX )
+ {
+ if( VISUAL_DEBUG ) { $("<span>"+thisc.direction+"d"+cache.deltanum+".dx="+dx+"*"+dirx+"</span>").css("color","black").addClass("testdebug")
+ .css("position","absolute")
+ .css("white-space","nowrap").offset( { left: thisc.mousex, top: thisc.mousey + 20*(cache.deltanum-1) } ).appendTo("body"); cache.deltanum++; };
+ if( dx <= 0 ) { c.push(thisc); continue; }
+ return { "dx":dx*dirx, "dy":0 };
+ }
+ else
+ {
+ if( VISUAL_DEBUG ) { $("<span>"+thisc.direction+"d"+cache.deltanum+".dy="+dy+"*"+diry+"</span>").css("color","black").addClass("testdebug")
+ .css("position","absolute")
+ .css("white-space","nowrap").offset( { left: thisc.mousex, top: thisc.mousey + 20*(cache.deltanum-1) } ).appendTo("body"); cache.deltanum++; };
+ if( dy <= 0 ) { c.push(thisc); continue; }
+ return { "dx":0, "dy":dy*diry };
+ }
+ }
+ return { "dx":0, "dy":0 };
+ };
+
+})(jQuery);
diff --git a/modules-available/roomplanner/page.inc.php b/modules-available/roomplanner/page.inc.php
new file mode 100644
index 00000000..b533cf2f
--- /dev/null
+++ b/modules-available/roomplanner/page.inc.php
@@ -0,0 +1,53 @@
+<?php
+
+class Page_Roomplanner extends Page
+{
+ protected function doPreprocess()
+ {
+ User::load();
+
+ if (!User::hasPermission('superadmin')) {
+ Message::addError('main.no-permission');
+ Util::redirect('?do=Main');
+ }
+
+ }
+
+ protected function doRender()
+ {
+ Render::addTemplate('page', []);
+ }
+
+ protected function doAjax()
+ {
+ $action = Request::get('action', null, 'string');
+
+ if ($action === 'getmachines') {
+ $query = Request::get('query', null, 'string');
+
+ /* the query could be anything: UUID, IP or macaddr */
+// $result = Database::simpleQuery('SELECT machineuuid, macaddr, clientip, hostname '
+// . ', MATCH (machineuuid, macaddr, clientip, hostname) AGAINST (:query) AS relevance '
+// . 'FROM machine '
+// . 'WHERE MATCH (machineuuid, macaddr, clientip, hostname) AGAINST (:query) '
+// . 'ORDER BY relevance DESC '
+// . 'LIMIT 5'
+// , ['query' => $query]);
+//
+ $result = Database::simpleQuery('SELECT machineuuid, macaddr, clientip, hostname '
+ . 'FROM machine '
+ . "WHERE machineuuid LIKE :query "
+ . " OR macaddr LIKE :query "
+ . " OR clientip LIKE :query "
+ . " OR hostname LIKE :query ", ['query' => "%$query%"]);
+
+ $returnObject = ['machines' => []];
+
+ while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
+ $returnObject['machines'][] = $row;
+ }
+ echo json_encode($returnObject, JSON_PRETTY_PRINT);
+
+ }
+ }
+}
diff --git a/modules-available/roomplanner/style.css b/modules-available/roomplanner/style.css
new file mode 100644
index 00000000..7ad7407b
--- /dev/null
+++ b/modules-available/roomplanner/style.css
@@ -0,0 +1,763 @@
+@CHARSET "UTF-8";
+
+body.split #drawpanel {
+ width:60%;
+ float: right;}
+
+
+body.full #drawpanel {
+ width:90%;
+ float: none;
+ margin: 0 auto 20px;
+ }
+
+#drawpanel {
+ position:relative;}
+
+#drawarea {
+ background: url('images/grid_100_sep.png');
+ background-size: 100px 100px;}
+
+#drawpanel .panel-body {
+ padding:0;
+ margin: 0;
+ overflow: hidden;
+ height: 350px;}
+
+#scaleContainer {
+ position: absolute;
+ bottom: 5px;
+ right: 30px;
+ width: 15%;
+ z-index: 10000;}
+
+#scaleslider {
+ position:relative;}
+
+
+
+#scaleContainer .glyphicon {
+ position: absolute;
+ top: -2px;
+ font-size: 1.1em;}
+
+#scaleContainer .glyphicon-zoom-out {
+ left:-20px;}
+
+#scaleContainer .glyphicon-zoom-in {
+ right:-20px; }
+
+
+[itemlook="computer"] { background: url('images/computer/computer.png') no-repeat;}
+
+
+[itemlook="door-nw"] { background: url('images/wall/door-nw.png') no-repeat;}
+[itemlook="door-ne"] { background: url('images/wall/door-ne.png') no-repeat;}
+[itemlook="door-sw"] { background: url('images/wall/door-sw.png') no-repeat;}
+[itemlook="door-se"] { background: url('images/wall/door-se.png') no-repeat;}
+[itemlook="door-en"] { background: url('images/wall/door-en.png') no-repeat;}
+[itemlook="door-es"] { background: url('images/wall/door-es.png') no-repeat;}
+[itemlook="door-wn"] { background: url('images/wall/door-wn.png') no-repeat;}
+[itemlook="door-ws"] { background: url('images/wall/door-ws.png') no-repeat;}
+
+[itemlook="copier"] {
+ background: url('images/electricalDevices_wIP/copier.png') no-repeat;
+ }
+
+/*
+[itemlook="pc"] {
+ background: url('images/electricalDevices_wIP/pc.png') no-repeat;
+ z-index:100;
+ }
+*/
+[itemlook="pc-east"] {
+ background: url('images/electricalDevices_wIP/pc_east.png') no-repeat;
+ }
+
+[itemlook="pc-south"] {
+ background: url('images/electricalDevices_wIP/pc_south.png') no-repeat;
+ }
+
+[itemlook="pc-west"] {
+ background: url('images/electricalDevices_wIP/pc_west.png') no-repeat;
+ }
+
+[itemlook="pc-north"] {
+ background: url('images/electricalDevices_wIP/pc_north.png') no-repeat;
+
+ }
+
+[itemlook="printer"] {
+ background: url('images/electricalDevices_wIP/printer.png') no-repeat;
+
+ }
+
+[itemlook="telephone"] {
+ background: url('images/electricalDevices_wIP/telephone.png') no-repeat;
+
+ }
+
+[itemlook="flatscreen"] {
+ background: url('images/electricalDevices_woIP/flatscreen.png') no-repeat;
+
+ }
+
+[itemlook="lamp"] {
+ background: url('images/electricalDevices_woIP/lamp.png') no-repeat;
+
+ }
+
+[itemlook="tvcamera"] {
+ background: url('images/electricalDevices_woIP/tvcamera.png') no-repeat;
+
+ }
+
+[itemlook="4chairs1squaretable"] {
+ background: url('images/furniture/4chairs1squaretable.png') no-repeat;
+
+ }
+
+/*
+[itemlook="6chairs1table"] {
+ background: url('images/furniture/6chairs1table.png') no-repeat;
+
+ }
+*/
+
+[itemlook="6chairs1table-horizontal"] {
+ background: url('images/furniture/6chairs1table_horizontal.png') no-repeat;
+
+ }
+
+[itemlook="6chairs1table-vertical"] {
+ background: url('images/furniture/6chairs1table_vertical.png') no-repeat;
+
+ }
+
+/*
+[itemlook="8chairs1conferencetable"] {
+ background: url('images/furniture/8chairs1conferencetable.png') no-repeat;
+
+ }
+*/
+
+
+[itemlook="8chairs1conferencetable-horizontal"] {
+ background: url('images/furniture/8chairs1conferencetable_horizontal.png') no-repeat;
+
+ }
+
+
+[itemlook="8chairs1conferencetable-vertical"] {
+ background: url('images/furniture/8chairs1conferencetable_vertical.png') no-repeat;
+
+ }
+
+/*
+[itemlook="armchair"] {
+ background: url('images/furniture/armchair.png') no-repeat;
+
+ }
+*/
+
+[itemlook="armchair-east"] {
+ background: url('images/furniture/armchair_east.png') no-repeat;
+
+ }
+
+[itemlook="armchair-south"] {
+ background: url('images/furniture/armchair_south.png') no-repeat;
+
+ }
+
+[itemlook="armchair-west"] {
+ background: url('images/furniture/armchair_west.png') no-repeat;
+
+ }
+
+[itemlook="armchair-north"] {
+ background: url('images/furniture/armchair_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="chair"] {
+ background: url('images/furniture/chair.png') no-repeat;
+
+ }
+*/
+
+[itemlook="chair-east"] {
+ background: url('images/furniture/chair_east.png') no-repeat;
+
+ }
+
+[itemlook="chair-south"] {
+ background: url('images/furniture/chair_south.png') no-repeat;
+
+ }
+
+[itemlook="chair-west"] {
+ background: url('images/furniture/chair_west.png') no-repeat;
+
+ }
+
+[itemlook="chair-north"] {
+ background: url('images/furniture/chair_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="chair2"] {
+ background: url('images/furniture/chair2.png') no-repeat;
+
+ }
+*/
+
+[itemlook="chair2-east"] {
+ background: url('images/furniture/chair2_east.png') no-repeat;
+
+ }
+
+[itemlook="chair2-south"] {
+ background: url('images/furniture/chair2_south.png') no-repeat;
+
+ }
+
+[itemlook="chair2-west"] {
+ background: url('images/furniture/chair2_west.png') no-repeat;
+
+ }
+
+[itemlook="chair2-north"] {
+ background: url('images/furniture/chair2_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="classroomdesk"] {
+ background: url('images/furniture/classroomdesk.png') no-repeat;
+
+ }
+*/
+
+[itemlook="classroomdesk-east"] {
+ background: url('images/furniture/classroomdesk_east.png') no-repeat;
+
+ }
+
+[itemlook="classroomdesk-south"] {
+ background: url('images/furniture/classroomdesk_south.png') no-repeat;
+
+ }
+
+[itemlook="classroomdesk-west"] {
+ background: url('images/furniture/classroomdesk_west.png') no-repeat;
+
+ }
+
+[itemlook="classroomdesk-north"] {
+ background: url('images/furniture/classroomdesk_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="classroomdeskchair"] {
+ background: url('images/furniture/classroomdeskchair.png') no-repeat;
+
+ }
+*/
+
+[itemlook="classroomdeskchair-east"] {
+ background: url('images/furniture/classroomdeskchair_east.png') no-repeat;
+
+ }
+
+[itemlook="classroomdeskchair-south"] {
+ background: url('images/furniture/classroomdeskchair_south.png') no-repeat;
+
+ }
+
+[itemlook="classroomdeskchair-west"] {
+ background: url('images/furniture/classroomdeskchair_west.png') no-repeat;
+
+ }
+
+[itemlook="classroomdeskchair-north"] {
+ background: url('images/furniture/classroomdeskchair_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="classroomtable"] {
+ background: url('images/furniture/classroomtable.png') no-repeat;
+
+ }
+*/
+
+[itemlook="classroomtable-east"] {
+ background: url('images/furniture/classroomtable_east.png') no-repeat;
+
+ }
+
+[itemlook="classroomtable-south"] {
+ background: url('images/furniture/classroomtable_south.png') no-repeat;
+
+ }
+
+[itemlook="classroomtable-west"] {
+ background: url('images/furniture/classroomtable_west.png') no-repeat;
+
+ }
+
+[itemlook="classroomtable-north"] {
+ background: url('images/furniture/classroomtable_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="classroomtablechair"] {
+ background: url('images/furniture/classroomtablechair.png') no-repeat;
+
+ }
+*/
+
+[itemlook="classroomtablechair-east"] {
+ background: url('images/furniture/classroomtablechair_east.png') no-repeat;
+
+ }
+
+[itemlook="classroomtablechair-south"] {
+ background: url('images/furniture/classroomtablechair_south.png') no-repeat;
+
+ }
+
+[itemlook="classroomtablechair-west"] {
+ background: url('images/furniture/classroomtablechair_west.png') no-repeat;
+
+ }
+
+[itemlook="classroomtablechair-north"] {
+ background: url('images/furniture/classroomtablechair_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="coatrack"] {
+ background: url('images/furniture/coatrack.png') no-repeat;
+
+ }
+*/
+
+[itemlook="coatrack-east"] {
+ background: url('images/furniture/coatrack_east.png') no-repeat;
+
+ }
+
+[itemlook="coatrack-south"] {
+ background: url('images/furniture/coatrack_south.png') no-repeat;
+
+ }
+
+[itemlook="coatrack-west"] {
+ background: url('images/furniture/coatrack_west.png') no-repeat;
+
+ }
+
+[itemlook="coatrack-north"] {
+ background: url('images/furniture/coatrack_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="conferencetable"] {
+ background: url('images/furniture/conferencetable.png') no-repeat;
+
+ }
+*/
+
+[itemlook="conferencetable-horizontal"] {
+ background: url('images/furniture/conferencetable_horizontal.png') no-repeat;
+
+ }
+
+[itemlook="conferencetable-vertical"] {
+ background: url('images/furniture/conferencetable_vertical.png') no-repeat;
+
+ }
+
+/*
+[itemlook="couch"] {
+ background: url('images/furniture/couch.png') no-repeat;
+
+ }
+*/
+
+[itemlook="couch-east"] {
+ background: url('images/furniture/couch_east.png') no-repeat;
+
+ }
+
+[itemlook="couch-south"] {
+ background: url('images/furniture/couch_south.png') no-repeat;
+
+ }
+
+[itemlook="couch-west"] {
+ background: url('images/furniture/couch_west.png') no-repeat;
+
+ }
+
+[itemlook="couch-north"] {
+ background: url('images/furniture/couch_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="greenchair"] {
+ background: url('images/furniture/greenchair.png') no-repeat;
+
+ }
+*/
+
+[itemlook="greenchair-east"] {
+ background: url('images/furniture/greenchair_east.png') no-repeat;
+
+ }
+
+[itemlook="greenchair-south"] {
+ background: url('images/furniture/greenchair_south.png') no-repeat;
+
+ }
+
+[itemlook="greenchair-west"] {
+ background: url('images/furniture/greenchair_west.png') no-repeat;
+
+ }
+
+[itemlook="greenchair-north"] {
+ background: url('images/furniture/greenchair_north.png') no-repeat;
+
+ }
+
+[itemlook="lecturetheaterrow"] {
+ background: url('images/furniture/lecturetheaterrow.png') no-repeat;
+
+ }
+
+[itemlook="lecturetheaterrowseats"] {
+ background: url('images/furniture/lecturetheaterrowseats.png') no-repeat;
+
+ }
+
+/*
+[itemlook="locker"] {
+ background: url('images/furniture/locker.png') no-repeat;
+
+ }
+*/
+
+[itemlook="locker-east"] {
+ background: url('images/furniture/locker_east.png') no-repeat;
+
+ }
+
+[itemlook="locker-south"] {
+ background: url('images/furniture/locker_south.png') no-repeat;
+
+ }
+
+[itemlook="locker-west"] {
+ background: url('images/furniture/locker_west.png') no-repeat;
+
+ }
+
+[itemlook="locker-north"] {
+ background: url('images/furniture/locker_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="podium"] {
+ background: url('images/furniture/podium.png') no-repeat;
+
+ }
+*/
+
+[itemlook="podium-east"] {
+ background: url('images/furniture/podium_east.png') no-repeat;
+
+ }
+
+[itemlook="podium-south"] {
+ background: url('images/furniture/podium_south.png') no-repeat;
+
+ }
+
+[itemlook="podium-west"] {
+ background: url('images/furniture/podium_west.png') no-repeat;
+
+ }
+
+[itemlook="podium-north"] {
+ background: url('images/furniture/podium_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="roundeddesk"] {
+ background: url('images/furniture/roundeddesk.png') no-repeat;
+
+ }
+*/
+
+[itemlook="roundeddesk-east"] {
+ background: url('images/furniture/roundeddesk_east.png') no-repeat;
+
+ }
+
+[itemlook="roundeddesk-south"] {
+ background: url('images/furniture/roundeddesk_south.png') no-repeat;
+
+ }
+
+[itemlook="roundeddesk-west"] {
+ background: url('images/furniture/roundeddesk_west.png') no-repeat;
+
+ }
+
+[itemlook="roundeddesk-north"] {
+ background: url('images/furniture/roundeddesk_north.png') no-repeat;
+
+ }
+
+[itemlook="roundtable"] {
+ background: url('images/furniture/roundtable.png') no-repeat;
+
+ }
+
+/*
+[itemlook="semicirculartable"] {
+ background: url('images/furniture/semicirculartable.png') no-repeat;
+
+ }
+*/
+
+[itemlook="semicirculartable-east"] {
+ background: url('images/furniture/semicirculartable_east.png') no-repeat;
+
+ }
+
+[itemlook="semicirculartable-south"] {
+ background: url('images/furniture/semicirculartable_south.png') no-repeat;
+
+ }
+
+[itemlook="semicirculartable-west"] {
+ background: url('images/furniture/semicirculartable_west.png') no-repeat;
+
+ }
+
+[itemlook="semicirculartable-north"] {
+ background: url('images/furniture/semicirculartable_north.png') no-repeat;
+
+ }
+
+[itemlook="squaretable"] {
+ background: url('images/furniture/squaretable.png') no-repeat;
+
+ }
+
+/*
+[itemlook="studentdesk"] {
+ background: url('images/furniture/studentdesk.png') no-repeat;
+
+ }
+*/
+
+[itemlook="studentdesk-east"] {
+ background: url('images/furniture/studentdesk_east.png') no-repeat;
+
+ }
+
+[itemlook="studentdesk-south"] {
+ background: url('images/furniture/studentdesk_south.png') no-repeat;
+
+ }
+
+[itemlook="studentdesk-west"] {
+ background: url('images/furniture/studentdesk_west.png') no-repeat;
+
+ }
+
+[itemlook="studentdesk-north"] {
+ background: url('images/furniture/studentdesk_north.png') no-repeat;
+
+ }
+
+/*
+[itemlook="studentdeskchair"] {
+ background: url('images/furniture/studentdeskchair.png') no-repeat;
+
+ }
+*/
+
+[itemlook="studentdeskchair-east"] {
+ background: url('images/furniture/studentdeskchair_east.png') no-repeat;
+
+ }
+
+[itemlook="studentdeskchair-south"] {
+ background: url('images/furniture/studentdeskchair_south.png') no-repeat;
+
+ }
+
+[itemlook="studentdeskchair-west"] {
+ background: url('images/furniture/studentdeskchair_west.png') no-repeat;
+
+ }
+
+[itemlook="studentdeskchair-north"] {
+ background: url('images/furniture/studentdeskchair_north.png') no-repeat;
+
+ }
+
+[itemlook="projectionscreen"] {
+ background: url('images/misc/projectionscreen.png') no-repeat;
+
+ }
+
+[itemlook="papertray"] {
+ background: url('images/officeSupply/papertray.png') no-repeat;
+
+ }
+
+[itemlook="wastecan"] {
+ background: url('images/officeSupply/wastecan.png') no-repeat;
+
+ }
+
+
+[itemlook="plant"] {
+ background: url('images/plants/plant.png') no-repeat;
+
+ }
+
+[itemlook="plant2"] {
+ background: url('images/plants/plant2.png') no-repeat;
+
+ }
+
+[itemlook="plant3"] {
+ background: url('images/plants/plant3.png') no-repeat;
+
+ }
+
+
+[itemlook|="door"] {
+ z-index:99;
+ background-size: 100% 100%;}
+
+
+[itemlook|="window"] {
+ z-index: 99;
+ background: #ffffff;
+ border: 1px solid #000000;}
+
+
+.collides {
+ background-color: red;}
+
+.marked {
+ background-color: blue;}
+
+ul.toollist {
+ list-style: none;}
+
+ul.toollist li {
+ display: inline-block;
+ padding: 2px;
+ margin-right: 10px;}
+
+
+.deleteHandle {
+ display:none;
+ float: right;}
+
+.rotationHandle {
+ display:none;
+ float: left;}
+
+div.draggable:hover .rotationHandle {
+ display:inline;
+ cursor: pointer;}
+
+div.draggable:hover .deleteHandle {
+ display:inline;
+ cursor: pointer;}
+
+
+[itemtype="furniture"], [itemtype="furniture_drag"] {
+ z-index: 99;
+ background-size: 100% 100%;}
+
+[itemtype="pc"], [itemtype="pc_drag"] {
+ z-index: 100;
+ background-size: 100% 100%;
+}
+
+[itemlook="wall-horizontal"] {
+ background: url('images/wall/wall-horizontal.png') repeat #ffffff;
+ border: 1px solid #000000;
+ background-size: auto 15%;
+}
+
+[itemlook="wall-vertical"] {
+ background: url('images/wall/wall-vertical.png') repeat #ffffff;
+ border: 1px solid #000000;
+ background-size: 15% auto;
+}
+
+
+
+/* select popup */
+.machine-entry {
+ width: 100%;
+ border: 1px solid #999;
+ border-radius: 5px;
+ margin: 5px 20px 5px 2px;
+ padding: 5px 10px 5px 10px;
+}
+
+.machine-entry .table {
+ font-size:12px;
+ margin-bottom: -5px;
+}
+.machine-entry .table tr {
+ line-height: 5px;
+}
+
+
+.machine-logo {
+ float: left;
+ width:36px;
+}
+.machine-logo i {
+ font-size: 20px;
+ line-height: 50px;
+}
+.machine-entry-header {
+ font-weight: bolder;
+ font-size: 18px;
+}
+
+.machine-uuid {
+}
+
+.machine-ip {
+}
+
+.selectize-dropdown-content {
+ max-height : 600px;
+}
+
diff --git a/modules-available/roomplanner/templates/page.html b/modules-available/roomplanner/templates/page.html
new file mode 100644
index 00000000..a8294dc5
--- /dev/null
+++ b/modules-available/roomplanner/templates/page.html
@@ -0,0 +1,350 @@
+<!-- Modal -->
+<div class="modal fade" id="selectMachineModal" role="dialog">
+ <div class="modal-dialog">
+
+ <!-- Modal content-->
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">&times;</button>
+ <h4>Add Machine</h4>
+ </div>
+ <div class="modal-body">
+ <ul class="nav nav-tabs">
+ <li class="active"><a data-toggle="tab" href="#subnet">Subnet</a></li>
+ <li><a data-toggle="tab" href="#search">Search</a></li>
+ </ul>
+ <div class="tab-content">
+ <div id="subnet" class="tab-pane fade in active">
+ <br/>
+ <p>
+ blah blah blah
+ </p>
+ <label for="subnetBox">Machines in this IP-Range</label>
+ <input id="subnetBox" class="form-control"/>
+ </div>
+ <div id="search" class="tab-pane fade">
+ <br/>
+ <p> Hier können sie durch alle bekannten Maschinen suchen, bla blah blah. </p>
+ <label for="machineSearchBox">All Machines</label>
+ <input id="machineSearchBox" class="form-control" />
+ </div>
+
+ </div>
+
+
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-default pull-left">Cancel</button>
+ <button class="btn btn-primary" id="selectMachineButton">Select</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<!-- berryous raumplaner -->
+</head>
+<body class="full">
+ <h1>Raumplaner</h1>
+
+ <div id="toolpanel" class="panel panel-default" style="z-index:200;">
+ <div class="panel-heading">
+ <h3 class="panel-title">Werkzeuge</h3>
+ </div>
+ <div class="panel-body">
+ <ul role="tablist" class="nav nav-tabs">
+ <li role="presentation" class="active"><a href="#computers"
+ aria-controls="computers" role="tab" data-toggle="tab">Rechner</a></li>
+ <li role="presentation"><a href="#walls"
+ aria-controls="walls" role="tab" data-toggle="tab">Bauelemente</a></li>
+ <li role="presentation"><a href="#electricaldevices"
+ aria-controls="electricaldevices" role="tab" data-toggle="tab">Elektrische Geräte</a></li>
+ <li role="presentation"><a href="#tables"
+ aria-controls="tables" role="tab" data-toggle="tab">Tische</a></li>
+ <li role="presentation"><a href="#chairs"
+ aria-controls="chairs" role="tab" data-toggle="tab">Stühle</a></li>
+ <li role="presentation"><a href="#furniture"
+ aria-controls="furniture" role="tab" data-toggle="tab">Sonstige Möbel</a></li>
+ <li role="presentation"><a href="#officesupply"
+ aria-controls="officesupply" role="tab" data-toggle="tab">Bürobedarf</a></li>
+ <li role="presentation"><a href="#plants"
+ aria-controls="plants" role="tab" data-toggle="tab">Pflanzen</a></li>
+ <li role="presentation"><a href="#misc"
+ aria-controls="misc" role="tab" data-toggle="tab">Anderes</a></li>
+ </ul>
+ <div class="tab-content">
+ <div role="tabpanel" class="tab-pane" id="walls">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" scalable="h" itemlook="wall-horizontal" class="draggable" obstacle=true style="width:100px; height:25px;" data-height="25" data-width="100" title="Wand (horizontal)"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" scalable="v" itemlook="wall-vertical" class="draggable" obstacle=true style="width:25px; height:100px;" data-height="100" data-width="25" title="Wand (vertial)"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" scalable="h" itemlook="window-horizontal" class="draggable" obstacle=true style="width:50px; height:25px;" data-height="25" data-width="50" title="Fenster"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" scalable="v" itemlook="window-vertical" class="draggable" obstacle=true style="width:25px; height:50px;" data-height="50" data-width="25" title="Fenster"></div>
+ </li>
+
+
+ <li>
+ <div itemtype="furniture" itemlook="door-nw" class="draggable" obstacle=true style="width:50px; height:100px;" data-height="100" data-width="50" title="Tür"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="door-ne" class="draggable" obstacle=true style="width:50px; height:100px;" data-height="100" data-width="50" title="Tür"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="door-sw" class="draggable" obstacle=true style="width:50px; height:100px;" data-height="100" data-width="50" title="Tür"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="door-se" class="draggable" obstacle=true style="width:50px; height:100px;" data-height="100" data-width="50" title="Tür"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="door-wn" class="draggable" obstacle=true style="width:100px; height:50px;" data-height="50" data-width="100" title="Tür"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="door-ws" class="draggable" obstacle=true style="width:100px; height:50px;" data-height="50" data-width="100" title="Tür"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="door-en" class="draggable" obstacle=true style="width:100px; height:50px;" data-height="50" data-width="100" title="Tür"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="door-es" class="draggable" obstacle=true style="width:100px; height:50px;" data-height="50" data-width="100" title="Tür"></div>
+ </li>
+
+ </ul>
+ </div>
+
+
+ <div role="tabpanel" class="tab-pane active" id="computers">
+ <ul class="toollist">
+ <li>
+ <div itemtype="pc" itemlook="pc-south" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="PC" noresize=1></div>
+ </li>
+ <li>
+ <div itemtype="pc" itemlook="copier" class="draggable" obstacle=true style="width:200px; height:100px;" data-height="100" data-width="200" title="Kopierer" noresize=1></div>
+ </li>
+ <li>
+ <div itemtype="pc" itemlook="printer" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="Drucker" noresize=1></div>
+ </li>
+ <li>
+ <div itemtype="pc" itemlook="telephone" class="draggable" obstacle=true style="width:50px; height:50px;" data-height="50" data-width="50" title="Telefon" noresize=1></div>
+ </li>
+ </ul>
+ </div>
+
+ <div role="tabpanel" class="tab-pane" id="electricaldevices">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" itemlook="flatscreen" class="draggable" obstacle=true style="width:75px; height:100px;" data-height="100" data-width="75" title="Flatscreen"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="lamp" class="draggable" obstacle=true style="width:125px; height:50px;" data-height="50" data-width="125" title="Schreibtischlampe"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="tvcamera" class="draggable" obstacle=true style="width:125px; height:50px;" data-height="50" data-width="125" title="Projektor"></div>
+ </li>
+ </ul>
+ </div>
+
+ <div role="tabpanel" class="tab-pane" id="tables">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" itemlook="4chairs1squaretable" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="4 Stühle und ein quadratischer Tisch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="6chairs1table-horizontal" class="draggable" obstacle=true style="width:100px; height:75px;" data-height="75" data-width="100" title="6 Stühle und ein Tisch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="8chairs1conferencetable-horizontal" class="draggable" obstacle=true style="width:175px; height:100px;" data-height="100" data-width="175" title="8 Stühle und 1 Konferenztisch"></div>
+ </li>
+
+ <li>
+ <div itemtype="furniture" itemlook="classroomdesk-north" class="draggable" obstacle=true style="width:275px; height:100px;" data-height="100" data-width="275" title="Klassenzimmerpult"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="classroomdeskchair-north" class="draggable" obstacle=true style="width:175px; height:100px;" data-height="100" data-width="175" title="Klassenzimmerpult mit Stuhl"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="classroomtable-east" class="draggable" obstacle=true style="width:75px; height:100px;" data-height="100" data-width="75" title="Klassenzimmertisch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="classroomtablechair-north" class="draggable" obstacle=true style="width:75px; height:100px;" data-height="100" data-width="75" title="Klassenzimmertisch mit Stuhl"></div>
+ </li>
+
+ <li>
+ <div itemtype="furniture" itemlook="conferencetable-horizontal" class="draggable" obstacle=true style="width:200px; height:100px;" data-height="100" data-width="200" title="Konferenztisch"></div>
+ </li>
+
+
+ <li>
+ <div itemtype="furniture" itemlook="podium-north" class="draggable" obstacle=true style="width:200px; height:100px;" data-height="100" data-width="200" title="Podium"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="roundeddesk-east" class="draggable" obstacle=true style="width:75px; height:100px;" data-height="100" data-width="75" title="Eckschreibtisch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="roundtable" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="Runder Tisch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="semicirculartable-north" class="draggable" obstacle=true style="width:200px; height:100px;" data-height="100" data-width="200" title="Nierentisch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="squaretable" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="Quadratischer Tisch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="studentdesk-north" class="draggable" obstacle=true style="width:150px; height:100px;" data-height="100" data-width="150" title="Schülerpult"></div>
+ </li>
+
+
+ </ul>
+
+ </div>
+
+ <div role="tabpanel" class="tab-pane" id="chairs">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" itemlook="armchair-south" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="Sessel"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="chair-south" class="draggable" obstacle=true style="width:125px; height:100px;" data-height="100" data-width="125" title="Stuhl"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="chair2-south" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="Stuhl"></div>
+ </li>
+
+
+ <li>
+ <div itemtype="furniture" itemlook="couch-south" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="Couch"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="greenchair-south" class="draggable" obstacle=true style="width:125px; height:100px;" data-height="100" data-width="125" title="Stuhl"></div>
+ </li>
+
+ <li>
+ <div itemtype="furniture" itemlook="studentdeskchair-north" class="draggable" obstacle=true style="width:100px; height:100px;" data-height="100" data-width="100" title="Schülerpult mit Stuhl"></div>
+ </li>
+ </ul>
+ </div>
+
+ <div role="tabpanel" class="tab-pane" id="furniture">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" itemlook="locker-east" class="draggable" obstacle=true style="width:100px; height:75px;" data-height="75" data-width="100" title="Schließfach"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="locker-north" class="draggable" obstacle=true style="width:75px; height:100px;" data-height="100" data-width="75" title="Schließfach"></div>
+ </li>
+
+ <li>
+ <div itemtype="furniture" itemlook="coatrack-east" class="draggable" obstacle=true style="width:25px; height:150px;" data-height="150" data-width="25" title="Garderobe"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="coatrack-north" class="draggable" obstacle=true style="width:150px; height:25px;" data-height="25" data-width="150" title="Garderobe"></div>
+ </li>
+
+
+ <li>
+ <div itemtype="furniture" itemlook="lecturetheaterrow" class="draggable" obstacle=true style="width:725px; height:100px;" data-height="100" data-width="725" title="Vorlesungssaalreihe mit Stühlen"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="lecturetheaterrowseats" class="draggable" obstacle=true style="width:725px; height:50px;" data-height="50" data-width="725" title="Vorlesungssaalstuhlreihe"></div>
+ </li>
+
+ </ul>
+ </div>
+
+ <div role="tabpanel" class="tab-pane" id="officesupply">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" itemlook="papertray" class="draggable" obstacle=true style="width:25px; height:50px;" data-height="50" data-width="25" title="Papierfach"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="wastecan" class="draggable" obstacle=true style="width:50px; height:50px;" data-height="50" data-width="50" title="Papierkorb"></div>
+ </li>
+
+ </ul>
+ </div>
+ <div role="tabpanel" class="tab-pane" id="plants">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" itemlook="plant" class="draggable" obstacle=true style="width:75px; height:75px;" data-height="75" data-width="75" title="Pflanze"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="plant2" class="draggable" obstacle=true style="width:75px; height:75px;" data-height="75" data-width="75" title="Pflanze"></div>
+ </li>
+ <li>
+ <div itemtype="furniture" itemlook="plant3" class="draggable" obstacle=true style="width:75px; height:75px;" data-height="75" data-width="75" title="Pflanze"></div>
+ </li>
+ </ul>
+ </div>
+ <div role="tabpanel" class="tab-pane" id="misc">
+ <ul class="toollist">
+ <li>
+ <div itemtype="furniture" itemlook="projectionscreen" class="draggable" obstacle=true style="width:525px; height:25px;" data-height="25" data-width="525" title="Projektionswand"></div>
+ </li>
+ </ul>
+ </div>
+
+ </div>
+ </div>
+ </div>
+
+
+
+ <div class="panel panel-default" id="drawpanel">
+ <div class="panel-heading">
+ <h3 class="panel-title">Sketchboard</h3>
+ </div>
+ <div class="panel-body">
+ <div id="drawarea" style="top:0px; left:0px;">
+ <div id="draw-element-area" style="width:100%; height:100%;"></div>
+ </div>
+ <div id="scaleContainer">
+ <div id="scaleslider"></div>
+ <span class="glyphicon glyphicon-zoom-out" aria-hidden="true"></span>
+ <span class="glyphicon glyphicon-zoom-in" aria-hidden="true"></span>
+ </div>
+ </div>
+
+
+ </div>
+
+ <div class="panel panel-default">
+ <div class="panel-heading"><h3 class="panel-title">Store / Restore</h3></div>
+ <div class="panel-body">
+ <a class="btn btn-default" href="#" role="button" id="loadButton">Load</a>
+ <a class="btn btn-default" href="#" role="button" id="serializeButton">Serialize</a>
+ <div class="form-group">
+ <label for="serializedRoom" class="col-sm-2 control-label">In-/Output</label>
+ <textarea class="form-control" rows="5" name="serializedRoom" id="serializedRoom"></textarea>
+ </div>
+ </div>
+ </div>
+
+</body>
+</html>
+
+
+
+
+
+<script type="application/javascript"><!--
+document.addEventListener("DOMContentLoaded", function () {
+
+ $.when(
+ $.getScript("modules/roomplanner/js/lib/jquery-collision.js"),
+ $.getScript("modules/roomplanner/js/lib/jquery-ui-draggable-collision.js"),
+ $.getScript("modules/roomplanner/js/grid.js"),
+ $.Deferred(function( deferred ){
+ $( deferred.resolve );
+ })
+ ).done(function() {
+ $.getScript("modules/roomplanner/js/init.js", function() {
+ initRoomplanner();
+ });
+ });
+});
+
+</script>