window.addEventListener("load", function () { init(); document.querySelector(".test img").onload = imgLoadHandler; initApplication(); } ) var lastRadius = 20; var lastRadiusX = 40, lastRadiusY = 20; var lastWidth = 50, lastHeight = 40; var shapeType = "ellipse"; var actShape = null; var actBgColor = "blue"; function setShapeType(typ) { shapeType = typ; } function init() { svg = Snap("#hotspots"); //podkladovy obrazek - klikani var img = document.querySelector(".test svg"); img.onclick = bgClicker; detachEdits(); window.addEventListener("keydown", hsKeyHandler); } function hsStart() { var type = this.node.nodeName; if (type == "ellipse") { this.ox = parseInt(this.attr("cx")); this.oy = parseInt(this.attr("cy")); } if (type == "rect") { this.ox = parseInt(this.attr("x")); this.oy = parseInt(this.attr("y")); } } function hsMove(dx, dy) { var type = this.node.nodeName; if (type == "ellipse") { this.attr({"cx": this.ox + dx, "cy": this.oy + dy}); } if (type == "rect") { this.attr({"x": this.ox + dx, "y": this.oy + dy}); } attachEdits(this.node); } var eb = { "s": 0, "n": 0, "e": 0, "w": 0 } function editStart() { this.ox = parseInt(this.attr("x")); this.oy = parseInt(this.attr("y")); } function editMoveNE(dx, dy) { this.attr({"x": this.ox + dx, "y": this.oy + dy}); eb.n = this.oy + dy +5; eb.e = this.ox + dx +5; updateEdits(); updateActShape(); } function editMoveNW(dx, dy) { this.attr({"x": this.ox + dx, "y": this.oy + dy}); eb.n = this.oy + dy +5; eb.w = this.ox + dx +5; updateEdits(); updateActShape(); } function editMoveN(dx, dy) { this.attr({"y": this.oy + dy}); eb.n = this.oy + dy +5; updateEdits(); updateActShape(); } function editMoveS(dx, dy) { this.attr({"y": this.oy + dy}); eb.s = this.oy + dy +5; updateEdits(); updateActShape(); } function editMoveE(dx, dy) { this.attr({"x": this.ox + dx}); eb.e = this.ox + dx +5; updateEdits(); updateActShape(); } function editMoveW(dx, dy) { this.attr({"x": this.ox + dx}); eb.w = this.ox + dx +5; updateEdits(); updateActShape(); } function editMoveSE(dx, dy) { this.attr({"x": this.ox + dx, "y": this.oy + dy}); eb.s = this.oy + dy +5; eb.e = this.ox + dx +5; updateEdits(); updateActShape(); } function editMoveSW(dx, dy) { this.attr({"x": this.ox + dx, "y": this.oy + dy}); eb.s = this.oy + dy +5; eb.w = this.ox + dx +5; updateEdits(); updateActShape(); } function addHotspot(cx, cy) { var hss= Snap("#hotspots") var newHS = null; if (shapeType == "ellipse") { newHS = hss.ellipse(cx, cy, lastRadiusX, lastRadiusY); } if (shapeType == "rect") { newHS = hss.rect(cx - lastWidth/2, cy - lastHeight/2, lastWidth, lastHeight); } newHS.addClass("hotspot"); newHS.drag(hsMove, hsStart); newHS.node.setAttribute("data-correct", "no") if( (/Firefox/i.test(navigator.userAgent)) ) { newHS.node.addEventListener("DOMMouseScroll", mouseWheelHandler, false); } else { newHS.node.addEventListener("mousewheel", mouseWheelHandler, false); } newHS.node.addEventListener("dblclick", hsDblClicker); newHS.node.addEventListener("click", hsClicker); newHS.node.style.fill = actBgColor; actShape = newHS.node; attachEdits(actShape); } function updateActShape() { if (!actShape) { return; } var box = Snap("#edits").getBBox(); var sx = Math.floor((eb.e + eb.w)/2) var sy = Math.floor((eb.s + eb.n)/2); var radiusX = Math.floor((eb.e - eb.w)/2); var radiusY = Math.floor((eb.s - eb.n)/2); if (actShape.nodeName == "ellipse") { actShape.setAttribute("cx", sx); actShape.setAttribute("cy", sy); actShape.setAttribute("ry", radiusY); actShape.setAttribute("rx", radiusX); lastRadiusX = radiusX; lastRadiusY = radiusY; } if (actShape.nodeName == "rect") { actShape.setAttribute("x", eb.w); actShape.setAttribute("y", eb.n); actShape.setAttribute("width", eb.e-eb.w); actShape.setAttribute("height", eb.s-eb.n); lastHeight = eb.s-eb.n; lastWidth = eb.e-eb.w; } } function deleteActShape() { if (actShape) { actShape.parentNode.removeChild(actShape); actShape = null; detachEdits(); } } function deleteAllShapes() { if (!confirm("Opravdu smazat všechny aktivní oblasti?")) return; var spots = document.querySelectorAll("#img_placeholder .hotspot"); for (var i = 0; i < spots.length; i++) { spots[i].parentNode.removeChild(spots[i]) } actShape = null; detachEdits(); } function setHsBackground(color) { actBgColor = color; var spots = document.querySelectorAll("#img_placeholder .hotspot"); for (var i = 0; i < spots.length; i++) { var spot = spots[i]; if (spot.getAttribute("data-correct") != "yes") { spot.style.fill = color; } } } function updateEdits() { var edit_nw = document.getElementById("edit-nw");//Snap("#edit-nw"); var edit_ne = Snap("#edit-ne"); var edit_n = Snap("#edit-n"); var edit_s = Snap("#edit-s"); var edit_w = Snap("#edit-w"); var edit_e = Snap("#edit-e"); var edit_sw = Snap("#edit-sw"); var edit_se = Snap("#edit-se"); var rect = Snap("#edit-border"); rect.attr({"x": eb.w, "y": eb.n, "width": eb.e - eb.w, "height": - eb.n + eb.s}); edit_nw.setAttribute("x", eb.w-5); edit_nw.setAttribute("y", eb.n-5); //edit_nw.attr({"x": eb.w-5, "y": eb.n -5}); edit_ne.attr({"x": eb.e -5, "y": eb.n-5}); edit_sw.attr({"x": eb.w-5, "y": eb.s-5}); edit_se.attr({"x": eb.e-5, "y": eb.s-5}); edit_n.attr({"x": (eb.w +eb.e)/2 -5, "y": eb.n-5}); edit_s.attr({"x": (eb.w +eb.e)/2 -5, "y": eb.s-5}); edit_w.attr({"x": eb.w -5, "y": (eb.n+eb.s)/2-5}); edit_e.attr({"x": eb.e-5, "y": (eb.n+eb.s)/2-5}); } function attachEdits(shape) { var edits = document.getElementById("edits"); edits.style.visibility = "visible"; var sx = 0, sy = 0; if (shape.nodeName == "ellipse") { sx = parseInt(shape.getAttribute("cx") ); sy = parseInt(shape.getAttribute("cy") ); var rx = parseInt(shape.getAttribute("rx") ); var ry = parseInt(shape.getAttribute("ry") ); eb.n = sy -ry; eb.s = sy + ry; eb.w = sx - rx; eb.e = sx + rx; console.log("N: " + eb.n) } if (shape.nodeName == "rect") { sx = parseInt(shape.getAttribute("x") ); sy = parseInt(shape.getAttribute("y") ); var rw = parseInt(shape.getAttribute("width") ); var rh = parseInt(shape.getAttribute("height") ); eb.n = sy; eb.s = sy + rh; eb.w = sx; eb.e = sx + rw; } updateEdits(); } function detachEdits() { actShape = null; document.getElementById("edits").style.visibility = "hidden"; } function bgClicker(evt) { var tgt = evt.target var box = tgt.getBoundingClientRect(); var cx = Math.round(evt.clientX - box.left) var cy = Math.round(evt.clientY - box.top) if (evt.ctrlKey) { // klik na pozadi + CTRL = pridani noveho krouzku addHotspot(cx, cy) } else { // detachEdits(); } } function hsClicker(evt) { evt.preventDefault(); evt.stopPropagation(); var tgt = evt.target console.log( "Klik " + evt.target.nodeName ); //evt.target.style.stroke = "red" //evt.target.style.strokeWidth = "3px" if (evt.altKey) { tgt.parentNode.removeChild(tgt); actShape = null; detachEdits(); } else { attachEdits(tgt); actShape = tgt; } } function hsDblClicker(evt) { var tgt = evt.target; if (tgt.getAttribute("data-correct") == "yes") { tgt.style.fill = actBgColor; tgt.style.stroke = "darkblue"; tgt.setAttribute("data-correct", "no") } else { tgt.style.fill = "green"; tgt.style.stroke = "green"; tgt.setAttribute("data-correct", "yes") } } function mouseWheelHandler (evt) { evt.preventDefault(); var type = evt.target.nodeName; var delta = Math.max(-1, Math.min(1, (evt.wheelDelta || -evt.detail))); //console.log( delta ); var shape = evt.currentTarget; var rx = 0, ry = 0; var koef = (evt.ctrlKey) ? 5 : 1 if (type == "ellipse") { rx = parseFloat(shape.getAttribute("rx")); ry = parseFloat(shape.getAttribute("ry")); var ratio = ry/rx; lastRadiusX = rx + delta*koef lastRadiusY = ry + delta*koef*ratio; lastRadiusX = Math.max(lastRadiusX, 10); lastRadiusY = Math.max(lastRadiusY, 10); shape.setAttribute("rx", lastRadiusX) shape.setAttribute("ry", lastRadiusY) } if (type == "rect") { rx = parseFloat(shape.getAttribute("x")); ry = parseFloat(shape.getAttribute("y")); rw = parseFloat(shape.getAttribute("width")); rh = parseFloat(shape.getAttribute("height")); var ratio = rh/rw; lastWidth = rw + delta*koef lastHeight = rh + delta*koef*ratio; lastWidth = Math.max(lastWidth, 10); lastHeight = Math.max(lastHeight, 10); shape.setAttribute("x", rx - delta*koef/2 ) shape.setAttribute("y", ry - delta*koef*ratio/2) shape.setAttribute("width", lastWidth) shape.setAttribute("height", lastHeight) } actShape = evt.target; attachEdits(actShape); } function hsKeyHandler(evt) { // var normal = 1, speedy = 10; if (!actShape) { return; } evt.preventDefault(); console.log("klavesa " + evt.keyCode ); var tgt = evt.target var cx = parseInt(actShape.getAttribute("cx")); var cy = parseInt(actShape.getAttribute("cy")); if (evt.keyCode == 37) { if (evt.shiftKey) { cx += - speedy } else { cx += -normal } } if (evt.keyCode == 38) { if (evt.shiftKey) { cy += - speedy } else { cy += - normal } } if (evt.keyCode == 40) { if (evt.shiftKey) { cy += speedy } else { cy += normal } } if (evt.keyCode == 39) { if (evt.shiftKey) { cx += speedy } else { cx += normal } } actShape.setAttribute("cx", cx); actShape.setAttribute("cy", cy); attachEdits(actShape); } var SVGHotspots = { getPreview: function () { var result = { content: "" } var figure = document.querySelector("#img_placeholder").cloneNode(true); var edits = figure.querySelector("#edits"); edits.parentNode.removeChild(edits); var content = document.querySelector("#preview_content .content"); content.innerHTML = ""; content.appendChild(figure); var checks = content.appendChild(document.createElement("div")) checks.className = "checks" var spots = figure.querySelectorAll(".hotspot"); for (var i = 0; i < spots.length; i++) { var spot = spots[i]; spot.setAttribute("data-index", i); spot.setAttribute("title", "Označit prvek"); spot.setAttribute("data-state", "free"); spot.addEventListener("click", hsPreviewClicker); spot.style.fill = document.getElementById("shape-color").value; var span = checks.appendChild(document.createElement("span")) span.setAttribute("data-index", i); var input = span.appendChild(document.createElement("input")); input.type = "checkbox"; } //result.content = content; }, getCode: function () { if (!document.querySelector("#img_placeholder [data-correct='yes']")) { return { content: "Otázka musí obsahovat alespoň jednu správnou variantu.", ok: "" } } var result = { content: "", ok: "" }; var output = ""; var spots = document.querySelectorAll("#qArea .hotspot") var spans = document.querySelectorAll(".checks span"); var spravne = ""; var checks = "
"; var bgImg = document.querySelector("#bg_test"); //("#img_placeholder img"); output += "
\n" output += "Podkladový obrázek\n"; var svgClass = ""; var hsStyle = "\n"; var hsColor = document.getElementById("shape-color").value.substring(1).toLowerCase(); if (hsColor != "0000ff") { hsStyle = hsStyle.replace( /color/g, hsColor); svgClass = " c" + hsColor; } else { hsStyle = ""; } output += "\n"; output += hsStyle; for (var i = 0; i < spots.length; i++) { var spot = spots[i]; var sname = spot.nodeName; var dx = 0, dy = 0; if (spot.hasAttribute("transform")) { var val = spot.getAttribute("transform"); val = val.substring(val.indexOf("(")+1, val.indexOf(")")); var vals = val.split(","); dx = parseInt(vals[4]); dy = parseInt(vals[5]); } if (sname == "circle") { var cx = parseInt(spot.getAttribute("cx")) + dx; var cy = parseInt(spot.getAttribute("cy")) + dy; var radius = parseInt(spot.getAttribute("r")); output += "\n" } if (sname == "ellipse") { var cx = parseInt(spot.getAttribute("cx")) + dx; var cy = parseInt(spot.getAttribute("cy")) + dy; var rx = parseInt(spot.getAttribute("rx")); var ry = parseInt(spot.getAttribute("ry")); output += "\n" } if (sname == "rect") { var cx = parseInt(spot.getAttribute("x")) + dx; var cy = parseInt(spot.getAttribute("y")) + dy; var rw = parseInt(spot.getAttribute("width")); var rh = parseInt(spot.getAttribute("height")); output += "\n" } var cor = spot.getAttribute("data-correct"); if (cor == "yes") { result.ok += ":c" + (i + 1) + "a ok\n" } checks += " :c" + (i+1) + "a " } output += "\n" output += "
\n" output += checks + "
\n" result.content = output; return result; } } function hsPreviewClicker(evt) { var tgt = evt.target; var state = tgt.getAttribute("data-state"); var content = tgt.parentNode; while ((content.nodeName != "DIV" && content.className != "content")) { content = content.parentNode; } var cid = tgt.getAttribute("data-index"); var input = content.querySelector(".checks [data-index='" + cid + "'] input"); if (state == "free") { tgt.setAttribute("data-state", "checked") input.checked = true; tgt.style.strokeWidth = "5px"; } else { tgt.setAttribute("data-state", "free") input.checked = false; tgt.style.strokeWidth = "0"; } console.log( evt.target.style.fill ); //evt.target.style.stroke = "red" //evt.target.style.strokeWidth = "3px" }