From 47e47ae610ddfc105c6e10969306e27850849c92 Mon Sep 17 00:00:00 2001 From: apb Date: Thu, 13 Sep 2012 22:56:39 +0100 Subject: [PATCH] defaults --- src/graphxq.xqm | 13 +- src/graphxq/app.css | 1 + src/graphxq/app.js | 86 +++++++- src/graphxq/dotui.xml | 194 +++++++++++++++++ src/graphxq/dotui.xqm | 29 +++ src/graphxq/jquery-svgpan.js | 381 ++++++++++++++++++++++++++++++++++ src/graphxq/views/dotform.xml | 47 ++++- src/graphxq/views/layout.xml | 7 +- 8 files changed, 737 insertions(+), 21 deletions(-) create mode 100644 src/graphxq/dotui.xml create mode 100644 src/graphxq/dotui.xqm create mode 100644 src/graphxq/jquery-svgpan.js diff --git a/src/graphxq.xqm b/src/graphxq.xqm index 64650a9..9bf5956 100644 --- a/src/graphxq.xqm +++ b/src/graphxq.xqm @@ -8,6 +8,7 @@ module namespace grxq = 'apb.graphviz.web'; declare default function namespace 'apb.graphviz.web'; import module namespace gr = 'apb.graphviz' at "graphxq/graphviz.xqm"; +import module namespace dotui = 'apb.graphxq.dotui' at "graphxq/dotui.xqm"; import module namespace txq = 'apb.txq' at "graphxq/lib/txq.xqm"; import module namespace request = "http://exquery.org/ns/request"; declare namespace rest = 'http://exquery.org/ns/restxq'; @@ -28,13 +29,15 @@ function graphxq($dot,$url) { return $page }; -(:~ +(:~ +: return svg for dot, with download option :) declare %rest:path("graphxq/svg") %rest:form-param("dot","{$dot}") %rest:form-param("url","{$url}") %rest:form-param("dl","{$dl}") +%output:media-type("image/svg+xml") function graphxq-svg($dot,$url,$dl) { let $dot2:=getdot($dot,$url) let $svg:=get-svg($dot2) @@ -50,7 +53,9 @@ declare %rest:GET %rest:path("graphxq/dot") %output:method("html5") function dotform(){ - render("graphxq/views/dotform.xml",map{}) + let $map:=map{"list-shapes":=dotui:shapes(""), + "list-colors":=dotui:colors("")} + return render("graphxq/views/dotform.xml",$map) }; declare @@ -59,6 +64,7 @@ declare function dotmlform(){ render("graphxq/views/dotmlform.xml",map{}) }; + declare %rest:GET %rest:path("graphxq/about") %output:method("html5") @@ -82,7 +88,8 @@ declare %private function getdot($dot,$url) as xs:string{ try{fn:unparsed-text(fn:resolve-uri($url))} catch * { "digraph {{ failed to load remote }}" } else $dot -}; +}; + (:~ post process svg :) declare %private function get-svg($dot as xs:string) as node(){ let $svgx:=gr:dot($dot,()) diff --git a/src/graphxq/app.css b/src/graphxq/app.css index a058729..5d508d0 100644 --- a/src/graphxq/app.css +++ b/src/graphxq/app.css @@ -110,3 +110,4 @@ table.ret { width:6em; text-align: center } +form.form-table label {text-align:right} \ No newline at end of file diff --git a/src/graphxq/app.js b/src/graphxq/app.js index 47b3b1d..c6b198b 100644 --- a/src/graphxq/app.js +++ b/src/graphxq/app.js @@ -1,24 +1,92 @@ // common app js // sidebar -$(function() { $("time.relative-date").prettyDate(); }); + +// http://stackoverflow.com/questions/4583703/jquery-post-request-not-ajax +jQuery(function($) { $.extend({ + form: function(url, data, method) { + if (method == null) method = 'POST'; + if (data == null) data = {}; + + var form = $('
').attr({ + method: method, + action: url + }).css({ + display: 'none' + }); + + var addData = function(name, data) { + if ($.isArray(data)) { + for (var i = 0; i < data.length; i++) { + var value = data[i]; + addData(name + '[]', value); + } + } else if (typeof data === 'object') { + for (var key in data) { + if (data.hasOwnProperty(key)) { + addData(name + '[' + key + ']', data[key]); + } + } + } else if (data != null) { + form.append($('').attr({ + type: 'hidden', + name: String(name), + value: String(data) + })); + } + }; + + for (var key in data) { + if (data.hasOwnProperty(key)) { + addData(key, data[key]); + } + } + + return form.appendTo('body'); + } +}); }); + + $(document).ready(function(){ $("#bnup").on("click",getsvg); $("#bnsvg").on("click",function(){ $("#dotForm").submit()}); - $("#bndn").on("click",function(){alert("down")}); + $("#bndn").on("click",function(){getsvg(true)}); $("#dot").on("keyup",getsvg); }); -function getsvg(){ - $.post( - 'svg', - $("#dotForm").serialize(), - function(data){ +function getsvg(dl){ + var f=$("#dotForm").serializeArray() + var d=$("#frm-defaults").serializeArray() + console.log("#frm-default",d) + // if(dl)f.push({"name":"dl","value":1}) + $.ajax({ + type:"POST", + url:"svg", + data:f, + dataType: "text", + success: function(str){ // console.log(data) + var oParser = new DOMParser(); + var data = oParser.parseFromString(str, "text/xml"); // http://stackoverflow.com/questions/3346106/accessing-a-dom-object-defined-in-an-external-svg-file var n = document.importNode(data.documentElement,true); $("#svgdiv").empty().append(n); + $("#svgsrc").empty().text(str); } - ); + }); }; - +function dotit(){ +// xsvg.innerText=""; + var sdot="digraph G {\n"; + var t=f1.lstBgcolors.value; + if(t){ sdot+="bgcolor="+t+"\n"}; + var t=f1.lstShapes.value; + if(t){ sdot+="node[shape="+t+",style=filled,fillcolor="+f1.lstColors.value+"]\n"}; + var t=f1.dotTitle.value; + if(t) sdot+='label="'+t+'"\n'; + var t=f1.dotRankDir.value; + if(t) sdot+=t+'\n'; + var t=f1.dotBody.value; + sdot+=t+"\n}"; + update(sdot,f1.filter.value); +} diff --git a/src/graphxq/dotui.xml b/src/graphxq/dotui.xml new file mode 100644 index 0000000..318847c --- /dev/null +++ b/src/graphxq/dotui.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/graphxq/dotui.xqm b/src/graphxq/dotui.xqm new file mode 100644 index 0000000..1c6d46f --- /dev/null +++ b/src/graphxq/dotui.xqm @@ -0,0 +1,29 @@ +xquery version "3.0"; +(:~ +: dot UI lists +: @author andy bunce +: @since sept 2012 +:) + +module namespace dotui = 'apb.graphxq.dotui'; +declare default function namespace 'apb.graphxq.dotui'; +declare variable $dotui:config:=fn:doc("dotui.xml")/graphviz; + +declare function list($items,$select as xs:string){ + for $i in $items + let $name:=$i/fn:string() + order by $name + return +}; + +declare function shapes($select as xs:string){ + list($dotui:config/shapes/option,$select) +}; +declare function colors($select as xs:string){ + list($dotui:config/colors/option,$select) +}; \ No newline at end of file diff --git a/src/graphxq/jquery-svgpan.js b/src/graphxq/jquery-svgpan.js new file mode 100644 index 0000000..881c851 --- /dev/null +++ b/src/graphxq/jquery-svgpan.js @@ -0,0 +1,381 @@ +/** + THIS LICENSE IS FOR JQUERY-SVGPAN. The original SVGPan library, + from which it derived, is governed by the second license below. + + Copyright 2012 John Krauss. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY JOHN KRAUSS ''AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL JOHN KRAUSS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + + The views and conclusions contained in the software and + documentation are those of the authors and should not be + interpreted as representing official policies, either expressed or + implied, of John Krauss. +**/ + +// SVGPan library 1.2.2 license and documentation: + +/** + * SVGPan library 1.2.2 + * ====================== + * + * Given an unique existing element with id "viewport" (or when missing, the + * first g-element), including the the library into any SVG adds the following + * capabilities: + * + * - Mouse panning + * - Mouse zooming (using the wheel) + * - Object dragging + * + * You can configure the behaviour of the pan/zoom/drag with the variables + * listed in the CONFIGURATION section of this file. + * + * Known issues: + * + * - Zooming (while panning) on Safari has still some issues + * + * Releases: + * + * 1.2.2, Tue Aug 30 17:21:56 CEST 2011, Andrea Leofreddi + * - Fixed viewBox on root tag (#7) + * - Improved zoom speed (#2) + * + * 1.2.1, Mon Jul 4 00:33:18 CEST 2011, Andrea Leofreddi + * - Fixed a regression with mouse wheel (now working on Firefox 5) + * - Working with viewBox attribute (#4) + * - Added "use strict;" and fixed resulting warnings (#5) + * - Added configuration variables, dragging is disabled by default (#3) + * + * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui + * Fixed a bug with browser mouse handler interaction + * + * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui + * Updated the zoom code to support the mouse wheel on Safari/Chrome + * + * 1.0, Andrea Leofreddi + * First release + * + * This code is licensed under the following BSD license: + * + * Copyright 2009-2010 Andrea Leofreddi . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of Andrea Leofreddi. + */ + +/*global define, jQuery, window*/ + +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + "use strict"; + var NONE = 0, + PAN = 1, + DRAG = 2, + init = function (root, svgRoot, enablePan, enableZoom, enableDrag, zoomScale) { + + var state = NONE, + stateTarget, + stateOrigin, + stateTf, + svgDoc = root, + $root = $(root), + $parent = $root.parent(), + recentOffset = $root.offset(), + + // FF sometimes doesn't calculate this anything near correctly + // for SVGs. + offsetIsBroken = Math.abs($root.offset().left) > 1e5, + isMouseOverElem = false, + + /** + * Dumps a matrix to a string (useful for debug). + */ + dumpMatrix = function (matrix) { + var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "]"; + + return s; + }, + + /** + * Instance an SVGPoint object with given event coordinates. + */ + getEventPoint = function (evt) { + var p = root.createSVGPoint(), + offsetX = evt.offsetX, + offsetY = evt.offsetY, + offset, + ctm, + matrix; + + if (typeof offsetX === "undefined" || typeof offsetY === "undefined") { + offset = offsetIsBroken ? $parent.offset() : recentOffset; + offsetX = evt.pageX - offset.left; + offsetY = evt.pageY - offset.top; + } + + p.x = offsetX; + p.y = offsetY; + + return p; + }, + + /** + * Sets the current transform matrix of an element. + */ + setCTM = function (element, matrix) { + var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; + + element.setAttribute("transform", s); + }, + + /** + * Handle mouse wheel event. + */ + handleMouseWheel = function (evt) { + if (!enableZoom) { + return; + } + + if (!isMouseOverElem) { + return; + } + + if (evt.preventDefault) { + evt.preventDefault(); + } + + evt.returnValue = false; + recentOffset = $root.offset(); + + var delta = evt.wheelDelta ? evt.wheelDelta / 360 : evt.detail / -9, + z = Math.pow(1 + zoomScale, delta), + g = svgRoot, + p = getEventPoint(evt), + k; + + p = p.matrixTransform(g.getCTM().inverse()); + + // Compute new scale matrix in current mouse position + k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y); + + setCTM(g, g.getCTM().multiply(k)); + + if (typeof stateTf === "undefined") { + stateTf = g.getCTM().inverse(); + } + + stateTf = stateTf.multiply(k.inverse()); + }, + + /** + * Handle mouse move event. + */ + handleMouseMove = function (evt) { + + if (evt.preventDefault) { + evt.preventDefault(); + } + + evt.returnValue = false; + + var g = svgRoot, + p; + + if (state === PAN && enablePan) { + // Pan mode + p = getEventPoint(evt).matrixTransform(stateTf); + + setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y)); + } else if (state === DRAG && enableDrag) { + // Drag mode + p = getEventPoint(evt).matrixTransform(g.getCTM().inverse()); + + setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM())); + + stateOrigin = p; + } + }, + + /** + * Handle mouseenter event. This has been added to stop ignoring + * inputs when the mouse is over the element. + **/ + handleMouseEnter = function (evt) { + // bind our mousemove listener only when we have mouse in view + if (!isMouseOverElem) { + recentOffset = $root.offset(); + $root.bind('mousemove', handleMouseMove); + isMouseOverElem = true; + } + }, + + /** + * Handle mouseleave event. This has been added to ignore + * inputs when the mouse is not over the element. + **/ + handleMouseLeave = function (evt) { + // unbind our mousemove listener only when we no longer have mouse in view + if (isMouseOverElem) { + $root.unbind('mousemove', handleMouseMove); + isMouseOverElem = false; + } + state = NONE; + }, + + /** + * Handle click event. + */ + handleMouseDown = function (evt) { + if (evt.preventDefault) { + evt.preventDefault(); + } + + evt.returnValue = false; + + //var svgDoc = evt.target.ownerDocument; + + //var g = getRoot(svgDoc); + var g = svgRoot; + + // Pan anyway when drag is disabled and the user clicked on an element + if (evt.target.tagName === "svg" || !enableDrag) { + // Pan mode + state = PAN; + + stateTf = g.getCTM().inverse(); + + stateOrigin = getEventPoint(evt).matrixTransform(stateTf); + } else { + // Drag mode + state = DRAG; + + stateTarget = evt.target; + + stateTf = g.getCTM().inverse(); + + stateOrigin = getEventPoint(evt).matrixTransform(stateTf); + } + }, + + /** + * Handle mouse button release event. + */ + handleMouseUp = function (evt) { + if (evt.preventDefault) { + evt.preventDefault(); + } + + evt.returnValue = false; + + //var svgDoc = evt.target.ownerDocument; + + if (state === PAN || state === DRAG) { + // Quit pan mode + state = NONE; + } + }; + + /** + * Register handlers + */ + + // MODIFICATION: registers events through jQuery + $root.bind('mouseup', handleMouseUp) + .bind('mousedown', handleMouseDown) + .bind('mouseenter', handleMouseEnter) + .bind('mouseleave', handleMouseLeave); + + //if (navigator.userAgent.toLowerCase().indexOf('webkit') >= 0) { + + if ($.browser.webkit) { + window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari + } else if ($.browser.mozilla) { + window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Firefox + } else { + window.addEventListener('mousewheel', handleMouseWheel, false); // others (Opera, Explorer9) + } + + }; + + /** + Enable SVG panning on an SVG element. + + @param viewportId the ID of an element to use as viewport for pan. Required. + @param enablePan Boolean enable or disable panning (default enabled) + @param enableZoom Boolean enable or disable zooming (default enabled) + @param enableDrag Boolean enable or disable dragging (default disabled) + @param zoomScale Float zoom sensitivity, defaults to .2 + **/ + $.fn.svgPan = function (viewportId, enablePan, enableZoom, enableDrag, zoomScale) { + enablePan = typeof enablePan !== 'undefined' ? enablePan : true; + enableZoom = typeof enableZoom !== 'undefined' ? enableZoom : true; + enableDrag = typeof enableDrag !== 'undefined' ? enableDrag : false; + zoomScale = typeof zoomScale !== 'undefined' ? zoomScale : 0.2; + + return $.each(this, function (i, el) { + var $el = $(el), + svg, + viewport; + // only call upon elements that are SVGs and haven't already been initialized. + if ($el.is('svg') && $el.data('SVGPan') !== true) { + viewport = $el.find('#' + viewportId)[0]; + if (viewport) { + init($el[0], viewport, enablePan, enableZoom, enableDrag, zoomScale); + } else { + throw "Could not find viewport with id #" + viewport; + } + } + }); + }; +})); diff --git a/src/graphxq/views/dotform.xml b/src/graphxq/views/dotform.xml index 645492c..1c288b9 100644 --- a/src/graphxq/views/dotform.xml +++ b/src/graphxq/views/dotform.xml @@ -1,9 +1,10 @@
-
+
@@ -13,14 +14,50 @@
- digraph ""{{ - }} + + + }} +
-
...
+ +
+
+ + + + + + + + + +
+ + +
+
+
source
+
-
+
svg here
- +