diff --git a/main/css/d3.slider.css b/main/css/d3.slider.css new file mode 100755 index 0000000..8f6874c --- /dev/null +++ b/main/css/d3.slider.css @@ -0,0 +1,86 @@ +.d3-slider { + position: relative; + font-family: Verdana,Arial,sans-serif; + font-size: 1.1em; + border: 1px solid #aaaaaa; + z-index: 2; +} + +.d3-slider-horizontal { + height: .8em; +} + +.d3-slider-range { + background:#2980b9; + left:0px; + right:0px; + height: 0.8em; + position: absolute; +} + +.d3-slider-range-vertical { + background:#2980b9; + left:0px; + right:0px; + position: absolute; + top:0; +} + +.d3-slider-vertical { + width: .8em; + height: 100px; +} + +.d3-slider-handle { + position: absolute; + width: 1.2em; + height: 1.2em; + border: 1px solid #d3d3d3; + border-radius: 4px; + background: #eee; + background: linear-gradient(to bottom, #eee 0%, #ddd 100%); + z-index: 3; +} + +.d3-slider-handle:hover { + border: 1px solid #999999; +} + +.d3-slider-horizontal .d3-slider-handle { + top: -.3em; + margin-left: -.6em; +} + +.d3-slider-axis { + position: relative; + z-index: 1; +} + +.d3-slider-axis-bottom { + top: .8em; +} + +.d3-slider-axis-right { + left: .8em; +} + +.d3-slider-axis path { + stroke-width: 0; + fill: none; +} + +.d3-slider-axis line { + fill: none; + stroke: #aaa; + shape-rendering: crispEdges; +} + +.d3-slider-axis text { + font-size: 11px; +} + +.d3-slider-vertical .d3-slider-handle { + left: -.25em; + margin-left: 0; + margin-bottom: -.6em; +} \ No newline at end of file diff --git a/main/css/style.css b/main/css/style.css old mode 100644 new mode 100755 index d38747d..b635711 --- a/main/css/style.css +++ b/main/css/style.css @@ -11,14 +11,14 @@ } .countries_1783{ - fill: gray; - stroke: black; + fill: #d7c7ad; + stroke: #766951; stroke-width: .5px; } .countries_1815{ - fill: gray; - stroke: black; + fill: #d7c7ad; + stroke: #766951; stroke-width: .5px; } @@ -29,8 +29,8 @@ .dropdown { position: absolute; - top: 40px; - left: 425px; + top: 80px; + left: 20px; z-index: 10; font-family: baskerville; font-size: 1em; @@ -38,4 +38,72 @@ padding: 2px; border: 1px solid #999; box-shadow: 2px 2px 4px #999; -} \ No newline at end of file +} + +.dropdownProjections{ + position: absolute; + top: 130px; + left: 20px; + z-index: 10; + font-family: baskerville; + font-size: 1em; + font-weight: bold; + padding: 2px; + border: 1px solid #999; + box-shadow: 2px 2px 4px #999; +} + +#controls{ + height: 10%;; +} + +#slider{ + padding-top: 100px; + +} + +#map { + height: 90%; +} + +body { + background-color: white; + font-size: 14px; + font-family: 'Raleway', sans-serif; +} + +p { + color: white; + margin: 50px; +} + +a { + color: #4FDEF2; +} + +.axis { + fill: gray; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.axis .halo { + stroke: gray; + stroke-width: 4px; + stroke-linecap: round; +} + +.slider .handle path { + stroke: black; + stroke-width: 3px; + stroke-linecap: round; + pointer-events: none; +} + +.slider .handle text { + fill: gray; + text-align: center; + font-size: 18px; +} + diff --git a/main/data/land.topojson b/main/data/land.topojson old mode 100644 new mode 100755 diff --git a/main/data/prepros.cfg b/main/data/prepros.cfg old mode 100644 new mode 100755 diff --git a/main/data/worldCountries.topojson b/main/data/worldCountries.topojson old mode 100644 new mode 100755 diff --git a/main/index.html b/main/index.html old mode 100644 new mode 100755 index 5a0dcd9..bde5c13 --- a/main/index.html +++ b/main/index.html @@ -1,29 +1,41 @@ - - - - Wooden Ships + + + + Wooden Ships + + + + + + + + + - - - - + - +

Wooden Ships

- - - - - - - +
+
+
+ + + + + + + + + + + + - - - - + + + + \ No newline at end of file diff --git a/main/js/main.js b/main/js/main.js old mode 100644 new mode 100755 index b8dafa6..acf0407 --- a/main/js/main.js +++ b/main/js/main.js @@ -1,141 +1,146 @@ +///this is Wooden Ships Main Javascript File +//All functions are here + var attrArray = ["countries_1715", "countries_1783", "countries_1815"]; var expressed = attrArray[0] -console.log(expressed) -//load map -window.onload = setMap(); +var attrProj = ["VDG", "Mercator", "sat"]; // list of projections + +globals = {} +globals.basemap = {} +globals.map = {} +globals.map.dimensions ={}; +globals.map.dimensions.height = $(window).height() * 0.9; //90% of the window height +globals.map.dimensions.width = $(window).width() //100% of the window width + + +globals.map.projection; +globals.map.path; + +var expressedProj = attrProj[0]; + + + +$(document).ready(function(){ + //stuff that happens as the map is created. + setMap(); //creates the map + createDropdown(attrArray); //creates the dropdown menu for years/basemap + projDropdown(attrProj); //creates the dropdown menu for projection + zoomed(); //allows map to zoom + createSlider(); //creates temporal slider + changeTime(date) //changes time on slider +}) + //set up map and call data function setMap(){ - //map frame dimensions - var width = window.innerWidth * 1, - height = 550; + //create new svg container for the map + globals.map.mapContainer = mapContainer = d3.select("#map") + .append("svg") + .attr("class", "mapContainer") + .attr("width", globals.map.dimensions.width) + .attr("height", globals.map.dimensions.width); - //create new svg container for the map - var mapContainer = d3.select("body") - .append("svg") - .attr("class", "mapContainer") - .attr("width", width) - .attr("height", height); + var zoom = d3.behavior.zoom() + .translate([0, 0]) + .scale(1) + .scaleExtent([1, 2]) //change scale here (default is 1 constrained at zoom level 2) + .on("zoom", zoomed); - var projection = d3.geo.vanDerGrinten4() - .scale(125) - .translate([width / 2, height / 2]) - .precision(.1); + console.log(zoom.scale()); + + //use queue.js to parallelize asynchronous data loading + d3_queue.queue() + .defer(d3.json, "data/land.topojson") //load base map data + .defer(d3.json, "data/cntry1715.topojson") //load overlay spatial data of countries + .defer(d3.json, "data/cntry1783.topojson") //load overlay spatial data of countries + .defer(d3.json, "data/cntry1815.topojson") //load overlay spatial data of countries + .await(callback); + + function callback(error, base, overlay1, overlay2, overlay3){ + //happens once the ajax have returned + console.log(error); + console.log(base); + + //translate europe TopoJSON + var landBase = topojson.feature(base, base.objects.ne_110m_land).features, + countriesOverlay1 = topojson.feature(overlay1, overlay1.objects.cntry1715).features; + countriesOverlay2 = topojson.feature(overlay2, overlay2.objects.cntry1783).features; + countriesOverlay3 = topojson.feature(overlay3, overlay3.objects.cntry1815).features; + + var countries_1715 = mapContainer.selectAll(".countries_1715") + .data(countriesOverlay1) + .enter() + .append("path") + .attr("class", function(d){ + return "countries_1715 " + d.properties.name; + }) + .call(zoom); + + globals.countries = countries_1715; + + globals.land = mapContainer.append("path") + .datum(landBase) + .attr("class", "land") + .call(zoom); + + changeProjection("VDG"); + }; //end of callback + +};//end of set map + +function zoomed() { + mapContainer.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); + mapContainer.selectAll(".land").style("stroke-width", 1.5 / d3.event.scale + "px"); + mapContainer.selectAll(".countries").style("stroke-width", .5 / d3.event.scale + "px"); +}; - var path = d3.geo.path() - .projection(projection); - - //use queue.js to parallelize asynchronous data loading - d3_queue.queue() - .defer(d3.json, "data/land.topojson") //load base map data - .defer(d3.json, "data/cntry1715.topojson") //load overlay spatial data of countries - .defer(d3.json, "data/cntry1783.topojson") //load overlay spatial data of countries - .defer(d3.json, "data/cntry1815.topojson") //load overlay spatial data of countries - .await(callback); - - function callback(error, base, overlay1, overlay2, overlay3){ - console.log(error); - console.log(base); - - //translate europe TopoJSON - var landBase = topojson.feature(base, base.objects.ne_110m_land), - countriesOverlay1 = topojson.feature(overlay1, overlay1.objects.cntry1715).features; - countriesOverlay2 = topojson.feature(overlay2, overlay2.objects.cntry1783).features; - countriesOverlay3 = topojson.feature(overlay3, overlay3.objects.cntry1815).features; - - //examine the results - console.log(landBase); - //examine the results - - //add France regions to map - var countries_1715 = mapContainer.selectAll(".countries_1715") - .data(countriesOverlay1) - .enter() - .append("path") - .attr("class", function(d){ - return "countries_1715 " + d.properties.name; - }) - .attr("d", path); - - //add France regions to map - // var countries_1783 = mapContainer.selectAll(".countries_1783") -// .data(countriesOverlay2) -// .enter() -// .append("path") -// .attr("class", function(d){ -// return "countries_1783 " + d.properties.name; -// }) -// .attr("d", path); - - //add France regions to map -// var countries_1815 = mapContainer.selectAll(".countries_1815") -// .data(countriesOverlay3) -// .enter() -// .append("path") -// .attr("class", function(d){ -// return "countries_1815 " + d.properties.name; -// }) -// .attr("d", path); - - //add Europe countries to map - var land = mapContainer.append("path") - .datum(landBase) - .attr("class", "land") - .attr("d", path); - //dropdown change listener handler +//dropdown change listener handler function changeAttribute(attribute){ //change the expressed attribute expressed = attribute; - console.log(expressed); if (expressed == attrArray[0]) { - console.log("hi") - //add France regions to map - var expressed = mapContainer.selectAll("." + expressed) + var expressed = globals.map.mapContainer.selectAll("." + expressed) .data(countriesOverlay1) .enter() .append("path") .attr("class", function(d){ return "countries_1715 " + d.properties.name; }) - .attr("d", path); + .attr("d", globals.map.path); } else if (expressed == attrArray[1]) { - console.log("hi") - //add France regions to map - var expressed = mapContainer.selectAll("." + expressed) + var expressed = globals.map.mapContainer.selectAll("." + expressed) .data(countriesOverlay2) .enter() .append("path") .attr("class", function(d){ return "countries_1783 " + d.properties.name; }) - .attr("d", path); + .attr("d", globals.map.path); } else { - console.log("hi") - var expressed = mapContainer.selectAll("." + expressed) + var expressed = globals.map.mapContainer.selectAll("." + expressed) .data(countriesOverlay3) .enter() .append("path") .attr("class", function(d){ return "countries_1815 " + d.properties.name; }) - .attr("d", path); - + .attr("d", globals.map.path); } - - }; + + //function to create a dropdown menu for attribute selection function createDropdown(attrArray){ //add select element - var dropdown = d3.select("body") + var dropdown = d3.select("#controls") .append("select") .attr("class", "dropdown") .on("change", function(){ @@ -156,51 +161,227 @@ function createDropdown(attrArray){ .attr("value", function(d){ return d }) .text(function(d){ return d }); }; + + + + +//function to create a dropdown menu for attribute selection +function projDropdown(attrProj){ + //add select element + var dropdownProjections = d3.select("#controls") + .append("select") + .attr("class", "dropdownProjections") + .on("change", function(){ + if (this.value == "Mercator"){ + changeProjection("mercator") + }else if (this.value == "VDG"){ + changeProjection("VDG"); + }else if(this.value == "sat"){ + changeProjection("sat") + } + }); + + //add initial option + var titleOption = dropdownProjections.append("option") + .attr("class", "titleOption") + .attr("disabled", "true") + .text("Projection"); + + //add attribute name options + var projOptions = dropdownProjections.selectAll("projOptions") + .data(attrProj) + .enter() + .append("option") + .attr("value", function(d){ return d }) + .text(function(d){ return d }); +}; - createDropdown(attrArray); + - }; + +//dropdown change listener handler +function changeProjection(projection, scale, center){ + //decide what projection to change to + if (projection == "VDG") { + var projection = d3.geo.vanDerGrinten4() + .scale(125) + .translate([globals.map.dimensions.width / 2, globals.map.dimensions.height / 2]) + .precision(.1); + } + else if (projection == "mercator"){ + var projection = d3.geo.mercator() + .scale((globals.map.dimensions.width + 1) / 2 / Math.PI) + .translate([globals.map.dimensions.width / 2, globals.map.dimensions.height / 2]) + .precision(.1); + + } + else if (projection == "sat"){ + var projection = d3.geo.satellite() + .distance(1.1) + .scale(5500) + .rotate([76.00, -34.50, 32.12]) + .center([-120, 37]) + .tilt(25) + .clipAngle(Math.acos(1 / 1.1) * 180 / Math.PI - 1e-6) + .precision(.1); + } + var path = d3.geo.path() + .projection(projection); + //make global + globals.map.projection = projection; + globals.map.path = path; + //do the update + globals.countries.transition().attr('d', path) + globals.land.transition().attr('d', path) }; +//function createSlider(){ + formatDate = d3.time.format("%Y"); + + // parameters + var margin = { + top: 50, + right: 50, + bottom: 50, + left: 50 + }, + width = 400 - margin.left - margin.right, + height = 100 - margin.bottom - margin.top; + + // scale function + var timeScale = d3.time.scale() + .domain([new Date('1700-01-02'), new Date('1851-01-01')]) + .range([0, width]) + .clamp(true); + + // initial value + var startValue = timeScale(new Date('1700-03-20')); + startingValue = new Date('1700-03-20'); + + ////////// + + // defines brush + var brush = d3.svg.brush() + .x(timeScale) + .extent([startingValue, startingValue]) + .on("brush", brushed); + + var svg = d3.select("#slider").append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + // classic transform to position g + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + svg.append("g") + .attr("class", "x axis") + // put in middle of screen + .attr("transform", "translate(0," + height / 2 + ")") + // inroduce axis + .call(d3.svg.axis() + .scale(timeScale) + .orient("bottom") + .tickFormat(function(d) { + return formatDate(d); + }) + .tickSize(0) + .tickPadding(12) + .tickValues([timeScale.domain()[0], timeScale.domain()[1]])) + .select(".domain") + .select(function() { + console.log(this); + return this.parentNode.appendChild(this.cloneNode(true)); + }) + .attr("class", "halo"); + + var slider = svg.append("g") + .attr("class", "slider") + .call(brush); + + slider.selectAll(".extent,.resize") + .remove(); + + slider.select(".background") + .attr("height", height); + + var handle = slider.append("g") + .attr("class", "handle") + + handle.append("path") + .attr("transform", "translate(0," + height / 2 + ")") + .attr("d", "M 0 -20 V 20") + + handle.append('text') + .text(startingValue) + .attr("transform", "translate(" + (-18) + " ," + (height / 2 - 25) + ")"); + + slider + .call(brush.event) + + function brushed() { + var value = brush.extent()[0]; + + if (d3.event.sourceEvent) { // not a programmatic event + value = timeScale.invert(d3.mouse(this)[0]); + brush.extent([value, value]); + } + + handle.attr("transform", "translate(" + timeScale(value) + ",0)"); + handle.select('text').text(formatDate(value)); + } +// }; // end createSlider function + +function changeTime(date){ + + var expressedTime = d3.selectAll("#map") + .attr("stroke", "none") + .attr("fill", "none"); + + if (timeScale < Date('1783-01-02')){ + + var expressed = globals.map.mapContainer.selectAll("." + expressed) + .data(countriesOverlay1) + .enter() + .append("path") + .attr("class", function(d){ + return "countries_1715 " + d.properties.name; + }) + .attr("d", globals.map.path) + .attr("stroke", red) + .attr("fill", red); + } + }; + + else if (timeScale < Date('1815-01-02')){ + + var expressed = globals.map.mapContainer.selectAll("." + expressed) + .data(countriesOverlay2) + .enter() + .append("path") + .attr("class", function(d){ + return "countries_1783 " + d.properties.name; + }) + .attr("d", globals.map.path) + .attr("stroke", red) + .attr("fill", red); + } + + else if (timeScale < Date('1815-01-02')){ + + var expressed = globals.map.mapContainer.selectAll("." + expressed) + .data(countriesOverlay3) + .enter() + .append("path") + .attr("class", function(d){ + return "countries_1815 " + d.properties.name; + }) + .attr("d", globals.map.path) + .attr("stroke", red) + .attr("fill", red); + } +}; //end changeTime function -// set_projection(new Option("Mercator", "mercator", false, false)); -// -// function set_projection(option) { -// proj = option.value -// -// projection = eval("d3.geo."+proj+"();"); -// -// path = d3.geo.path() -// .projection(projection); -// -// svg.countries_1715.selectAll("path").transition() -// .duration(1000) -// .attr("d", path); -// } -// -// function projection_selected(e){ -// set_projection(e.target[e.target.selectedIndex]) -// } -// -// var newSelect = document.createElement("select"); -// newSelect.id = "selectlistid"; // add some attributes -// newSelect.onchange = projection_selected; // call the somethingChanged function when a change is made -// newSelect[newSelect.length] = new Option("Aitoff","aitoff",false, false) -// newSelect[newSelect.length] = new Option("Albers equal-area conic","albers",false, false); -// newSelect[newSelect.length] = new Option("Armadillo","armadillo",false, false); -// newSelect[newSelect.length] = new Option("August conformal","august",false, false); -// newSelect[newSelect.length] = new Option("Lambert azimuthal equal-area","azimuthalEqualArea",false, false); -// newSelect[newSelect.length] = new Option("azimuthal equidistant","azimuthalEquidistant",false, false); -// newSelect[newSelect.length] = new Option("Baker Dinomic","baker",false, false); -// newSelect[newSelect.length] = new Option("Berghaus Star","berghaus",false, false); -// newSelect[newSelect.length] = new Option("Boggs eumorphic","boggs",false, false); -// newSelect[newSelect.length] = new Option("Bonne","bonne",false, false); -// -// newSelect[newSelect.length] = new Option("Mercator","mercator",false, true); -// -// //document.getElementById('myDiv').appendChild(newSelect); // myDiv is the container to hold the select list -// diff --git a/main/lib/d3-queue.v2.min.js b/main/lib/d3-queue.v2.min.js old mode 100644 new mode 100755 diff --git a/main/lib/d3.min.js b/main/lib/d3.min.js old mode 100644 new mode 100755 diff --git a/main/lib/d3.slider.js b/main/lib/d3.slider.js new file mode 100755 index 0000000..d9e3c58 --- /dev/null +++ b/main/lib/d3.slider.js @@ -0,0 +1,427 @@ +/* + D3.js Slider + Inspired by jQuery UI Slider + Copyright (c) 2013, Bjorn Sandvik - http://blog.thematicmapping.org + BSD license: http://opensource.org/licenses/BSD-3-Clause +*/ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['d3'], factory); + } else if (typeof exports === 'object') { + if (process.browser) { + // Browserify. Import css too using cssify. + require('./d3.slider.css'); + } + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(require('d3')); + } else { + // Browser globals (root is window) + root.d3.slider = factory(root.d3); + } +}(this, function (d3) { +return function module() { + "use strict"; + + // Public variables width default settings + var min = 0, + max = 100, + step = 0.01, + animate = true, + orientation = "horizontal", + axis = false, + margin = 50, + value, + active = 1, + snap = false, + scale; + + // Private variables + var axisScale, + dispatch = d3.dispatch("slide", "slideend"), + formatPercent = d3.format(".2%"), + tickFormat = d3.format(".0"), + handle1, + handle2 = null, + divRange, + sliderLength; + + function slider(selection) { + selection.each(function() { + + // Create scale if not defined by user + if (!scale) { + scale = d3.scale.linear().domain([min, max]); + } + + // Start value + value = value || scale.domain()[0]; + + // DIV container + var div = d3.select(this).classed("d3-slider d3-slider-" + orientation, true); + + var drag = d3.behavior.drag(); + drag.on('dragend', function () { + dispatch.slideend(d3.event, value); + }) + + // Slider handle + //if range slider, create two + // var divRange; + + if (toType(value) == "array" && value.length == 2) { + handle1 = div.append("a") + .classed("d3-slider-handle", true) + .attr("xlink:href", "#") + .attr('id', "handle-one") + .on("click", stopPropagation) + .call(drag); + handle2 = div.append("a") + .classed("d3-slider-handle", true) + .attr('id', "handle-two") + .attr("xlink:href", "#") + .on("click", stopPropagation) + .call(drag); + } else { + handle1 = div.append("a") + .classed("d3-slider-handle", true) + .attr("xlink:href", "#") + .attr('id', "handle-one") + .on("click", stopPropagation) + .call(drag); + } + + // Horizontal slider + if (orientation === "horizontal") { + + div.on("click", onClickHorizontal); + + if (toType(value) == "array" && value.length == 2) { + divRange = d3.select(this).append('div').classed("d3-slider-range", true); + + handle1.style("left", formatPercent(scale(value[ 0 ]))); + divRange.style("left", formatPercent(scale(value[ 0 ]))); + drag.on("drag", onDragHorizontal); + + var width = 100 - parseFloat(formatPercent(scale(value[ 1 ]))); + handle2.style("left", formatPercent(scale(value[ 1 ]))); + divRange.style("right", width+"%"); + drag.on("drag", onDragHorizontal); + + } else { + handle1.style("left", formatPercent(scale(value))); + drag.on("drag", onDragHorizontal); + } + + sliderLength = parseInt(div.style("width"), 10); + + } else { // Vertical + + div.on("click", onClickVertical); + drag.on("drag", onDragVertical); + if (toType(value) == "array" && value.length == 2) { + divRange = d3.select(this).append('div').classed("d3-slider-range-vertical", true); + + handle1.style("bottom", formatPercent(scale(value[ 0 ]))); + divRange.style("bottom", formatPercent(scale(value[ 0 ]))); + drag.on("drag", onDragVertical); + + var top = 100 - parseFloat(formatPercent(scale(value[ 1 ]))); + handle2.style("bottom", formatPercent(scale(value[ 1 ]))); + divRange.style("top", top+"%"); + drag.on("drag", onDragVertical); + + } else { + handle1.style("bottom", formatPercent(scale(value))); + drag.on("drag", onDragVertical); + } + + sliderLength = parseInt(div.style("height"), 10); + + } + + if (axis) { + createAxis(div); + } + + + function createAxis(dom) { + + // Create axis if not defined by user + if (typeof axis === "boolean") { + + axis = d3.svg.axis() + .ticks(Math.round(sliderLength / 100)) + .tickFormat(tickFormat) + .orient((orientation === "horizontal") ? "bottom" : "right"); + + } + + // Copy slider scale to move from percentages to pixels + axisScale = scale.ticks ? scale.copy().range([0, sliderLength]) : scale.copy().rangePoints([0, sliderLength], 0.5); + axis.scale(axisScale); + + // Create SVG axis container + var svg = dom.append("svg") + .classed("d3-slider-axis d3-slider-axis-" + axis.orient(), true) + .on("click", stopPropagation); + + var g = svg.append("g"); + + // Horizontal axis + if (orientation === "horizontal") { + + svg.style("margin-left", -margin + "px"); + + svg.attr({ + width: sliderLength + margin * 2, + height: margin + }); + + if (axis.orient() === "top") { + svg.style("top", -margin + "px"); + g.attr("transform", "translate(" + margin + "," + margin + ")"); + } else { // bottom + g.attr("transform", "translate(" + margin + ",0)"); + } + + } else { // Vertical + + svg.style("top", -margin + "px"); + + svg.attr({ + width: margin, + height: sliderLength + margin * 2 + }); + + if (axis.orient() === "left") { + svg.style("left", -margin + "px"); + g.attr("transform", "translate(" + margin + "," + margin + ")"); + } else { // right + g.attr("transform", "translate(" + 0 + "," + margin + ")"); + } + + } + + g.call(axis); + + } + + function onClickHorizontal() { + if (toType(value) != "array") { + var pos = Math.max(0, Math.min(sliderLength, d3.event.offsetX || d3.event.layerX)); + moveHandle(scale.invert ? + stepValue(scale.invert(pos / sliderLength)) + : nearestTick(pos / sliderLength)); + } + } + + function onClickVertical() { + if (toType(value) != "array") { + var pos = sliderLength - Math.max(0, Math.min(sliderLength, d3.event.offsetY || d3.event.layerY)); + moveHandle(scale.invert ? + stepValue(scale.invert(pos / sliderLength)) + : nearestTick(pos / sliderLength)); + } + } + + function onDragHorizontal() { + if ( d3.event.sourceEvent.target.id === "handle-one") { + active = 1; + } else if ( d3.event.sourceEvent.target.id == "handle-two" ) { + active = 2; + } + var pos = Math.max(0, Math.min(sliderLength, d3.event.x)); + moveHandle(scale.invert ? + stepValue(scale.invert(pos / sliderLength)) + : nearestTick(pos / sliderLength)); + } + + function onDragVertical() { + if ( d3.event.sourceEvent.target.id === "handle-one") { + active = 1; + } else if ( d3.event.sourceEvent.target.id == "handle-two" ) { + active = 2; + } + var pos = sliderLength - Math.max(0, Math.min(sliderLength, d3.event.y)) + moveHandle(scale.invert ? + stepValue(scale.invert(pos / sliderLength)) + : nearestTick(pos / sliderLength)); + } + + function stopPropagation() { + d3.event.stopPropagation(); + } + + }); + + } + + // Move slider handle on click/drag + function moveHandle(newValue) { + var currentValue = toType(value) == "array" && value.length == 2 ? value[active - 1]: value, + oldPos = formatPercent(scale(stepValue(currentValue))), + newPos = formatPercent(scale(stepValue(newValue))), + position = (orientation === "horizontal") ? "left" : "bottom"; + if (oldPos !== newPos) { + + if (toType(value) == "array" && value.length == 2) { + value[ active - 1 ] = newValue; + if (d3.event) { + dispatch.slide(d3.event, value ); + }; + } else { + if (d3.event) { + dispatch.slide(d3.event.sourceEvent || d3.event, value = newValue); + }; + } + + if ( value[ 0 ] >= value[ 1 ] ) return; + if ( active === 1 ) { + if (toType(value) == "array" && value.length == 2) { + (position === "left") ? divRange.style("left", newPos) : divRange.style("bottom", newPos); + } + + if (animate) { + handle1.transition() + .styleTween(position, function() { return d3.interpolate(oldPos, newPos); }) + .duration((typeof animate === "number") ? animate : 250); + } else { + handle1.style(position, newPos); + } + } else { + + var width = 100 - parseFloat(newPos); + var top = 100 - parseFloat(newPos); + + (position === "left") ? divRange.style("right", width + "%") : divRange.style("top", top + "%"); + + if (animate) { + handle2.transition() + .styleTween(position, function() { return d3.interpolate(oldPos, newPos); }) + .duration((typeof animate === "number") ? animate : 250); + } else { + handle2.style(position, newPos); + } + } + } + } + + // Calculate nearest step value + function stepValue(val) { + + if (val === scale.domain()[0] || val === scale.domain()[1]) { + return val; + } + + var alignValue = val; + if (snap) { + alignValue = nearestTick(scale(val)); + } else{ + var valModStep = (val - scale.domain()[0]) % step; + alignValue = val - valModStep; + + if (Math.abs(valModStep) * 2 >= step) { + alignValue += (valModStep > 0) ? step : -step; + } + }; + + return alignValue; + + } + + // Find the nearest tick + function nearestTick(pos) { + var ticks = scale.ticks ? scale.ticks() : scale.domain(); + var dist = ticks.map(function(d) {return pos - scale(d);}); + var i = -1, + index = 0, + r = scale.ticks ? scale.range()[1] : scale.rangeExtent()[1]; + do { + i++; + if (Math.abs(dist[i]) < r) { + r = Math.abs(dist[i]); + index = i; + }; + } while (dist[i] > 0 && i < dist.length - 1); + + return ticks[index]; + }; + + // Return the type of an object + function toType(v) { + return ({}).toString.call(v).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); + }; + + // Getter/setter functions + slider.min = function(_) { + if (!arguments.length) return min; + min = _; + return slider; + }; + + slider.max = function(_) { + if (!arguments.length) return max; + max = _; + return slider; + }; + + slider.step = function(_) { + if (!arguments.length) return step; + step = _; + return slider; + }; + + slider.animate = function(_) { + if (!arguments.length) return animate; + animate = _; + return slider; + }; + + slider.orientation = function(_) { + if (!arguments.length) return orientation; + orientation = _; + return slider; + }; + + slider.axis = function(_) { + if (!arguments.length) return axis; + axis = _; + return slider; + }; + + slider.margin = function(_) { + if (!arguments.length) return margin; + margin = _; + return slider; + }; + + slider.value = function(_) { + if (!arguments.length) return value; + if (value) { + moveHandle(stepValue(_)); + }; + value = _; + return slider; + }; + + slider.snap = function(_) { + if (!arguments.length) return snap; + snap = _; + return slider; + }; + + slider.scale = function(_) { + if (!arguments.length) return scale; + scale = _; + return slider; + }; + + d3.rebind(slider, dispatch, "on"); + + return slider; + +} +})); diff --git a/main/prepros.cfg b/main/prepros.cfg old mode 100644 new mode 100755 index 5174634..96d1aee --- a/main/prepros.cfg +++ b/main/prepros.cfg @@ -20,27 +20,27 @@ "parents": [], "type": "html" }, - "0c7b55b5": { - "id": "0c7b55b5", - "path": "css/style.css", - "output": "css/style-dist.css", - "name": "style.css", - "category": "CSS", + "deb94307": { + "id": "deb94307", + "path": "lib/d3-queue.v2.min.js", + "output": "lib/d3-queue.v2.min-dist.js", + "name": "d3-queue.v2.min.js", + "category": "JS", "autoCompile": false, + "uglify": true, + "mangle": true, + "babel": false, "sourceMaps": false, - "compress": true, - "cssnext": false, - "autoprefixer": false, "customOutput": false, "imported": false, "parents": [], - "type": "css" + "type": "javascript" }, - "50ef0fa9": { - "id": "50ef0fa9", - "path": "js/main.js", - "output": "js/main-dist.js", - "name": "main.js", + "c19791d0": { + "id": "c19791d0", + "path": "lib/d3.geo.projection.min.js", + "output": "lib/d3.geo.projection.min-dist.js", + "name": "d3.geo.projection.min.js", "category": "JS", "autoCompile": false, "uglify": true, @@ -52,27 +52,27 @@ "parents": [], "type": "javascript" }, - "deb94307": { - "id": "deb94307", - "path": "lib/d3-queue.v2.min.js", - "output": "lib/d3-queue.v2.min-dist.js", - "name": "d3-queue.v2.min.js", - "category": "JS", + "0c7b55b5": { + "id": "0c7b55b5", + "path": "css/style.css", + "output": "css/style-dist.css", + "name": "style.css", + "category": "CSS", "autoCompile": false, - "uglify": true, - "mangle": true, - "babel": false, "sourceMaps": false, + "compress": true, + "cssnext": false, + "autoprefixer": false, "customOutput": false, "imported": false, "parents": [], - "type": "javascript" + "type": "css" }, - "c19791d0": { - "id": "c19791d0", - "path": "lib/d3.geo.projection.min.js", - "output": "lib/d3.geo.projection.min-dist.js", - "name": "d3.geo.projection.min.js", + "50ef0fa9": { + "id": "50ef0fa9", + "path": "js/main.js", + "output": "js/main-dist.js", + "name": "main.js", "category": "JS", "autoCompile": false, "uglify": true, @@ -131,6 +131,38 @@ "imported": false, "parents": [], "type": "javascript" + }, + "f5509667": { + "id": "f5509667", + "path": "lib/d3.slider.js", + "output": "lib/d3.slider-dist.js", + "name": "d3.slider.js", + "category": "JS", + "autoCompile": false, + "uglify": true, + "mangle": true, + "babel": false, + "sourceMaps": false, + "customOutput": false, + "imported": false, + "parents": [], + "type": "javascript" + }, + "37318a5d": { + "id": "37318a5d", + "path": "css/d3.slider.css", + "output": "css/d3.slider-dist.css", + "name": "d3.slider.css", + "category": "CSS", + "autoCompile": false, + "sourceMaps": false, + "compress": true, + "cssnext": false, + "autoprefixer": false, + "customOutput": false, + "imported": false, + "parents": [], + "type": "css" } }, "deploymentHistory": {},