event-tickets-with-ticket-scanner
Last commit date
3rd
1 year ago
css
1 year ago
img
1 year ago
languages
1 year ago
ticket
1 year ago
vendors
1 year ago
SASO_EVENTTICKETS.php
1 year ago
backend.js
1 year ago
changelog.txt
1 year ago
db.php
1 year ago
index.php
1 year ago
init_file.php
1 year ago
js_seatingplan.js
1 year ago
order_details.js
1 year ago
readme.txt
1 year ago
saso-eventtickets-validator.js
1 year ago
sasoEventtickets_AdminSettings.php
1 year ago
sasoEventtickets_Authtoken.php
1 year ago
sasoEventtickets_Base.php
1 year ago
sasoEventtickets_Core.php
1 year ago
sasoEventtickets_Frontend.php
1 year ago
sasoEventtickets_Messenger.php
1 year ago
sasoEventtickets_Options.php
1 year ago
sasoEventtickets_PDF.php
1 year ago
sasoEventtickets_Ticket.php
1 year ago
sasoEventtickets_TicketBadge.php
1 year ago
sasoEventtickets_TicketDesigner.php
1 year ago
sasoEventtickets_TicketQR.php
1 year ago
ticket_events.js
1 year ago
ticket_scanner.js
1 year ago
validator.js
1 year ago
wc_backend.js
1 year ago
wc_frontend.js
1 year ago
woocommerce-hooks.php
1 year ago
js_seatingplan.js
402 lines
| 1 | function sasoEventtickets_js_seatingplan(PARAS) { |
| 2 | let CONTROL_PANEL = null; |
| 3 | let CONTROL_PANEL2 = null; |
| 4 | |
| 5 | function init(cbf) { |
| 6 | addScriptTag(myAjax._plugin_home_url+"/3rd/raphael/raphael_2.3.0.min.js", 'raphael', ()=>{ |
| 7 | console.log('Seating plan JS initialized'); |
| 8 | console.log(PARAS); |
| 9 | cbf && cbf(); |
| 10 | }, {'crossorigin':"anonymous", "charset":"utf8"}); |
| 11 | } |
| 12 | |
| 13 | function displaySeatingPlan() { |
| 14 | let div = PARAS.div; |
| 15 | // draw 2 divs next to each other |
| 16 | div.html(""); |
| 17 | div.css("display", "flex"); |
| 18 | div.css("flex-direction", "row"); |
| 19 | div.css("align-items", "flex-start"); |
| 20 | div.css("justify-content", "space-between"); |
| 21 | div.css("width", "100%"); |
| 22 | div.css("height", "100%"); |
| 23 | |
| 24 | let div2 = $('<div style="width:80%;background:white;padding:15px;border-radius:15px;">').appendTo(div); |
| 25 | CONTROL_PANEL = $('<div style="width:20%;background:yellow;padding:15px;border-radius:15px;">').appendTo(div); |
| 26 | CONTROL_PANEL2 = $('<div style="width:20%;background:#efefef;padding:15px;border-radius:15px;">').appendTo(div); |
| 27 | |
| 28 | let is_plan_loaded = false; |
| 29 | |
| 30 | // https://dmitrybaranovskiy.github.io/raphael/reference.html#Paper.setSize |
| 31 | |
| 32 | div2.html(""); |
| 33 | let div_drawing_area_id = myAjax.divPrefix + '_div_drawing_area'; |
| 34 | let div_drawing_area = $('<div style="border:2px solid black;width:80%;height:400px;background-color:white;" id="'+div_drawing_area_id+'"></div>') |
| 35 | |
| 36 | let btn_grp = $('<div style="margin-bottom:15px;">').appendTo(div2); |
| 37 | let btn_grp_2 = $('<div style="margin-bottom:15px;visibility:hidden;">').appendTo(div2); |
| 38 | |
| 39 | let input_pre = $('<input type="checkbox">'); |
| 40 | let input_x = $('<input type="number" placeholder="x-offset">'); |
| 41 | let input_y = $('<input type="number" placeholder="y-offset">'); |
| 42 | if (PARAS.calibrate) { |
| 43 | input_pre.appendTo(div2); |
| 44 | input_x.appendTo(div2); |
| 45 | input_y.appendTo(div2); |
| 46 | } |
| 47 | |
| 48 | div_drawing_area.appendTo(div2); |
| 49 | let info = $('<div>').appendTo(div2); // for messages like "Seat added" or "saved" |
| 50 | |
| 51 | function listAllObjects() { |
| 52 | CONTROL_PANEL2.html(""); |
| 53 | let ul = $('<ul>').appendTo(CONTROL_PANEL2); |
| 54 | seats.forEach((seat, index) => { |
| 55 | let li = $('<li>').text(seat.typeName + " " + (index+1) + ": " + seat.attr['name']).appendTo(ul); |
| 56 | li.on("click", e=>{ |
| 57 | paper.getById(seat.svgObject.id).node.click(); |
| 58 | }); |
| 59 | }); |
| 60 | if (seats.length == 0) { |
| 61 | $('<li>').text("No seats added yet").appendTo(ul); |
| 62 | } |
| 63 | if (paper) { |
| 64 | let text_objects = getByType("text"); |
| 65 | if (text_objects.length > 0) { |
| 66 | $('<li>').text("Text objects:").appendTo(ul); |
| 67 | text_objects.forEach((text, index) => { |
| 68 | let li_text = $('<li>').text("Text " + (index+1) + ": " + text.attr('text')).appendTo(ul); |
| 69 | li_text.on("click", e=>{ |
| 70 | text.node.click(); |
| 71 | }); |
| 72 | }); |
| 73 | } |
| 74 | } |
| 75 | if (paper && getByType("image").length > 0) { |
| 76 | $('<li>').text("Image objects:").appendTo(ul); |
| 77 | getByType("image").forEach((img, index) => { |
| 78 | let li_img = $('<li>').text("Image " + (index+1) + ": " + img.attr('src')).appendTo(ul); |
| 79 | li_img.on("click", e=>{ |
| 80 | img.node.click(); |
| 81 | }); |
| 82 | }); |
| 83 | } |
| 84 | if (paper && getByType("path").length > 0) { |
| 85 | $('<li>').text("Path objects:").appendTo(ul); |
| 86 | getByType("path").forEach((path, index) => { |
| 87 | let li_path = $('<li>').text("Path " + (index+1) + ": " + path.attr('d')).appendTo(ul); |
| 88 | li_path.on("click", e=>{ |
| 89 | path.node.click(); |
| 90 | }); |
| 91 | }); |
| 92 | } |
| 93 | if (paper && getByType("rect").length > 0) { |
| 94 | $('<li>').text("Rect objects:").appendTo(ul); |
| 95 | getByType("rect").forEach((rect, index) => { |
| 96 | let li_rect = $('<li>').text("Rect " + (index+1) + ": " + rect.attr('x') + "," + rect.attr('y') + " (" + rect.attr('width') + "x" + rect.attr('height') + ")").appendTo(ul); |
| 97 | li_rect.on("click", e=>{ |
| 98 | rect.node.click(); |
| 99 | }); |
| 100 | }); |
| 101 | } |
| 102 | if (paper && getByType("circle").length > 0) { |
| 103 | $('<li>').text("Circle objects:").appendTo(ul); |
| 104 | getByType("circle").forEach((circle, index) => { |
| 105 | let li_circle = $('<li>').text("Circle " + (index+1) + ": " + circle.attr('cx') + "," + circle.attr('cy') + " (r=" + circle.attr('r') + ")").appendTo(ul); |
| 106 | li_circle.on("click", e=>{ |
| 107 | circle.node.click(); |
| 108 | }); |
| 109 | }); |
| 110 | } |
| 111 | if (paper && getByType("ellipse").length > 0) { |
| 112 | $('<li>').text("Ellipse objects:").appendTo(ul); |
| 113 | getByType("ellipse").forEach((ellipse, index) => { |
| 114 | let li_ellipse = $('<li>').text("Ellipse " + (index+1) + ": " + ellipse.attr('cx') + "," + ellipse.attr('cy') + " (rx=" + ellipse.attr('rx') + ", ry=" + ellipse.attr('ry') + ")").appendTo(ul); |
| 115 | li_ellipse.on("click", e=>{ |
| 116 | ellipse.node.click(); |
| 117 | }); |
| 118 | }); |
| 119 | } |
| 120 | if (paper && getByType("set").length > 0) { |
| 121 | $('<li>').text("Set objects:").appendTo(ul); |
| 122 | getByType("set").forEach((set, index) => { |
| 123 | let li_set = $('<li>').text("Set " + (index+1) + ": " + set.items.length + " items").appendTo(ul); |
| 124 | li_set.on("click", e=>{ |
| 125 | set.node.click(); |
| 126 | }); |
| 127 | }); |
| 128 | } |
| 129 | if (paper && getByType("g").length > 0) { |
| 130 | $('<li>').text("Group objects:").appendTo(ul); |
| 131 | getByType("g").forEach((group, index) => { |
| 132 | let li_group = $('<li>').text("Group " + (index+1) + ": " + group.items.length + " items").appendTo(ul); |
| 133 | li_group.on("click", e=>{ |
| 134 | group.node.click(); |
| 135 | }); |
| 136 | }); |
| 137 | } |
| 138 | if (paper && getByType("symbol").length > 0) { |
| 139 | $('<li>').text("Symbol objects:").appendTo(ul); |
| 140 | getByType("symbol").forEach((symbol, index) => { |
| 141 | let li_symbol = $('<li>').text("Symbol " + (index+1) + ": " + symbol.attr('id')).appendTo(ul); |
| 142 | li_symbol.on("click", e=>{ |
| 143 | symbol.node.click(); |
| 144 | }); |
| 145 | }); |
| 146 | } |
| 147 | if (paper && getByType("text").length > 0) { |
| 148 | $('<li>').text("Text objects:").appendTo(ul); |
| 149 | getByType("text").forEach((text, index) => { |
| 150 | let li_text = $('<li>').text("Text " + (index+1) + ": " + text.attr('text')).appendTo(ul); |
| 151 | li_text.on("click", e=>{ |
| 152 | text.node.click(); |
| 153 | }); |
| 154 | }); |
| 155 | } |
| 156 | |
| 157 | } |
| 158 | |
| 159 | // not allowed functions, because it will be serialized and stored in the database |
| 160 | function Seat(svgObject, typeName) { |
| 161 | this.svgObject = svgObject; |
| 162 | this.typeName = typeName; |
| 163 | this.attr = {}; |
| 164 | } |
| 165 | |
| 166 | let seats = []; |
| 167 | let paper; |
| 168 | |
| 169 | let _info_timer = null; |
| 170 | function _setInfo(msg, dont_clear) { |
| 171 | if (_info_timer) { |
| 172 | clearTimeout(_info_timer); |
| 173 | } |
| 174 | info.html(msg); |
| 175 | if (!dont_clear) { |
| 176 | _info_timer = setTimeout(()=>{ |
| 177 | info.html(""); |
| 178 | }, 2000); |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | function getByType(type) { |
| 183 | return seats.filter(seat => seat.attr("type") === type); |
| 184 | } |
| 185 | |
| 186 | $('<button>').text("Add new Seating plan").on("click", e=>{ |
| 187 | if (is_plan_loaded) { |
| 188 | if (confirm("Overwrite plan?")) { |
| 189 | __renderArea(); |
| 190 | } |
| 191 | } else { |
| 192 | __renderArea(); |
| 193 | } |
| 194 | function __renderArea() { |
| 195 | is_plan_loaded = true; |
| 196 | btn_grp_2.css("visibility", "visible"); |
| 197 | div_drawing_area.html(""); |
| 198 | paper = Raphael(div_drawing_area[0], "100%", 400); |
| 199 | paper.text(50,10, "Seating plan"); |
| 200 | //console.log(div_drawing_area.html()); |
| 201 | listAllObjects(); |
| 202 | } |
| 203 | }).addClass("button-primary").appendTo(btn_grp); |
| 204 | |
| 205 | // add button to add a text to the drawing area |
| 206 | $('<button>').text("Add text").on("click", e=>{ |
| 207 | if (!is_plan_loaded) { |
| 208 | _setInfo("Please create a seating plan first"); |
| 209 | return; |
| 210 | } |
| 211 | let drag_start_x = 50; |
| 212 | let drag_start_y = 40; |
| 213 | let text = paper.text(50, 50, "New Text"); |
| 214 | seats.push(text); |
| 215 | |
| 216 | text.attr({ |
| 217 | "font-size": 20, |
| 218 | "font-family": "Arial", |
| 219 | "fill": "#000", |
| 220 | //"stroke": "#fff", |
| 221 | //"stroke-width": 1 |
| 222 | }); |
| 223 | text.drag((dx,dy,x,y,elem)=>{ // onmove |
| 224 | text.attr("x", dx+50); |
| 225 | text.attr("y", dy+50); |
| 226 | }, (x,y,elem)=>{ // onstart |
| 227 | text.attr("opacity", 0.7); |
| 228 | }, (x,y,elem)=>{ // onend |
| 229 | text.attr("opacity", 1); |
| 230 | }); |
| 231 | _setInfo("Text added"); |
| 232 | text.drag((dx,dy,x,y,elem)=>{ // onmove |
| 233 | text.attr("x", dx+drag_start_x); |
| 234 | text.attr("y", dy+drag_start_y); |
| 235 | }, (x,y,elem)=>{ // onstart |
| 236 | text.attr("opacity", 0.7); |
| 237 | }, (x,y,elem)=>{ // onend |
| 238 | drag_start_x = text.attr("x"); |
| 239 | drag_start_y = text.attr("y"); |
| 240 | text.attr("opacity", 1); |
| 241 | }); |
| 242 | text.dblclick(()=>{ |
| 243 | _setInfo("Text selected"); |
| 244 | CONTROL_PANEL.html(""); // clear control panel |
| 245 | let div_mask =$('<div>').appendTo(CONTROL_PANEL); |
| 246 | let div_buttons = $('<div>').appendTo(CONTROL_PANEL); |
| 247 | |
| 248 | let text_id = paper.getById(text.id); |
| 249 | let text_content = $('<input type="text" placeholder="Text content">').appendTo(div_mask); |
| 250 | let text_color = $('<input type="color">').appendTo(div_mask); |
| 251 | |
| 252 | text_color.val(text.attr("fill")); |
| 253 | text_content.val(text.attr("text")); |
| 254 | |
| 255 | let text_save = $('<button>').text("Save").appendTo(div_buttons); |
| 256 | // add listener to change the color immediately |
| 257 | text_color.on("input", e=>{ |
| 258 | text.attr("fill", text_color.val()); |
| 259 | //text.attr("stroke", text_color.val() == '#ffffff' ? '#000' : '#fff'); |
| 260 | _setInfo("Text color changed"); |
| 261 | }); |
| 262 | // add listener to change the text immediately |
| 263 | text_content.on("input", e=>{ |
| 264 | text.attr("text", text_content.val().trim()); |
| 265 | _setInfo("Text content changed"); |
| 266 | }); |
| 267 | // save the text and color |
| 268 | text_save.on("click", e=>{ |
| 269 | console.log("save"); |
| 270 | text_content.val(text_content.val().trim()); |
| 271 | text.attr("text", text_content.val()); |
| 272 | let c = text_color.val(); |
| 273 | text.attr("fill", c); |
| 274 | //text.attr("stroke", c == '#ffffff' ? '#000' : '#fff'); |
| 275 | _setInfo("Text saved"); |
| 276 | listAllObjects(); |
| 277 | }); |
| 278 | let text_delete = $('<button>').text("Delete").appendTo(div_buttons); |
| 279 | text_delete.on("click", e=>{ |
| 280 | if (confirm("Delete text?")) { |
| 281 | paper.getById(text.id).remove(); |
| 282 | _setInfo("Text deleted"); |
| 283 | listAllObjects(); |
| 284 | } |
| 285 | }); |
| 286 | // store the values for cancel |
| 287 | let orig_text_content = text_content.val(); |
| 288 | let orig_text_color = text_color.val(); |
| 289 | let text_cancel = $('<button>').text("Cancel").appendTo(div_buttons); |
| 290 | text_cancel.on("click", e=>{ |
| 291 | text.attr("text", orig_text_content); |
| 292 | text.attr("fill", orig_text_color); |
| 293 | CONTROL_PANEL.html(""); // clear control panel |
| 294 | _setInfo("Text edit cancelled"); |
| 295 | listAllObjects(); |
| 296 | }); |
| 297 | |
| 298 | }); |
| 299 | }).addClass("button-primary").appendTo(btn_grp_2); |
| 300 | |
| 301 | $('<button>').text("Add new Seat Box").on("click", e=>{ |
| 302 | let circle; |
| 303 | let drag_start_x = 50; |
| 304 | let drag_start_y = 40; |
| 305 | //circle = paper.circle(50, 40, 10); |
| 306 | circle = paper.rect(drag_start_x, drag_start_y, 40, 40); |
| 307 | let seat = new Seat(circle, "box"); |
| 308 | seat.attr['name'] = "Seat "+(seats.length+1); |
| 309 | seats.push(seat); |
| 310 | circle.attr("fill", "#f00000"); |
| 311 | circle.attr("stroke", "#fff"); |
| 312 | circle.attr("name", "Seat "+seats.length); |
| 313 | |
| 314 | circle.drag((dx,dy,x,y,elem)=>{ // onmove |
| 315 | circle.attr("x", dx+drag_start_x); |
| 316 | circle.attr("y", dy+drag_start_y); |
| 317 | }, (x,y,elem)=>{ // onstart |
| 318 | circle.attr("opacity", 0.7); |
| 319 | }, (x,y,elem)=>{ // onend |
| 320 | drag_start_x = circle.attr("x"); |
| 321 | drag_start_y = circle.attr("y"); |
| 322 | circle.attr("opacity", 1); |
| 323 | }); |
| 324 | _setInfo("Seat added"); |
| 325 | }).addClass("button-primary").appendTo(btn_grp_2); |
| 326 | |
| 327 | $('<button>').text("Add new Seat Circle").on("click", e=>{ |
| 328 | let circle; |
| 329 | let drag_start_x = 50; |
| 330 | let drag_start_y = 40; |
| 331 | circle = paper.circle(drag_start_x, drag_start_y, 20); |
| 332 | let seat = new Seat(circle, "box"); |
| 333 | seat.attr['name'] = "Seat "+(seats.length+1); |
| 334 | seats.push(seat); |
| 335 | circle.attr("fill", "#f00000"); |
| 336 | circle.attr("stroke", "#fff"); |
| 337 | circle.attr("name", "Seat "+seats.length); |
| 338 | |
| 339 | // allow the circle to be dragged |
| 340 | circle.drag((dx,dy,x,y,elem)=>{ // onmove |
| 341 | circle.attr("cx", dx+drag_start_x); |
| 342 | circle.attr("cy", dy+drag_start_y); |
| 343 | }, (x,y,elem)=>{ // onstart |
| 344 | circle.attr("opacity", 0.7); |
| 345 | }, (x,y,elem)=>{ // onend |
| 346 | drag_start_x = circle.attr("cx"); |
| 347 | drag_start_y = circle.attr("cy"); |
| 348 | circle.attr("opacity", 1); |
| 349 | }); |
| 350 | _setInfo("Seat added"); |
| 351 | |
| 352 | circle.dblclick(()=>{ |
| 353 | _setInfo("Seat selected"); |
| 354 | CONTROL_PANEL.html(""); |
| 355 | |
| 356 | let seat = seats.find(s=>s.svgObject==circle); |
| 357 | |
| 358 | let seat_id = seats.indexOf(seat); |
| 359 | let seat_name = $('<input type="text" placeholder="Give seat name/number">').appendTo(CONTROL_PANEL); |
| 360 | let seat_color = $('<input type="color">').appendTo(CONTROL_PANEL); |
| 361 | seat_color.val(seat.svgObject.attr("fill")); |
| 362 | let seat_save = $('<button>').text("Save").appendTo(CONTROL_PANEL); |
| 363 | seat_save.on("click", e=>{ |
| 364 | console.log("save"); |
| 365 | seat.attr["name"] = seat_name.val(); |
| 366 | let c = seat_color.val(); |
| 367 | seat.svgObject.attr("fill", c); |
| 368 | seat.svgObject.attr("stroke", c == '#ffffff' ? '#000' : '#fff'); |
| 369 | _setInfo("Seat saved"); |
| 370 | listAllObjects(); |
| 371 | }); |
| 372 | let seat_delete = $('<button>').text("Delete").appendTo(CONTROL_PANEL); |
| 373 | seat_delete.on("click", e=>{ |
| 374 | if (confirm("Delete seat?")) { |
| 375 | seats.splice(seat_id, 1); |
| 376 | seat.svgObject.remove(); |
| 377 | _setInfo("Seat deleted"); |
| 378 | listAllObjects(); |
| 379 | } |
| 380 | }); |
| 381 | seat_name.val(seat.attr['name'] ? seat.attr['name'] : ''); |
| 382 | seat_color.val(circle.attr("fill")); |
| 383 | }); |
| 384 | |
| 385 | /* |
| 386 | circle.dblclick(()=>{ |
| 387 | console.log("double clicked"); |
| 388 | console.log(seats); |
| 389 | }); |
| 390 | */ |
| 391 | |
| 392 | circle.node.click(); |
| 393 | |
| 394 | }).addClass("button-primary").appendTo(btn_grp_2); |
| 395 | } |
| 396 | |
| 397 | function start() { |
| 398 | init(displaySeatingPlan); |
| 399 | } |
| 400 | |
| 401 | start(); |
| 402 | } |