XForms/Supply and Demand
< XForms
Motivation
editYou want to create a simple illustration of a concept using a dynamic graph. You want to use a range control to change in input and see the impact of that change on an output.
Screen Image
editSample Program
editThis is not working yet with the range control. I wrote it with just SVG and JavaScript and I am in the process of porting it to XForms. I also need to use CSS to clean up the markup.
<?xml version="1.0" encoding="utf-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"> <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="300" height="450" onload="OnLoadEvent(evt)"> <defs> <g id="arrowMarker"> <g stroke="black" stroke-width="1"> <line x1="6" y1="-2" x2="0" y2="0"/> <line x1="6" y1="+2" x2="0" y2="0"/> </g> </g> <marker id="startMarker" markerWidth="48" markerHeight="24" viewBox="-4 -4 25 5" orient="auto" refX="0" refY="0" markerUnits="strokeWidth"> <g> <use xlink:href="#arrowMarker" transform="rotate(180)" stroke-width="1" stroke="black"/> </g> </marker> </defs> <!-- Title --> <text x="125" y="30" style="text-anchor:middle; font-family:Ariel-Narrow; font-weight:bold; font-size:18">Price and Demand</text> <!-- bounding box including all elements --> <rect x="10" y="10" width="250" height="430" style="stroke:black; stroke-width:2; fill:none"/> <!-- all drawing is done with the origin being at (0,0) --> <!-- graph itself --> <g transform="translate(30 40)"> <!-- vertical price axis --> <line x1="0" x2="0" y1="200" y2="0" style="fill:none;stroke:black;stroke-width:1;" marker-end="url(#startMarker)"/> <text x="15" y="10">P</text> <!-- horizontal axis quantity--> <line x1="0" x2="200" y1="200" y2="200" style="fill:none;stroke:black;stroke-width:1;" marker-end="url(#startMarker)"/> <text x="205" y="205">Q</text> <!-- fixed demmand curve --> <path id="demmand_curve" style="stroke:red; stroke-width:3" d="M0,0 200,200"/> <text x="120" y="-10" transform="rotate(45)">Demand</text> <!-- initial value of price --> <circle id="newPrice" cx="0" cy="100" r="4" style="stroke:blue; fill:blue"/> <text id="priceLabel" x="163" y="20" style="text-anchor:end">Input: Price =</text> <text id="priceText" x="163" y="20">100</text> <text id="quantityLabel" x="163" y="35" style="text-anchor:end">Output: Quantity =</text> <text id="quantityText" x="163" y="35">100</text> <line id="vertLine" x1="100" y1="100" x2="100" y2="200" style="stroke-dasharray: 1, 4;stroke:black;stroke-width:1; "/> <line id="horizLine" x1="0" y1="100" x2="100" y2="100" style="stroke-dasharray: 1, 4;stroke:black;stroke-width:1; "/> <g id="explanation" transform="translate(0 260)"> <text x="10" y="0">Adjust price by moving the slider.</text> <text x="0" y="50">Note that as the input (price) changes.</text> <text x="10" y="65">the quantity sold also changes.</text> <text x="0" y="90">At high prices a low quantity is sold.</text> <text x="0" y="110">At low prices a high quantity is sold.</text> </g> <g id="slider" transform="translate(0 220)" xoffset="30"> <rect x="0" y="0" width="210" height="20" style="fill:#c0c0c0"/> <line style="stroke:black;stroke-width:2;" x1="5" y1="6" x2="205" y2="6"/> <line style="stroke:white;stroke-width:2;" x1="5" y1="8" x2="205" y2="8"/> <path style="stroke:black;fill:none;" d="M5,16 5,20 M25,16 25,20 M45,16 45,20 M65,16 65,20 M85,16 85,20 M105,16 105,20 M125,16 125,20 M145,16 145,20 M165,16 165,20 M185,16 185,20 M205,16 205,20"/> <g id="thumb" transform="translate(100 0)"> <path style="stroke:none;fill:#c0c0c0;" d="M1,2 1,12 5,15 9,12 9,2 Z"/> <path style="stroke:white;fill:none;" d="M9,1 1,1 1,11"/> <path style="stroke:black;fill:none;" d="M5,16 10,12 10,2"/> </g> <g id="explanation" transform="translate(20 230)"> <text x="0" y="0">Note that as the input (price) moves, the quantity sold changes.</text> <text x="0" y="20">At high prices a low quantity is sold.</text> <text x="0" y="40">At low prices a high low quantity is sold.</text> </g> </g> </g> <script><![CDATA[ // == Slider object based on version by Dr. Stefan Goessner at http://www.mecxpert.de/svg/slider.html var slider=null, thumb=null, sliderActive = false; var newPrice=null, priceText=null, quantityText=null, vertLine=null, horizLine=null; // ----------------------------------------------------------- function SliderDown(event) { sliderActive = true; } function SliderUp(event) { sliderActive = false; // window.status = "slider is inactive"; } function SliderMove(event) { var value = event.getClientX() - parseFloat(slider.getAttribute("xoffset")) - 4; if (sliderActive && value > 0 && value < 200) { thumb.setAttribute("transform", "translate(" + (value) + " 0)"); SliderCallback(value); } } function SliderClick(event) { var value = event.getClientX() - parseFloat(slider.getAttribute("xoffset")) - 4; if (value > 0 && value < 200) { thumb.setAttribute("transform", "translate(" + (value) + " 0)"); SliderCallback(value); } } function SliderCallback(val) { // this is where we change the values newPrice.setAttribute("cy", val); horizLine.setAttribute("y1", val); horizLine.setAttribute("y2", val); horizLine.setAttribute("x2", val); vertLine.setAttribute("x1", val); vertLine.setAttribute("x2", val); vertLine.setAttribute("y1", val); priceText.firstChild.nodeValue=(200-val); quantityText.firstChild.nodeValue=(val); //= Math.round((val*1000)/1000); window.status = "price is " + (val); } function OnLoadEvent(event) // called, when svg file is loaded (s. onLoad=..) .. { var doc = event.getTarget() != null ? event.getTarget().getOwnerDocument() : null; if (doc != null) { slider = doc.getElementById("slider"); thumb = doc.getElementById("thumb"); newPrice = doc.getElementById("newPrice"); priceText = doc.getElementById("priceText"); quantityText = doc.getElementById("quantityText"); vertLine = doc.getElementById("vertLine"); horizLine = doc.getElementById("horizLine"); slider.addEventListener("mousedown", SliderDown, false); slider.addEventListener("mouseup", SliderUp, false); slider.addEventListener("mousemove", SliderMove, false); slider.addEventListener("click", SliderClick, false); } } ]]></script> </svg> <header> <xf:model> <xf:instance xmlns=""> <data> <price>100</price> </data> </xf:instance> </xf:model> </header> <body> <xf:range ref="price" start="0" end="200" step="1"> <xf:label>Price: </xf:label> </xf:range> <xf:output ref="price" > <xf:label>Price: </xf:label> </xf:output> </body> </html>