refactor
parent
d2fc40b9e4
commit
0e35cdaa04
|
@ -246,7 +246,7 @@ html, body {
|
|||
z-index: 2;
|
||||
}
|
||||
|
||||
#tools_top {
|
||||
#panels {
|
||||
position: absolute;
|
||||
width: 160px;
|
||||
height: 100%;
|
||||
|
@ -258,7 +258,7 @@ html, body {
|
|||
padding: 0 0 0 15px;
|
||||
}
|
||||
|
||||
.touch #tools_top {
|
||||
.touch #panels {
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
|
@ -299,15 +299,15 @@ div#font-selector .font-item:hover {
|
|||
background-color: #eee;
|
||||
}
|
||||
|
||||
#tools_top #marker_panel * {
|
||||
#panels #marker_panel * {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#tools_top #marker_panel h4 {
|
||||
#panels #marker_panel h4 {
|
||||
float: none;
|
||||
}
|
||||
|
||||
#tools_top #marker_panel .dropdown .icon_label {
|
||||
#panels #marker_panel .dropdown .icon_label {
|
||||
width: 36px;
|
||||
height: 20px;
|
||||
margin-top: 2px;
|
||||
|
@ -315,17 +315,17 @@ div#font-selector .font-item:hover {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
#tools_top #marker_panel .dropdown button {
|
||||
#panels #marker_panel .dropdown button {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
#tools_top #marker_panel #marker_panel_title {
|
||||
#panels #marker_panel #marker_panel_title {
|
||||
float: none;
|
||||
color: #fff;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
#tools_top #marker_panel .dropdown .icon_label img {
|
||||
#panels #marker_panel .dropdown .icon_label img {
|
||||
float: none;
|
||||
}
|
||||
|
||||
|
@ -536,27 +536,27 @@ box-shadow: inset 0 3px 10px rgba(255, 255, 255, 0.1),
|
|||
}
|
||||
|
||||
|
||||
#tools_top h4 {
|
||||
#panels h4 {
|
||||
color: #fff;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 10px 0 5px 0;
|
||||
}
|
||||
|
||||
#tools_top .dropdown .icon_label {
|
||||
#panels .dropdown .icon_label {
|
||||
border: 1px solid transparent;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#tools_top.multiselected #align_tools {
|
||||
#panels.multiselected #align_tools {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#tools_top.multiselected #multiselected_panel {
|
||||
#panels.multiselected #multiselected_panel {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
#tools_top.multiselected #multiselected_panel .hidable {
|
||||
#panels.multiselected #multiselected_panel .hidable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,21 +118,25 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tools_top" class="tools_panel">
|
||||
<div id="panels" class="tools_panel">
|
||||
|
||||
<div id="canvas_panel" class="context_panel">
|
||||
|
||||
<h4 class="clearfix">Canvas</h4>
|
||||
|
||||
<label data-title="Change canvas width">
|
||||
<input size="3" id="canvas_width" type="text" pattern="[0-9]*" />
|
||||
<span class="icon_label">Width</span>
|
||||
</label>
|
||||
<label data-title="Change canvas height">
|
||||
<input id="canvas_height" size="3" type="text" pattern="[0-9]*" />
|
||||
<span class="icon_label">Height</span>
|
||||
</label>
|
||||
|
||||
|
||||
<div class="draginput">
|
||||
<label data-title="Change canvas width">
|
||||
<input size="3" id="canvas_width" type="text" pattern="[0-9]*" value="800" />
|
||||
<span class="icon_label">Width</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="draginput">
|
||||
<label data-title="Change canvas height">
|
||||
<input id="canvas_height" size="3" type="text" pattern="[0-9]*" value="600" />
|
||||
<span class="icon_label">Height</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label data-title="Change canvas color" class="draginput">
|
||||
<span>Color</span>
|
||||
|
@ -514,31 +518,31 @@
|
|||
|
||||
|
||||
<div id="tools_left" class="tools_panel">
|
||||
<div class="tool_button" id="tool_select" title="Select Tool [V]">
|
||||
<div class="tool_button" id="tool_select" data-mode="select" title="Select Tool [V]">
|
||||
<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path d="M17.15 20.76l-2.94 1.5-3.68-6-4.41 3V1.24l12.5 12.01-4.41 1.5 2.94 6z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="tool_button" id="tool_fhpath" title="Pencil Tool [P]">
|
||||
<div class="tool_button" id="tool_fhpath" data-mode="fhpath" title="Pencil Tool [P]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" style="transform: scale(-1,1)"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" /></svg>
|
||||
</div>
|
||||
<div class="tool_button" id="tool_line" title="Line Tool [L]">
|
||||
<div class="tool_button" id="tool_line" data-mode="line" title="Line Tool [L]">
|
||||
<svg viewBox="0 0 27 27" xmlns="http://www.w3.org/2000/svg" width="24" height="24" >
|
||||
<path d="M 3 1 L 26 24 L 24 26 L 1 3 L 3 1 Z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="tool_button" id="tool_rect" title="Square/Rect Tool [R]">
|
||||
<div class="tool_button" id="tool_rect" data-mode="rect" title="Square/Rect Tool [R]">
|
||||
<svg viewBox="0 0 27 27" xmlns="http://www.w3.org/2000/svg" width="24" height="24">
|
||||
<path d="M 0 8 L 0 24 L 24 24 L 25 8 L 0 8 Z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="tool_button" id="tool_ellipse" title="Ellipse/Circle Tool [C]">
|
||||
<div class="tool_button" id="tool_ellipse" data-mode="ellipse" title="Ellipse/Circle Tool [C]">
|
||||
<svg viewBox="0 0 27 27" xmlns="http://www.w3.org/2000/svg" width="24" height="24">
|
||||
<ellipse cx="13" cy="13" rx="13" ry="9"></ellipse>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="tool_button" title="Shape Tool [C]" id="tool_shapelib">
|
||||
<div class="tool_button" id="tool_shapelib" data-mode="shapelib" title="Shape Tool [C]" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="27" width="27" viewBox="0 0 24 24" >
|
||||
<polygon points="14.43,10 12,2 9.57,10 2,10 8.18,14.41 5.83,22 12,17.31 18.18,22 15.83,14.41 22,10"/>
|
||||
</svg>
|
||||
|
@ -547,20 +551,20 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tool_button" id="tool_path" title="Path Tool [P]">
|
||||
<div class="tool_button" id="tool_path" data-mode="path" title="Path Tool [P]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" width="27" height="27">
|
||||
<path d="M12.2 1.9c0-.36.86 0 .86 0V14a1.3 1.3 0 10.88 0V1.9s.87-.36.87 0c0 6.81 5.22 11.68 5.22 11.68l-3.25 8.2h-6.55l-3.26-8.2s5.22-4.87 5.22-11.68zM7.83 25.26v-2.61h11.32v2.6H7.84z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="tool_button" id="tool_text" title="Text Tool [T]">
|
||||
<div class="tool_button" id="tool_text" data-mode="text" title="Text Tool [T]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="2 2 20 20" width="27" height="27"><path d="M5 4v3h5.5v12h3V7H19V4z"/></svg>
|
||||
</div>
|
||||
|
||||
<div class="tool_button" id="tool_zoom" title="Zoom Tool [Z]">
|
||||
<div class="tool_button" id="tool_zoom" data-mode="zoom" title="Zoom Tool [Z]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="2 2 20 20" width="27"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
|
||||
</div>
|
||||
|
||||
<div class="tool_button" id="tool_eyedropper" title="Eyedropper Tool [Z]">
|
||||
<div class="tool_button" id="tool_eyedropper" data-mode="eyedropper" title="Eyedropper Tool [Z]">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="2 2 20 20" width="27" style="transform: scale(-1, 1)"><path d="M20.71 5.63l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-3.12 3.12-1.93-1.91-1.41 1.41 1.42 1.42L3 16.25V21h4.75l8.92-8.92 1.42 1.42 1.41-1.41-1.92-1.92 3.12-3.12c.4-.4.4-1.03.01-1.42zM6.92 19L5 17.08l8.06-8.06 1.92 1.92L6.92 19z"/></svg>
|
||||
</div>
|
||||
|
||||
|
@ -663,30 +667,43 @@
|
|||
<div id="shape_buttons"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- build:js all.js -->
|
||||
<script type="text/javascript" src="js/lib/jquery-3.5.1.min.js"></script>
|
||||
<script type="text/javascript" src="js/lib/pathseg.js"></script>
|
||||
<script type="text/javascript" src="js/lib/touch.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery.hotkeys.min.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery.jgraduate.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery.contextMenu.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery-ui-1.8.17.custom.min.js"></script>
|
||||
<script type="text/javascript" src="js/fonts.js"></script>
|
||||
<script type="text/javascript" src="js/browser.js"></script>
|
||||
<script type="text/javascript" src="js/svgtransformlist.js"></script>
|
||||
<script type="text/javascript" src="js/math.js"></script>
|
||||
<script type="text/javascript" src="js/units.js"></script>
|
||||
<script type="text/javascript" src="js/svgutils.js"></script>
|
||||
<script type="text/javascript" src="js/jquery.attr.js"></script>
|
||||
<script type="text/javascript" src="js/utils.js"></script>
|
||||
<script type="text/javascript" src="js/dao.js"></script>
|
||||
<script type="text/javascript" src="js/state.js"></script>
|
||||
<script type="text/javascript" src="js/sanitize.js"></script>
|
||||
<script type="text/javascript" src="js/browser.js"></script>
|
||||
<script type="text/javascript" src="js/svgutils.js"></script>
|
||||
<script type="text/javascript" src="js/history.js"></script>
|
||||
<script type="text/javascript" src="js/select.js"></script>
|
||||
<script type="text/javascript" src="js/draw.js"></script>
|
||||
<script type="text/javascript" src="js/path.js"></script>
|
||||
<script type="text/javascript" src="js/dialog.js"></script>
|
||||
<script type="text/javascript" src="js/sanitize.js"></script>
|
||||
<script type="text/javascript" src="js/units.js"></script>
|
||||
<script type="text/javascript" src="js/math.js"></script>
|
||||
<script type="text/javascript" src="js/translate.js"></script>
|
||||
<script type="text/javascript" src="js/svgtransformlist.js"></script>
|
||||
<script type="text/javascript" src="js/draw.js"></script>
|
||||
<script type="text/javascript" src="js/svgcanvas.js"></script>
|
||||
<script type="text/javascript" src="js/rulers.js"></script>
|
||||
<script type="text/javascript" src="js/method-draw.js"></script>
|
||||
<script type="text/javascript" src="js/editor.js"></script>
|
||||
<script type="text/javascript" src="js/Rulers.js"></script>
|
||||
<script type="text/javascript" src="js/Toolbar.js"></script>
|
||||
<script type="text/javascript" src="js/Menu.js"></script>
|
||||
<script type="text/javascript" src="js/start.js"></script>
|
||||
<script type="text/javascript" src="js/fonts.js"></script>
|
||||
<script type="text/javascript" src="js/dialog.js"></script>
|
||||
<script type="text/javascript" src="js/contextChanged.js"></script>
|
||||
<script type="text/javascript" src="js/zoomChanged.js"></script>
|
||||
<script type="text/javascript" src="js/exportHandler.js"></script>
|
||||
<script type="text/javascript" src="js/elementChanged.js"></script>
|
||||
<script type="text/javascript" src="js/elementTransition.js"></script>
|
||||
<script type="text/javascript" src="js/bindCanvas.js"></script>
|
||||
<script type="text/javascript" src="js/palette.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery-draginput.js"></script>
|
||||
<script type="text/javascript" src="js/lib/contextmenu.js"></script>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
MD.Menu = function(){
|
||||
// top dropdown menus
|
||||
$('.menu_title')
|
||||
.on('mousedown', function() {
|
||||
$("#tools_shapelib").hide()
|
||||
$("#menu_bar").toggleClass('active');
|
||||
$('.menu').removeClass('open');
|
||||
$(this).parent().addClass('open');
|
||||
})
|
||||
.on('mouseover', function() {
|
||||
$('.menu').removeClass('open');
|
||||
$(this).parent().addClass('open');
|
||||
});
|
||||
|
||||
function blink(e) {
|
||||
e.target.style.background = "#fff";
|
||||
setTimeout(function(){e.target.style.background = "#ddd";}, 50);
|
||||
setTimeout(function(){e.target.style.background = "#fff";}, 150);
|
||||
setTimeout(function(){e.target.style.background = "#ddd";}, 200);
|
||||
setTimeout(function(){e.target.style.background = "";}, 200);
|
||||
setTimeout(function(){$('#menu_bar').removeClass('active')}, 250);
|
||||
return false;
|
||||
}
|
||||
|
||||
function close(e){
|
||||
if (e.target.nodeName && e.target.nodeName.toLowerCase() === "input") return false;
|
||||
if (!$(e.target).hasClass("menu_title") && !$(e.target).parent().hasClass("menu_title")) {
|
||||
if(!$(e.target).hasClass("disabled") && $(e.target).hasClass("menu_item")) blinker(e)
|
||||
else $('#menu_bar').removeClass('active')
|
||||
}
|
||||
}
|
||||
|
||||
function flash($menu){
|
||||
var menu_title = $menu.prev();
|
||||
menu_title.css({
|
||||
"background": "white",
|
||||
"color": "black"
|
||||
});
|
||||
setTimeout(function(){menu_title.removeAttr("style")}, 200);
|
||||
}
|
||||
|
||||
$('.menu_item').on('click', blink);
|
||||
$("body").on('mousedown', close);
|
||||
|
||||
this.flash = flash;
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
MD.Toolbar = function(){
|
||||
|
||||
// tools left
|
||||
$("#tools_left .tool_button").on("click", function(){
|
||||
const mode = this.getAttribute("data-mode");
|
||||
state.set("canvasMode", mode)
|
||||
setMode(mode);
|
||||
});
|
||||
|
||||
function setMode(mode) {
|
||||
$(".tool_button").removeClass("current");
|
||||
$("#tool_" + mode).addClass("current");
|
||||
svgCanvas.setMode(mode);
|
||||
}
|
||||
|
||||
this.setMode = setMode;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// bind the selected event to our function that handles updates to the UI
|
||||
svgCanvas.bind("selected", editor.selectedChanged);
|
||||
svgCanvas.bind("transition", elementTransition);
|
||||
//svgCanvas.bind("changed", elementChanged);
|
||||
svgCanvas.bind("exported", exportHandler);
|
||||
svgCanvas.bind("zoomed", zoomChanged);
|
||||
svgCanvas.bind("contextset", contextChanged);
|
||||
svgCanvas.textActions.setInputElem($("#text")[0]);
|
|
@ -0,0 +1,25 @@
|
|||
var contextChanged = function(win, context) {
|
||||
|
||||
var link_str = '';
|
||||
if(context) {
|
||||
var str = '';
|
||||
link_str = '<a href="#" data-root="y">' + svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>';
|
||||
|
||||
$(context).parentsUntil('#svgcontent > g').addBack().each(function() {
|
||||
if(this.id) {
|
||||
str += ' > ' + this.id;
|
||||
if(this !== context) {
|
||||
link_str += ' > <a href="#">' + this.id + '</a>';
|
||||
} else {
|
||||
link_str += ' > ' + this.id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cur_context = str;
|
||||
} else {
|
||||
cur_context = null;
|
||||
}
|
||||
$('#cur_context_panel').toggle(!!context).html(link_str);
|
||||
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
const dao = [
|
||||
|
||||
// public, appears in builder
|
||||
|
||||
{
|
||||
name: "canvasId",
|
||||
label: "Canvas ID",
|
||||
type: "id",
|
||||
default: "",
|
||||
private: false,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasTitle",
|
||||
label: "Canvas Title",
|
||||
type: "string",
|
||||
default: "",
|
||||
private: false,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasSize",
|
||||
label: "Canvas Size",
|
||||
type: "array",
|
||||
default: [800, 600],
|
||||
private: false,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasRulers",
|
||||
label: "Canvas Rulers",
|
||||
type: "boolean",
|
||||
default: true,
|
||||
private: false,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasContent",
|
||||
label: "Canvas Content",
|
||||
type: "string",
|
||||
default: "<svg xmlns='http://www.w3.org/2000/svg' width='800' height='600' viewBox='0 0 800 600'></svg>",
|
||||
private: true,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasMode",
|
||||
label: "Canvas Mode",
|
||||
type: "string",
|
||||
default: "select",
|
||||
private: true,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasFill",
|
||||
label: "Canvas Fill",
|
||||
type: "object",
|
||||
default: {color: 'fff', opacity: 1},
|
||||
private: true,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasStroke",
|
||||
label: "Canvas Stroke",
|
||||
type: "object",
|
||||
default: {width: 1.5, color: '000', opacity: 1},
|
||||
private: true,
|
||||
save: true
|
||||
},
|
||||
|
||||
{
|
||||
name: "canvasCreationDate",
|
||||
label: "Canvas Creation Date",
|
||||
type: "string",
|
||||
default: new Date().toString(),
|
||||
private: true,
|
||||
save: false
|
||||
},
|
||||
// When this page was created
|
||||
{
|
||||
name: "canvasLastModified",
|
||||
label: "Canvas Last Modified",
|
||||
type: "string",
|
||||
default: new Date().toString(),
|
||||
private: true,
|
||||
save: false
|
||||
},
|
||||
|
||||
// system level fields
|
||||
{
|
||||
name: "darkmode",
|
||||
label: "Dark Mode",
|
||||
type: "boolean",
|
||||
default: true,
|
||||
private: true,
|
||||
save: true,
|
||||
},
|
||||
// english or spanish, set by the browser
|
||||
{
|
||||
name: "language",
|
||||
label: "Language",
|
||||
type: "string",
|
||||
default: null,
|
||||
private: true,
|
||||
save: true,
|
||||
},
|
||||
// if it is the first time visitor we onboard them
|
||||
{
|
||||
name: "visited",
|
||||
label: "Has visited before",
|
||||
type: "boolean",
|
||||
default: false,
|
||||
private: true,
|
||||
save: true,
|
||||
},
|
||||
|
||||
// how many seconds have passed since the user moved the mouse
|
||||
// mostly for hiding UI, but we could also use it for exercises
|
||||
// where we want to force keyboard usage to edit, for example
|
||||
{
|
||||
name: "mouseIdle",
|
||||
label: "Mouse Idle",
|
||||
type: "number",
|
||||
default: false,
|
||||
private: true,
|
||||
save: false,
|
||||
},
|
||||
];
|
||||
|
||||
dao.forEach(thing => {
|
||||
thing.clean = function(value){
|
||||
if (thing.type === "number") return isNaN(value) ? 0 : parseInt(value, 10);
|
||||
if (thing.type === "string") return value || "";
|
||||
if (thing.type === "boolean") return value === "true" || value === true ? true : false;
|
||||
if (thing.type === "url") return value || "";
|
||||
if (thing.type === "id") return value || 0;
|
||||
if (thing.type === "array") return typeof value === "object" ? value : value ? value.split(",") : [];
|
||||
if (thing.type === "object") return typeof value === "object" ? value : value ? JSON.parse(value) : {};
|
||||
else throw "type " + thing.type + " does not exist";
|
||||
}
|
||||
});
|
|
@ -0,0 +1,264 @@
|
|||
const MD = {};
|
||||
|
||||
MD.Editor = function(){
|
||||
|
||||
// called when we've selected a different element
|
||||
function selectedChanged(window,elems) {
|
||||
const mode = svgCanvas.getMode();
|
||||
if(mode === "select") editor.toolbar.setMode("select");
|
||||
if (mode === "pathedit") return updateContextPanel();
|
||||
elems = elems.filter(Boolean);
|
||||
$('.context_panel').hide();
|
||||
$('#panels').toggleClass("multiselected", elems.length > 1);
|
||||
$('#multiselected_panel').toggle(elems.length > 1);
|
||||
$('#canvas_panel').toggle(!elems.length);
|
||||
// multiselected, nothing else needs to be done
|
||||
if (elems.length > 1) return;
|
||||
|
||||
const selectedElement = elems[0];
|
||||
const tagName = selectedElement.tagName;
|
||||
$("#" + tagName + "_panel").show();
|
||||
$('#stroke_width').val(selectedElement.getAttribute("stroke-width") || 0);
|
||||
var dash = selectedElement.getAttribute("stroke-dasharray") || "none"
|
||||
$('option', '#stroke_style').removeAttr('selected');
|
||||
$('#stroke_style option[value="'+ dash +'"]').attr("selected", "selected");
|
||||
$('#stroke_style').trigger('change');
|
||||
|
||||
$.fn.dragInput.updateCursor($('#stroke_width')[0])
|
||||
$.fn.dragInput.updateCursor($('#blur')[0])
|
||||
|
||||
updateContextPanel(elems);
|
||||
};
|
||||
|
||||
function updateContextPanel(elems) {
|
||||
var elem = elems[0];
|
||||
// If element has just been deleted, consider it null
|
||||
if(elem != null && !elem.parentNode) elem = null;
|
||||
const multiselected = elems.length > 1;
|
||||
|
||||
var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName();
|
||||
var currentMode = svgCanvas.getMode();
|
||||
var unit = 'px';
|
||||
var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
|
||||
|
||||
if (is_node) {
|
||||
$('.context_panel').hide();
|
||||
$('#path_node_panel').show();
|
||||
$('#stroke_panel').hide();
|
||||
var point = path.getNodePoint();
|
||||
$('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button');
|
||||
$('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes);
|
||||
|
||||
if(point) {
|
||||
var seg_type = $('#seg_type');
|
||||
if(unit) {
|
||||
point.x = svgedit.units.convertUnit(point.x);
|
||||
point.y = svgedit.units.convertUnit(point.y);
|
||||
}
|
||||
$('#path_node_x').val(Math.round(point.x));
|
||||
$('#path_node_y').val(Math.round(point.y));
|
||||
if(point.type) {
|
||||
seg_type.val(point.type).removeAttr('disabled');
|
||||
$("#seg_type_label").html(point.type == 4 ? "Straight" : "Curve")
|
||||
} else {
|
||||
seg_type.val(4).attr('disabled','disabled');
|
||||
}
|
||||
}
|
||||
$("#panels").removeClass("multiselected")
|
||||
$("#stroke_panel").hide();
|
||||
$("#canvas_panel").hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var menu_items = $('#cmenu_canvas li');
|
||||
$('.context_panel').hide();
|
||||
$('.menu_item', '#edit_menu').addClass('disabled');
|
||||
$('.menu_item', '#object_menu').addClass('disabled');
|
||||
|
||||
|
||||
//hack to show the proper multialign box
|
||||
if (multiselected) {
|
||||
multiselected = multiselected.filter(Boolean);
|
||||
elem = (svgCanvas.elementsAreSame(multiselected)) ? multiselected[0] : null
|
||||
if (elem) $("#panels").addClass("multiselected")
|
||||
}
|
||||
|
||||
if (!elem && !multiselected) {
|
||||
$("#panels").removeClass("multiselected")
|
||||
$("#stroke_panel").hide();
|
||||
$("#canvas_panel").show();
|
||||
}
|
||||
|
||||
if (elem != null) {
|
||||
$("#stroke_panel").show();
|
||||
var elname = elem.nodeName;
|
||||
var angle = svgCanvas.getRotationAngle(elem);
|
||||
$('#angle').val(Math.round(angle));
|
||||
|
||||
var blurval = svgCanvas.getBlur(elem);
|
||||
$('#blur').val(blurval);
|
||||
if(!is_node && currentMode != 'pathedit') {
|
||||
$('#selected_panel').show();
|
||||
$('.action_selected').removeClass('disabled');
|
||||
// Elements in this array already have coord fields
|
||||
var x, y
|
||||
if(['g', 'polyline', 'path'].indexOf(elname) >= 0) {
|
||||
var bb = svgCanvas.getStrokedBBox([elem]);
|
||||
if(bb) {
|
||||
x = bb.x;
|
||||
y = bb.y;
|
||||
}
|
||||
}
|
||||
|
||||
if(unit) {
|
||||
x = svgedit.units.convertUnit(x);
|
||||
y = svgedit.units.convertUnit(y);
|
||||
}
|
||||
|
||||
$("#" + elname +"_x").val(Math.round(x))
|
||||
$("#" + elname +"_y").val(Math.round(y))
|
||||
if (elname === "polyline") {
|
||||
//we're acting as if polylines were paths
|
||||
$("#path_x").val(Math.round(x))
|
||||
$("#path_y").val(Math.round(y))
|
||||
}
|
||||
|
||||
// Elements in this array cannot be converted to a path
|
||||
var no_path = ['image', 'text', 'path', 'g', 'use'].indexOf(elname) == -1;
|
||||
if (no_path) $('.action_path_convert_selected').removeClass('disabled');
|
||||
if (elname === "path") $('.action_path_selected').removeClass('disabled');
|
||||
|
||||
}
|
||||
|
||||
var link_href = null;
|
||||
if (el_name === 'a') {
|
||||
link_href = svgCanvas.getHref(elem);
|
||||
$('#g_panel').show();
|
||||
}
|
||||
|
||||
if(elem.parentNode.tagName === 'a') {
|
||||
if(!$(elem).siblings().length) {
|
||||
$('#a_panel').show();
|
||||
link_href = svgCanvas.getHref(elem.parentNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide/show the make_link buttons
|
||||
$('#tool_make_link, #tool_make_link').toggle(!link_href);
|
||||
|
||||
if(link_href) {
|
||||
$('#link_url').val(link_href);
|
||||
}
|
||||
|
||||
// update contextual tools here
|
||||
var panels = {
|
||||
g: [],
|
||||
a: [],
|
||||
rect: ['rx','width','height', 'x', 'y'],
|
||||
image: ['width','height', 'x', 'y'],
|
||||
circle: ['cx','cy','r'],
|
||||
ellipse: ['cx','cy','rx','ry'],
|
||||
line: ['x1','y1','x2','y2'],
|
||||
text: ['x', 'y'],
|
||||
'use': [],
|
||||
path : []
|
||||
};
|
||||
|
||||
var el_name = elem.tagName;
|
||||
|
||||
if($(elem).data('gsvg')) {
|
||||
$('#g_panel').show();
|
||||
}
|
||||
|
||||
if (el_name == "path" || el_name == "polyline") {
|
||||
$('#path_panel').show();
|
||||
}
|
||||
|
||||
if(panels[el_name]) {
|
||||
var cur_panel = panels[el_name];
|
||||
$('#' + el_name + '_panel').show();
|
||||
|
||||
// corner radius has to live in a different panel
|
||||
// because otherwise it changes the position of the
|
||||
// of the elements
|
||||
if(el_name == "rect") $("#cornerRadiusLabel").show()
|
||||
else $("#cornerRadiusLabel").hide()
|
||||
|
||||
$.each(cur_panel, function(i, item) {
|
||||
var attrVal = elem.getAttribute(item);
|
||||
//update the draginput cursors
|
||||
var name_item = document.getElementById(el_name + '_' + item);
|
||||
name_item.value = Math.round(attrVal) || 0;
|
||||
if (name_item.getAttribute("data-cursor") === "true") {
|
||||
$.fn.dragInput.updateCursor(name_item );
|
||||
}
|
||||
});
|
||||
|
||||
if(el_name == 'text') {
|
||||
var font_family = elem.getAttribute("font-family");
|
||||
var cleanFontFamily = font_family.split(",")[0].replace(/'/g, "");
|
||||
var select = document.getElementById("font_family_dropdown");
|
||||
$('#text_panel').css("display", "inline");
|
||||
$('#tool_italic').toggleClass('active', svgCanvas.getItalic())
|
||||
$('#tool_bold').toggleClass('active', svgCanvas.getBold())
|
||||
$('#tool_italic').toggleClass('disabled', fonts[cleanFontFamily] ? !fonts[cleanFontFamily]["Italic"] : false)
|
||||
$('#tool_bold').toggleClass('disabled', fonts[cleanFontFamily] ? !fonts[cleanFontFamily]["Bold"] : false);
|
||||
$('#font_family').val(font_family);
|
||||
$(select).find(`option[value=${font_family}]`).prop("selected", true);
|
||||
$('#font_size').val(elem.getAttribute("font-size"));
|
||||
$('#text').val(elem.textContent);
|
||||
$('#preview_font').text(cleanFontFamily).css('font-family', font_family);
|
||||
} // text
|
||||
else if(el_name == 'image') {
|
||||
setImageURL(svgCanvas.getHref(elem));
|
||||
} // image
|
||||
else if(el_name === 'g' || el_name === 'use') {
|
||||
$('#container_panel').show();
|
||||
$('.action_group_selected').removeClass('disabled');
|
||||
var title = svgCanvas.getTitle();
|
||||
}
|
||||
}
|
||||
menu_items[(el_name === 'g' ? 'en':'dis') + 'ableContextMenuItems']('#ungroup');
|
||||
menu_items[((el_name === 'g' || !multiselected) ? 'dis':'en') + 'ableContextMenuItems']('#group');
|
||||
}
|
||||
|
||||
if (multiselected) {
|
||||
$('#multiselected_panel').show();
|
||||
$('.action_multi_selected').removeClass('disabled');
|
||||
menu_items
|
||||
.enableContextMenuItems('#group')
|
||||
.disableContextMenuItems('#ungroup');
|
||||
}
|
||||
|
||||
if (!elem) {
|
||||
menu_items.disableContextMenuItems('#delete,#cut,#copy,#ungroup,#move_front,#move_up,#move_down,#move_back');
|
||||
}
|
||||
|
||||
// update history buttons
|
||||
if (svgCanvas.undoMgr.getUndoStackSize() > 0) {
|
||||
$('#tool_undo').removeClass( 'disabled');
|
||||
}
|
||||
else {
|
||||
$('#tool_undo').addClass( 'disabled');
|
||||
}
|
||||
if (svgCanvas.undoMgr.getRedoStackSize() > 0) {
|
||||
$('#tool_redo').removeClass( 'disabled');
|
||||
}
|
||||
else {
|
||||
$('#tool_redo').addClass( 'disabled');
|
||||
}
|
||||
|
||||
svgCanvas.addedNew = false;
|
||||
|
||||
if ( (elem && !is_node) || multiselected) {
|
||||
// update the selected elements' layer
|
||||
$('#selLayerNames').removeAttr('disabled').val(currentLayerName);
|
||||
|
||||
// Enable regular menu options
|
||||
$("#cmenu_canvas").enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back');
|
||||
}
|
||||
};
|
||||
|
||||
this.selectedChanged = selectedChanged;
|
||||
this.updateContextPanel = updateContextPanel;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
// called when any element has changed
|
||||
var elementChanged = function(window,elems) {
|
||||
var mode = svgCanvas.getMode();
|
||||
if(mode === "select") {
|
||||
setSelectMode();
|
||||
}
|
||||
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
var elem = elems[i];
|
||||
|
||||
// if the element changed was the svg, then it could be a resolution change
|
||||
if (elem && elem.tagName === "svg") {
|
||||
//populateLayers();
|
||||
updateCanvas();
|
||||
}
|
||||
// Update selectedElement if element is no longer part of the image.
|
||||
// This occurs for the text elements in Firefox
|
||||
else if(elem && selectedElement && selectedElement.parentNode == null) {
|
||||
// || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why
|
||||
selectedElement = elem;
|
||||
}
|
||||
}
|
||||
|
||||
// we update the contextual panel with potentially new
|
||||
// positional/sizing information (we DON'T want to update the
|
||||
// toolbar here as that creates an infinite loop)
|
||||
// also this updates the history buttons
|
||||
|
||||
// we tell it to skip focusing the text control if the
|
||||
// text element was previously in focus
|
||||
updateContextPanel();
|
||||
|
||||
// In the event a gradient was flipped:
|
||||
if(selectedElement && mode === "select") {
|
||||
Editor.paintBox.fill.update();
|
||||
Editor.paintBox.stroke.update();
|
||||
}
|
||||
|
||||
svgCanvas.runExtensions("elementChanged", {
|
||||
elems: elems
|
||||
});
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
// Call when part of element is in process of changing, generally
|
||||
// on mousemove actions like rotate, move, etc.
|
||||
var elementTransition = function(window,elems) {
|
||||
var mode = svgCanvas.getMode();
|
||||
var elem = elems[0];
|
||||
|
||||
if(!elem) return;
|
||||
|
||||
const multiselected = (elems.length >= 2 && elems[1] != null) ? elems : null;
|
||||
// Only updating fields for single elements for now
|
||||
if(!multiselected) {
|
||||
switch ( mode ) {
|
||||
case "rotate":
|
||||
var ang = svgCanvas.getRotationAngle(elem);
|
||||
$('#angle').val(Math.round(ang));
|
||||
rotateCursor(ang);
|
||||
$('#tool_reorient').toggleClass('disabled', ang == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
svgCanvas.runExtensions("elementTransition", {
|
||||
elems: elems
|
||||
});
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
var exportHandler = function(window, data) {
|
||||
var issues = data.issues;
|
||||
|
||||
if(!$('#export_canvas').length) {
|
||||
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
|
||||
}
|
||||
var c = $('#export_canvas')[0];
|
||||
|
||||
c.width = svgCanvas.contentW;
|
||||
c.height = svgCanvas.contentH;
|
||||
canvg(c, data.svg, {renderCallback: function() {
|
||||
var datauri = c.toDataURL('image/png');
|
||||
if (!datauri) return false;
|
||||
var filename = "Method Draw Image";
|
||||
var type = 'image/png';
|
||||
var file = svgedit.utilities.dataURItoBlob(datauri, type);
|
||||
if (window.navigator.msSaveOrOpenBlob) // IE10+
|
||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
else { // Others
|
||||
var a = document.createElement("a"),
|
||||
url = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(function() {
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 0);
|
||||
}
|
||||
}});
|
||||
};
|
|
@ -1,3 +1,6 @@
|
|||
var methodDraw = {};
|
||||
methodDraw.addExtension = function(){}
|
||||
|
||||
/*
|
||||
* ext-eyedropper.js
|
||||
*
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
(function() {
|
||||
|
||||
// This fixes $(...).attr() to work as expected with SVG elements.
|
||||
// Does not currently use *AttributeNS() since we rarely need that.
|
||||
|
||||
// See http://api.jquery.com/attr/ for basic documentation of .attr()
|
||||
|
||||
// Additional functionality:
|
||||
// - When getting attributes, a string that's a number is return as type number.
|
||||
// - If an array is supplied as first parameter, multiple values are returned
|
||||
// as an object with values for each given attributes
|
||||
|
||||
var proxied = jQuery.fn.attr, svgns = "http://www.w3.org/2000/svg";
|
||||
jQuery.fn.attr = function(key, value) {
|
||||
var len = this.length;
|
||||
if(!len) return proxied.apply(this, arguments);
|
||||
for(var i=0; i<len; i++) {
|
||||
var elem = this[i];
|
||||
// set/get SVG attribute
|
||||
if(elem.namespaceURI === svgns) {
|
||||
// Setting attribute
|
||||
if(value !== undefined) {
|
||||
elem.setAttribute(key, value);
|
||||
} else if($.isArray(key)) {
|
||||
// Getting attributes from array
|
||||
var j = key.length, obj = {};
|
||||
|
||||
while(j--) {
|
||||
var aname = key[j];
|
||||
var attr = elem.getAttribute(aname);
|
||||
// This returns a number when appropriate
|
||||
if(attr || attr === "0") {
|
||||
attr = isNaN(attr)?attr:attr-0;
|
||||
}
|
||||
obj[aname] = attr;
|
||||
}
|
||||
return obj;
|
||||
|
||||
} else if(typeof key === "object") {
|
||||
// Setting attributes form object
|
||||
for(var v in key) {
|
||||
elem.setAttribute(v, key[v]);
|
||||
}
|
||||
// Getting attribute
|
||||
} else {
|
||||
var attr = elem.getAttribute(key);
|
||||
if(attr || attr === "0") {
|
||||
attr = isNaN(attr)?attr:attr-0;
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
} else {
|
||||
return proxied.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
}());
|
|
@ -53,14 +53,11 @@ var svgedit = svgedit || {};
|
|||
var menuItemIsValid = function(menuItem) {
|
||||
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function';
|
||||
}
|
||||
|
||||
// Defer injection to wait out initial menu processing. This probably goes away once all context
|
||||
// menu behavior is brought here.
|
||||
methodDraw.ready(function() {
|
||||
for (menuItem in contextMenuExtensions) {
|
||||
injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]);
|
||||
}
|
||||
});
|
||||
|
||||
for (menuItem in contextMenuExtensions) {
|
||||
injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]);
|
||||
}
|
||||
|
||||
svgedit.contextmenu.resetCustomMenus = function(){self.contextMenuExtensions = {}}
|
||||
svgedit.contextmenu.add = addContextMenuItem;
|
||||
svgedit.contextmenu.hasCustomHandler = hasCustomHandler;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
window.methodDraw = function() {
|
||||
var svgCanvas;
|
||||
var Editor = {};
|
||||
var is_ready = false;
|
||||
var curConfig = {
|
||||
|
@ -41,7 +40,7 @@ window.methodDraw = function() {
|
|||
$("#canvas_height").val(curConfig.dimensions[1]);
|
||||
|
||||
|
||||
Editor.canvas = svgCanvas = new $.SvgCanvas(document.getElementById("svgcanvas"), curConfig);
|
||||
Editor.canvas = svgCanvas;
|
||||
Editor.paintBox = {fill: null, stroke:null, canvas:null};
|
||||
var isMac = (navigator.platform.indexOf("Mac") >= 0),
|
||||
isWebkit = (navigator.userAgent.indexOf("AppleWebKit") >= 0),
|
||||
|
@ -101,196 +100,6 @@ window.methodDraw = function() {
|
|||
var preferences = false;
|
||||
var cur_context = '';
|
||||
|
||||
var saveHandler = function(window,svg) {
|
||||
|
||||
};
|
||||
|
||||
var exportHandler = function(window, data) {
|
||||
var issues = data.issues;
|
||||
|
||||
if(!$('#export_canvas').length) {
|
||||
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
|
||||
}
|
||||
var c = $('#export_canvas')[0];
|
||||
|
||||
c.width = svgCanvas.contentW;
|
||||
c.height = svgCanvas.contentH;
|
||||
canvg(c, data.svg, {renderCallback: function() {
|
||||
var datauri = c.toDataURL('image/png');
|
||||
if (!datauri) return false;
|
||||
var filename = "Method Draw Image";
|
||||
var type = 'image/png';
|
||||
var file = svgedit.utilities.dataURItoBlob(datauri, type);
|
||||
if (window.navigator.msSaveOrOpenBlob) // IE10+
|
||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
else { // Others
|
||||
var a = document.createElement("a"),
|
||||
url = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(function() {
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 0);
|
||||
}
|
||||
}});
|
||||
};
|
||||
|
||||
// called when we've selected a different element
|
||||
var selectedChanged = function(window,elems) {
|
||||
var mode = svgCanvas.getMode();
|
||||
if(mode === "select") setSelectMode();
|
||||
if (mode === "pathedit") return updateContextPanel();
|
||||
// if elems[1] is present, then we have more than one element
|
||||
selectedElement = (elems.length == 1 || elems[1] == null ? elems[0] : null);
|
||||
elems = elems.filter(Boolean)
|
||||
multiselected = (elems.length >= 2) ? elems : false;
|
||||
if (svgCanvas.elementsAreSame(multiselected)) selectedElement = multiselected[0]
|
||||
if (selectedElement != null) {
|
||||
$('#multiselected_panel').hide()
|
||||
updateToolbar();
|
||||
if (multiselected.length) { //multiselected elements are the same
|
||||
$('#tools_top').addClass('multiselected')
|
||||
}
|
||||
}
|
||||
else if (multiselected.length) {
|
||||
$('.context_panel').hide()
|
||||
$('#tools_top').removeClass('multiselected')
|
||||
$('#multiselected_panel').show()
|
||||
}
|
||||
else {
|
||||
$('.context_panel').hide()
|
||||
$('#canvas_panel').show()
|
||||
$('#tools_top').removeClass('multiselected')
|
||||
}
|
||||
|
||||
// We need to update the context panel always when we've selected a different element. Otherwise some
|
||||
// menu items are disabled even if they shouldn't be (e.g. group multiple elements)
|
||||
updateContextPanel();
|
||||
|
||||
svgCanvas.runExtensions("selectedChanged", {
|
||||
elems: elems,
|
||||
selectedElement: selectedElement,
|
||||
multiselected: multiselected
|
||||
});
|
||||
};
|
||||
|
||||
// Call when part of element is in process of changing, generally
|
||||
// on mousemove actions like rotate, move, etc.
|
||||
var elementTransition = function(window,elems) {
|
||||
var mode = svgCanvas.getMode();
|
||||
var elem = elems[0];
|
||||
|
||||
if(!elem) return;
|
||||
|
||||
multiselected = (elems.length >= 2 && elems[1] != null) ? elems : null;
|
||||
// Only updating fields for single elements for now
|
||||
if(!multiselected) {
|
||||
switch ( mode ) {
|
||||
case "rotate":
|
||||
var ang = svgCanvas.getRotationAngle(elem);
|
||||
$('#angle').val(Math.round(ang));
|
||||
rotateCursor(ang);
|
||||
$('#tool_reorient').toggleClass('disabled', ang == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
svgCanvas.runExtensions("elementTransition", {
|
||||
elems: elems
|
||||
});
|
||||
};
|
||||
|
||||
// called when any element has changed
|
||||
var elementChanged = function(window,elems) {
|
||||
var mode = svgCanvas.getMode();
|
||||
if(mode === "select") {
|
||||
setSelectMode();
|
||||
}
|
||||
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
var elem = elems[i];
|
||||
|
||||
// if the element changed was the svg, then it could be a resolution change
|
||||
if (elem && elem.tagName === "svg") {
|
||||
//populateLayers();
|
||||
updateCanvas();
|
||||
}
|
||||
// Update selectedElement if element is no longer part of the image.
|
||||
// This occurs for the text elements in Firefox
|
||||
else if(elem && selectedElement && selectedElement.parentNode == null) {
|
||||
// || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why
|
||||
selectedElement = elem;
|
||||
}
|
||||
}
|
||||
|
||||
// we update the contextual panel with potentially new
|
||||
// positional/sizing information (we DON'T want to update the
|
||||
// toolbar here as that creates an infinite loop)
|
||||
// also this updates the history buttons
|
||||
|
||||
// we tell it to skip focusing the text control if the
|
||||
// text element was previously in focus
|
||||
updateContextPanel();
|
||||
|
||||
// In the event a gradient was flipped:
|
||||
if(selectedElement && mode === "select") {
|
||||
Editor.paintBox.fill.update();
|
||||
Editor.paintBox.stroke.update();
|
||||
}
|
||||
|
||||
svgCanvas.runExtensions("elementChanged", {
|
||||
elems: elems
|
||||
});
|
||||
};
|
||||
|
||||
var zoomChanged = function(window, bbox, autoCenter) {
|
||||
var scrbar = 15,
|
||||
res = svgCanvas.getResolution(),
|
||||
w_area = workarea,
|
||||
canvas_pos = $('#svgcanvas').position();
|
||||
var z_info = svgCanvas.setBBoxZoom(bbox, w_area.width()-scrbar, w_area.height()-scrbar);
|
||||
if(!z_info) return;
|
||||
var zoomlevel = z_info.zoom,
|
||||
bb = z_info.bbox;
|
||||
|
||||
if(zoomlevel < .001) {
|
||||
changeZoom({value: .1});
|
||||
return;
|
||||
}
|
||||
if (typeof animatedZoom != 'undefined') window.cancelAnimationFrame(animatedZoom)
|
||||
// zoom duration 500ms
|
||||
var start = Date.now();
|
||||
var duration = 500;
|
||||
var diff = (zoomlevel) - (res.zoom)
|
||||
var zoom = $('#zoom')[0]
|
||||
var current_zoom = res.zoom
|
||||
var animateZoom = function(timestamp) {
|
||||
var progress = Date.now() - start
|
||||
var tick = progress / duration
|
||||
tick = (Math.pow((tick-1), 3) +1);
|
||||
svgCanvas.setZoom(current_zoom + (diff*tick));
|
||||
updateCanvas();
|
||||
if (tick < 1 && tick > -.90) {
|
||||
window.animatedZoom = requestAnimationFrame(animateZoom)
|
||||
}
|
||||
else {
|
||||
$("#zoom").val(parseInt(zoomlevel*100))
|
||||
$("option", "#zoom_select").removeAttr("selected")
|
||||
$("option[value="+ parseInt(zoomlevel*100) +"]", "#zoom_select").attr("selected", "selected")
|
||||
}
|
||||
}
|
||||
animateZoom()
|
||||
|
||||
if(svgCanvas.getMode() == 'zoom' && bb.width) {
|
||||
// Go to select if a zoom box was drawn
|
||||
setSelectMode();
|
||||
}
|
||||
|
||||
zoomDone();
|
||||
}
|
||||
|
||||
$('#cur_context_panel').delegate('a', 'click', function() {
|
||||
var link = $(this);
|
||||
if(link.attr('data-root')) {
|
||||
|
@ -301,37 +110,7 @@ window.methodDraw = function() {
|
|||
svgCanvas.clearSelection();
|
||||
return false;
|
||||
});
|
||||
|
||||
var contextChanged = function(win, context) {
|
||||
|
||||
var link_str = '';
|
||||
if(context) {
|
||||
var str = '';
|
||||
link_str = '<a href="#" data-root="y">' + svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>';
|
||||
|
||||
$(context).parentsUntil('#svgcontent > g').addBack().each(function() {
|
||||
if(this.id) {
|
||||
str += ' > ' + this.id;
|
||||
if(this !== context) {
|
||||
link_str += ' > <a href="#">' + this.id + '</a>';
|
||||
} else {
|
||||
link_str += ' > ' + this.id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cur_context = str;
|
||||
} else {
|
||||
cur_context = null;
|
||||
}
|
||||
$('#cur_context_panel').toggle(!!context).html(link_str);
|
||||
|
||||
}
|
||||
|
||||
var extAdded = function(window, ext) {
|
||||
if(ext.callback) ext.callback();
|
||||
}
|
||||
|
||||
// Makes sure the current selected paint is available to work with
|
||||
var prepPaints = function() {
|
||||
Editor.paintBox.fill.prep();
|
||||
|
@ -398,56 +177,6 @@ window.methodDraw = function() {
|
|||
if (!document.getElementById('canvas_background')) createBackground();
|
||||
var fill = document.getElementById('canvas_background').getAttribute("fill");
|
||||
|
||||
// updates the toolbar (colors, opacity, etc) based on the selected element
|
||||
// This function also updates the opacity and id elements that are in the context panel
|
||||
var updateToolbar = function() {
|
||||
if (selectedElement != null) {
|
||||
switch ( selectedElement.tagName ) {
|
||||
case 'use':
|
||||
$(".context_panel").hide();
|
||||
$("#use_panel").show();
|
||||
break;
|
||||
case 'image':
|
||||
$(".context_panel").hide();
|
||||
$("#image_panel").show();
|
||||
break;
|
||||
case 'foreignObject':
|
||||
$(".context_panel").hide();
|
||||
break;
|
||||
case 'g':
|
||||
case 'a':
|
||||
// Look for common styles
|
||||
var gWidth = null;
|
||||
|
||||
var childs = selectedElement.getElementsByTagName('*');
|
||||
for(var i = 0, len = childs.length; i < len; i++) {
|
||||
var swidth = childs[i].getAttribute("stroke-width");
|
||||
if(i === 0) {
|
||||
gWidth = swidth;
|
||||
} else if(gWidth !== swidth) {
|
||||
gWidth = null;
|
||||
}
|
||||
}
|
||||
|
||||
$('#stroke_width').val(gWidth === null ? "0" : gWidth);
|
||||
updateContextPanel();
|
||||
break;
|
||||
default:
|
||||
//removed because multiselect shouldnt set color
|
||||
//Editor.paintBox.fill.update(false);
|
||||
//Editor.paintBox.stroke.update(false);
|
||||
|
||||
$('#stroke_width').val(selectedElement.getAttribute("stroke-width") || 0);
|
||||
var dash = selectedElement.getAttribute("stroke-dasharray") || "none"
|
||||
$('option', '#stroke_style').removeAttr('selected');
|
||||
$('#stroke_style option[value="'+ dash +'"]').attr("selected", "selected");
|
||||
$('#stroke_style').trigger('change');
|
||||
|
||||
$.fn.dragInput.updateCursor($('#stroke_width')[0])
|
||||
$.fn.dragInput.updateCursor($('#blur')[0])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// All elements including image and group have opacity
|
||||
if(selectedElement != null) {
|
||||
|
@ -470,249 +199,6 @@ window.methodDraw = function() {
|
|||
}
|
||||
|
||||
// updates the context panel tools based on the selected element
|
||||
var updateContextPanel = function(e) {
|
||||
var elem = selectedElement;
|
||||
// If element has just been deleted, consider it null
|
||||
if(elem != null && !elem.parentNode) elem = null;
|
||||
if (multiselected && multiselected[0] != null && !multiselected[0].parentNode) multiselected = false;
|
||||
|
||||
var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName();
|
||||
var currentMode = svgCanvas.getMode();
|
||||
var unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null;
|
||||
var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
|
||||
|
||||
if (is_node) {
|
||||
$('.context_panel').hide();
|
||||
$('#path_node_panel').show();
|
||||
$('#stroke_panel').hide();
|
||||
var point = path.getNodePoint();
|
||||
$('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button');
|
||||
$('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes);
|
||||
|
||||
if(point) {
|
||||
var seg_type = $('#seg_type');
|
||||
if(unit) {
|
||||
point.x = svgedit.units.convertUnit(point.x);
|
||||
point.y = svgedit.units.convertUnit(point.y);
|
||||
}
|
||||
$('#path_node_x').val(Math.round(point.x));
|
||||
$('#path_node_y').val(Math.round(point.y));
|
||||
if(point.type) {
|
||||
seg_type.val(point.type).removeAttr('disabled');
|
||||
$("#seg_type_label").html(point.type == 4 ? "Straight" : "Curve")
|
||||
} else {
|
||||
seg_type.val(4).attr('disabled','disabled');
|
||||
}
|
||||
}
|
||||
$("#tools_top").removeClass("multiselected")
|
||||
$("#stroke_panel").hide();
|
||||
$("#canvas_panel").hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var menu_items = $('#cmenu_canvas li');
|
||||
$('.context_panel').hide();
|
||||
$('.menu_item', '#edit_menu').addClass('disabled');
|
||||
$('.menu_item', '#object_menu').addClass('disabled');
|
||||
|
||||
|
||||
//hack to show the proper multialign box
|
||||
if (multiselected) {
|
||||
multiselected = multiselected.filter(Boolean);
|
||||
elem = (svgCanvas.elementsAreSame(multiselected)) ? multiselected[0] : null
|
||||
if (elem) $("#tools_top").addClass("multiselected")
|
||||
}
|
||||
|
||||
if (!elem && !multiselected) {
|
||||
$("#tools_top").removeClass("multiselected")
|
||||
$("#stroke_panel").hide();
|
||||
$("#canvas_panel").show();
|
||||
}
|
||||
|
||||
if (elem != null) {
|
||||
$("#stroke_panel").show();
|
||||
var elname = elem.nodeName;
|
||||
var angle = svgCanvas.getRotationAngle(elem);
|
||||
$('#angle').val(Math.round(angle));
|
||||
|
||||
var blurval = svgCanvas.getBlur(elem);
|
||||
$('#blur').val(blurval);
|
||||
if(!is_node && currentMode != 'pathedit') {
|
||||
$('#selected_panel').show();
|
||||
$('.action_selected').removeClass('disabled');
|
||||
// Elements in this array already have coord fields
|
||||
var x, y
|
||||
if(['g', 'polyline', 'path'].indexOf(elname) >= 0) {
|
||||
var bb = svgCanvas.getStrokedBBox([elem]);
|
||||
if(bb) {
|
||||
x = bb.x;
|
||||
y = bb.y;
|
||||
}
|
||||
}
|
||||
|
||||
if(unit) {
|
||||
x = svgedit.units.convertUnit(x);
|
||||
y = svgedit.units.convertUnit(y);
|
||||
}
|
||||
|
||||
$("#" + elname +"_x").val(Math.round(x))
|
||||
$("#" + elname +"_y").val(Math.round(y))
|
||||
if (elname === "polyline") {
|
||||
//we're acting as if polylines were paths
|
||||
$("#path_x").val(Math.round(x))
|
||||
$("#path_y").val(Math.round(y))
|
||||
}
|
||||
|
||||
// Elements in this array cannot be converted to a path
|
||||
var no_path = ['image', 'text', 'path', 'g', 'use'].indexOf(elname) == -1;
|
||||
if (no_path) $('.action_path_convert_selected').removeClass('disabled');
|
||||
if (elname === "path") $('.action_path_selected').removeClass('disabled');
|
||||
|
||||
}
|
||||
|
||||
var link_href = null;
|
||||
if (el_name === 'a') {
|
||||
link_href = svgCanvas.getHref(elem);
|
||||
$('#g_panel').show();
|
||||
}
|
||||
|
||||
if(elem.parentNode.tagName === 'a') {
|
||||
if(!$(elem).siblings().length) {
|
||||
$('#a_panel').show();
|
||||
link_href = svgCanvas.getHref(elem.parentNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide/show the make_link buttons
|
||||
$('#tool_make_link, #tool_make_link').toggle(!link_href);
|
||||
|
||||
if(link_href) {
|
||||
$('#link_url').val(link_href);
|
||||
}
|
||||
|
||||
// update contextual tools here
|
||||
var panels = {
|
||||
g: [],
|
||||
a: [],
|
||||
rect: ['rx','width','height', 'x', 'y'],
|
||||
image: ['width','height', 'x', 'y'],
|
||||
circle: ['cx','cy','r'],
|
||||
ellipse: ['cx','cy','rx','ry'],
|
||||
line: ['x1','y1','x2','y2'],
|
||||
text: ['x', 'y'],
|
||||
'use': [],
|
||||
path : []
|
||||
};
|
||||
|
||||
var el_name = elem.tagName;
|
||||
|
||||
if($(elem).data('gsvg')) {
|
||||
$('#g_panel').show();
|
||||
}
|
||||
|
||||
if (el_name == "path" || el_name == "polyline") {
|
||||
$('#path_panel').show();
|
||||
}
|
||||
|
||||
if(panels[el_name]) {
|
||||
var cur_panel = panels[el_name];
|
||||
$('#' + el_name + '_panel').show();
|
||||
|
||||
// corner radius has to live in a different panel
|
||||
// because otherwise it changes the position of the
|
||||
// of the elements
|
||||
if(el_name == "rect") $("#cornerRadiusLabel").show()
|
||||
else $("#cornerRadiusLabel").hide()
|
||||
|
||||
$.each(cur_panel, function(i, item) {
|
||||
var attrVal = elem.getAttribute(item);
|
||||
if(curConfig.baseUnit !== 'px' && elem[item]) {
|
||||
var bv = elem[item].baseVal.value;
|
||||
attrVal = svgedit.units.convertUnit(bv);
|
||||
}
|
||||
|
||||
//update the draginput cursors
|
||||
var name_item = document.getElementById(el_name + '_' + item);
|
||||
name_item.value = Math.round(attrVal) || 0;
|
||||
if (name_item.getAttribute("data-cursor") === "true") {
|
||||
$.fn.dragInput.updateCursor(name_item );
|
||||
}
|
||||
});
|
||||
|
||||
if(el_name == 'text') {
|
||||
var font_family = elem.getAttribute("font-family");
|
||||
var cleanFontFamily = font_family.split(",")[0].replace(/'/g, "");
|
||||
var select = document.getElementById("font_family_dropdown");
|
||||
$('#text_panel').css("display", "inline");
|
||||
$('#tool_italic').toggleClass('active', svgCanvas.getItalic())
|
||||
$('#tool_bold').toggleClass('active', svgCanvas.getBold())
|
||||
$('#tool_italic').toggleClass('disabled', fonts[cleanFontFamily] ? !fonts[cleanFontFamily]["Italic"] : false)
|
||||
$('#tool_bold').toggleClass('disabled', fonts[cleanFontFamily] ? !fonts[cleanFontFamily]["Bold"] : false);
|
||||
$('#font_family').val(font_family);
|
||||
$(select).find(`option[value=${font_family}]`).prop("selected", true);
|
||||
$('#font_size').val(elem.getAttribute("font-size"));
|
||||
$('#text').val(elem.textContent);
|
||||
$('#preview_font').text(cleanFontFamily).css('font-family', font_family);
|
||||
} // text
|
||||
else if(el_name == 'image') {
|
||||
setImageURL(svgCanvas.getHref(elem));
|
||||
} // image
|
||||
else if(el_name === 'g' || el_name === 'use') {
|
||||
$('#container_panel').show();
|
||||
$('.action_group_selected').removeClass('disabled');
|
||||
var title = svgCanvas.getTitle();
|
||||
}
|
||||
}
|
||||
menu_items[(el_name === 'g' ? 'en':'dis') + 'ableContextMenuItems']('#ungroup');
|
||||
menu_items[((el_name === 'g' || !multiselected) ? 'dis':'en') + 'ableContextMenuItems']('#group');
|
||||
}
|
||||
|
||||
if (multiselected) {
|
||||
$('#multiselected_panel').show();
|
||||
$('.action_multi_selected').removeClass('disabled');
|
||||
menu_items
|
||||
.enableContextMenuItems('#group')
|
||||
.disableContextMenuItems('#ungroup');
|
||||
}
|
||||
|
||||
if (!elem) {
|
||||
menu_items.disableContextMenuItems('#delete,#cut,#copy,#ungroup,#move_front,#move_up,#move_down,#move_back');
|
||||
}
|
||||
|
||||
// update history buttons
|
||||
if (undoMgr.getUndoStackSize() > 0) {
|
||||
$('#tool_undo').removeClass( 'disabled');
|
||||
}
|
||||
else {
|
||||
$('#tool_undo').addClass( 'disabled');
|
||||
}
|
||||
if (undoMgr.getRedoStackSize() > 0) {
|
||||
$('#tool_redo').removeClass( 'disabled');
|
||||
}
|
||||
else {
|
||||
$('#tool_redo').addClass( 'disabled');
|
||||
}
|
||||
|
||||
svgCanvas.addedNew = false;
|
||||
|
||||
if ( (elem && !is_node) || multiselected) {
|
||||
// update the selected elements' layer
|
||||
$('#selLayerNames').removeAttr('disabled').val(currentLayerName);
|
||||
|
||||
// Enable regular menu options
|
||||
canv_menu.enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back');
|
||||
}
|
||||
};
|
||||
|
||||
// bind the selected event to our function that handles updates to the UI
|
||||
svgCanvas.bind("selected", selectedChanged);
|
||||
svgCanvas.bind("transition", elementTransition);
|
||||
svgCanvas.bind("changed", elementChanged);
|
||||
svgCanvas.bind("exported", exportHandler);
|
||||
svgCanvas.bind("zoomed", zoomChanged);
|
||||
svgCanvas.bind("contextset", contextChanged);
|
||||
svgCanvas.bind("extension_added", extAdded);
|
||||
svgCanvas.textActions.setInputElem($("#text")[0]);
|
||||
|
||||
var changeFontSize = function(ctl) {
|
||||
svgCanvas.setFontSize(ctl.value);
|
||||
|
@ -904,29 +390,6 @@ window.methodDraw = function() {
|
|||
$(opt).addClass('current').siblings().removeClass('current');
|
||||
}
|
||||
|
||||
//menu handling
|
||||
var menus = $('.menu');
|
||||
var blinker = function(e) {
|
||||
e.target.style.background = "#fff";
|
||||
setTimeout(function(){e.target.style.background = "#ddd";}, 50);
|
||||
setTimeout(function(){e.target.style.background = "#fff";}, 150);
|
||||
setTimeout(function(){e.target.style.background = "#ddd";}, 200);
|
||||
setTimeout(function(){e.target.style.background = "";}, 200);
|
||||
setTimeout(function(){$('#menu_bar').removeClass('active')}, 220);
|
||||
return false;
|
||||
}
|
||||
var closer = function(e){
|
||||
if (e.target.nodeName && e.target.nodeName.toLowerCase() === "input") return false;
|
||||
if (!$(e.target).hasClass("menu_title") && !$(e.target).parent().hasClass("menu_title")) {
|
||||
if(!$(e.target).hasClass("disabled") && $(e.target).hasClass("menu_item")) blinker(e)
|
||||
else $('#menu_bar').removeClass('active')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$('.menu_item').on('mousedown touchstart', function(e){blinker(e)});
|
||||
$("svg, body").on('mousedown touchstart', function(e){closer(e)});
|
||||
|
||||
var accumulatedDelta = 0
|
||||
$('#workarea').on('mousewheel', function(e, delta, deltaX, deltaY){
|
||||
if (e.altKey || e.ctrlKey) {
|
||||
|
|
307
src/js/rulers.js
307
src/js/rulers.js
|
@ -1,169 +1,174 @@
|
|||
// todo remove from global scope;
|
||||
var r_intervals = [];
|
||||
for(var i = .1; i < 1E5; i *= 10) {
|
||||
r_intervals.push(1 * i);
|
||||
r_intervals.push(2 * i);
|
||||
r_intervals.push(5 * i);
|
||||
}
|
||||
MD.Rulers = function(){
|
||||
|
||||
function updateRulers(svgCanvas, scanvas, zoom) {
|
||||
var r_intervals = [];
|
||||
for(var i = .1; i < 1E5; i *= 10) {
|
||||
r_intervals.push(1 * i);
|
||||
r_intervals.push(2 * i);
|
||||
r_intervals.push(5 * i);
|
||||
}
|
||||
|
||||
var workarea = document.getElementById("workarea");
|
||||
var title_show = document.getElementById("title_show");
|
||||
var offset_x = 66;
|
||||
var offset_y = 48;
|
||||
if(!zoom) zoom = svgCanvas.getZoom();
|
||||
if(!scanvas) scanvas = $("#svgcanvas");
|
||||
|
||||
var limit = 30000;
|
||||
|
||||
var c_elem = svgCanvas.getContentElem();
|
||||
|
||||
var units = svgedit.units.getTypeMap();
|
||||
var unit = 1;
|
||||
function update(zoom) {
|
||||
|
||||
for(var d = 0; d < 2; d++) {
|
||||
var is_x = (d === 0);
|
||||
var dim = is_x ? 'x' : 'y';
|
||||
var lentype = is_x ?'width':'height';
|
||||
var notlentype = is_x ?'height':'width';
|
||||
var content_d = c_elem.getAttribute(dim)-0;
|
||||
var workarea = document.getElementById("workarea");
|
||||
var title_show = document.getElementById("title_show");
|
||||
var offset_x = 66;
|
||||
var offset_y = 48;
|
||||
if(!zoom) zoom = svgCanvas.getZoom();
|
||||
const scanvas = $("#svgcanvas");
|
||||
|
||||
var $hcanv_orig = $('#ruler_' + dim + ' canvas:first');
|
||||
var limit = 30000;
|
||||
|
||||
// Bit of a hack to fully clear the canvas in Safari & IE9
|
||||
$hcanv = $hcanv_orig.clone();
|
||||
$hcanv_orig.replaceWith($hcanv);
|
||||
var c_elem = svgCanvas.getContentElem();
|
||||
|
||||
var hcanv = $hcanv[0];
|
||||
|
||||
// Set the canvas size to the width of the container
|
||||
var ruler_len = scanvas[lentype]()*2;
|
||||
var total_len = ruler_len;
|
||||
hcanv.parentNode.style[lentype] = total_len + 'px';
|
||||
|
||||
var canv_count = 1;
|
||||
var ctx_num = 0;
|
||||
var ctx_arr;
|
||||
var ctx = hcanv.getContext("2d");
|
||||
var scale = window.devicePixelRatio || 1;
|
||||
hcanv.style[lentype] = total_len + "px";
|
||||
hcanv.style[notlentype] = 15 + "px";
|
||||
hcanv[lentype] = Math.floor(total_len * scale);
|
||||
hcanv[notlentype] = Math.floor(15 * scale);
|
||||
ctx.scale(scale,scale);
|
||||
var units = svgedit.units.getTypeMap();
|
||||
var unit = 1;
|
||||
|
||||
ctx.fillStyle = "rgb(200,0,0)";
|
||||
ctx.fillRect(0,0,hcanv.width/scale,hcanv.height/scale);
|
||||
|
||||
// Remove any existing canvasses
|
||||
$hcanv.siblings().remove();
|
||||
|
||||
// Create multiple canvases when necessary (due to browser limits)
|
||||
if(ruler_len >= limit) {
|
||||
var num = parseInt(ruler_len / limit) + 1;
|
||||
ctx_arr = Array(num);
|
||||
ctx_arr[0] = ctx;
|
||||
for(var i = 1; i < num; i++) {
|
||||
hcanv[lentype] = limit;
|
||||
var copy = hcanv.cloneNode(true);
|
||||
hcanv.parentNode.appendChild(copy);
|
||||
ctx_arr[i] = copy.getContext('2d');
|
||||
}
|
||||
for(var d = 0; d < 2; d++) {
|
||||
var is_x = (d === 0);
|
||||
var dim = is_x ? 'x' : 'y';
|
||||
var lentype = is_x ?'width':'height';
|
||||
var notlentype = is_x ?'height':'width';
|
||||
var content_d = c_elem.getAttribute(dim)-0;
|
||||
|
||||
copy[lentype] = ruler_len % limit;
|
||||
var $hcanv_orig = $('#ruler_' + dim + ' canvas:first');
|
||||
|
||||
// set copy width to last
|
||||
ruler_len = limit;
|
||||
}
|
||||
|
||||
hcanv[lentype] = ruler_len * scale;
|
||||
|
||||
var u_multi = unit * zoom;
|
||||
|
||||
// Calculate the main number interval
|
||||
var raw_m = 50 / u_multi;
|
||||
var multi = 1;
|
||||
for(var i = 0; i < r_intervals.length; i++) {
|
||||
var num = r_intervals[i];
|
||||
multi = num;
|
||||
if(raw_m <= num) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var big_int = multi * u_multi;
|
||||
ctx.font = "normal 9px 'Verdana', sans-serif";
|
||||
ctx.fillStyle = "#777";
|
||||
ctx.scale(scale,scale);
|
||||
// Bit of a hack to fully clear the canvas in Safari & IE9
|
||||
$hcanv = $hcanv_orig.clone();
|
||||
$hcanv_orig.replaceWith($hcanv);
|
||||
|
||||
var hcanv = $hcanv[0];
|
||||
|
||||
// Set the canvas size to the width of the container
|
||||
var ruler_len = scanvas[lentype]()*2;
|
||||
var total_len = ruler_len;
|
||||
hcanv.parentNode.style[lentype] = total_len + 'px';
|
||||
|
||||
var canv_count = 1;
|
||||
var ctx_num = 0;
|
||||
var ctx_arr;
|
||||
var ctx = hcanv.getContext("2d");
|
||||
var scale = window.devicePixelRatio || 1;
|
||||
hcanv.style[lentype] = total_len + "px";
|
||||
hcanv.style[notlentype] = 15 + "px";
|
||||
hcanv[lentype] = Math.floor(total_len * scale);
|
||||
hcanv[notlentype] = Math.floor(15 * scale);
|
||||
ctx.scale(scale,scale);
|
||||
|
||||
var ruler_d = ((content_d / u_multi) % multi) * u_multi;
|
||||
var label_pos = ruler_d - big_int;
|
||||
for (; ruler_d < total_len; ruler_d += big_int) {
|
||||
label_pos += big_int;
|
||||
var real_d = ruler_d - content_d;
|
||||
|
||||
var cur_d = Math.round(ruler_d) + .5;
|
||||
if(is_x) {
|
||||
ctx.moveTo(cur_d, 15);
|
||||
ctx.lineTo(cur_d, 0);
|
||||
} else {
|
||||
ctx.moveTo(15, cur_d);
|
||||
ctx.lineTo(0, cur_d);
|
||||
}
|
||||
|
||||
var num = (label_pos - content_d) / u_multi;
|
||||
var label;
|
||||
if(multi >= 1) {
|
||||
label = Math.round(num);
|
||||
} else {
|
||||
var decs = (multi+'').split('.')[1].length;
|
||||
label = num.toFixed(decs)-0;
|
||||
}
|
||||
ctx.fillStyle = "rgb(200,0,0)";
|
||||
ctx.fillRect(0,0,hcanv.width/scale,hcanv.height/scale);
|
||||
|
||||
// Change 1000s to Ks
|
||||
if(label !== 0 && label !== 1000 && label % 1000 === 0) {
|
||||
label = (label / 1000) + 'K';
|
||||
}
|
||||
// Remove any existing canvasses
|
||||
$hcanv.siblings().remove();
|
||||
|
||||
if(is_x) {
|
||||
ctx.fillText(label, ruler_d+2, 8);
|
||||
ctx.fillStyle = "#777";
|
||||
} else {
|
||||
var str = (label+'').split('');
|
||||
for(var i = 0; i < str.length; i++) {
|
||||
ctx.fillText(str[i], 1, (ruler_d+9) + i*9);
|
||||
ctx.fillStyle = "#777";
|
||||
}
|
||||
}
|
||||
|
||||
var part = big_int / 10;
|
||||
for(var i = 1; i < 10; i++) {
|
||||
var sub_d = Math.round(ruler_d + part * i) + .5;
|
||||
if(ctx_arr && sub_d > ruler_len) {
|
||||
ctx_num++;
|
||||
ctx.stroke();
|
||||
if(ctx_num >= ctx_arr.length) {
|
||||
i = 10;
|
||||
ruler_d = total_len;
|
||||
continue;
|
||||
}
|
||||
ctx = ctx_arr[ctx_num];
|
||||
ruler_d -= limit;
|
||||
sub_d = Math.round(ruler_d + part * i) + .5;
|
||||
// Create multiple canvases when necessary (due to browser limits)
|
||||
if(ruler_len >= limit) {
|
||||
var num = parseInt(ruler_len / limit) + 1;
|
||||
ctx_arr = Array(num);
|
||||
ctx_arr[0] = ctx;
|
||||
for(var i = 1; i < num; i++) {
|
||||
hcanv[lentype] = limit;
|
||||
var copy = hcanv.cloneNode(true);
|
||||
hcanv.parentNode.appendChild(copy);
|
||||
ctx_arr[i] = copy.getContext('2d');
|
||||
}
|
||||
|
||||
var line_num = (i % 2)?12:10;
|
||||
if(is_x) {
|
||||
ctx.moveTo(sub_d, 15);
|
||||
ctx.lineTo(sub_d, line_num);
|
||||
} else {
|
||||
ctx.moveTo(15, sub_d);
|
||||
ctx.lineTo(line_num ,sub_d);
|
||||
copy[lentype] = ruler_len % limit;
|
||||
|
||||
// set copy width to last
|
||||
ruler_len = limit;
|
||||
}
|
||||
|
||||
hcanv[lentype] = ruler_len * scale;
|
||||
|
||||
var u_multi = unit * zoom;
|
||||
|
||||
// Calculate the main number interval
|
||||
var raw_m = 50 / u_multi;
|
||||
var multi = 1;
|
||||
for(var i = 0; i < r_intervals.length; i++) {
|
||||
var num = r_intervals[i];
|
||||
multi = num;
|
||||
if(raw_m <= num) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var big_int = multi * u_multi;
|
||||
ctx.font = "normal 9px 'Verdana', sans-serif";
|
||||
ctx.fillStyle = "#777";
|
||||
ctx.scale(scale,scale);
|
||||
|
||||
var ruler_d = ((content_d / u_multi) % multi) * u_multi;
|
||||
var label_pos = ruler_d - big_int;
|
||||
for (; ruler_d < total_len; ruler_d += big_int) {
|
||||
label_pos += big_int;
|
||||
var real_d = ruler_d - content_d;
|
||||
|
||||
var cur_d = Math.round(ruler_d) + .5;
|
||||
if(is_x) {
|
||||
ctx.moveTo(cur_d, 15);
|
||||
ctx.lineTo(cur_d, 0);
|
||||
} else {
|
||||
ctx.moveTo(15, cur_d);
|
||||
ctx.lineTo(0, cur_d);
|
||||
}
|
||||
|
||||
var num = (label_pos - content_d) / u_multi;
|
||||
var label;
|
||||
if(multi >= 1) {
|
||||
label = Math.round(num);
|
||||
} else {
|
||||
var decs = (multi+'').split('.')[1].length;
|
||||
label = num.toFixed(decs)-0;
|
||||
}
|
||||
|
||||
// Change 1000s to Ks
|
||||
if(label !== 0 && label !== 1000 && label % 1000 === 0) {
|
||||
label = (label / 1000) + 'K';
|
||||
}
|
||||
|
||||
if(is_x) {
|
||||
ctx.fillText(label, ruler_d+2, 8);
|
||||
ctx.fillStyle = "#777";
|
||||
} else {
|
||||
var str = (label+'').split('');
|
||||
for(var i = 0; i < str.length; i++) {
|
||||
ctx.fillText(str[i], 1, (ruler_d+9) + i*9);
|
||||
ctx.fillStyle = "#777";
|
||||
}
|
||||
}
|
||||
|
||||
var part = big_int / 10;
|
||||
for(var i = 1; i < 10; i++) {
|
||||
var sub_d = Math.round(ruler_d + part * i) + .5;
|
||||
if(ctx_arr && sub_d > ruler_len) {
|
||||
ctx_num++;
|
||||
ctx.stroke();
|
||||
if(ctx_num >= ctx_arr.length) {
|
||||
i = 10;
|
||||
ruler_d = total_len;
|
||||
continue;
|
||||
}
|
||||
ctx = ctx_arr[ctx_num];
|
||||
ruler_d -= limit;
|
||||
sub_d = Math.round(ruler_d + part * i) + .5;
|
||||
}
|
||||
|
||||
var line_num = (i % 2)?12:10;
|
||||
if(is_x) {
|
||||
ctx.moveTo(sub_d, 15);
|
||||
ctx.lineTo(sub_d, line_num);
|
||||
} else {
|
||||
ctx.moveTo(15, sub_d);
|
||||
ctx.lineTo(line_num ,sub_d);
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.strokeStyle = "#666";
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.strokeStyle = "#666";
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
this.update = update();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
// globals
|
||||
const svgCanvas = new $.SvgCanvas(document.getElementById("svgcanvas"));
|
||||
const editor = new MD.Editor();
|
||||
editor.menu = new MD.Menu();
|
||||
editor.toolbar = new MD.Toolbar();
|
||||
editor.rulers = new MD.Rulers();
|
||||
const state = new State();
|
||||
state.set("canvasId", t("Untitled"));
|
||||
state.set("canvasMode", state.get("canvasMode"));
|
|
@ -0,0 +1,73 @@
|
|||
function State(){
|
||||
|
||||
const _self = this;
|
||||
const tenThousandThings = dao.map(thing => thing.name);
|
||||
const saveableKeys = dao.filter(thing => thing.save).map(thing => thing.name);
|
||||
|
||||
this.data = _loadData();
|
||||
|
||||
this.set = (key, val) => {
|
||||
key = key.split("-")[0] || key;
|
||||
if (tenThousandThings.indexOf(key) === -1) return console.warn( key + " not implemented");
|
||||
const archetype = dao.find(thing => thing.name === key);
|
||||
val = _self.data[_getKey(key)] = archetype.clean(val);
|
||||
if (~saveableKeys.indexOf(key)) _save(_getKey(key), val);
|
||||
_self[key](val);
|
||||
}
|
||||
|
||||
this.get = (key) => {
|
||||
return _self.data[_getKey(key)];
|
||||
}
|
||||
|
||||
this.refresh = () => { dao.forEach(thing => this[thing.name]( this.get(thing.name) ) ); }
|
||||
|
||||
// canvas data
|
||||
this.canvasId = (id) => {/* noop */}
|
||||
this.canvasMode = (mode) => { editor.toolbar.setMode(mode) }
|
||||
|
||||
|
||||
this.clean = (warn = true) => {
|
||||
if (warn) {
|
||||
const confirmed = confirm("Deletes all configuration and text, are you sure?");
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
Object.keys(localStorage).forEach(key => localStorage.removeItem(key));
|
||||
write.reset();
|
||||
}
|
||||
|
||||
// INNER UTILS
|
||||
|
||||
function _save(key, val) {
|
||||
// basic checks
|
||||
//console.log(key, val)
|
||||
if (val === undefined || val === null) throw "wont save nuthin, " + key + " " + val;
|
||||
localStorage.setItem("write" + "-" + key, val.toString());
|
||||
}
|
||||
|
||||
function _getKey(name) {
|
||||
const key = name.indexOf("page") !== -1
|
||||
|| name.indexOf("assignment") !== -1
|
||||
? name + ID
|
||||
: name + "-0"; // system
|
||||
return key;
|
||||
}
|
||||
|
||||
function _loadData() {
|
||||
|
||||
const data = dao.map(thing => {
|
||||
return {
|
||||
[_getKey(thing.name)]: _getValue(_getKey(thing.name), utils.findGetParameter(thing.name) || thing.default)
|
||||
}
|
||||
});
|
||||
return Object.assign({}, ...data);
|
||||
};
|
||||
|
||||
function _getValue(key, def) {
|
||||
const item = localStorage.getItem("write-" + key) || def;
|
||||
const archetype = dao.find(thing => thing.name === key.split("-")[0]);
|
||||
if (archetype) return archetype.clean(item);
|
||||
else throw "Unkown archetype";
|
||||
}
|
||||
|
||||
}
|
|
@ -24,68 +24,6 @@
|
|||
|
||||
/*jslint browser: true*/
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
// This fixes $(...).attr() to work as expected with SVG elements.
|
||||
// Does not currently use *AttributeNS() since we rarely need that.
|
||||
|
||||
// See http://api.jquery.com/attr/ for basic documentation of .attr()
|
||||
|
||||
// Additional functionality:
|
||||
// - When getting attributes, a string that's a number is return as type number.
|
||||
// - If an array is supplied as first parameter, multiple values are returned
|
||||
// as an object with values for each given attributes
|
||||
|
||||
var proxied = jQuery.fn.attr, svgns = "http://www.w3.org/2000/svg";
|
||||
jQuery.fn.attr = function(key, value) {
|
||||
var len = this.length;
|
||||
if(!len) return proxied.apply(this, arguments);
|
||||
for(var i=0; i<len; i++) {
|
||||
var elem = this[i];
|
||||
// set/get SVG attribute
|
||||
if(elem.namespaceURI === svgns) {
|
||||
// Setting attribute
|
||||
if(value !== undefined) {
|
||||
elem.setAttribute(key, value);
|
||||
} else if($.isArray(key)) {
|
||||
// Getting attributes from array
|
||||
var j = key.length, obj = {};
|
||||
|
||||
while(j--) {
|
||||
var aname = key[j];
|
||||
var attr = elem.getAttribute(aname);
|
||||
// This returns a number when appropriate
|
||||
if(attr || attr === "0") {
|
||||
attr = isNaN(attr)?attr:attr-0;
|
||||
}
|
||||
obj[aname] = attr;
|
||||
}
|
||||
return obj;
|
||||
|
||||
} else if(typeof key === "object") {
|
||||
// Setting attributes form object
|
||||
for(var v in key) {
|
||||
elem.setAttribute(v, key[v]);
|
||||
}
|
||||
// Getting attribute
|
||||
} else {
|
||||
var attr = elem.getAttribute(key);
|
||||
if(attr || attr === "0") {
|
||||
attr = isNaN(attr)?attr:attr-0;
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
} else {
|
||||
return proxied.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
// Class: SvgCanvas
|
||||
// The main SvgCanvas class that manages all SVG-related functions
|
||||
//
|
||||
|
@ -107,7 +45,10 @@ var svgns = "http://www.w3.org/2000/svg",
|
|||
var curConfig = {
|
||||
show_outside_canvas: true,
|
||||
selectNew: true,
|
||||
dimensions: [640, 480]
|
||||
dimensions: [800, 600],
|
||||
initFill: {color: 'fff', opacity: 1},
|
||||
initStroke: {width: 1, color: '000', opacity: 1},
|
||||
imgPath: 'images/',
|
||||
};
|
||||
|
||||
// Update config with new one if given
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
function t(key){
|
||||
|
||||
const lang = typeof state === "undefined" ? "en" : state.get("language");
|
||||
|
||||
const dict = {
|
||||
"Untitled": "Sin Título",
|
||||
}
|
||||
|
||||
const keys = Object.keys(dict);
|
||||
const values = Object.values(dict);
|
||||
const originWord = keys.find(word => key === word);
|
||||
const destinationWord = values.find(word => key === word);
|
||||
|
||||
if (!originWord && !destinationWord) {
|
||||
console.log( "translation missing: " + key);
|
||||
return key;
|
||||
}
|
||||
|
||||
const translation = lang === "en" ? key : dict[key]// english input;
|
||||
|
||||
return translation
|
||||
|
||||
}
|
||||
|
||||
function translateDom(lang){
|
||||
const els = dom.qsa("[data-translate]");
|
||||
els.forEach(el => {
|
||||
const translation = el.getAttribute("data-translate");
|
||||
const source = el.innerHTML;
|
||||
el.innerHTML = translation;
|
||||
el.setAttribute("data-translate", source);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
const utils = {};
|
||||
|
||||
utils.findGetParameter = function(parameterName) {
|
||||
var result = null,
|
||||
tmp = [];
|
||||
var items = location.search.substr(1).split("&");
|
||||
for (var index = 0; index < items.length; index++) {
|
||||
tmp = items[index].split("=");
|
||||
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
var zoomChanged = function(window, bbox, autoCenter) {
|
||||
var scrbar = 15,
|
||||
res = svgCanvas.getResolution(),
|
||||
w_area = workarea,
|
||||
canvas_pos = $('#svgcanvas').position();
|
||||
var z_info = svgCanvas.setBBoxZoom(bbox, w_area.width()-scrbar, w_area.height()-scrbar);
|
||||
if(!z_info) return;
|
||||
var zoomlevel = z_info.zoom,
|
||||
bb = z_info.bbox;
|
||||
|
||||
if(zoomlevel < .001) {
|
||||
changeZoom({value: .1});
|
||||
return;
|
||||
}
|
||||
if (typeof animatedZoom != 'undefined') window.cancelAnimationFrame(animatedZoom)
|
||||
// zoom duration 500ms
|
||||
var start = Date.now();
|
||||
var duration = 500;
|
||||
var diff = (zoomlevel) - (res.zoom)
|
||||
var zoom = $('#zoom')[0]
|
||||
var current_zoom = res.zoom
|
||||
var animateZoom = function(timestamp) {
|
||||
var progress = Date.now() - start
|
||||
var tick = progress / duration
|
||||
tick = (Math.pow((tick-1), 3) +1);
|
||||
svgCanvas.setZoom(current_zoom + (diff*tick));
|
||||
updateCanvas();
|
||||
if (tick < 1 && tick > -.90) {
|
||||
window.animatedZoom = requestAnimationFrame(animateZoom)
|
||||
}
|
||||
else {
|
||||
$("#zoom").val(parseInt(zoomlevel*100))
|
||||
$("option", "#zoom_select").removeAttr("selected")
|
||||
$("option[value="+ parseInt(zoomlevel*100) +"]", "#zoom_select").attr("selected", "selected")
|
||||
}
|
||||
}
|
||||
animateZoom()
|
||||
|
||||
if(svgCanvas.getMode() == 'zoom' && bb.width) {
|
||||
// Go to select if a zoom box was drawn
|
||||
setSelectMode();
|
||||
}
|
||||
|
||||
zoomDone();
|
||||
}
|
Loading…
Reference in New Issue