├── LICENSE ├── README.md ├── bin └── compile.sh ├── dist ├── 0.1 │ ├── css │ │ ├── crosslet-min.css │ │ └── crosslet.css │ └── js │ │ ├── crosslet-min.js │ │ ├── crosslet-raw-min.js │ │ ├── crosslet-raw.js │ │ └── crosslet.js ├── 1.1 │ ├── css │ │ ├── crosslet-min.css │ │ └── crosslet.css │ └── js │ │ ├── crosslet-min.js │ │ ├── crosslet-raw-min.js │ │ ├── crosslet-raw.js │ │ └── crosslet.js ├── crosslet-0.1.zip └── crosslet-1.1.zip ├── lib ├── cie.js ├── crossfilter.min.js └── topojson.js ├── src ├── coffee │ ├── data.coffee │ ├── init.coffee │ └── views │ │ ├── datasetsView.coffee │ │ └── mapView.coffee ├── js │ └── barChart.js └── less │ └── crosslet.less └── test └── 1 ├── coffee ├── config.coffee └── config.js ├── data ├── imd.tsv ├── lsoa.json └── prices.tsv ├── index.html ├── js ├── barChart.js ├── coffee ├── data.js ├── init.js └── views │ ├── datasetsView.js │ └── mapView.js ├── less ├── crosslet.less └── styles.less └── lib /LICENSE: -------------------------------------------------------------------------------- 1 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 2 | this file except in compliance with the License. You may obtain a copy of the 3 | License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed 8 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 9 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | specific language governing permissions and limitations under the License. 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | crosslet 2 | ======== 3 | 4 | See [Crosslet page](http://sztanko.github.com/crosslet/) for documentation and examples. 5 | 6 | **Crosslet** is a small javascript widget for interactive visualisation and analysis of geostatistical datasets, e.g. GDP per country, election results for each region of the country, etc. You can also use it for comparing multiple features. 7 | 8 | It is a combination of three very powerfull javascript libraries: 9 | * [Leaflet](http://leafletjs.com/), an elegant and beautiful mapping solution, and 10 | * [Crossfilter](http://square.github.com/crossfilter/), a library for exploring large multivariate datasets in the browser. 11 | * [D3](http://d3js.org/), used for manipulating documents based on data. 12 | 13 | See [Crosslet page](http://sztanko.github.com/crosslet/) for documentation and examples. 14 | 15 | ## License 16 | Crosslet is contributed under Apache 2.0 License 17 | -------------------------------------------------------------------------------- /bin/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | 4 | uglify="uglifyjs" 5 | lessc="lessc" 6 | #uglify="cat" 7 | version="1.1" 8 | 9 | d="../dist/$version/js" 10 | cxf="$d/crosslet.js" 11 | cx="$d/crosslet-raw.js" 12 | cxfm="$d/crosslet-min.js" 13 | cxm="$d/crosslet-raw-min.js" 14 | rm -rf $d 15 | mkdir -p $d 16 | for f in `find ../lib/ -type f -name "*.js" | sort` 17 | do 18 | echo $f 19 | cat $f >> $cxf 20 | done 21 | 22 | for f in `find ../src/ -type f -name "*.js" | sort` 23 | do 24 | echo $f 25 | cat $f >> $cx 26 | done 27 | 28 | coffee -cbp ../src/coffee/init.coffee >> $cx 29 | for f in `find ../src/ -type f -name "*.coffee" | sort | grep -v init.coffee` 30 | do 31 | echo $f 32 | echo "coffee -cbp $f " 33 | coffee -cbp $f >> $cx 34 | done 35 | 36 | cat $cx >> $cxf 37 | cat $cx | $uglify > $cxm 38 | cat $cxf | $uglify > $cxfm 39 | 40 | d="../dist/$version/css" 41 | rm -rf $d 42 | mkdir -p $d 43 | 44 | cssf="$d/crosslet.css" 45 | cssfm="$d/crosslet-min.css" 46 | $lessc ../src/less/*.less > $cssf 47 | $lessc --yui-compress ../src/less/*.less > $cssfm 48 | 49 | zipname="crosslet-$version.zip" 50 | cd ../dist/ 51 | rm $zipname 52 | zip -r "$zipname" "$version" 53 | -------------------------------------------------------------------------------- /dist/0.1/css/crosslet-min.css: -------------------------------------------------------------------------------- 1 | .crosslet, 2 | .crosslet * { 3 | font-family: georgia, "times new roman", times, serif; 4 | } 5 | .crosslet .crosslet_panel, 6 | .crosslet * .crosslet_panel { 7 | /*display: none;*/ 8 | /*width: 950px;*/ 9 | color: #565656; 10 | top: -10px; 11 | } 12 | .crosslet .crosslet_panel .box, 13 | .crosslet * .crosslet_panel .box { 14 | /*float:left;*/ 15 | display: inline-block; 16 | vertical-align: top; 17 | width: 215px; 18 | margin-left: 5px; 19 | background-color: #efefef; 20 | transition: background-color 0.2s; 21 | -moz-transition: background-color 0.2s; 22 | /* Firefox 4 */ 23 | -webkit-transition: background-color 0.2s; 24 | /* Safari and Chrome */ 25 | -o-transition: background-color 0.2s; 26 | /* Opera */ 27 | /*background: -webkit-linear-gradient(left top, white, darken(white,5%));*/ 28 | border-bottom-right-radius: 15px; 29 | /*opacity: 0.9;*/ 30 | border-bottom-left-radius: 15px; 31 | border: 1px solid #d6d6d6; 32 | border-top: none; 33 | box-shadow: 0 10px 14px -10px rgba(0, 0, 0, 0.8); 34 | padding: 5px; 35 | font-size: 11px; 36 | text-align: center; 37 | line-height: 10px; 38 | } 39 | .crosslet .crosslet_panel .box .legendForm, 40 | .crosslet * .crosslet_panel .box .legendForm { 41 | display: none; 42 | } 43 | .crosslet .crosslet_panel .box .legendText h2, 44 | .crosslet * .crosslet_panel .box .legendText h2, 45 | .crosslet .crosslet_panel .box .legendForm h2, 46 | .crosslet * .crosslet_panel .box .legendForm h2 { 47 | font-size: 1.1em; 48 | margin: 0px; 49 | margin-bottom: 4px; 50 | text-align: center; 51 | line-height: 1.3em; 52 | } 53 | .crosslet .crosslet_panel .box .legendText p, 54 | .crosslet * .crosslet_panel .box .legendText p, 55 | .crosslet .crosslet_panel .box .legendForm p, 56 | .crosslet * .crosslet_panel .box .legendForm p { 57 | margin: 0px; 58 | } 59 | .crosslet .crosslet_panel .box .legendText select, 60 | .crosslet * .crosslet_panel .box .legendText select, 61 | .crosslet .crosslet_panel .box .legendForm select, 62 | .crosslet * .crosslet_panel .box .legendForm select, 63 | .crosslet .crosslet_panel .box .legendText input[type="text"], 64 | .crosslet * .crosslet_panel .box .legendText input[type="text"], 65 | .crosslet .crosslet_panel .box .legendForm input[type="text"], 66 | .crosslet * .crosslet_panel .box .legendForm input[type="text"] { 67 | background-color: #efefef; 68 | width: auto; 69 | padding: 0px; 70 | padding-left: 4px; 71 | height: 12px; 72 | line-height: 13px; 73 | font-size: 12px; 74 | text-align: center; 75 | border: 1px solid #efefef; 76 | border-radius: 6px; 77 | font-weight: bold; 78 | margin: 0px; 79 | transition: background-color 0.2s; 80 | -moz-transition: background-color 0.2s; 81 | /* Firefox 4 */ 82 | -webkit-transition: background-color 0.2s; 83 | /* Safari and Chrome */ 84 | -o-transition: background-color 0.2s; 85 | /* Opera */ 86 | /*text-align: center;*/ 87 | } 88 | .crosslet .crosslet_panel .box .graph, 89 | .crosslet * .crosslet_panel .box .graph { 90 | /*.transition(height);*/ 91 | display: none; 92 | } 93 | .crosslet .crosslet_panel .box .graph, 94 | .crosslet * .crosslet_panel .box .graph { 95 | display: inline-block; 96 | margin-bottom: 0px; 97 | } 98 | .crosslet .crosslet_panel .box .background.bar, 99 | .crosslet * .crosslet_panel .box .background.bar { 100 | fill: #d6d6d6; 101 | } 102 | .crosslet .crosslet_panel .box .axis, 103 | .crosslet * .crosslet_panel .box .axis { 104 | display: none; 105 | } 106 | .crosslet .crosslet_panel .box .axis path, 107 | .crosslet * .crosslet_panel .box .axis path, 108 | .crosslet .crosslet_panel .box .axis line, 109 | .crosslet * .crosslet_panel .box .axis line { 110 | fill: none; 111 | stroke: #000; 112 | shape-rendering: crispEdges; 113 | } 114 | .crosslet .crosslet_panel .box .axis text, 115 | .crosslet * .crosslet_panel .box .axis text { 116 | font: 10px sans-serif; 117 | } 118 | .crosslet .crosslet_panel .box .brush rect.extent, 119 | .crosslet * .crosslet_panel .box .brush rect.extent { 120 | fill: steelblue; 121 | fill-opacity: .125; 122 | } 123 | .crosslet .crosslet_panel .box .brush .resize, 124 | .crosslet * .crosslet_panel .box .brush .resize { 125 | display: none; 126 | } 127 | .crosslet .crosslet_panel .box .brush .resize path, 128 | .crosslet * .crosslet_panel .box .brush .resize path { 129 | fill: #eee; 130 | stroke: #666; 131 | } 132 | .crosslet .crosslet_panel .box svg, 133 | .crosslet * .crosslet_panel .box svg { 134 | height: 25px; 135 | transition: height 0.2s; 136 | -moz-transition: height 0.2s; 137 | /* Firefox 4 */ 138 | -webkit-transition: height 0.2s; 139 | /* Safari and Chrome */ 140 | -o-transition: height 0.2s; 141 | /* Opera */ 142 | } 143 | .crosslet .crosslet_panel .box.selected, 144 | .crosslet * .crosslet_panel .box.selected, 145 | .crosslet .crosslet_panel .box:hover, 146 | .crosslet * .crosslet_panel .box:hover { 147 | opacity: 1; 148 | background: #ffffff; 149 | border-color: #b3b3b3; 150 | transition: background-color 0.2s; 151 | -moz-transition: background-color 0.2s; 152 | /* Firefox 4 */ 153 | -webkit-transition: background-color 0.2s; 154 | /* Safari and Chrome */ 155 | -o-transition: background-color 0.2s; 156 | /* Opera */ 157 | /*min-height: 110px;*/ 158 | color: black; 159 | } 160 | .crosslet .crosslet_panel .box.selected .legendForm, 161 | .crosslet * .crosslet_panel .box.selected .legendForm, 162 | .crosslet .crosslet_panel .box:hover .legendForm, 163 | .crosslet * .crosslet_panel .box:hover .legendForm { 164 | display: block; 165 | } 166 | .crosslet .crosslet_panel .box.selected .legendText, 167 | .crosslet * .crosslet_panel .box.selected .legendText, 168 | .crosslet .crosslet_panel .box:hover .legendText, 169 | .crosslet * .crosslet_panel .box:hover .legendText { 170 | display: none; 171 | } 172 | .crosslet .crosslet_panel .box.selected select, 173 | .crosslet * .crosslet_panel .box.selected select, 174 | .crosslet .crosslet_panel .box:hover select, 175 | .crosslet * .crosslet_panel .box:hover select, 176 | .crosslet .crosslet_panel .box.selected input[type="text"], 177 | .crosslet * .crosslet_panel .box.selected input[type="text"], 178 | .crosslet .crosslet_panel .box:hover input[type="text"], 179 | .crosslet * .crosslet_panel .box:hover input[type="text"] { 180 | background-color: #ffffff; 181 | border: 1px solid #b3b3b3; 182 | transition: background-color 0.2s; 183 | -moz-transition: background-color 0.2s; 184 | /* Firefox 4 */ 185 | -webkit-transition: background-color 0.2s; 186 | /* Safari and Chrome */ 187 | -o-transition: background-color 0.2s; 188 | /* Opera */ 189 | } 190 | .crosslet .crosslet_panel .box.selected .graph, 191 | .crosslet * .crosslet_panel .box.selected .graph, 192 | .crosslet .crosslet_panel .box:hover .graph, 193 | .crosslet * .crosslet_panel .box:hover .graph { 194 | /*border: 1px dotted @inactive-border;*/ 195 | /*height: 55px;*/ 196 | margin: 5px; 197 | margin-bottom: 2px; 198 | display: block; 199 | /* 200 | 201 | 202 | }*/ 203 | } 204 | .crosslet .crosslet_panel .box.selected .graph svg, 205 | .crosslet * .crosslet_panel .box.selected .graph svg, 206 | .crosslet .crosslet_panel .box:hover .graph svg, 207 | .crosslet * .crosslet_panel .box:hover .graph svg { 208 | height: 45px; 209 | transition: height 0.2s; 210 | -moz-transition: height 0.2s; 211 | /* Firefox 4 */ 212 | -webkit-transition: height 0.2s; 213 | /* Safari and Chrome */ 214 | -o-transition: height 0.2s; 215 | /* Opera */ 216 | } 217 | .crosslet .crosslet_panel .box.selected .graph .axis, 218 | .crosslet * .crosslet_panel .box.selected .graph .axis, 219 | .crosslet .crosslet_panel .box:hover .graph .axis, 220 | .crosslet * .crosslet_panel .box:hover .graph .axis { 221 | display: inline; 222 | transition: display 0.2s; 223 | -moz-transition: display 0.2s; 224 | /* Firefox 4 */ 225 | -webkit-transition: display 0.2s; 226 | /* Safari and Chrome */ 227 | -o-transition: display 0.2s; 228 | /* Opera */ 229 | } 230 | .crosslet .crosslet_panel .box.selected .graph .brush .resize, 231 | .crosslet * .crosslet_panel .box.selected .graph .brush .resize, 232 | .crosslet .crosslet_panel .box:hover .graph .brush .resize, 233 | .crosslet * .crosslet_panel .box:hover .graph .brush .resize { 234 | display: inline; 235 | } 236 | .crosslet .crosslet_panel .box.selected .graph .background.bar, 237 | .crosslet * .crosslet_panel .box.selected .graph .background.bar, 238 | .crosslet .crosslet_panel .box:hover .graph .background.bar, 239 | .crosslet * .crosslet_panel .box:hover .graph .background.bar { 240 | fill: #cccccc; 241 | } 242 | .crosslet .box:not(.selected):hover .foreground.bar, 243 | .crosslet * .box:not(.selected):hover .foreground.bar { 244 | fill: #808080; 245 | } 246 | .crosslet .box:not(.selected) .foreground.bar, 247 | .crosslet * .box:not(.selected) .foreground.bar { 248 | fill: #bcbcbc; 249 | /*fill: steelblue;*/ 250 | } 251 | .crosslet .box.selected #imd .foreground.bar, 252 | .crosslet * .box.selected #imd .foreground.bar { 253 | /* fill: inherit; */ 254 | } 255 | .crosslet svg g.crosslet_geometry { 256 | fill-opacity: 0.5; 257 | } 258 | .crosslet svg g.crosslet_geometry path { 259 | fill: white; 260 | stroke: none; 261 | /*stroke: black; */ 262 | } 263 | .crosslet svg g.crosslet_geometry path:hover { 264 | fill-opacity: 0.2; 265 | stroke-width: 2px; 266 | stroke: white; 267 | box-shadow: -5px -5px -5px -5px rgba(0, 0, 0, 0.8); 268 | } 269 | .crosslet svg .hover { 270 | display: none; 271 | } 272 | .crosslet svg .hover rect { 273 | stroke: none; 274 | fill-opacity: 0.5; 275 | fill: #efefef; 276 | border-radius: 5px; 277 | } 278 | .crosslet svg .hover text { 279 | font-size: 12px; 280 | fill: black; 281 | font-weight: bold; 282 | } 283 | .crosslet svg:hover .hover { 284 | display: inline; 285 | } 286 | -------------------------------------------------------------------------------- /dist/0.1/css/crosslet.css: -------------------------------------------------------------------------------- 1 | .crosslet, 2 | .crosslet * { 3 | font-family: georgia, "times new roman", times, serif; 4 | } 5 | .crosslet .crosslet_panel, 6 | .crosslet * .crosslet_panel { 7 | /*display: none;*/ 8 | /*width: 950px;*/ 9 | color: #565656; 10 | top: -10px; 11 | } 12 | .crosslet .crosslet_panel .box, 13 | .crosslet * .crosslet_panel .box { 14 | /*float:left;*/ 15 | display: inline-block; 16 | vertical-align: top; 17 | width: 215px; 18 | margin-left: 5px; 19 | background-color: #efefef; 20 | transition: background-color 0.2s; 21 | -moz-transition: background-color 0.2s; 22 | /* Firefox 4 */ 23 | -webkit-transition: background-color 0.2s; 24 | /* Safari and Chrome */ 25 | -o-transition: background-color 0.2s; 26 | /* Opera */ 27 | /*background: -webkit-linear-gradient(left top, white, darken(white,5%));*/ 28 | border-bottom-right-radius: 15px; 29 | /*opacity: 0.9;*/ 30 | border-bottom-left-radius: 15px; 31 | border: 1px solid #d6d6d6; 32 | border-top: none; 33 | box-shadow: 0 10px 14px -10px rgba(0, 0, 0, 0.8); 34 | padding: 5px; 35 | font-size: 11px; 36 | text-align: center; 37 | line-height: 10px; 38 | } 39 | .crosslet .crosslet_panel .box .legendForm, 40 | .crosslet * .crosslet_panel .box .legendForm { 41 | display: none; 42 | } 43 | .crosslet .crosslet_panel .box .legendText h2, 44 | .crosslet * .crosslet_panel .box .legendText h2, 45 | .crosslet .crosslet_panel .box .legendForm h2, 46 | .crosslet * .crosslet_panel .box .legendForm h2 { 47 | font-size: 1.1em; 48 | margin: 0px; 49 | margin-bottom: 4px; 50 | text-align: center; 51 | line-height: 1.3em; 52 | } 53 | .crosslet .crosslet_panel .box .legendText p, 54 | .crosslet * .crosslet_panel .box .legendText p, 55 | .crosslet .crosslet_panel .box .legendForm p, 56 | .crosslet * .crosslet_panel .box .legendForm p { 57 | margin: 0px; 58 | } 59 | .crosslet .crosslet_panel .box .legendText select, 60 | .crosslet * .crosslet_panel .box .legendText select, 61 | .crosslet .crosslet_panel .box .legendForm select, 62 | .crosslet * .crosslet_panel .box .legendForm select, 63 | .crosslet .crosslet_panel .box .legendText input[type="text"], 64 | .crosslet * .crosslet_panel .box .legendText input[type="text"], 65 | .crosslet .crosslet_panel .box .legendForm input[type="text"], 66 | .crosslet * .crosslet_panel .box .legendForm input[type="text"] { 67 | background-color: #efefef; 68 | width: auto; 69 | padding: 0px; 70 | padding-left: 4px; 71 | height: 12px; 72 | line-height: 13px; 73 | font-size: 12px; 74 | text-align: center; 75 | border: 1px solid #efefef; 76 | border-radius: 6px; 77 | font-weight: bold; 78 | margin: 0px; 79 | transition: background-color 0.2s; 80 | -moz-transition: background-color 0.2s; 81 | /* Firefox 4 */ 82 | -webkit-transition: background-color 0.2s; 83 | /* Safari and Chrome */ 84 | -o-transition: background-color 0.2s; 85 | /* Opera */ 86 | /*text-align: center;*/ 87 | } 88 | .crosslet .crosslet_panel .box .graph, 89 | .crosslet * .crosslet_panel .box .graph { 90 | /*.transition(height);*/ 91 | display: none; 92 | } 93 | .crosslet .crosslet_panel .box .graph, 94 | .crosslet * .crosslet_panel .box .graph { 95 | display: inline-block; 96 | margin-bottom: 0px; 97 | } 98 | .crosslet .crosslet_panel .box .background.bar, 99 | .crosslet * .crosslet_panel .box .background.bar { 100 | fill: #d6d6d6; 101 | } 102 | .crosslet .crosslet_panel .box .axis, 103 | .crosslet * .crosslet_panel .box .axis { 104 | display: none; 105 | } 106 | .crosslet .crosslet_panel .box .axis path, 107 | .crosslet * .crosslet_panel .box .axis path, 108 | .crosslet .crosslet_panel .box .axis line, 109 | .crosslet * .crosslet_panel .box .axis line { 110 | fill: none; 111 | stroke: #000; 112 | shape-rendering: crispEdges; 113 | } 114 | .crosslet .crosslet_panel .box .axis text, 115 | .crosslet * .crosslet_panel .box .axis text { 116 | font: 10px sans-serif; 117 | } 118 | .crosslet .crosslet_panel .box .brush rect.extent, 119 | .crosslet * .crosslet_panel .box .brush rect.extent { 120 | fill: steelblue; 121 | fill-opacity: .125; 122 | } 123 | .crosslet .crosslet_panel .box .brush .resize, 124 | .crosslet * .crosslet_panel .box .brush .resize { 125 | display: none; 126 | } 127 | .crosslet .crosslet_panel .box .brush .resize path, 128 | .crosslet * .crosslet_panel .box .brush .resize path { 129 | fill: #eee; 130 | stroke: #666; 131 | } 132 | .crosslet .crosslet_panel .box svg, 133 | .crosslet * .crosslet_panel .box svg { 134 | height: 25px; 135 | transition: height 0.2s; 136 | -moz-transition: height 0.2s; 137 | /* Firefox 4 */ 138 | -webkit-transition: height 0.2s; 139 | /* Safari and Chrome */ 140 | -o-transition: height 0.2s; 141 | /* Opera */ 142 | } 143 | .crosslet .crosslet_panel .box.selected, 144 | .crosslet * .crosslet_panel .box.selected, 145 | .crosslet .crosslet_panel .box:hover, 146 | .crosslet * .crosslet_panel .box:hover { 147 | opacity: 1; 148 | background: #ffffff; 149 | border-color: #b3b3b3; 150 | transition: background-color 0.2s; 151 | -moz-transition: background-color 0.2s; 152 | /* Firefox 4 */ 153 | -webkit-transition: background-color 0.2s; 154 | /* Safari and Chrome */ 155 | -o-transition: background-color 0.2s; 156 | /* Opera */ 157 | /*min-height: 110px;*/ 158 | color: black; 159 | } 160 | .crosslet .crosslet_panel .box.selected .legendForm, 161 | .crosslet * .crosslet_panel .box.selected .legendForm, 162 | .crosslet .crosslet_panel .box:hover .legendForm, 163 | .crosslet * .crosslet_panel .box:hover .legendForm { 164 | display: block; 165 | } 166 | .crosslet .crosslet_panel .box.selected .legendText, 167 | .crosslet * .crosslet_panel .box.selected .legendText, 168 | .crosslet .crosslet_panel .box:hover .legendText, 169 | .crosslet * .crosslet_panel .box:hover .legendText { 170 | display: none; 171 | } 172 | .crosslet .crosslet_panel .box.selected select, 173 | .crosslet * .crosslet_panel .box.selected select, 174 | .crosslet .crosslet_panel .box:hover select, 175 | .crosslet * .crosslet_panel .box:hover select, 176 | .crosslet .crosslet_panel .box.selected input[type="text"], 177 | .crosslet * .crosslet_panel .box.selected input[type="text"], 178 | .crosslet .crosslet_panel .box:hover input[type="text"], 179 | .crosslet * .crosslet_panel .box:hover input[type="text"] { 180 | background-color: #ffffff; 181 | border: 1px solid #b3b3b3; 182 | transition: background-color 0.2s; 183 | -moz-transition: background-color 0.2s; 184 | /* Firefox 4 */ 185 | -webkit-transition: background-color 0.2s; 186 | /* Safari and Chrome */ 187 | -o-transition: background-color 0.2s; 188 | /* Opera */ 189 | } 190 | .crosslet .crosslet_panel .box.selected .graph, 191 | .crosslet * .crosslet_panel .box.selected .graph, 192 | .crosslet .crosslet_panel .box:hover .graph, 193 | .crosslet * .crosslet_panel .box:hover .graph { 194 | /*border: 1px dotted @inactive-border;*/ 195 | /*height: 55px;*/ 196 | margin: 5px; 197 | margin-bottom: 2px; 198 | display: block; 199 | /* 200 | 201 | 202 | }*/ 203 | } 204 | .crosslet .crosslet_panel .box.selected .graph svg, 205 | .crosslet * .crosslet_panel .box.selected .graph svg, 206 | .crosslet .crosslet_panel .box:hover .graph svg, 207 | .crosslet * .crosslet_panel .box:hover .graph svg { 208 | height: 45px; 209 | transition: height 0.2s; 210 | -moz-transition: height 0.2s; 211 | /* Firefox 4 */ 212 | -webkit-transition: height 0.2s; 213 | /* Safari and Chrome */ 214 | -o-transition: height 0.2s; 215 | /* Opera */ 216 | } 217 | .crosslet .crosslet_panel .box.selected .graph .axis, 218 | .crosslet * .crosslet_panel .box.selected .graph .axis, 219 | .crosslet .crosslet_panel .box:hover .graph .axis, 220 | .crosslet * .crosslet_panel .box:hover .graph .axis { 221 | display: inline; 222 | transition: display 0.2s; 223 | -moz-transition: display 0.2s; 224 | /* Firefox 4 */ 225 | -webkit-transition: display 0.2s; 226 | /* Safari and Chrome */ 227 | -o-transition: display 0.2s; 228 | /* Opera */ 229 | } 230 | .crosslet .crosslet_panel .box.selected .graph .brush .resize, 231 | .crosslet * .crosslet_panel .box.selected .graph .brush .resize, 232 | .crosslet .crosslet_panel .box:hover .graph .brush .resize, 233 | .crosslet * .crosslet_panel .box:hover .graph .brush .resize { 234 | display: inline; 235 | } 236 | .crosslet .crosslet_panel .box.selected .graph .background.bar, 237 | .crosslet * .crosslet_panel .box.selected .graph .background.bar, 238 | .crosslet .crosslet_panel .box:hover .graph .background.bar, 239 | .crosslet * .crosslet_panel .box:hover .graph .background.bar { 240 | fill: #cccccc; 241 | } 242 | .crosslet .box:not(.selected):hover .foreground.bar, 243 | .crosslet * .box:not(.selected):hover .foreground.bar { 244 | fill: #808080; 245 | } 246 | .crosslet .box:not(.selected) .foreground.bar, 247 | .crosslet * .box:not(.selected) .foreground.bar { 248 | fill: #bcbcbc; 249 | /*fill: steelblue;*/ 250 | } 251 | .crosslet .box.selected #imd .foreground.bar, 252 | .crosslet * .box.selected #imd .foreground.bar { 253 | /* fill: inherit; */ 254 | } 255 | .crosslet svg g.crosslet_geometry { 256 | fill-opacity: 0.5; 257 | } 258 | .crosslet svg g.crosslet_geometry path { 259 | fill: white; 260 | stroke: none; 261 | /*stroke: black; */ 262 | } 263 | .crosslet svg g.crosslet_geometry path:hover { 264 | fill-opacity: 0.2; 265 | stroke-width: 2px; 266 | stroke: white; 267 | box-shadow: -5px -5px -5px -5px rgba(0, 0, 0, 0.8); 268 | } 269 | .crosslet svg .hover { 270 | display: none; 271 | } 272 | .crosslet svg .hover rect { 273 | stroke: none; 274 | fill-opacity: 0.5; 275 | fill: #efefef; 276 | border-radius: 5px; 277 | } 278 | .crosslet svg .hover text { 279 | font-size: 12px; 280 | fill: black; 281 | font-weight: bold; 282 | } 283 | .crosslet svg:hover .hover { 284 | display: inline; 285 | } 286 | -------------------------------------------------------------------------------- /dist/0.1/js/crosslet-min.js: -------------------------------------------------------------------------------- 1 | (function(d3){var cie=d3.cie={};cie.lab=function(l,a,b){return arguments.length===1?l instanceof Lab?lab(l.l,l.a,l.b):l instanceof Lch?lch_lab(l.l,l.c,l.h):rgb_lab((l=d3.rgb(l)).r,l.g,l.b):lab(+l,+a,+b)};cie.lch=function(l,c,h){return arguments.length===1?l instanceof Lch?lch(l.l,l.c,l.h):l instanceof Lab?lab_lch(l.l,l.a,l.b):lab_lch((l=rgb_lab((l=d3.rgb(l)).r,l.g,l.b)).l,l.a,l.b):lch(+l,+c,+h)};cie.interpolateLab=function(a,b){a=cie.lab(a);b=cie.lab(b);var al=a.l,aa=a.a,ab=a.b,bl=b.l-al,ba=b.a-aa,bb=b.b-ab;return function(t){return lab_rgb(al+bl*t,aa+ba*t,ab+bb*t)+""}};cie.interpolateLch=function(a,b){a=cie.lch(a);b=cie.lch(b);var al=a.l,ac=a.c,ah=a.h,bl=b.l-al,bc=b.c-ac,bh=b.h-ah;if(bh>180)bh-=360;else if(bh<-180)bh+=360;return function(t){return lch_lab(al+bl*t,ac+bc*t,ah+bh*t)+""}};function lab(l,a,b){return new Lab(l,a,b)}function Lab(l,a,b){this.l=l;this.a=a;this.b=b}Lab.prototype.brighter=function(k){return lab(Math.min(100,this.l+K*(arguments.length?k:1)),this.a,this.b)};Lab.prototype.darker=function(k){return lab(Math.max(0,this.l-K*(arguments.length?k:1)),this.a,this.b)};Lab.prototype.rgb=function(){return lab_rgb(this.l,this.a,this.b)};Lab.prototype.toString=function(){return this.rgb()+""};function lch(l,c,h){return new Lch(l,c,h)}function Lch(l,c,h){this.l=l;this.c=c;this.h=h}Lch.prototype.brighter=function(k){return lch(Math.min(100,this.l+K*(arguments.length?k:1)),this.c,this.h)};Lch.prototype.darker=function(k){return lch(Math.max(0,this.l-K*(arguments.length?k:1)),this.c,this.h)};Lch.prototype.rgb=function(){return lch_lab(this.l,this.c,this.h).rgb()};Lch.prototype.toString=function(){return this.rgb()+""};var K=18;var X=.95047,Y=1,Z=1.08883;function lab_rgb(l,a,b){var y=(l+16)/116,x=y+a/500,z=y-b/200;x=lab_xyz(x)*X;y=lab_xyz(y)*Y;z=lab_xyz(z)*Z;return d3.rgb(xyz_rgb(3.2404542*x-1.5371385*y-.4985314*z),xyz_rgb(-.969266*x+1.8760108*y+.041556*z),xyz_rgb(.0556434*x-.2040259*y+1.0572252*z))}function rgb_lab(r,g,b){r=rgb_xyz(r);g=rgb_xyz(g);b=rgb_xyz(b);var x=xyz_lab((.4124564*r+.3575761*g+.1804375*b)/X),y=xyz_lab((.2126729*r+.7151522*g+.072175*b)/Y),z=xyz_lab((.0193339*r+.119192*g+.9503041*b)/Z);return lab(116*y-16,500*(x-y),200*(y-z))}function lab_lch(l,a,b){var c=Math.sqrt(a*a+b*b),h=Math.atan2(b,a)/Math.PI*180;return lch(l,c,h)}function lch_lab(l,c,h){h=h*Math.PI/180;return lab(l,Math.cos(h)*c,Math.sin(h)*c)}function lab_xyz(x){return x>.206893034?x*x*x:(x-4/29)/7.787037}function xyz_lab(x){return x>.008856?Math.pow(x,1/3):7.787037*x+4/29}function xyz_rgb(r){return Math.round(255*(r<=.00304?12.92*r:1.055*Math.pow(r,1/2.4)-.055))}function rgb_xyz(r){return(r/=255)<=.04045?r/12.92:Math.pow((r+.055)/1.055,2.4)}})(d3);(function(a){function b(a){return a}function c(a,b){for(var c=0,d=b.length,e=new Array(d);c>1;a(b[f])>1;c>>1)+1;while(--f>0)d(a,f,e,b);return a}function c(a,b,c){var e=c-b,f;while(--e>0)f=a[b],a[b]=a[b+e],a[b+e]=f,d(a,1,e,b);return a}function d(b,c,d,e){var f=b[--e+c],g=a(f),h;while((h=c<<1)<=d){ha(b[e+h+1])&&h++;if(g<=a(b[e+h]))break;b[e+c]=b[e+h],c=h}b[e+c]=f}return b.sort=c,b}function i(a){function c(c,d,e,f){var g=new Array(f=Math.min(e-d,f)),h,i,j,k;for(i=0;ih)g[0]=k,h=a(b(g,0,f)[0]);while(++dc&&a(b[f-1])>h;--f)b[f]=b[f-1];b[f]=g}return b}return b}function m(a){function c(a,c,e){return(e-c>1,j=i-f,k=i+f,l=b[g],m=a(l),n=b[j],o=a(n),p=b[i],q=a(p),r=b[k],s=a(r),t=b[h],u=a(t),v;m>o&&(v=l,l=n,n=v,v=m,m=o,o=v),s>u&&(v=r,r=t,t=v,v=s,s=u,u=v),m>q&&(v=l,l=p,p=v,v=m,m=q,q=v),o>q&&(v=n,n=p,p=v,v=o,o=q,q=v),m>s&&(v=l,l=r,r=v,v=m,m=s,s=v),q>s&&(v=p,p=r,r=v,v=q,q=s,s=v),o>u&&(v=n,n=t,t=v,v=o,o=u,u=v),o>q&&(v=n,n=p,p=v,v=o,o=q,q=v),s>u&&(v=r,r=t,t=v,v=s,s=u,u=v);var w=n,x=o,y=r,z=s;b[g]=l,b[j]=b[d],b[i]=p,b[k]=b[e-1],b[h]=t;var A=d+1,B=e-2,C=x<=z&&x>=z;if(C)for(var D=A;D<=B;++D){var E=b[D],F=a(E);if(Fx)for(;;){var G=a(b[B]);if(G>x){B--;continue}if(Gz)for(;;){var G=a(b[B]);if(G>z){B--;if(Bh){var H,G;while((H=a(b[A]))<=x&&H>=x)++A;while((G=a(b[B]))<=z&&G>=z)--B;for(var D=A;D<=B;D++){var E=b[D],F=a(E);if(F<=x&&F>=x)D!==A&&(b[D]=b[A],b[A]=E),A++;else if(F<=z&&F>=z)for(;;){var G=a(b[B]);if(G<=z&&G>=z){B--;if(BN)for(b=N,c=Math.min(e,O);bO)for(b=Math.max(e,O),c=f;b=N&&a>0)k[d=D[c]]||(b.push(e[d]),--a);return b}function X(a){var b=[],c=N,d;while(c0)k[d=D[c]]||(b.push(e[d]),--a),c++;return b}function Y(a){function K(b,c,g,i){function Q(){++n===m&&(p=s(p,j<<=1),h=s(h,j),m=G(j))}var o=d,p=E(n,m),t=v,u=F,w=n,y=0,z=0,A,B,C,D,K,L;J&&(t=u=x),d=new Array(n),n=0,h=w>1?r(h,f):E(f,m),w&&(C=(B=o[0]).key);while(z=D))++z;while(zL)){h[A=c[z]+g]=n,k[A]&q||(K.value=t(K.value,e[A]));if(++z>=i)break;D=a(b[z])}Q()}while(yy)for(y=0;y1?(H=M,I=O):(n===1?(H=N,I=P):(H=x,I=x),h=null),l[A]=H}function M(a,b,c){if(a===p||J)return;var f,g,i,j;for(f=0,i=b.length;fj&&(k=s(k,j<<=1)),P(e,0,f),Q(e,0,f),o}function t(){function i(a,d,g){var i;if(h)return;for(i=d;i1){var geomsByArc=[],geom;function arc(i){if(i<0)i=~i;(geomsByArc[i]||(geomsByArc[i]=[])).push(geom)}function line(arcs){arcs.forEach(arc)}function polygon(arcs){arcs.forEach(line)}function geometry(o){geom=o;geometryType[o.type](o.arcs)}var geometryType={LineString:line,MultiLineString:polygon,Polygon:polygon,MultiPolygon:function(arcs){arcs.forEach(polygon)}};o.type==="GeometryCollection"?o.geometries.forEach(geometry):geometry(o);geomsByArc.forEach(arguments.length<3?function(geoms,i){arcs.push([i])}:function(geoms,i){if(filter(geoms[0],geoms[geoms.length-1]))arcs.push([i])})}else{for(var i=0,n=topology.arcs.length;i>>1;if(a[mid]0){if(status)status.text(axis.tickFormat()(extent[0])+" - "+axis.tickFormat()(extent[1]))}else{if(status)status.text("")}});brush.on("brushend.chart",function(){if(brush.empty()){var div=d3.select(this.parentNode.parentNode.parentNode);div.select("#clip-"+id+" rect").attr("x",null).attr("width","100%");dimension.filterAll();filter=null}});chart.margin=function(_){if(!arguments.length)return margin;margin=_;return chart};chart.x=function(_){if(!arguments.length)return x;x=_;axis.scale(x);brush.x(x);return chart};chart.tickFormat=function(_){if(!arguments.length)return tickFormat;tickFormat=_;axis.tickFormat(tickFormat);return chart};chart.name_id=function(_){if(!arguments.length)return name_id;name_id=_;return chart};chart.ticks=function(a){if(!arguments.length)return tickSize;ticks=a;if(a.length){axis.tickValues(ticks)}else axis.ticks(ticks);return chart};chart.fill=function(_){if(!arguments.length)return fill;fill=_;return chart};chart.y=function(_){if(!arguments.length)return y;y=_;return chart};chart.dimension=function(_){if(!arguments.length)return dimension;dimension=_;return chart};chart.filter=function(_){if(!arguments.length)return filter;if(_){filter=_;brush.extent(_);dimension.filterRange(_);if(status)status.text(axis.tickFormat()(filter[0])+" - "+axis.tickFormat()(filter[1]))}else{brush.clear();filter=null;dimension.filterAll()}brushDirty=true;return chart};chart.group=function(_){if(!arguments.length)return group;group=_;return chart};chart.round=function(_){if(!arguments.length)return round;round=_;return chart};return d3.rebind(chart,brush,"on")};var crosslet;crosslet={};if(!_){console.log("Please include underscore.js")}crosslet.createConfig=function(defaultConfig,config){var c;return c=jQuery.extend(true,jQuery.extend(true,{},defaultConfig),config)};crosslet.id=function(d){return d};crosslet.idf=function(d){return crosslet.id};crosslet.notimplemented=function(){throw"This function is not set. Please check your config."};crosslet.changeSelect=function(select,val){return $(select).find("option").filter(function(){return $(this).val()===val}).attr("selected",true)};crosslet.defaultConfig={map:{leaflet:{url:"http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png",key:"--your key--",styleId:64657,attribution:'Map data © OpenStreetMap contributors, ODbL, Imagery © CloudMade'},view:{center:[51.505,-.09],zoom:11},geo:{url:"please specify correct location of your geojson",name_field:"name",id_field:"code",topo_object:"please specify correct object name"}}};({data:{version:"1.0",id_field:"id"},dimensions:{},defaults:{colorscale:d3.scale.linear().domain([1,10,20]).range(["green","yellow","red"]).interpolate(d3.cie.interpolateLab),opacity:.75,order:[]}});crosslet.defaultDimensionConfig={p:{},filter:null,data:{interval:null,filter:null,field:function(d){return d.id},dataSet:crosslet.notimplemented,method:d3.tsv,preformat:function(dd){return function(d){return+d}},ticks:4,colorscale:d3.scale.linear().domain([1,10,20]).range(["green","yellow","red"]).interpolate(d3.cie.interpolateLab),exponent:1},format:{"short":function(d){return d3.format(",.2f")},"long":function(d){return d.format.short(d)},input:function(d){return d3.format(".2f")},axis:function(d){return d.format.short(d)}},render:{legend:function(d,el){var f,html;f=d.title?d.title:d.data.field_func(d);html="

"+f+"

";return el.html(html)},range:function(d,el){var html;html="

"+d.format.short(d)(d.filter[0])+""+d.format.short(d)(d.filter[1])+"

";return el.html(html)},form:function(d,el){return d.render.legend(d,el)},rangeForm:function(d,el){var html,size;size=_.max(_.map(d.data.interval,function(dd){return("_"+d.format.input(d)(dd)).length-1}));html="Range: ";return el.html(html)}},submitter:function(d,el){var out;out={};$(el).find("input, select").each(function(index,el){return out[$(el).attr("name")]=$(el).val()});return out}};var __bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i=0){this.executeCallbacks(this.callbackList[urlv],this.cache[urlv]);return this}else{if(this.status[urlv]!=="loading"){this.status[urlv]="loading";method(url,function(data){_this.cache[urlv]=data;_this.executeCallbacks(_this.callbackList[urlv],_this.cache[urlv]);_this.status[urlv]="done";return _this})}}return this};DataLoader.prototype.executeCallbacks=function(list,data){var _results;_results=[];while(list.length>0){_results.push(list.pop()(data))}return _results};return DataLoader}();var _ref,_ref1,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child};crosslet.PanelView=function(_super){__extends(PanelView,_super);function PanelView(){this.renderCubes=__bind(this.renderCubes,this);this.createCube=__bind(this.createCube,this);this.setActive=__bind(this.setActive,this);this._renderMap=__bind(this._renderMap,this);this.getSelection=__bind(this.getSelection,this);_ref=PanelView.__super__.constructor.apply(this,arguments);return _ref}PanelView.prototype.initialize=function(el,config,parent){var e,o,_i,_len,_ref1;this.config=crosslet.createConfig(crosslet.defaultConfig,config);this.parent=parent;this.el=el;this.ds=parent.ds;this.boxes={};this.render();this.width=200;this.active=this.config.defaults.active?this.config.defaults.active:this.config.defaults.order[0];this.numloads=this.config.defaults.order.length;_ref1=this.config.defaults.order;for(_i=0,_len=_ref1.length;_i<_len;_i++){o=_ref1[_i];e=$("
");this.boxes[o]=new crosslet.BoxView(e,this.config.dimensions[o],this,o);$(this.el).append(e)}this.boxes[this.active].setActive(true);this.renderMap=_.debounce(this._renderMap,300);return this.boxes};PanelView.prototype.loaded=function(){this.numloads=this.numloads-1;if(this.numloads<=0){return this.createCube()}};PanelView.prototype.getSelection=function(){var abox,adata,k,keys,out,_i,_len;abox=this.boxes[this.active];adata=abox.getFilteredData();keys=this.intersection(_.map(_.values(this.boxes),function(b){return _.keys(b.getFilteredData()).sort()}));out={};for(_i=0,_len=keys.length;_i<_len;_i++){k=keys[_i];out[k]=adata[k]}return out};PanelView.prototype._renderMap=function(){var abox,f,out,_this=this;abox=this.boxes[this.active];out=this.getSelection();f=abox.config.format.long(abox.config);this.parent.renderMap(out,function(v){return abox.config.data.colorscale(abox.config.scale(v))},function(data,value){return data.properties[_this.config.map.geo.name_field]+" - "+f(value)});return this};PanelView.prototype.setActive=function(activeBox){if(activeBox!==this.active){this.boxes[this.active].setActive(false);this.active=activeBox;this.boxes[this.active].setActive(true);return this.renderMap()}};PanelView.prototype.intersection=function(a){var intersect_safe,o,out,_i,_len,_ref1;intersect_safe=function(a,b){var ai,bi,result;ai=bi=0;result=[];while(aib[bi]){bi++}if(a[ai]===b[bi]){result.push(a[ai]);ai++;bi++}}return result};switch(a.length){case 0:return a;case 1:return a[0];case 2:return intersect_safe(a[0],a[1]);default:out=a[0];_ref1=a.slice(1);for(_i=0,_len=_ref1.length;_i<_len;_i++){o=_ref1[_i];out=intersect_safe(out,o)}return out}};PanelView.prototype.createCube=function(){var bName,box,brushevent,chart,d,dg,getRounder,groups,int,js_bName,js_box,key,keys,o,row,t1,t15,t2,yscale,_i,_j,_len,_len1,_ref1,_ref2,_ref3;this.rows=[];t1=(new Date).getTime();keys=_.map(_.values(this.boxes),function(b){return _.keys(b.data).sort()});t15=(new Date).getTime();int=this.intersection(keys);for(_i=0,_len=int.length;_i<_len;_i++){key=int[_i];row={};_ref1=this.boxes;for(bName in _ref1){box=_ref1[bName];row[bName]=box.data[key]}this.rows.push(row)}t2=(new Date).getTime();this.cube=crossfilter(this.rows);getRounder=function(m1,m2,w,exp){var scale,t;t=5*(m2-m1)/w;scale=d3.scale.pow().exponent(exp).range([m1/t,m2/t]).domain([m1/t,m2/t]);return function(d){return t*scale.invert(Math.floor(scale(+d/t)))}};groups={};this.charts={};brushevent=function(box,ctx){return function(){box.event_click();return ctx.renderCubes()}};_ref2=this.boxes;for(bName in _ref2){box=_ref2[bName];var chart,js_box,js_bName;js_box=box;js_bName=bName;d=this.cube.dimension(function(dd){return dd[bName]});dg=d.group(getRounder(box.config.data.interval[0],box.config.data.interval[1],this.width-20,box.config.data.exponent));box.graph.empty();yscale=d3.scale.linear().clamp(true).range([20,0]);chart=barChart().dimension(d).name_id(bName).group(dg).x(d3.scale.pow().exponent(box.config.data.exponent).domain(box.config.data.interval).rangeRound([0,this.width-20])).y(yscale.copy()).ticks(box.config.data.ticks).tickFormat(box.config.format.axis(box.config)).fill(box.config.data.colorscale);chart.on("brush",brushevent(box,this));chart.on("brushend",this.renderCubes);box.chart=chart;this.charts[bName]=chart}if(this.parent.ds.isGeoLoaded){this.renderCubes()}_ref3=this.config.defaults.order;for(_j=0,_len1=_ref3.length;_j<_len1;_j++){o=_ref3[_j];if(this.config.dimensions[o].filter){this.boxes[o].setFilter(this.config.dimensions[o].filter,true)}}return this};PanelView.prototype.renderCubes=function(){var abox,bName,box,_ref1;_ref1=this.boxes;for(bName in _ref1){box=_ref1[bName];box.chart(box.graph);$(box.el).on("mousedown",box.event_click);box.setFilter(box.chart.filter(),false)}abox=this.boxes[this.active];abox.setFilter(abox.chart.filter(),false);this.renderMap();return this};return PanelView}(Backbone.View);crosslet.BoxView=function(_super){__extends(BoxView,_super);function BoxView(){this.setFilter=__bind(this.setFilter,this);this.event_click=__bind(this.event_click,this);this.setActive=__bind(this.setActive,this);this.dataLoaded=__bind(this.dataLoaded,this);_ref1=BoxView.__super__.constructor.apply(this,arguments);return _ref1}BoxView.prototype.initialize=function(el,config,parent,name){this.el=el;this.config=crosslet.createConfig(crosslet.defaultDimensionConfig,config);this.config.id=name;this.config.data.field_func=!_.isFunction(this.config.data.field)?function(d){return d.data.field 2 | }:this.config.data.field;$(this.el).on("mousedown",this.event_click);$(this.el).on("tap",this.event_click);$(this.el)[0].onmousedown=$(this.el)[0].ondblclick=L.DomEvent.stopPropagation;this.legend={};this.legend.all=$("
");this.legend.text=$("
");this.legend.text_p=$("
");this.legend.text_range=$("
");this.legend.text.append(this.legend.text_p).append(this.legend.text_range);this.legend.form=$("
");this.legend.form_p=$("
");this.legend.form_range=$("
");this.legend.form.append(this.legend.form_p).append(this.legend.form_range);this.legend.all.append(this.legend.text).append(this.legend.form);$(el).append(this.legend.all);this.graph=$("
");$(el).append(this.graph);this.parent=parent;this.ds=parent.ds;this.active=false;this.name=name;return this.loadData()};BoxView.prototype.loadData=function(){if(_.isString(this.config.data.dataSet)){return this.parent.ds.loadData(this.config.data.dataSet,this.dataLoaded,this.config.data.method)}else{if(_.isFunction(this.config.data.dataSet)){return this.parent.ds.loadData(this.config.data.dataSet(this.config),this.dataLoaded,this.config.data.method)}else{return this.parent.ds.addData(this.config.data.dataSet,this.dataLoaded)}}};BoxView.prototype.dataLoaded=function(){var f,id,pd,preformatter,val,_ref2;this.data={};f=this.config.data.field_func(this.config);preformatter=this.config.data.preformat(this.config);_ref2=this.parent.ds.data;for(id in _ref2){val=_ref2[id];if(_.isNumber(val[f])){pd=preformatter(val[f])}if(_.isNumber(pd)){this.data[id]=pd}}if(!this.config.data.interval){this.config.data.interval=[_.min(_.values(this.data)),_.max(_.values(this.data))]}if(!this.config.filter){this.config.filter=[_.min(_.values(this.data)),_.max(_.values(this.data))]}this.config.scale=d3.scale.pow().exponent(this.config.data.exponent).domain(this.config.data.interval).rangeRound([0,20]);this.config.scale.name="yes";this.render();return this.parent.loaded()};BoxView.prototype.setActive=function(isActive){this.active=isActive;if(isActive){return $(this.el).addClass("selected")}else{return $(this.el).removeClass("selected")}};BoxView.prototype.event_click=function(event){if(!this.active){this.parent.setActive(this.name)}return true};BoxView.prototype.setFilter=function(f,redrawCube){if(redrawCube==null){redrawCube=false}if(redrawCube){this.chart.filter(f);this.parent.renderCubes()}if(!f){f=this.config.data.interval}this.config.filter=f;this.filterElements[0].val(this.config.format.input(this.config)(f[0]));this.filterElements[1].val(this.config.format.input(this.config)(f[1]));$(this.legend.text_range).find(".m0").text(this.config.format.short(this.config)(f[0]));$(this.legend.text_range).find(".m1").text(this.config.format.short(this.config)(f[1]));return this};BoxView.prototype.getFilteredData=function(){var f,k,out,v,_ref2,_ref3;if(!this.chart.filter()){return this.data}f=(_ref2=this.chart.filter())!=null?_ref2:this.config.data.interval;out={};_ref3=this.data;for(k in _ref3){v=_ref3[k];if(f[0]<=v&&v<=f[1]){out[k]=v}}return out};BoxView.prototype.renderRange=function(){this.config.render.range(this.config,this.legend.text_range);return this.config.render.rangeForm(this.config,this.legend.form_range)};BoxView.prototype.render=function(){var _this=this;this.config.render.legend(this.config,this.legend.text_p);this.config.render.form(this.config,this.legend.form_p);this.renderRange();$(this.legend.form_range).find("input").on("change",function(){var f;f=[+_this.filterElements[0].val(),+_this.filterElements[1].val()];if(f[0]>f[1]){f.reverse()}f[0]=_.max([_this.config.data.interval[0],f[0]]);f[1]=_.min([_this.config.data.interval[1],f[1]]);if(_.isEqual(f,_this.config.data.interval)){f=null}return _this.setFilter(f,true)});$(this.legend.form_p).find("input, select").on("change",function(){var p;_this.config.data.interval=null;_this.config.scale=null;_this.config.filter=null;p=_this.config.submitter(_this.config,_this.legend.form_p);_this.config.p=p;console.log(p);return _this.loadData()});return this.filterElements=[$(this.legend.form_range).find("input[name=m0]"),$(this.legend.form_range).find("input[name=m1]")]};return BoxView}(Backbone.View);var _ref,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child};crosslet.MapView=function(_super){__extends(MapView,_super);function MapView(){this._renderMap=__bind(this._renderMap,this);this.getSelection=__bind(this.getSelection,this);this.hover=__bind(this.hover,this);this.mouseMove=__bind(this.mouseMove,this);this.reset=__bind(this.reset,this);this.beforezoom=__bind(this.beforezoom,this);this.project=__bind(this.project,this);_ref=MapView.__super__.constructor.apply(this,arguments);return _ref}MapView.prototype.initialize=function(el,config){var _this=this;this.config=crosslet.createConfig(crosslet.defaultConfig,config);this.geoURL=this.config.map.geo.url;this.opacity=this.config.defaults.opacity;this.ds=new crosslet.DataStore(this.config);this.el=el;this.hoverFunc=this.default_hover;$(this.el).attr("class","crosslet");this.map=L.map(el[0]).setView(this.config.map.view.center,this.config.map.view.zoom);L.tileLayer(this.config.map.leaflet.url,this.config.map.leaflet).addTo(this.map);this.control=$("
");this.info=L.Control.extend({options:{position:"topright"},onAdd:function(map){return _this.control[0]}});this.map.addControl(new this.info);this.panel=new crosslet.PanelView(this.control,this.config,this);this.renderMap=this._renderMap;return this.ds.loadGeo(this.geoURL,this.config.map.geo.id_field,function(ds){_this.bounds=_this.ds.bounds;_this.path=d3.geo.path().projection(_this.project);_this.svg=d3.select(_this.map.getPanes().overlayPane).append("svg");_this.g=_this.svg.append("g");_this.g.attr("class","crosslet_geometry");_this.feature=_this.g.selectAll("path").data(ds.geometries).enter().append("path").attr("id",function(d){return"path_"+d.properties[_this.config.map.geo.id_field]}).on("mouseover",function(d){return _this.hover(d)}).on("mousemove",_this.mouseMove);_this.reset();_this.map.on("viewreset",_this.reset);_this.map.on("zoomstart",_this.beforezoom);_this.hoverElement=_this.svg.append("g").attr("class","hover");_this.hoverElementRect=_this.hoverElement.append("svg:rect").attr("x",0).attr("y",0).attr("width",10).attr("height",30).attr("rx",5).attr("ry",5);_this.hoverElementText=_this.hoverElement.append("text").attr("x",0).attr("y",0);_this.hoverElementTextBB={width:0,height:0,x:0,y:0};if(_this.panel.numloads<=0){return _this.panel.createCube()}},this.config.map.geo.topo_object)};MapView.prototype.project=function(x){var point;point=this.map.latLngToLayerPoint(new L.LatLng(x[1],x[0]));return[point.x,point.y]};MapView.prototype.beforezoom=function(){return this.g.style("display","none")};MapView.prototype.reset=function(){var bottomLeft,topRight;bottomLeft=this.project(this.bounds[0]);topRight=this.project(this.bounds[1]);this.svg.attr("width",topRight[0]-bottomLeft[0]).attr("height",bottomLeft[1]-topRight[1]).style("margin-left",bottomLeft[0]+"px").style("margin-top",topRight[1]+"px");this.g.attr("transform","translate("+-bottomLeft[0]+","+-topRight[1]+")");this.feature.attr("d",this.path);this.g.style("display","inline");return true};MapView.prototype.mouseMove=function(){var br,dx,dy,matrix,pos,trp;br=jQuery.browser;pos=d3.mouse(this.svg.node());if(br.mozilla){trp=this.svg.node().parentNode.parentNode.parentNode;matrix=$(trp).css("transform").split("(")[1].split(")")[0].split(",");dx=+matrix[4];dy=+matrix[5];pos[0]-=dx;pos[1]-=dy}pos[0]+=30;pos[1]+=30;if(this.hoverElementTextBB.width+pos[0]>=this.svg.attr("width")){pos[0]-=this.hoverElementTextBB.width+60}if(this.hoverElementTextBB.height+pos[1]>=this.svg.attr("height")){pos[1]-=this.hoverElementTextBB.height+60}return this.hoverElement.attr("transform","translate("+pos[0]+","+pos[1]+")")};MapView.prototype.hover=function(data){var text;text=this.hoverFunc(data,data.properties.value);this.hoverElementText.text(text);this.hoverElementTextBB=this.hoverElementText.node().getBBox();return this.hoverElementRect.attr("width",this.hoverElementTextBB.width+10).attr("height",this.hoverElementTextBB.height+10).attr("x",this.hoverElementTextBB.x-5).attr("y",this.hoverElementTextBB.y-5)};MapView.prototype.getSelection=function(){return this.panel.getSelection()};MapView.prototype.default_hover=function(data,value){return data.properties[this.config.map.geo.name_field]+" - "+value};MapView.prototype._renderMap=function(data,formatter,hoverFunc){var _this=this;if(hoverFunc){this.hoverFunc=hoverFunc}this.feature.attr("style",function(d){var id;id=d.properties[_this.config.map.geo.id_field];d.properties.value=data[id];if(_.isNumber(data[id])){return"fill: "+formatter(d.properties.value)}else{return"display:none"}});return this};return MapView}(Backbone.View); -------------------------------------------------------------------------------- /dist/0.1/js/crosslet-raw-min.js: -------------------------------------------------------------------------------- 1 | barChart=function(){if(!barChart.id)barChart.id=0;var margin={top:5,right:10,bottom:20,left:10},x,y=d3.scale.pow().exponent(.01).clamp(true).range([20,0]),id=barChart.id++,axis=d3.svg.axis().orient("bottom"),brush=d3.svg.brush(),brushDirty,dimension,group,round,tickFormat,tickSize,filter=null,name_id,status,fill;function chart(div){var width=x.range()[1],height=y.range()[0];y.domain([group.top(1)[0].value/100,group.top(1)[0].value]);div.each(function(){var div=d3.select(this),g=div.select("g");if(g.empty()){var svg=div.append("svg").attr("width",width+margin.left+margin.right).attr("height",height+margin.top+margin.bottom).attr("id",name_id);if(fill){fill_svg=svg.append("defs").append("linearGradient").attr("id","lg-"+id).attr("x1","0%").attr("y1","0%").attr("x2","100%").attr("y2","0%");var rr=x.copy().domain([0,20]).range(x.range);for(var i=0;i<20;i++){fill_svg.append("stop").attr("stop-color",fill(i)).attr("offset",i*5+"%").attr("stop-opacity","1")}}g=svg.append("g").attr("transform","translate("+margin.left+","+margin.top+")");if(filter)status.text(axis.tickFormat()(filter[0])+" - "+axis.tickFormat()(filter[1]));g.append("clipPath").attr("id","clip-"+id).append("rect").attr("width",width).attr("height",height);g.selectAll(".bar").data(["background","foreground"]).enter().append("path").attr("class",function(d){return d+" bar"}).datum(group.all());g.selectAll(".foreground.bar").attr("clip-path","url(#clip-"+id+")").attr("fill","url(#lg-"+id+")");g.append("g").attr("class","axis").attr("transform","translate(0,"+height+")").call(axis);var gBrush=g.append("g").attr("class","brush").call(brush);gBrush.selectAll("rect").attr("height",height);gBrush.selectAll(".resize").append("path").attr("d",resizePath)}if(brushDirty){brushDirty=false;g.selectAll(".brush").call(brush);div.select(".title a").style("display",brush.empty()?"none":null);if(brush.empty()){g.selectAll("#clip-"+id+" rect").attr("x",0).attr("width",width)}else{var extent=brush.extent();g.selectAll("#clip-"+id+" rect").attr("x",x(extent[0])).attr("width",x(extent[1])-x(extent[0]))}}g.selectAll(".bar").attr("d",barPath)});function barPath(groups){var path=[],i=-1,n=groups.length,d;while(++i0){if(status)status.text(axis.tickFormat()(extent[0])+" - "+axis.tickFormat()(extent[1]))}else{if(status)status.text("")}});brush.on("brushend.chart",function(){if(brush.empty()){var div=d3.select(this.parentNode.parentNode.parentNode);div.select("#clip-"+id+" rect").attr("x",null).attr("width","100%");dimension.filterAll();filter=null}});chart.margin=function(_){if(!arguments.length)return margin;margin=_;return chart};chart.x=function(_){if(!arguments.length)return x;x=_;axis.scale(x);brush.x(x);return chart};chart.tickFormat=function(_){if(!arguments.length)return tickFormat;tickFormat=_;axis.tickFormat(tickFormat);return chart};chart.name_id=function(_){if(!arguments.length)return name_id;name_id=_;return chart};chart.ticks=function(a){if(!arguments.length)return tickSize;ticks=a;if(a.length){axis.tickValues(ticks)}else axis.ticks(ticks);return chart};chart.fill=function(_){if(!arguments.length)return fill;fill=_;return chart};chart.y=function(_){if(!arguments.length)return y;y=_;return chart};chart.dimension=function(_){if(!arguments.length)return dimension;dimension=_;return chart};chart.filter=function(_){if(!arguments.length)return filter;if(_){filter=_;brush.extent(_);dimension.filterRange(_);if(status)status.text(axis.tickFormat()(filter[0])+" - "+axis.tickFormat()(filter[1]))}else{brush.clear();filter=null;dimension.filterAll()}brushDirty=true;return chart};chart.group=function(_){if(!arguments.length)return group;group=_;return chart};chart.round=function(_){if(!arguments.length)return round;round=_;return chart};return d3.rebind(chart,brush,"on")};var crosslet;crosslet={};if(!_){console.log("Please include underscore.js")}crosslet.createConfig=function(defaultConfig,config){var c;return c=jQuery.extend(true,jQuery.extend(true,{},defaultConfig),config)};crosslet.id=function(d){return d};crosslet.idf=function(d){return crosslet.id};crosslet.notimplemented=function(){throw"This function is not set. Please check your config."};crosslet.changeSelect=function(select,val){return $(select).find("option").filter(function(){return $(this).val()===val}).attr("selected",true)};crosslet.defaultConfig={map:{leaflet:{url:"http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png",key:"--your key--",styleId:64657,attribution:'Map data © OpenStreetMap contributors, ODbL, Imagery © CloudMade'},view:{center:[51.505,-.09],zoom:11},geo:{url:"please specify correct location of your geojson",name_field:"name",id_field:"code",topo_object:"please specify correct object name"}}};({data:{version:"1.0",id_field:"id"},dimensions:{},defaults:{colorscale:d3.scale.linear().domain([1,10,20]).range(["green","yellow","red"]).interpolate(d3.cie.interpolateLab),opacity:.75,order:[]}});crosslet.defaultDimensionConfig={p:{},filter:null,data:{interval:null,filter:null,field:function(d){return d.id},dataSet:crosslet.notimplemented,method:d3.tsv,preformat:function(dd){return function(d){return+d}},ticks:4,colorscale:d3.scale.linear().domain([1,10,20]).range(["green","yellow","red"]).interpolate(d3.cie.interpolateLab),exponent:1},format:{"short":function(d){return d3.format(",.2f")},"long":function(d){return d.format.short(d)},input:function(d){return d3.format(".2f")},axis:function(d){return d.format.short(d)}},render:{legend:function(d,el){var f,html;f=d.title?d.title:d.data.field_func(d);html="

"+f+"

";return el.html(html)},range:function(d,el){var html;html="

"+d.format.short(d)(d.filter[0])+""+d.format.short(d)(d.filter[1])+"

";return el.html(html)},form:function(d,el){return d.render.legend(d,el)},rangeForm:function(d,el){var html,size;size=_.max(_.map(d.data.interval,function(dd){return("_"+d.format.input(d)(dd)).length-1}));html="Range: ";return el.html(html)}},submitter:function(d,el){var out;out={};$(el).find("input, select").each(function(index,el){return out[$(el).attr("name")]=$(el).val()});return out}};var __bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i=0){this.executeCallbacks(this.callbackList[urlv],this.cache[urlv]);return this}else{if(this.status[urlv]!=="loading"){this.status[urlv]="loading";method(url,function(data){_this.cache[urlv]=data;_this.executeCallbacks(_this.callbackList[urlv],_this.cache[urlv]);_this.status[urlv]="done";return _this})}}return this};DataLoader.prototype.executeCallbacks=function(list,data){var _results;_results=[];while(list.length>0){_results.push(list.pop()(data))}return _results};return DataLoader}();var _ref,_ref1,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child};crosslet.PanelView=function(_super){__extends(PanelView,_super);function PanelView(){this.renderCubes=__bind(this.renderCubes,this);this.createCube=__bind(this.createCube,this);this.setActive=__bind(this.setActive,this);this._renderMap=__bind(this._renderMap,this);this.getSelection=__bind(this.getSelection,this);_ref=PanelView.__super__.constructor.apply(this,arguments);return _ref}PanelView.prototype.initialize=function(el,config,parent){var e,o,_i,_len,_ref1;this.config=crosslet.createConfig(crosslet.defaultConfig,config);this.parent=parent;this.el=el;this.ds=parent.ds;this.boxes={};this.render();this.width=200;this.active=this.config.defaults.active?this.config.defaults.active:this.config.defaults.order[0];this.numloads=this.config.defaults.order.length;_ref1=this.config.defaults.order;for(_i=0,_len=_ref1.length;_i<_len;_i++){o=_ref1[_i];e=$("
");this.boxes[o]=new crosslet.BoxView(e,this.config.dimensions[o],this,o);$(this.el).append(e)}this.boxes[this.active].setActive(true);this.renderMap=_.debounce(this._renderMap,300);return this.boxes};PanelView.prototype.loaded=function(){this.numloads=this.numloads-1;if(this.numloads<=0){return this.createCube()}};PanelView.prototype.getSelection=function(){var abox,adata,k,keys,out,_i,_len;abox=this.boxes[this.active];adata=abox.getFilteredData();keys=this.intersection(_.map(_.values(this.boxes),function(b){return _.keys(b.getFilteredData()).sort()}));out={};for(_i=0,_len=keys.length;_i<_len;_i++){k=keys[_i];out[k]=adata[k]}return out};PanelView.prototype._renderMap=function(){var abox,f,out,_this=this;abox=this.boxes[this.active];out=this.getSelection();f=abox.config.format.long(abox.config);this.parent.renderMap(out,function(v){return abox.config.data.colorscale(abox.config.scale(v))},function(data,value){return data.properties[_this.config.map.geo.name_field]+" - "+f(value)});return this};PanelView.prototype.setActive=function(activeBox){if(activeBox!==this.active){this.boxes[this.active].setActive(false);this.active=activeBox;this.boxes[this.active].setActive(true);return this.renderMap()}};PanelView.prototype.intersection=function(a){var intersect_safe,o,out,_i,_len,_ref1;intersect_safe=function(a,b){var ai,bi,result;ai=bi=0;result=[];while(aib[bi]){bi++}if(a[ai]===b[bi]){result.push(a[ai]);ai++;bi++}}return result};switch(a.length){case 0:return a;case 1:return a[0];case 2:return intersect_safe(a[0],a[1]);default:out=a[0];_ref1=a.slice(1);for(_i=0,_len=_ref1.length;_i<_len;_i++){o=_ref1[_i];out=intersect_safe(out,o)}return out}};PanelView.prototype.createCube=function(){var bName,box,brushevent,chart,d,dg,getRounder,groups,int,js_bName,js_box,key,keys,o,row,t1,t15,t2,yscale,_i,_j,_len,_len1,_ref1,_ref2,_ref3;this.rows=[];t1=(new Date).getTime();keys=_.map(_.values(this.boxes),function(b){return _.keys(b.data).sort()});t15=(new Date).getTime();int=this.intersection(keys);for(_i=0,_len=int.length;_i<_len;_i++){key=int[_i];row={};_ref1=this.boxes;for(bName in _ref1){box=_ref1[bName];row[bName]=box.data[key]}this.rows.push(row)}t2=(new Date).getTime();this.cube=crossfilter(this.rows);getRounder=function(m1,m2,w,exp){var scale,t;t=5*(m2-m1)/w;scale=d3.scale.pow().exponent(exp).range([m1/t,m2/t]).domain([m1/t,m2/t]);return function(d){return t*scale.invert(Math.floor(scale(+d/t)))}};groups={};this.charts={};brushevent=function(box,ctx){return function(){box.event_click();return ctx.renderCubes()}};_ref2=this.boxes;for(bName in _ref2){box=_ref2[bName];var chart,js_box,js_bName;js_box=box;js_bName=bName;d=this.cube.dimension(function(dd){return dd[bName]});dg=d.group(getRounder(box.config.data.interval[0],box.config.data.interval[1],this.width-20,box.config.data.exponent));box.graph.empty();yscale=d3.scale.linear().clamp(true).range([20,0]);chart=barChart().dimension(d).name_id(bName).group(dg).x(d3.scale.pow().exponent(box.config.data.exponent).domain(box.config.data.interval).rangeRound([0,this.width-20])).y(yscale.copy()).ticks(box.config.data.ticks).tickFormat(box.config.format.axis(box.config)).fill(box.config.data.colorscale);chart.on("brush",brushevent(box,this));chart.on("brushend",this.renderCubes);box.chart=chart;this.charts[bName]=chart}if(this.parent.ds.isGeoLoaded){this.renderCubes()}_ref3=this.config.defaults.order;for(_j=0,_len1=_ref3.length;_j<_len1;_j++){o=_ref3[_j];if(this.config.dimensions[o].filter){this.boxes[o].setFilter(this.config.dimensions[o].filter,true)}}return this};PanelView.prototype.renderCubes=function(){var abox,bName,box,_ref1;_ref1=this.boxes;for(bName in _ref1){box=_ref1[bName];box.chart(box.graph);$(box.el).on("mousedown",box.event_click);box.setFilter(box.chart.filter(),false)}abox=this.boxes[this.active];abox.setFilter(abox.chart.filter(),false);this.renderMap();return this};return PanelView}(Backbone.View);crosslet.BoxView=function(_super){__extends(BoxView,_super);function BoxView(){this.setFilter=__bind(this.setFilter,this);this.event_click=__bind(this.event_click,this);this.setActive=__bind(this.setActive,this);this.dataLoaded=__bind(this.dataLoaded,this);_ref1=BoxView.__super__.constructor.apply(this,arguments);return _ref1}BoxView.prototype.initialize=function(el,config,parent,name){this.el=el;this.config=crosslet.createConfig(crosslet.defaultDimensionConfig,config);this.config.id=name;this.config.data.field_func=!_.isFunction(this.config.data.field)?function(d){return d.data.field}:this.config.data.field;$(this.el).on("mousedown",this.event_click);$(this.el).on("tap",this.event_click);$(this.el)[0].onmousedown=$(this.el)[0].ondblclick=L.DomEvent.stopPropagation;this.legend={};this.legend.all=$("
");this.legend.text=$("
");this.legend.text_p=$("
");this.legend.text_range=$("
");this.legend.text.append(this.legend.text_p).append(this.legend.text_range);this.legend.form=$("
");this.legend.form_p=$("
");this.legend.form_range=$("
");this.legend.form.append(this.legend.form_p).append(this.legend.form_range);this.legend.all.append(this.legend.text).append(this.legend.form);$(el).append(this.legend.all);this.graph=$("
");$(el).append(this.graph);this.parent=parent;this.ds=parent.ds;this.active=false;this.name=name;return this.loadData()};BoxView.prototype.loadData=function(){if(_.isString(this.config.data.dataSet)){return this.parent.ds.loadData(this.config.data.dataSet,this.dataLoaded,this.config.data.method)}else{if(_.isFunction(this.config.data.dataSet)){return this.parent.ds.loadData(this.config.data.dataSet(this.config),this.dataLoaded,this.config.data.method)}else{return this.parent.ds.addData(this.config.data.dataSet,this.dataLoaded)}}};BoxView.prototype.dataLoaded=function(){var f,id,pd,preformatter,val,_ref2;this.data={};f=this.config.data.field_func(this.config);preformatter=this.config.data.preformat(this.config);_ref2=this.parent.ds.data;for(id in _ref2){val=_ref2[id];if(_.isNumber(val[f])){pd=preformatter(val[f])}if(_.isNumber(pd)){this.data[id]=pd}}if(!this.config.data.interval){this.config.data.interval=[_.min(_.values(this.data)),_.max(_.values(this.data))]}if(!this.config.filter){this.config.filter=[_.min(_.values(this.data)),_.max(_.values(this.data))]}this.config.scale=d3.scale.pow().exponent(this.config.data.exponent).domain(this.config.data.interval).rangeRound([0,20]);this.config.scale.name="yes";this.render();return this.parent.loaded()};BoxView.prototype.setActive=function(isActive){this.active=isActive;if(isActive){return $(this.el).addClass("selected")}else{return $(this.el).removeClass("selected")}};BoxView.prototype.event_click=function(event){if(!this.active){this.parent.setActive(this.name)}return true};BoxView.prototype.setFilter=function(f,redrawCube){if(redrawCube==null){redrawCube=false}if(redrawCube){this.chart.filter(f);this.parent.renderCubes()}if(!f){f=this.config.data.interval}this.config.filter=f;this.filterElements[0].val(this.config.format.input(this.config)(f[0]));this.filterElements[1].val(this.config.format.input(this.config)(f[1]));$(this.legend.text_range).find(".m0").text(this.config.format.short(this.config)(f[0]));$(this.legend.text_range).find(".m1").text(this.config.format.short(this.config)(f[1]));return this};BoxView.prototype.getFilteredData=function(){var f,k,out,v,_ref2,_ref3;if(!this.chart.filter()){return this.data}f=(_ref2=this.chart.filter())!=null?_ref2:this.config.data.interval;out={};_ref3=this.data;for(k in _ref3){v=_ref3[k];if(f[0]<=v&&v<=f[1]){out[k]=v}}return out};BoxView.prototype.renderRange=function(){this.config.render.range(this.config,this.legend.text_range);return this.config.render.rangeForm(this.config,this.legend.form_range)};BoxView.prototype.render=function(){var _this=this;this.config.render.legend(this.config,this.legend.text_p);this.config.render.form(this.config,this.legend.form_p);this.renderRange();$(this.legend.form_range).find("input").on("change",function(){var f;f=[+_this.filterElements[0].val(),+_this.filterElements[1].val()];if(f[0]>f[1]){f.reverse()}f[0]=_.max([_this.config.data.interval[0],f[0]]);f[1]=_.min([_this.config.data.interval[1],f[1]]);if(_.isEqual(f,_this.config.data.interval)){f=null}return _this.setFilter(f,true)});$(this.legend.form_p).find("input, select").on("change",function(){var p;_this.config.data.interval=null;_this.config.scale=null;_this.config.filter=null;p=_this.config.submitter(_this.config,_this.legend.form_p);_this.config.p=p;console.log(p);return _this.loadData()});return this.filterElements=[$(this.legend.form_range).find("input[name=m0]"),$(this.legend.form_range).find("input[name=m1]")]};return BoxView}(Backbone.View);var _ref,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child};crosslet.MapView=function(_super){__extends(MapView,_super);function MapView(){this._renderMap=__bind(this._renderMap,this);this.getSelection=__bind(this.getSelection,this);this.hover=__bind(this.hover,this);this.mouseMove=__bind(this.mouseMove,this);this.reset=__bind(this.reset,this);this.beforezoom=__bind(this.beforezoom,this);this.project=__bind(this.project,this);_ref=MapView.__super__.constructor.apply(this,arguments);return _ref}MapView.prototype.initialize=function(el,config){var _this=this;this.config=crosslet.createConfig(crosslet.defaultConfig,config);this.geoURL=this.config.map.geo.url;this.opacity=this.config.defaults.opacity;this.ds=new crosslet.DataStore(this.config);this.el=el;this.hoverFunc=this.default_hover;$(this.el).attr("class","crosslet");this.map=L.map(el[0]).setView(this.config.map.view.center,this.config.map.view.zoom);L.tileLayer(this.config.map.leaflet.url,this.config.map.leaflet).addTo(this.map);this.control=$("
");this.info=L.Control.extend({options:{position:"topright"},onAdd:function(map){return _this.control[0]}});this.map.addControl(new this.info);this.panel=new crosslet.PanelView(this.control,this.config,this);this.renderMap=this._renderMap;return this.ds.loadGeo(this.geoURL,this.config.map.geo.id_field,function(ds){_this.bounds=_this.ds.bounds;_this.path=d3.geo.path().projection(_this.project);_this.svg=d3.select(_this.map.getPanes().overlayPane).append("svg");_this.g=_this.svg.append("g");_this.g.attr("class","crosslet_geometry");_this.feature=_this.g.selectAll("path").data(ds.geometries).enter().append("path").attr("id",function(d){return"path_"+d.properties[_this.config.map.geo.id_field]}).on("mouseover",function(d){return _this.hover(d)}).on("mousemove",_this.mouseMove);_this.reset();_this.map.on("viewreset",_this.reset);_this.map.on("zoomstart",_this.beforezoom);_this.hoverElement=_this.svg.append("g").attr("class","hover");_this.hoverElementRect=_this.hoverElement.append("svg:rect").attr("x",0).attr("y",0).attr("width",10).attr("height",30).attr("rx",5).attr("ry",5);_this.hoverElementText=_this.hoverElement.append("text").attr("x",0).attr("y",0);_this.hoverElementTextBB={width:0,height:0,x:0,y:0};if(_this.panel.numloads<=0){return _this.panel.createCube()}},this.config.map.geo.topo_object)};MapView.prototype.project=function(x){var point;point=this.map.latLngToLayerPoint(new L.LatLng(x[1],x[0]));return[point.x,point.y]};MapView.prototype.beforezoom=function(){return this.g.style("display","none")};MapView.prototype.reset=function(){var bottomLeft,topRight;bottomLeft=this.project(this.bounds[0]);topRight=this.project(this.bounds[1]);this.svg.attr("width",topRight[0]-bottomLeft[0]).attr("height",bottomLeft[1]-topRight[1]).style("margin-left",bottomLeft[0]+"px").style("margin-top",topRight[1]+"px");this.g.attr("transform","translate("+-bottomLeft[0]+","+-topRight[1]+")");this.feature.attr("d",this.path);this.g.style("display","inline");return true};MapView.prototype.mouseMove=function(){var br,dx,dy,matrix,pos,trp;br=jQuery.browser;pos=d3.mouse(this.svg.node());if(br.mozilla){trp=this.svg.node().parentNode.parentNode.parentNode;matrix=$(trp).css("transform").split("(")[1].split(")")[0].split(",");dx=+matrix[4];dy=+matrix[5];pos[0]-=dx;pos[1]-=dy}pos[0]+=30;pos[1]+=30;if(this.hoverElementTextBB.width+pos[0]>=this.svg.attr("width")){pos[0]-=this.hoverElementTextBB.width+60}if(this.hoverElementTextBB.height+pos[1]>=this.svg.attr("height")){pos[1]-=this.hoverElementTextBB.height+60}return this.hoverElement.attr("transform","translate("+pos[0]+","+pos[1]+")")};MapView.prototype.hover=function(data){var text;text=this.hoverFunc(data,data.properties.value);this.hoverElementText.text(text);this.hoverElementTextBB=this.hoverElementText.node().getBBox();return this.hoverElementRect.attr("width",this.hoverElementTextBB.width+10).attr("height",this.hoverElementTextBB.height+10).attr("x",this.hoverElementTextBB.x-5).attr("y",this.hoverElementTextBB.y-5)};MapView.prototype.getSelection=function(){return this.panel.getSelection()};MapView.prototype.default_hover=function(data,value){return data.properties[this.config.map.geo.name_field]+" - "+value};MapView.prototype._renderMap=function(data,formatter,hoverFunc){var _this=this;if(hoverFunc){this.hoverFunc=hoverFunc}this.feature.attr("style",function(d){var id;id=d.properties[_this.config.map.geo.id_field];d.properties.value=data[id];if(_.isNumber(data[id])){return"fill: "+formatter(d.properties.value)}else{return"display:none"}});return this};return MapView}(Backbone.View); -------------------------------------------------------------------------------- /dist/1.1/css/crosslet-min.css: -------------------------------------------------------------------------------- 1 | .crosslet, 2 | .crosslet * { 3 | font-family: georgia, "times new roman", times, serif; 4 | } 5 | .crosslet .crosslet_panel, 6 | .crosslet * .crosslet_panel { 7 | /*display: none;*/ 8 | /*width: 950px;*/ 9 | color: #565656; 10 | top: -10px; 11 | } 12 | .crosslet .crosslet_panel .box, 13 | .crosslet * .crosslet_panel .box { 14 | /*float:left;*/ 15 | display: inline-block; 16 | vertical-align: top; 17 | width: 215px; 18 | margin-left: 5px; 19 | background-color: #efefef; 20 | transition: background-color 0.2s; 21 | -moz-transition: background-color 0.2s; 22 | /* Firefox 4 */ 23 | -webkit-transition: background-color 0.2s; 24 | /* Safari and Chrome */ 25 | -o-transition: background-color 0.2s; 26 | /* Opera */ 27 | /*background: -webkit-linear-gradient(left top, white, darken(white,5%));*/ 28 | border-bottom-right-radius: 15px; 29 | /*opacity: 0.9;*/ 30 | border-bottom-left-radius: 15px; 31 | border: 1px solid #d6d6d6; 32 | border-top: none; 33 | box-shadow: 0 10px 14px -10px rgba(0, 0, 0, 0.8); 34 | padding: 5px; 35 | font-size: 11px; 36 | text-align: center; 37 | line-height: 10px; 38 | } 39 | .crosslet .crosslet_panel .box .legendForm, 40 | .crosslet * .crosslet_panel .box .legendForm { 41 | display: none; 42 | } 43 | .crosslet .crosslet_panel .box .legendText h2, 44 | .crosslet * .crosslet_panel .box .legendText h2, 45 | .crosslet .crosslet_panel .box .legendForm h2, 46 | .crosslet * .crosslet_panel .box .legendForm h2 { 47 | font-size: 1.1em; 48 | margin: 0px; 49 | margin-bottom: 4px; 50 | text-align: center; 51 | line-height: 1.3em; 52 | } 53 | .crosslet .crosslet_panel .box .legendText p, 54 | .crosslet * .crosslet_panel .box .legendText p, 55 | .crosslet .crosslet_panel .box .legendForm p, 56 | .crosslet * .crosslet_panel .box .legendForm p { 57 | margin: 0px; 58 | } 59 | .crosslet .crosslet_panel .box .legendText select, 60 | .crosslet * .crosslet_panel .box .legendText select, 61 | .crosslet .crosslet_panel .box .legendForm select, 62 | .crosslet * .crosslet_panel .box .legendForm select, 63 | .crosslet .crosslet_panel .box .legendText input[type="text"], 64 | .crosslet * .crosslet_panel .box .legendText input[type="text"], 65 | .crosslet .crosslet_panel .box .legendForm input[type="text"], 66 | .crosslet * .crosslet_panel .box .legendForm input[type="text"] { 67 | background-color: #efefef; 68 | width: auto; 69 | padding: 0px; 70 | padding-left: 4px; 71 | height: 12px; 72 | line-height: 13px; 73 | font-size: 12px; 74 | text-align: center; 75 | border: 1px solid #efefef; 76 | border-radius: 6px; 77 | font-weight: bold; 78 | margin: 0px; 79 | transition: background-color 0.2s; 80 | -moz-transition: background-color 0.2s; 81 | /* Firefox 4 */ 82 | -webkit-transition: background-color 0.2s; 83 | /* Safari and Chrome */ 84 | -o-transition: background-color 0.2s; 85 | /* Opera */ 86 | /*text-align: center;*/ 87 | } 88 | .crosslet .crosslet_panel .box .graph, 89 | .crosslet * .crosslet_panel .box .graph { 90 | /*.transition(height);*/ 91 | display: none; 92 | } 93 | .crosslet .crosslet_panel .box .graph, 94 | .crosslet * .crosslet_panel .box .graph { 95 | display: inline-block; 96 | margin-bottom: 0px; 97 | } 98 | .crosslet .crosslet_panel .box .background.bar, 99 | .crosslet * .crosslet_panel .box .background.bar { 100 | fill: #d6d6d6; 101 | } 102 | .crosslet .crosslet_panel .box .axis, 103 | .crosslet * .crosslet_panel .box .axis { 104 | display: none; 105 | } 106 | .crosslet .crosslet_panel .box .axis path, 107 | .crosslet * .crosslet_panel .box .axis path, 108 | .crosslet .crosslet_panel .box .axis line, 109 | .crosslet * .crosslet_panel .box .axis line { 110 | fill: none; 111 | stroke: #000; 112 | shape-rendering: crispEdges; 113 | } 114 | .crosslet .crosslet_panel .box .axis text, 115 | .crosslet * .crosslet_panel .box .axis text { 116 | font: 10px sans-serif; 117 | } 118 | .crosslet .crosslet_panel .box .brush rect.extent, 119 | .crosslet * .crosslet_panel .box .brush rect.extent { 120 | fill: steelblue; 121 | fill-opacity: .125; 122 | } 123 | .crosslet .crosslet_panel .box .brush .resize, 124 | .crosslet * .crosslet_panel .box .brush .resize { 125 | display: none; 126 | } 127 | .crosslet .crosslet_panel .box .brush .resize path, 128 | .crosslet * .crosslet_panel .box .brush .resize path { 129 | fill: #eee; 130 | stroke: #666; 131 | } 132 | .crosslet .crosslet_panel .box svg, 133 | .crosslet * .crosslet_panel .box svg { 134 | height: 25px; 135 | transition: height 0.2s; 136 | -moz-transition: height 0.2s; 137 | /* Firefox 4 */ 138 | -webkit-transition: height 0.2s; 139 | /* Safari and Chrome */ 140 | -o-transition: height 0.2s; 141 | /* Opera */ 142 | } 143 | .crosslet .crosslet_panel .box.selected, 144 | .crosslet * .crosslet_panel .box.selected, 145 | .crosslet .crosslet_panel .box:hover, 146 | .crosslet * .crosslet_panel .box:hover { 147 | opacity: 1; 148 | background: #ffffff; 149 | border-color: #b3b3b3; 150 | transition: background-color 0.2s; 151 | -moz-transition: background-color 0.2s; 152 | /* Firefox 4 */ 153 | -webkit-transition: background-color 0.2s; 154 | /* Safari and Chrome */ 155 | -o-transition: background-color 0.2s; 156 | /* Opera */ 157 | /*min-height: 110px;*/ 158 | color: black; 159 | } 160 | .crosslet .crosslet_panel .box.selected .legendForm, 161 | .crosslet * .crosslet_panel .box.selected .legendForm, 162 | .crosslet .crosslet_panel .box:hover .legendForm, 163 | .crosslet * .crosslet_panel .box:hover .legendForm { 164 | display: block; 165 | } 166 | .crosslet .crosslet_panel .box.selected .legendText, 167 | .crosslet * .crosslet_panel .box.selected .legendText, 168 | .crosslet .crosslet_panel .box:hover .legendText, 169 | .crosslet * .crosslet_panel .box:hover .legendText { 170 | display: none; 171 | } 172 | .crosslet .crosslet_panel .box.selected select, 173 | .crosslet * .crosslet_panel .box.selected select, 174 | .crosslet .crosslet_panel .box:hover select, 175 | .crosslet * .crosslet_panel .box:hover select, 176 | .crosslet .crosslet_panel .box.selected input[type="text"], 177 | .crosslet * .crosslet_panel .box.selected input[type="text"], 178 | .crosslet .crosslet_panel .box:hover input[type="text"], 179 | .crosslet * .crosslet_panel .box:hover input[type="text"] { 180 | background-color: #ffffff; 181 | border: 1px solid #b3b3b3; 182 | transition: background-color 0.2s; 183 | -moz-transition: background-color 0.2s; 184 | /* Firefox 4 */ 185 | -webkit-transition: background-color 0.2s; 186 | /* Safari and Chrome */ 187 | -o-transition: background-color 0.2s; 188 | /* Opera */ 189 | } 190 | .crosslet .crosslet_panel .box.selected .graph, 191 | .crosslet * .crosslet_panel .box.selected .graph, 192 | .crosslet .crosslet_panel .box:hover .graph, 193 | .crosslet * .crosslet_panel .box:hover .graph { 194 | /*border: 1px dotted @inactive-border;*/ 195 | /*height: 55px;*/ 196 | margin: 5px; 197 | margin-bottom: 2px; 198 | display: block; 199 | /* 200 | 201 | 202 | }*/ 203 | } 204 | .crosslet .crosslet_panel .box.selected .graph svg, 205 | .crosslet * .crosslet_panel .box.selected .graph svg, 206 | .crosslet .crosslet_panel .box:hover .graph svg, 207 | .crosslet * .crosslet_panel .box:hover .graph svg { 208 | height: 45px; 209 | transition: height 0.2s; 210 | -moz-transition: height 0.2s; 211 | /* Firefox 4 */ 212 | -webkit-transition: height 0.2s; 213 | /* Safari and Chrome */ 214 | -o-transition: height 0.2s; 215 | /* Opera */ 216 | } 217 | .crosslet .crosslet_panel .box.selected .graph .axis, 218 | .crosslet * .crosslet_panel .box.selected .graph .axis, 219 | .crosslet .crosslet_panel .box:hover .graph .axis, 220 | .crosslet * .crosslet_panel .box:hover .graph .axis { 221 | display: inline; 222 | transition: display 0.2s; 223 | -moz-transition: display 0.2s; 224 | /* Firefox 4 */ 225 | -webkit-transition: display 0.2s; 226 | /* Safari and Chrome */ 227 | -o-transition: display 0.2s; 228 | /* Opera */ 229 | } 230 | .crosslet .crosslet_panel .box.selected .graph .brush .resize, 231 | .crosslet * .crosslet_panel .box.selected .graph .brush .resize, 232 | .crosslet .crosslet_panel .box:hover .graph .brush .resize, 233 | .crosslet * .crosslet_panel .box:hover .graph .brush .resize { 234 | display: inline; 235 | } 236 | .crosslet .crosslet_panel .box.selected .graph .background.bar, 237 | .crosslet * .crosslet_panel .box.selected .graph .background.bar, 238 | .crosslet .crosslet_panel .box:hover .graph .background.bar, 239 | .crosslet * .crosslet_panel .box:hover .graph .background.bar { 240 | fill: #cccccc; 241 | } 242 | .crosslet .box:not(.selected):hover .foreground.bar, 243 | .crosslet * .box:not(.selected):hover .foreground.bar { 244 | fill: #808080; 245 | } 246 | .crosslet .box:not(.selected) .foreground.bar, 247 | .crosslet * .box:not(.selected) .foreground.bar { 248 | fill: #bcbcbc; 249 | /*fill: steelblue;*/ 250 | } 251 | .crosslet .box.selected #imd .foreground.bar, 252 | .crosslet * .box.selected #imd .foreground.bar { 253 | /* fill: inherit; */ 254 | } 255 | .crosslet svg g.crosslet_geometry { 256 | fill-opacity: 0.5; 257 | } 258 | .crosslet svg g.crosslet_geometry path { 259 | fill: white; 260 | stroke: none; 261 | /*stroke: black; */ 262 | } 263 | .crosslet svg g.crosslet_geometry path:hover { 264 | fill-opacity: 0.2; 265 | stroke-width: 2px; 266 | stroke: white; 267 | box-shadow: -5px -5px -5px -5px rgba(0, 0, 0, 0.8); 268 | } 269 | .crosslet svg .hover { 270 | display: none; 271 | } 272 | .crosslet svg .hover rect { 273 | stroke: none; 274 | fill-opacity: 0.5; 275 | fill: #efefef; 276 | border-radius: 5px; 277 | } 278 | .crosslet svg .hover text { 279 | font-size: 12px; 280 | fill: black; 281 | font-weight: bold; 282 | } 283 | .crosslet svg:hover .hover { 284 | display: inline; 285 | } 286 | -------------------------------------------------------------------------------- /dist/1.1/css/crosslet.css: -------------------------------------------------------------------------------- 1 | .crosslet, 2 | .crosslet * { 3 | font-family: georgia, "times new roman", times, serif; 4 | } 5 | .crosslet .crosslet_panel, 6 | .crosslet * .crosslet_panel { 7 | /*display: none;*/ 8 | /*width: 950px;*/ 9 | color: #565656; 10 | top: -10px; 11 | } 12 | .crosslet .crosslet_panel .box, 13 | .crosslet * .crosslet_panel .box { 14 | /*float:left;*/ 15 | display: inline-block; 16 | vertical-align: top; 17 | width: 215px; 18 | margin-left: 5px; 19 | background-color: #efefef; 20 | transition: background-color 0.2s; 21 | -moz-transition: background-color 0.2s; 22 | /* Firefox 4 */ 23 | -webkit-transition: background-color 0.2s; 24 | /* Safari and Chrome */ 25 | -o-transition: background-color 0.2s; 26 | /* Opera */ 27 | /*background: -webkit-linear-gradient(left top, white, darken(white,5%));*/ 28 | border-bottom-right-radius: 15px; 29 | /*opacity: 0.9;*/ 30 | border-bottom-left-radius: 15px; 31 | border: 1px solid #d6d6d6; 32 | border-top: none; 33 | box-shadow: 0 10px 14px -10px rgba(0, 0, 0, 0.8); 34 | padding: 5px; 35 | font-size: 11px; 36 | text-align: center; 37 | line-height: 10px; 38 | } 39 | .crosslet .crosslet_panel .box .legendForm, 40 | .crosslet * .crosslet_panel .box .legendForm { 41 | display: none; 42 | } 43 | .crosslet .crosslet_panel .box .legendText h2, 44 | .crosslet * .crosslet_panel .box .legendText h2, 45 | .crosslet .crosslet_panel .box .legendForm h2, 46 | .crosslet * .crosslet_panel .box .legendForm h2 { 47 | font-size: 1.1em; 48 | margin: 0px; 49 | margin-bottom: 4px; 50 | text-align: center; 51 | line-height: 1.3em; 52 | } 53 | .crosslet .crosslet_panel .box .legendText p, 54 | .crosslet * .crosslet_panel .box .legendText p, 55 | .crosslet .crosslet_panel .box .legendForm p, 56 | .crosslet * .crosslet_panel .box .legendForm p { 57 | margin: 0px; 58 | } 59 | .crosslet .crosslet_panel .box .legendText select, 60 | .crosslet * .crosslet_panel .box .legendText select, 61 | .crosslet .crosslet_panel .box .legendForm select, 62 | .crosslet * .crosslet_panel .box .legendForm select, 63 | .crosslet .crosslet_panel .box .legendText input[type="text"], 64 | .crosslet * .crosslet_panel .box .legendText input[type="text"], 65 | .crosslet .crosslet_panel .box .legendForm input[type="text"], 66 | .crosslet * .crosslet_panel .box .legendForm input[type="text"] { 67 | background-color: #efefef; 68 | width: auto; 69 | padding: 0px; 70 | padding-left: 4px; 71 | height: 12px; 72 | line-height: 13px; 73 | font-size: 12px; 74 | text-align: center; 75 | border: 1px solid #efefef; 76 | border-radius: 6px; 77 | font-weight: bold; 78 | margin: 0px; 79 | transition: background-color 0.2s; 80 | -moz-transition: background-color 0.2s; 81 | /* Firefox 4 */ 82 | -webkit-transition: background-color 0.2s; 83 | /* Safari and Chrome */ 84 | -o-transition: background-color 0.2s; 85 | /* Opera */ 86 | /*text-align: center;*/ 87 | } 88 | .crosslet .crosslet_panel .box .graph, 89 | .crosslet * .crosslet_panel .box .graph { 90 | /*.transition(height);*/ 91 | display: none; 92 | } 93 | .crosslet .crosslet_panel .box .graph, 94 | .crosslet * .crosslet_panel .box .graph { 95 | display: inline-block; 96 | margin-bottom: 0px; 97 | } 98 | .crosslet .crosslet_panel .box .background.bar, 99 | .crosslet * .crosslet_panel .box .background.bar { 100 | fill: #d6d6d6; 101 | } 102 | .crosslet .crosslet_panel .box .axis, 103 | .crosslet * .crosslet_panel .box .axis { 104 | display: none; 105 | } 106 | .crosslet .crosslet_panel .box .axis path, 107 | .crosslet * .crosslet_panel .box .axis path, 108 | .crosslet .crosslet_panel .box .axis line, 109 | .crosslet * .crosslet_panel .box .axis line { 110 | fill: none; 111 | stroke: #000; 112 | shape-rendering: crispEdges; 113 | } 114 | .crosslet .crosslet_panel .box .axis text, 115 | .crosslet * .crosslet_panel .box .axis text { 116 | font: 10px sans-serif; 117 | } 118 | .crosslet .crosslet_panel .box .brush rect.extent, 119 | .crosslet * .crosslet_panel .box .brush rect.extent { 120 | fill: steelblue; 121 | fill-opacity: .125; 122 | } 123 | .crosslet .crosslet_panel .box .brush .resize, 124 | .crosslet * .crosslet_panel .box .brush .resize { 125 | display: none; 126 | } 127 | .crosslet .crosslet_panel .box .brush .resize path, 128 | .crosslet * .crosslet_panel .box .brush .resize path { 129 | fill: #eee; 130 | stroke: #666; 131 | } 132 | .crosslet .crosslet_panel .box svg, 133 | .crosslet * .crosslet_panel .box svg { 134 | height: 25px; 135 | transition: height 0.2s; 136 | -moz-transition: height 0.2s; 137 | /* Firefox 4 */ 138 | -webkit-transition: height 0.2s; 139 | /* Safari and Chrome */ 140 | -o-transition: height 0.2s; 141 | /* Opera */ 142 | } 143 | .crosslet .crosslet_panel .box.selected, 144 | .crosslet * .crosslet_panel .box.selected, 145 | .crosslet .crosslet_panel .box:hover, 146 | .crosslet * .crosslet_panel .box:hover { 147 | opacity: 1; 148 | background: #ffffff; 149 | border-color: #b3b3b3; 150 | transition: background-color 0.2s; 151 | -moz-transition: background-color 0.2s; 152 | /* Firefox 4 */ 153 | -webkit-transition: background-color 0.2s; 154 | /* Safari and Chrome */ 155 | -o-transition: background-color 0.2s; 156 | /* Opera */ 157 | /*min-height: 110px;*/ 158 | color: black; 159 | } 160 | .crosslet .crosslet_panel .box.selected .legendForm, 161 | .crosslet * .crosslet_panel .box.selected .legendForm, 162 | .crosslet .crosslet_panel .box:hover .legendForm, 163 | .crosslet * .crosslet_panel .box:hover .legendForm { 164 | display: block; 165 | } 166 | .crosslet .crosslet_panel .box.selected .legendText, 167 | .crosslet * .crosslet_panel .box.selected .legendText, 168 | .crosslet .crosslet_panel .box:hover .legendText, 169 | .crosslet * .crosslet_panel .box:hover .legendText { 170 | display: none; 171 | } 172 | .crosslet .crosslet_panel .box.selected select, 173 | .crosslet * .crosslet_panel .box.selected select, 174 | .crosslet .crosslet_panel .box:hover select, 175 | .crosslet * .crosslet_panel .box:hover select, 176 | .crosslet .crosslet_panel .box.selected input[type="text"], 177 | .crosslet * .crosslet_panel .box.selected input[type="text"], 178 | .crosslet .crosslet_panel .box:hover input[type="text"], 179 | .crosslet * .crosslet_panel .box:hover input[type="text"] { 180 | background-color: #ffffff; 181 | border: 1px solid #b3b3b3; 182 | transition: background-color 0.2s; 183 | -moz-transition: background-color 0.2s; 184 | /* Firefox 4 */ 185 | -webkit-transition: background-color 0.2s; 186 | /* Safari and Chrome */ 187 | -o-transition: background-color 0.2s; 188 | /* Opera */ 189 | } 190 | .crosslet .crosslet_panel .box.selected .graph, 191 | .crosslet * .crosslet_panel .box.selected .graph, 192 | .crosslet .crosslet_panel .box:hover .graph, 193 | .crosslet * .crosslet_panel .box:hover .graph { 194 | /*border: 1px dotted @inactive-border;*/ 195 | /*height: 55px;*/ 196 | margin: 5px; 197 | margin-bottom: 2px; 198 | display: block; 199 | /* 200 | 201 | 202 | }*/ 203 | } 204 | .crosslet .crosslet_panel .box.selected .graph svg, 205 | .crosslet * .crosslet_panel .box.selected .graph svg, 206 | .crosslet .crosslet_panel .box:hover .graph svg, 207 | .crosslet * .crosslet_panel .box:hover .graph svg { 208 | height: 45px; 209 | transition: height 0.2s; 210 | -moz-transition: height 0.2s; 211 | /* Firefox 4 */ 212 | -webkit-transition: height 0.2s; 213 | /* Safari and Chrome */ 214 | -o-transition: height 0.2s; 215 | /* Opera */ 216 | } 217 | .crosslet .crosslet_panel .box.selected .graph .axis, 218 | .crosslet * .crosslet_panel .box.selected .graph .axis, 219 | .crosslet .crosslet_panel .box:hover .graph .axis, 220 | .crosslet * .crosslet_panel .box:hover .graph .axis { 221 | display: inline; 222 | transition: display 0.2s; 223 | -moz-transition: display 0.2s; 224 | /* Firefox 4 */ 225 | -webkit-transition: display 0.2s; 226 | /* Safari and Chrome */ 227 | -o-transition: display 0.2s; 228 | /* Opera */ 229 | } 230 | .crosslet .crosslet_panel .box.selected .graph .brush .resize, 231 | .crosslet * .crosslet_panel .box.selected .graph .brush .resize, 232 | .crosslet .crosslet_panel .box:hover .graph .brush .resize, 233 | .crosslet * .crosslet_panel .box:hover .graph .brush .resize { 234 | display: inline; 235 | } 236 | .crosslet .crosslet_panel .box.selected .graph .background.bar, 237 | .crosslet * .crosslet_panel .box.selected .graph .background.bar, 238 | .crosslet .crosslet_panel .box:hover .graph .background.bar, 239 | .crosslet * .crosslet_panel .box:hover .graph .background.bar { 240 | fill: #cccccc; 241 | } 242 | .crosslet .box:not(.selected):hover .foreground.bar, 243 | .crosslet * .box:not(.selected):hover .foreground.bar { 244 | fill: #808080; 245 | } 246 | .crosslet .box:not(.selected) .foreground.bar, 247 | .crosslet * .box:not(.selected) .foreground.bar { 248 | fill: #bcbcbc; 249 | /*fill: steelblue;*/ 250 | } 251 | .crosslet .box.selected #imd .foreground.bar, 252 | .crosslet * .box.selected #imd .foreground.bar { 253 | /* fill: inherit; */ 254 | } 255 | .crosslet svg g.crosslet_geometry { 256 | fill-opacity: 0.5; 257 | } 258 | .crosslet svg g.crosslet_geometry path { 259 | fill: white; 260 | stroke: none; 261 | /*stroke: black; */ 262 | } 263 | .crosslet svg g.crosslet_geometry path:hover { 264 | fill-opacity: 0.2; 265 | stroke-width: 2px; 266 | stroke: white; 267 | box-shadow: -5px -5px -5px -5px rgba(0, 0, 0, 0.8); 268 | } 269 | .crosslet svg .hover { 270 | display: none; 271 | } 272 | .crosslet svg .hover rect { 273 | stroke: none; 274 | fill-opacity: 0.5; 275 | fill: #efefef; 276 | border-radius: 5px; 277 | } 278 | .crosslet svg .hover text { 279 | font-size: 12px; 280 | fill: black; 281 | font-weight: bold; 282 | } 283 | .crosslet svg:hover .hover { 284 | display: inline; 285 | } 286 | -------------------------------------------------------------------------------- /dist/1.1/js/crosslet-raw-min.js: -------------------------------------------------------------------------------- 1 | barChart=function(){if(!barChart.id)barChart.id=0;var margin={top:5,right:10,bottom:20,left:10},x,y=d3.scale.pow().exponent(.01).clamp(true).range([20,0]),id=barChart.id++,axis=d3.svg.axis().orient("bottom"),brush=d3.svg.brush(),brushDirty,dimension,group,round,tickFormat,tickSize,filter=null,name_id,status,fill;function chart(div){var width=x.range()[1],height=y.range()[0];y.domain([group.top(1)[0].value/100,group.top(1)[0].value]);div.each(function(){var div=d3.select(this),g=div.select("g");if(g.empty()){var svg=div.append("svg").attr("width",width+margin.left+margin.right).attr("height",height+margin.top+margin.bottom).attr("id",name_id);if(fill){fill_svg=svg.append("defs").append("linearGradient").attr("id","lg-"+id).attr("x1","0%").attr("y1","0%").attr("x2","100%").attr("y2","0%");var rr=x.copy().domain([0,20]).range(x.range);for(var i=0;i<20;i++){fill_svg.append("stop").attr("stop-color",fill(i)).attr("offset",i*5+"%").attr("stop-opacity","1")}}g=svg.append("g").attr("transform","translate("+margin.left+","+margin.top+")");if(filter)status.text(axis.tickFormat()(filter[0])+" - "+axis.tickFormat()(filter[1]));g.append("clipPath").attr("id","clip-"+id).append("rect").attr("width",width).attr("height",height);g.selectAll(".bar").data(["background","foreground"]).enter().append("path").attr("class",function(d){return d+" bar"}).datum(group.all());g.selectAll(".foreground.bar").attr("clip-path","url(#clip-"+id+")").attr("fill","url(#lg-"+id+")");g.append("g").attr("class","axis").attr("transform","translate(0,"+height+")").call(axis);var gBrush=g.append("g").attr("class","brush").call(brush);gBrush.selectAll("rect").attr("height",height);gBrush.selectAll(".resize").append("path").attr("d",resizePath)}if(brushDirty){brushDirty=false;g.selectAll(".brush").call(brush);div.select(".title a").style("display",brush.empty()?"none":null);if(brush.empty()){g.selectAll("#clip-"+id+" rect").attr("x",0).attr("width",width)}else{var extent=brush.extent();g.selectAll("#clip-"+id+" rect").attr("x",x(extent[0])).attr("width",x(extent[1])-x(extent[0]))}}g.selectAll(".bar").attr("d",barPath)});function barPath(groups){var path=[],i=-1,n=groups.length,d;while(++i0){if(status)status.text(axis.tickFormat()(extent[0])+" - "+axis.tickFormat()(extent[1]))}else{if(status)status.text("")}});brush.on("brushend.chart",function(){if(brush.empty()){var div=d3.select(this.parentNode.parentNode.parentNode);div.select("#clip-"+id+" rect").attr("x",null).attr("width","100%");dimension.filterAll();filter=null}});chart.margin=function(_){if(!arguments.length)return margin;margin=_;return chart};chart.x=function(_){if(!arguments.length)return x;x=_;axis.scale(x);brush.x(x);return chart};chart.tickFormat=function(_){if(!arguments.length)return tickFormat;tickFormat=_;axis.tickFormat(tickFormat);return chart};chart.name_id=function(_){if(!arguments.length)return name_id;name_id=_;return chart};chart.ticks=function(a){if(!arguments.length)return tickSize;ticks=a;if(a.length){axis.tickValues(ticks)}else axis.ticks(ticks);return chart};chart.fill=function(_){if(!arguments.length)return fill;fill=_;return chart};chart.y=function(_){if(!arguments.length)return y;y=_;return chart};chart.dimension=function(_){if(!arguments.length)return dimension;dimension=_;return chart};chart.filter=function(_){if(!arguments.length)return filter;if(_){filter=_;brush.extent(_);dimension.filterRange(_);if(status)status.text(axis.tickFormat()(filter[0])+" - "+axis.tickFormat()(filter[1]))}else{brush.clear();filter=null;dimension.filterAll()}brushDirty=true;return chart};chart.group=function(_){if(!arguments.length)return group;group=_;return chart};chart.round=function(_){if(!arguments.length)return round;round=_;return chart};return d3.rebind(chart,brush,"on")};var crosslet;crosslet={};if(!_){console.log("Please include underscore.js")}crosslet.createConfig=function(defaultConfig,config){var c;return c=jQuery.extend(true,jQuery.extend(true,{},defaultConfig),config)};crosslet.id=function(d){return d};crosslet.idf=function(d){return crosslet.id};crosslet.notimplemented=function(){throw"This function is not set. Please check your config."};crosslet.changeSelect=function(select,val){return $(select).find("option").filter(function(){return $(this).val()===val}).attr("selected",true)};crosslet.defaultConfig={map:{leaflet:{url:"http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png",key:"--your key--",styleId:64657,attribution:'Map data © OpenStreetMap contributors, ODbL, Imagery © CloudMade'},view:{center:[51.505,-.09],zoom:11},geo:{url:"please specify correct location of your geojson",name_field:"name",id_field:"code",topo_object:"please specify correct object name"}}};({data:{version:"1.0",id_field:"id"},dimensions:{},defaults:{colorscale:d3.scale.linear().domain([1,10,20]).range(["green","yellow","red"]).interpolate(d3.cie.interpolateLab),opacity:.75,order:[]}});crosslet.defaultDimensionConfig={p:{},filter:null,data:{interval:null,filter:null,field:function(d){return d.id},dataSet:crosslet.notimplemented,method:d3.tsv,preformat:function(dd){return function(d){return+d}},ticks:4,colorscale:d3.scale.linear().domain([1,10,20]).range(["green","yellow","red"]).interpolate(d3.cie.interpolateLab),exponent:1},format:{"short":function(d){return d3.format(",.2f")},"long":function(d){return d.format.short(d)},input:function(d){return d3.format(".2f")},axis:function(d){return d.format.short(d)}},render:{legend:function(d,el){var f,html;f=d.title?d.title:d.data.field_func(d);html="

"+f+"

";return el.html(html)},range:function(d,el){var html;html="

"+d.format.short(d)(d.filter[0])+""+d.format.short(d)(d.filter[1])+"

";return el.html(html)},form:function(d,el){return d.render.legend(d,el)},rangeForm:function(d,el){var html,size;size=_.max(_.map(d.data.interval,function(dd){return("_"+d.format.input(d)(dd)).length-1}));html="Range: ";return el.html(html)}},submitter:function(d,el){var out;out={};$(el).find("input, select").each(function(index,el){return out[$(el).attr("name")]=$(el).val()});return out}};var __bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i=0){this.executeCallbacks(this.callbackList[urlv],this.cache[urlv]);return this}else{if(this.status[urlv]!=="loading"){this.status[urlv]="loading";method(url,function(data){_this.cache[urlv]=data;_this.executeCallbacks(_this.callbackList[urlv],_this.cache[urlv]);_this.status[urlv]="done";return _this})}}return this};DataLoader.prototype.executeCallbacks=function(list,data){var _results;_results=[];while(list.length>0){_results.push(list.pop()(data))}return _results};return DataLoader}();var _ref,_ref1,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child};crosslet.PanelView=function(_super){__extends(PanelView,_super);function PanelView(){this.renderCubes=__bind(this.renderCubes,this);this.createCube=__bind(this.createCube,this);this.setActive=__bind(this.setActive,this);this._renderMap=__bind(this._renderMap,this);this.getSelection=__bind(this.getSelection,this);_ref=PanelView.__super__.constructor.apply(this,arguments);return _ref}PanelView.prototype.initialize=function(el,config,parent){var e,o,_i,_len,_ref1;this.config=crosslet.createConfig(crosslet.defaultConfig,config);this.parent=parent;this.el=el;this.ds=parent.ds;this.boxes={};this.render();this.width=200;this.active=this.config.defaults.active?this.config.defaults.active:this.config.defaults.order[0];this.numloads=this.config.defaults.order.length;_ref1=this.config.defaults.order;for(_i=0,_len=_ref1.length;_i<_len;_i++){o=_ref1[_i];e=$("
");this.boxes[o]=new crosslet.BoxView(e,this.config.dimensions[o],this,o);$(this.el).append(e)}this.boxes[this.active].setActive(true);this.renderMap=_.debounce(this._renderMap,300);return this.boxes};PanelView.prototype.loaded=function(){this.numloads=this.numloads-1;if(this.numloads<=0){return this.createCube()}};PanelView.prototype.getSelection=function(){var abox,adata,k,keys,out,_i,_len;abox=this.boxes[this.active];adata=abox.getFilteredData();keys=this.intersection(_.map(_.values(this.boxes),function(b){return _.keys(b.getFilteredData()).sort()}));out={};for(_i=0,_len=keys.length;_i<_len;_i++){k=keys[_i];out[k]=adata[k]}return out};PanelView.prototype._renderMap=function(){var abox,f,out,_this=this;abox=this.boxes[this.active];out=this.getSelection();f=abox.config.format.long(abox.config);this.parent.renderMap(out,function(v){return abox.config.data.colorscale(abox.config.scale(v))},function(data,value){return data.properties[_this.config.map.geo.name_field]+" - "+f(value)});return this};PanelView.prototype.setActive=function(activeBox){if(activeBox!==this.active){this.boxes[this.active].setActive(false);this.active=activeBox;this.boxes[this.active].setActive(true);return this.renderMap()}};PanelView.prototype.intersection=function(a){var intersect_safe,o,out,_i,_len,_ref1;intersect_safe=function(a,b){var ai,bi,result;ai=bi=0;result=[];while(aib[bi]){bi++}if(a[ai]===b[bi]){result.push(a[ai]);ai++;bi++}}return result};switch(a.length){case 0:return a;case 1:return a[0];case 2:return intersect_safe(a[0],a[1]);default:out=a[0];_ref1=a.slice(1);for(_i=0,_len=_ref1.length;_i<_len;_i++){o=_ref1[_i];out=intersect_safe(out,o)}return out}};PanelView.prototype.createCube=function(){var bName,box,brushevent,chart,d,dg,getRounder,groups,int,js_bName,js_box,key,keys,o,row,t1,t15,t2,yscale,_i,_j,_len,_len1,_ref1,_ref2,_ref3;this.rows=[];t1=(new Date).getTime();keys=_.map(_.values(this.boxes),function(b){return _.keys(b.data).sort()});t15=(new Date).getTime();int=this.intersection(keys);for(_i=0,_len=int.length;_i<_len;_i++){key=int[_i];row={};_ref1=this.boxes;for(bName in _ref1){box=_ref1[bName];row[bName]=box.data[key]}this.rows.push(row)}t2=(new Date).getTime();this.cube=crossfilter(this.rows);getRounder=function(m1,m2,w,exp){var scale,t;t=5*(m2-m1)/w;scale=d3.scale.pow().exponent(exp).range([m1/t,m2/t]).domain([m1/t,m2/t]);return function(d){return t*scale.invert(Math.floor(scale(+d/t)))}};groups={};this.charts={};brushevent=function(box,ctx){return function(){box.event_click();return ctx.renderCubes()}};_ref2=this.boxes;for(bName in _ref2){box=_ref2[bName];var chart,js_box,js_bName;js_box=box;js_bName=bName;d=this.cube.dimension(function(dd){return dd[bName]});dg=d.group(getRounder(box.config.data.interval[0],box.config.data.interval[1],this.width-20,box.config.data.exponent));box.graph.empty();yscale=d3.scale.linear().clamp(true).range([20,0]);chart=barChart().dimension(d).name_id(bName).group(dg).x(d3.scale.pow().exponent(box.config.data.exponent).domain(box.config.data.interval).rangeRound([0,this.width-20])).y(yscale.copy()).ticks(box.config.data.ticks).tickFormat(box.config.format.axis(box.config)).fill(box.config.data.colorscale);chart.on("brush",brushevent(box,this));chart.on("brushend",this.renderCubes);box.chart=chart;this.charts[bName]=chart}if(this.parent.ds.isGeoLoaded){this.renderCubes()}_ref3=this.config.defaults.order;for(_j=0,_len1=_ref3.length;_j<_len1;_j++){o=_ref3[_j];if(this.config.dimensions[o].filter){this.boxes[o].setFilter(this.config.dimensions[o].filter,true)}}return this};PanelView.prototype.renderCubes=function(){var abox,bName,box,_ref1;_ref1=this.boxes;for(bName in _ref1){box=_ref1[bName];box.chart(box.graph);$(box.el).on("mousedown",box.event_click);box.setFilter(box.chart.filter(),false)}abox=this.boxes[this.active];abox.setFilter(abox.chart.filter(),false);this.renderMap();return this};return PanelView}(Backbone.View);crosslet.BoxView=function(_super){__extends(BoxView,_super);function BoxView(){this.setFilter=__bind(this.setFilter,this);this.event_click=__bind(this.event_click,this);this.setActive=__bind(this.setActive,this);this.dataLoaded=__bind(this.dataLoaded,this);_ref1=BoxView.__super__.constructor.apply(this,arguments);return _ref1}BoxView.prototype.initialize=function(el,config,parent,name){this.el=el;this.config=crosslet.createConfig(crosslet.defaultDimensionConfig,config);this.config.id=name;this.config.data.field_func=!_.isFunction(this.config.data.field)?function(d){return d.data.field}:this.config.data.field;$(this.el).on("mousedown",this.event_click);$(this.el).on("tap",this.event_click);$(this.el)[0].onmousedown=$(this.el)[0].ondblclick=L.DomEvent.stopPropagation;this.legend={};this.legend.all=$("
");this.legend.text=$("
");this.legend.text_p=$("
");this.legend.text_range=$("
");this.legend.text.append(this.legend.text_p).append(this.legend.text_range);this.legend.form=$("
");this.legend.form_p=$("
");this.legend.form_range=$("
");this.legend.form.append(this.legend.form_p).append(this.legend.form_range);this.legend.all.append(this.legend.text).append(this.legend.form);$(el).append(this.legend.all);this.graph=$("
");$(el).append(this.graph);this.parent=parent;this.ds=parent.ds;this.active=false;this.name=name;return this.loadData()};BoxView.prototype.loadData=function(){if(_.isString(this.config.data.dataSet)){return this.parent.ds.loadData(this.config.data.dataSet,this.dataLoaded,this.config.data.method)}else{if(_.isFunction(this.config.data.dataSet)){return this.parent.ds.loadData(this.config.data.dataSet(this.config),this.dataLoaded,this.config.data.method)}else{return this.parent.ds.addData(this.config.data.dataSet,this.dataLoaded)}}};BoxView.prototype.dataLoaded=function(){var f,id,pd,preformatter,val,_ref2;this.data={};f=this.config.data.field_func(this.config);preformatter=this.config.data.preformat(this.config);_ref2=this.parent.ds.data;for(id in _ref2){val=_ref2[id];if(_.isNumber(val[f])){pd=preformatter(val[f])}if(_.isNumber(pd)){this.data[id]=pd}}if(!this.config.data.interval){this.config.data.interval=[_.min(_.values(this.data)),_.max(_.values(this.data))]}if(!this.config.filter){this.config.filter=[_.min(_.values(this.data)),_.max(_.values(this.data))]}this.config.scale=d3.scale.pow().exponent(this.config.data.exponent).domain(this.config.data.interval).rangeRound([0,20]);this.config.scale.name="yes";this.render();return this.parent.loaded()};BoxView.prototype.setActive=function(isActive){this.active=isActive;if(isActive){return $(this.el).addClass("selected")}else{return $(this.el).removeClass("selected")}};BoxView.prototype.event_click=function(event){if(!this.active){this.parent.setActive(this.name)}return true};BoxView.prototype.setFilter=function(f,redrawCube){if(redrawCube==null){redrawCube=false}if(redrawCube){this.chart.filter(f);this.parent.renderCubes()}if(!f){f=this.config.data.interval}this.config.filter=f;this.filterElements[0].val(this.config.format.input(this.config)(f[0]));this.filterElements[1].val(this.config.format.input(this.config)(f[1]));$(this.legend.text_range).find(".m0").text(this.config.format.short(this.config)(f[0]));$(this.legend.text_range).find(".m1").text(this.config.format.short(this.config)(f[1]));return this};BoxView.prototype.getFilteredData=function(){var f,k,out,v,_ref2,_ref3;if(!this.chart.filter()){return this.data}f=(_ref2=this.chart.filter())!=null?_ref2:this.config.data.interval;out={};_ref3=this.data;for(k in _ref3){v=_ref3[k];if(f[0]<=v&&v<=f[1]){out[k]=v}}return out};BoxView.prototype.renderRange=function(){this.config.render.range(this.config,this.legend.text_range);return this.config.render.rangeForm(this.config,this.legend.form_range)};BoxView.prototype.render=function(){var _this=this;this.config.render.legend(this.config,this.legend.text_p);this.config.render.form(this.config,this.legend.form_p);this.renderRange();$(this.legend.form_range).find("input").on("change",function(){var f;f=[+_this.filterElements[0].val(),+_this.filterElements[1].val()];if(f[0]>f[1]){f.reverse()}f[0]=_.max([_this.config.data.interval[0],f[0]]);f[1]=_.min([_this.config.data.interval[1],f[1]]);if(_.isEqual(f,_this.config.data.interval)){f=null}return _this.setFilter(f,true)});$(this.legend.form_p).find("input, select").on("change",function(){var p;_this.config.data.interval=null;_this.config.scale=null;_this.config.filter=null;p=_this.config.submitter(_this.config,_this.legend.form_p);_this.config.p=p;console.log(p);return _this.loadData()});return this.filterElements=[$(this.legend.form_range).find("input[name=m0]"),$(this.legend.form_range).find("input[name=m1]")]};return BoxView}(Backbone.View);var _ref,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child};crosslet.MapView=function(_super){__extends(MapView,_super);function MapView(){this._renderMap=__bind(this._renderMap,this);this.getSelection=__bind(this.getSelection,this);this.hover=__bind(this.hover,this);this.mouseMove=__bind(this.mouseMove,this);this.reset=__bind(this.reset,this);this.beforezoom=__bind(this.beforezoom,this);this.project=__bind(this.project,this);_ref=MapView.__super__.constructor.apply(this,arguments);return _ref}MapView.prototype.initialize=function(el,config){var _this=this;this.config=crosslet.createConfig(crosslet.defaultConfig,config);this.geoURL=this.config.map.geo.url;this.version="1.1";this.opacity=this.config.defaults.opacity;this.ds=new crosslet.DataStore(this.config);this.el=el;this.hoverFunc=this.default_hover;$(this.el).attr("class","crosslet");this.map=L.map(el[0]).setView(this.config.map.view.center,this.config.map.view.zoom);L.tileLayer(this.config.map.leaflet.url,this.config.map.leaflet).addTo(this.map);this.control=$("
");this.info=L.Control.extend({options:{position:"topright"},onAdd:function(map){return _this.control[0]}});this.map.addControl(new this.info);this.panel=new crosslet.PanelView(this.control,this.config,this);this.renderMap=this._renderMap;return this.ds.loadGeo(this.geoURL,this.config.map.geo.id_field,function(ds){_this.bounds=_this.ds.bounds;_this.path=d3.geo.path().projection(_this.project);_this.svg=d3.select(_this.map.getPanes().overlayPane).append("svg");_this.g=_this.svg.append("g");_this.g.attr("class","crosslet_geometry");_this.feature=_this.g.selectAll("path").data(ds.geometries).enter().append("path").attr("id",function(d){return"path_"+d.properties[_this.config.map.geo.id_field]}).on("mouseover",function(d){return _this.hover(d)}).on("mousemove",_this.mouseMove);_this.reset();_this.map.on("viewreset",_this.reset);_this.map.on("zoomstart",_this.beforezoom);_this.hoverElement=_this.svg.append("g").attr("class","hover");_this.hoverElementRect=_this.hoverElement.append("svg:rect").attr("x",0).attr("y",0).attr("width",10).attr("height",30).attr("rx",5).attr("ry",5);_this.hoverElementText=_this.hoverElement.append("text").attr("x",0).attr("y",0);_this.hoverElementTextBB={width:0,height:0,x:0,y:0};if(_this.panel.numloads<=0){return _this.panel.createCube()}},this.config.map.geo.topo_object)};MapView.prototype.project=function(x){var point;point=this.map.latLngToLayerPoint(new L.LatLng(x[1],x[0]));return[point.x,point.y]};MapView.prototype.beforezoom=function(){return this.g.style("display","none")};MapView.prototype.reset=function(){var bottomLeft,topRight;bottomLeft=this.project(this.bounds[0]);topRight=this.project(this.bounds[1]);this.svg.attr("width",topRight[0]-bottomLeft[0]).attr("height",bottomLeft[1]-topRight[1]).style("margin-left",bottomLeft[0]+"px").style("margin-top",topRight[1]+"px");this.g.attr("transform","translate("+-bottomLeft[0]+","+-topRight[1]+")");this.feature.attr("d",this.path);this.g.style("display","inline");return true};MapView.prototype.mouseMove=function(){var br,dx,dy,matrix,pos,trp;br=jQuery.browser;pos=d3.mouse(this.svg.node());if(br.mozilla){trp=this.svg.node().parentNode.parentNode.parentNode;matrix=$(trp).css("transform").split("(")[1].split(")")[0].split(",");dx=+matrix[4];dy=+matrix[5];pos[0]-=dx;pos[1]-=dy}pos[0]+=30;pos[1]+=30;if(this.hoverElementTextBB.width+pos[0]>=this.svg.attr("width")){pos[0]-=this.hoverElementTextBB.width+60}if(this.hoverElementTextBB.height+pos[1]>=this.svg.attr("height")){pos[1]-=this.hoverElementTextBB.height+60}return this.hoverElement.attr("transform","translate("+pos[0]+","+pos[1]+")")};MapView.prototype.hover=function(data){var text;text=this.hoverFunc(data,data.properties.value);this.hoverElementText.text(text);this.hoverElementTextBB=this.hoverElementText.node().getBBox();return this.hoverElementRect.attr("width",this.hoverElementTextBB.width+10).attr("height",this.hoverElementTextBB.height+10).attr("x",this.hoverElementTextBB.x-5).attr("y",this.hoverElementTextBB.y-5)};MapView.prototype.getSelection=function(){return this.panel.getSelection()};MapView.prototype.default_hover=function(data,value){return data.properties[this.config.map.geo.name_field]+" - "+value};MapView.prototype._renderMap=function(data,formatter,hoverFunc){var _this=this;if(hoverFunc){this.hoverFunc=hoverFunc}this.feature.attr("style",function(d){var id;id=d.properties[_this.config.map.geo.id_field];d.properties.value=data[id];if(_.isNumber(data[id])){return"fill: "+formatter(d.properties.value)}else{return"display:none"}});return this};return MapView}(Backbone.View); -------------------------------------------------------------------------------- /dist/crosslet-0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sztanko/crosslet/ae9dfac28be6c373c15636bb94060e76d49a139a/dist/crosslet-0.1.zip -------------------------------------------------------------------------------- /dist/crosslet-1.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sztanko/crosslet/ae9dfac28be6c373c15636bb94060e76d49a139a/dist/crosslet-1.1.zip -------------------------------------------------------------------------------- /lib/cie.js: -------------------------------------------------------------------------------- 1 | (function(d3) { 2 | var cie = d3.cie = {}; 3 | 4 | cie.lab = function(l, a, b) { 5 | return arguments.length === 1 6 | ? (l instanceof Lab ? lab(l.l, l.a, l.b) 7 | : (l instanceof Lch ? lch_lab(l.l, l.c, l.h) 8 | : rgb_lab((l = d3.rgb(l)).r, l.g, l.b))) 9 | : lab(+l, +a, +b); 10 | }; 11 | 12 | cie.lch = function(l, c, h) { 13 | return arguments.length === 1 14 | ? (l instanceof Lch ? lch(l.l, l.c, l.h) 15 | : (l instanceof Lab ? lab_lch(l.l, l.a, l.b) 16 | : lab_lch((l = rgb_lab((l = d3.rgb(l)).r, l.g, l.b)).l, l.a, l.b))) 17 | : lch(+l, +c, +h); 18 | }; 19 | 20 | cie.interpolateLab = function(a, b) { 21 | a = cie.lab(a); 22 | b = cie.lab(b); 23 | var al = a.l, 24 | aa = a.a, 25 | ab = a.b, 26 | bl = b.l - al, 27 | ba = b.a - aa, 28 | bb = b.b - ab; 29 | return function(t) { 30 | return lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; 31 | }; 32 | }; 33 | 34 | cie.interpolateLch = function(a, b) { 35 | a = cie.lch(a); 36 | b = cie.lch(b); 37 | var al = a.l, 38 | ac = a.c, 39 | ah = a.h, 40 | bl = b.l - al, 41 | bc = b.c - ac, 42 | bh = b.h - ah; 43 | if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; // shortest path 44 | return function(t) { 45 | return lch_lab(al + bl * t, ac + bc * t, ah + bh * t) + ""; 46 | }; 47 | }; 48 | 49 | function lab(l, a, b) { 50 | return new Lab(l, a, b); 51 | } 52 | 53 | function Lab(l, a, b) { 54 | this.l = l; 55 | this.a = a; 56 | this.b = b; 57 | } 58 | 59 | Lab.prototype.brighter = function(k) { 60 | return lab(Math.min(100, this.l + K * (arguments.length ? k : 1)), this.a, this.b); 61 | }; 62 | 63 | Lab.prototype.darker = function(k) { 64 | return lab(Math.max(0, this.l - K * (arguments.length ? k : 1)), this.a, this.b); 65 | }; 66 | 67 | Lab.prototype.rgb = function() { 68 | return lab_rgb(this.l, this.a, this.b); 69 | }; 70 | 71 | Lab.prototype.toString = function() { 72 | return this.rgb() + ""; 73 | }; 74 | 75 | function lch(l, c, h) { 76 | return new Lch(l, c, h); 77 | } 78 | 79 | function Lch(l, c, h) { 80 | this.l = l; 81 | this.c = c; 82 | this.h = h; 83 | } 84 | 85 | Lch.prototype.brighter = function(k) { 86 | return lch(Math.min(100, this.l + K * (arguments.length ? k : 1)), this.c, this.h); 87 | }; 88 | 89 | Lch.prototype.darker = function(k) { 90 | return lch(Math.max(0, this.l - K * (arguments.length ? k : 1)), this.c, this.h); 91 | }; 92 | 93 | Lch.prototype.rgb = function() { 94 | return lch_lab(this.l, this.c, this.h).rgb(); 95 | }; 96 | 97 | Lch.prototype.toString = function() { 98 | return this.rgb() + ""; 99 | }; 100 | 101 | // Corresponds roughly to RGB brighter/darker 102 | var K = 18; 103 | 104 | // D65 standard referent 105 | var X = 0.950470, Y = 1, Z = 1.088830; 106 | 107 | function lab_rgb(l, a, b) { 108 | var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; 109 | x = lab_xyz(x) * X; 110 | y = lab_xyz(y) * Y; 111 | z = lab_xyz(z) * Z; 112 | return d3.rgb( 113 | xyz_rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), 114 | xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), 115 | xyz_rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z) 116 | ); 117 | } 118 | 119 | function rgb_lab(r, g, b) { 120 | r = rgb_xyz(r); 121 | g = rgb_xyz(g); 122 | b = rgb_xyz(b); 123 | var x = xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / X), 124 | y = xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / Y), 125 | z = xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / Z); 126 | return lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); 127 | } 128 | 129 | function lab_lch(l, a, b) { 130 | var c = Math.sqrt(a * a + b * b), 131 | h = Math.atan2(b, a) / Math.PI * 180; 132 | return lch(l, c, h); 133 | } 134 | 135 | function lch_lab(l, c, h) { 136 | h = h * Math.PI / 180; 137 | return lab(l, Math.cos(h) * c, Math.sin(h) * c); 138 | } 139 | 140 | function lab_xyz(x) { 141 | return x > 0.206893034 ? x * x * x : (x - 4 / 29) / 7.787037; 142 | } 143 | 144 | function xyz_lab(x) { 145 | return x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; 146 | } 147 | 148 | function xyz_rgb(r) { 149 | return Math.round(255 * (r <= 0.00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - 0.055)); 150 | } 151 | 152 | function rgb_xyz(r) { 153 | return (r /= 255) <= 0.04045 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4); 154 | } 155 | })(d3); 156 | -------------------------------------------------------------------------------- /lib/crossfilter.min.js: -------------------------------------------------------------------------------- 1 | (function(a){function b(a){return a}function c(a,b){for(var c=0,d=b.length,e=new Array(d);c>1;a(b[f])>1;c>>1)+1;while(--f>0)d(a,f,e,b);return a}function c(a,b,c){var e=c-b,f;while(--e>0)f=a[b],a[b]=a[b+e],a[b+e]=f,d(a,1,e,b);return a}function d(b,c,d,e){var f=b[--e+c],g=a(f),h;while((h=c<<1)<=d){ha(b[e+h+1])&&h++;if(g<=a(b[e+h]))break;b[e+c]=b[e+h],c=h}b[e+c]=f}return b.sort=c,b}function i(a){function c(c,d,e,f){var g=new Array(f=Math.min(e-d,f)),h,i,j,k;for(i=0;ih)g[0]=k,h=a(b(g,0,f)[0]);while(++dc&&a(b[f-1])>h;--f)b[f]=b[f-1];b[f]=g}return b}return b}function m(a){function c(a,c,e){return(e-c>1,j=i-f,k=i+f,l=b[g],m=a(l),n=b[j],o=a(n),p=b[i],q=a(p),r=b[k],s=a(r),t=b[h],u=a(t),v;m>o&&(v=l,l=n,n=v,v=m,m=o,o=v),s>u&&(v=r,r=t,t=v,v=s,s=u,u=v),m>q&&(v=l,l=p,p=v,v=m,m=q,q=v),o>q&&(v=n,n=p,p=v,v=o,o=q,q=v),m>s&&(v=l,l=r,r=v,v=m,m=s,s=v),q>s&&(v=p,p=r,r=v,v=q,q=s,s=v),o>u&&(v=n,n=t,t=v,v=o,o=u,u=v),o>q&&(v=n,n=p,p=v,v=o,o=q,q=v),s>u&&(v=r,r=t,t=v,v=s,s=u,u=v);var w=n,x=o,y=r,z=s;b[g]=l,b[j]=b[d],b[i]=p,b[k]=b[e-1],b[h]=t;var A=d+1,B=e-2,C=x<=z&&x>=z;if(C)for(var D=A;D<=B;++D){var E=b[D],F=a(E);if(Fx)for(;;){var G=a(b[B]);if(G>x){B--;continue}if(Gz)for(;;){var G=a(b[B]);if(G>z){B--;if(Bh){var H,G;while((H=a(b[A]))<=x&&H>=x)++A;while((G=a(b[B]))<=z&&G>=z)--B;for(var D=A;D<=B;D++){var E=b[D],F=a(E);if(F<=x&&F>=x)D!==A&&(b[D]=b[A],b[A]=E),A++;else if(F<=z&&F>=z)for(;;){var G=a(b[B]);if(G<=z&&G>=z){B--;if(BN)for(b=N,c=Math.min(e,O);bO)for(b=Math.max(e,O),c=f;b=N&&a>0)k[d=D[c]]||(b.push(e[d]),--a);return b}function X(a){var b=[],c=N,d;while(c0)k[d=D[c]]||(b.push(e[d]),--a),c++;return b}function Y(a){function K(b,c,g,i){function Q(){++n===m&&(p=s(p,j<<=1),h=s(h,j),m=G(j))}var o=d,p=E(n,m),t=v,u=F,w=n,y=0,z=0,A,B,C,D,K,L;J&&(t=u=x),d=new Array(n),n=0,h=w>1?r(h,f):E(f,m),w&&(C=(B=o[0]).key);while(z=D))++z;while(zL)){h[A=c[z]+g]=n,k[A]&q||(K.value=t(K.value,e[A]));if(++z>=i)break;D=a(b[z])}Q()}while(yy)for(y=0;y1?(H=M,I=O):(n===1?(H=N,I=P):(H=x,I=x),h=null),l[A]=H}function M(a,b,c){if(a===p||J)return;var f,g,i,j;for(f=0,i=b.length;fj&&(k=s(k,j<<=1)),P(e,0,f),Q(e,0,f),o}function t(){function i(a,d,g){var i;if(h)return;for(i=d;i 1) { 105 | var geomsByArc = [], 106 | geom; 107 | 108 | function arc(i) { 109 | if (i < 0) i = ~i; 110 | (geomsByArc[i] || (geomsByArc[i] = [])).push(geom); 111 | } 112 | 113 | function line(arcs) { 114 | arcs.forEach(arc); 115 | } 116 | 117 | function polygon(arcs) { 118 | arcs.forEach(line); 119 | } 120 | 121 | function geometry(o) { 122 | geom = o; 123 | geometryType[o.type](o.arcs); 124 | } 125 | 126 | var geometryType = { 127 | LineString: line, 128 | MultiLineString: polygon, 129 | Polygon: polygon, 130 | MultiPolygon: function(arcs) { arcs.forEach(polygon); } 131 | }; 132 | 133 | o.type === "GeometryCollection" 134 | ? o.geometries.forEach(geometry) 135 | : geometry(o); 136 | 137 | geomsByArc.forEach(arguments.length < 3 138 | ? function(geoms, i) { arcs.push([i]); } 139 | : function(geoms, i) { if (filter(geoms[0], geoms[geoms.length - 1])) arcs.push([i]); }); 140 | } else { 141 | for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push([i]); 142 | } 143 | 144 | return object(topology, {type: "MultiLineString", arcs: merge(topology, arcs)}); 145 | } 146 | 147 | function object(topology, o) { 148 | var tf = topology.transform, 149 | kx = tf.scale[0], 150 | ky = tf.scale[1], 151 | dx = tf.translate[0], 152 | dy = tf.translate[1], 153 | arcs = topology.arcs; 154 | 155 | function arc(i, points) { 156 | if (points.length) points.pop(); 157 | for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, x = 0, y = 0, p; k < n; ++k) points.push([ 158 | (x += (p = a[k])[0]) * kx + dx, 159 | (y += p[1]) * ky + dy 160 | ]); 161 | if (i < 0) reverse(points, n); 162 | } 163 | 164 | function line(arcs) { 165 | var points = []; 166 | for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); 167 | return points; 168 | } 169 | 170 | function polygon(arcs) { 171 | return arcs.map(line); 172 | } 173 | 174 | function geometry(o) { 175 | o = Object.create(o); 176 | o.coordinates = geometryType[o.type](o.arcs); 177 | return o; 178 | } 179 | 180 | var geometryType = { 181 | LineString: line, 182 | MultiLineString: polygon, 183 | Polygon: polygon, 184 | MultiPolygon: function(arcs) { return arcs.map(polygon); } 185 | }; 186 | 187 | return o.type === "GeometryCollection" 188 | ? (o = Object.create(o), o.geometries = o.geometries.map(geometry), o) 189 | : geometry(o); 190 | } 191 | 192 | function reverse(array, n) { 193 | var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; 194 | } 195 | 196 | function bisect(a, x) { 197 | var lo = 0, hi = a.length; 198 | while (lo < hi) { 199 | var mid = lo + hi >>> 1; 200 | if (a[mid] < x) lo = mid + 1; 201 | else hi = mid; 202 | } 203 | return lo; 204 | } 205 | 206 | function neighbors(topology, objects) { 207 | var objectsByArc = [], 208 | neighbors = objects.map(function() { return []; }); 209 | 210 | function line(arcs, i) { 211 | arcs.forEach(function(a) { 212 | if (a < 0) a = ~a; 213 | var o = objectsByArc[a] || (objectsByArc[a] = []); 214 | if (!o[i]) o.forEach(function(j) { 215 | var n, k; 216 | k = bisect(n = neighbors[i], j); if (n[k] !== j) n.splice(k, 0, j); 217 | k = bisect(n = neighbors[j], i); if (n[k] !== i) n.splice(k, 0, i); 218 | }), o[i] = i; 219 | }); 220 | } 221 | 222 | function polygon(arcs, i) { 223 | arcs.forEach(function(arc) { line(arc, i); }); 224 | } 225 | 226 | function geometry(o, i) { 227 | geometryType[o.type](o.arcs, i); 228 | } 229 | 230 | var geometryType = { 231 | LineString: line, 232 | MultiLineString: polygon, 233 | Polygon: polygon, 234 | MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } 235 | }; 236 | 237 | objects.forEach(geometry); 238 | return neighbors; 239 | } 240 | 241 | return { 242 | version: "0.0.4", 243 | mesh: mesh, 244 | object: object, 245 | neighbors: neighbors 246 | }; 247 | })(); 248 | -------------------------------------------------------------------------------- /src/coffee/data.coffee: -------------------------------------------------------------------------------- 1 | #Class for transforming the data into the usable form 2 | class crosslet.DataStore 3 | data: {} 4 | geometries: null 5 | isGeoLoaded: false 6 | isDataLoaded: false 7 | 8 | constructor: (initData) -> 9 | @geoURL=initData.map.geo.url 10 | @version=initData.data.version 11 | @idField=initData.data.id_field ? "id" 12 | @geoIdField=initData.map.geo.id_field ? "id" 13 | #console.log(@geoIdField) 14 | window.dataloader = new crosslet.DataLoader() if not window.dataloader 15 | #@projection=initData.projection 16 | @l=window.dataloader 17 | 18 | addData: (data,callback) -> 19 | #debugger 20 | for d in data 21 | #debugger if d[@idField]=='F85679' 22 | @data[d[@idField]]={} if not @data[d[@idField]] 23 | for k,v of d 24 | @data[d[@idField]][k]=+v if v!="" and not _.isNaN(+v) 25 | @isDataLoaded=true 26 | callback(data) if callback 27 | 28 | loadData: (url, callback, method) -> 29 | method= d3.tsv if not method 30 | @l.load url, method, (data) => 31 | @addData(data,callback) 32 | return @ 33 | 34 | get_bounds_topo: (c) -> 35 | o=[] 36 | for f in [_.min,_.max] 37 | a=[] 38 | for i in [0,1] 39 | a.push(f _.map c,(d) -> f _.map d.coordinates[0],(dd) ->dd[i]) 40 | o.push(a) 41 | return o 42 | 43 | loadGeo: (url, geoIdField, callback, topo_objectName) => 44 | @l.load url, d3.json, (t) => 45 | if t.arcs 46 | t=topojson.object(t,t.objects[topo_objectName]) 47 | @geometries=t.geometries 48 | #console.log(@geometries) 49 | #@bounds=@get_bounds_topo(@geometries) 50 | #debugger; 51 | else 52 | @geometries=t.features 53 | @bounds=d3.geo.bounds(t) 54 | #console.log(@bounds) 55 | for f in @geometries 56 | #console.log(f) 57 | if f.properties 58 | if not @data[f.properties[@geoIdField]] 59 | @data[f.properties[@geoIdField]]=f.properties 60 | else 61 | @data[f.properties[@geoIdField]]=jQuery.extend(true, @data[f.properties[@geoIdField]], f.properties) 62 | @data[f.properties[@geoIdField]].bbox=d3.geo.bounds(f) 63 | #@path = d3.geo.path().projection(@projection) 64 | @isGeoLoaded=true 65 | callback(@) if callback 66 | return @ 67 | 68 | 69 | #Class for loading/caching data 70 | #TODO: add IndexeDB support 71 | class crosslet.DataLoader 72 | cache: {} 73 | status: {} 74 | callbackList: {} 75 | constructor: (version) -> 76 | version=1+".0" if not version 77 | @version=version 78 | @indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB; 79 | 80 | load: (url, method,callback) -> 81 | urlv=url+@version 82 | @callbackList[urlv]=[] if not @callbackList[urlv] 83 | @status[urlv]="init" if not @status[urlv] 84 | @callbackList[urlv].push(callback) if callback 85 | #console.log("Status of "+url+" is "+@status[urlv]) 86 | if urlv in @cache 87 | @executeCallbacks(@callbackList[urlv],@cache[urlv]) 88 | return @ 89 | else 90 | if @status[urlv]!="loading" 91 | @status[urlv]="loading" 92 | method(url, (data) => 93 | @cache[urlv]=data 94 | @executeCallbacks(@callbackList[urlv],@cache[urlv]) 95 | @status[urlv]="done" 96 | return @ 97 | ) 98 | 99 | return @ 100 | 101 | executeCallbacks: (list,data) -> 102 | #console.log("There are "+list.length+" callbacks in the list") 103 | while list.length>0 104 | list.pop()(data) 105 | -------------------------------------------------------------------------------- /src/coffee/init.coffee: -------------------------------------------------------------------------------- 1 | crosslet={} 2 | if not _ 3 | console.log("Please include underscore.js") 4 | 5 | crosslet.createConfig= (defaultConfig,config) -> 6 | c=jQuery.extend(true,jQuery.extend(true, {}, defaultConfig),config) 7 | 8 | crosslet.id= (d) -> d 9 | crosslet.idf= (d) -> crosslet.id 10 | crosslet.notimplemented = () -> throw("This function is not set. Please check your config."); 11 | crosslet.changeSelect= (select, val) -> 12 | $(select).find("option").filter(() -> 13 | #console.log($(this).val()) 14 | return $(this).val() == val 15 | ).attr('selected', true) 16 | crosslet.defaultConfig= 17 | map: 18 | leaflet: 19 | url: "http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png" #Tiles server's url 20 | key: "--your key--" #Obtain your own key at http://developers.cloudmade.com/projects 21 | styleId: 64657 #Get any style from here: http://maps.cloudmade.com/editor 22 | attribution: 'Map data © OpenStreetMap contributors, ODbL, Imagery © CloudMade' 23 | view: 24 | center: [51.505, -0.09] #thats center of London. 25 | zoom: 11 #zoomlevel for abig city 26 | geo: 27 | url: "please specify correct location of your geojson" #the geojson file. Please make sure it is not larger then 2-3MB. 28 | name_field: "name" #the field in properties of each feature that is a name of the area 29 | id_field: "code" # code of the area. This will be the join key of the data 30 | topo_object: "please specify correct object name" 31 | data: 32 | version: "1.0" # data will be kept in cache. Increase the number if you want to use new datasets 33 | id_field: "id" # area code will be used for joining with geo.id_field 34 | dimensions: {} # see crosslet.defaultDimensionConfig 35 | defaults: 36 | colorscale: d3.scale.linear().domain([1,10,20]).range(["green","yellow", "red"]).interpolate(d3.cie.interpolateLab); 37 | opacity: 0.75 38 | order: [] # order of data boxes 39 | 40 | crosslet.defaultDimensionConfig= 41 | p: {} # here we store parameters of the box. That's for advanced usage. 42 | filter: null #initial filter of the data 43 | data: 44 | interval: null 45 | filter: null 46 | field: (d) -> d.id 47 | dataSet: crosslet.notimplemented # this can be either a url, a function that returns a url or an object 48 | method: d3.tsv # what is the data format of the file? Use d3.tsv or d3.csv 49 | preformat: (dd) -> ((d) -> +d) 50 | ticks: 4 # how many ticks do you want to see on the scale. 51 | colorscale: d3.scale.linear().domain([1,10,20]).range(["green","yellow", "red"]).interpolate(d3.cie.interpolateLab) # color scale of data 52 | exponent: 1 53 | format: 54 | short: (d) -> d3.format(",.2f") # used to display in ranges 55 | long: (d) -> d.format.short(d) # use to display on hover 56 | input: (d) -> d3.format(".2f") # how to show it in the filter inputs 57 | axis: (d) -> d.format.short(d) # the format of axis 58 | render: 59 | legend: (d,el) -> # thats the title of the box 60 | f= if d.title then d.title else d.data.field_func(d) 61 | html= '

' +f+ '

' 62 | el.html(html) 63 | range: (d,el) -> # that's the part which shows the current range 64 | html= "

"+d.format.short(d)(d.filter[0])+""+d.format.short(d)(d.filter[1])+"

" 65 | el.html(html) 66 | form: (d,el) -> # the part that renders the parameter form. By default there are no parameters. 67 | d.render.legend(d,el) 68 | rangeForm: (d,el) -> # form for rendering the range inputs 69 | size=_.max(_.map(d.data.interval,(dd) ->("_"+d.format.input(d)(dd)).length-1)) 70 | html= "Range: " 71 | el.html(html) 72 | submitter: (d,el) -> 73 | out={} 74 | $(el).find("input, select").each((index,el) -> out[$(el).attr("name")]=$(el).val()) 75 | #console.log(out) 76 | return out 77 | -------------------------------------------------------------------------------- /src/coffee/views/datasetsView.coffee: -------------------------------------------------------------------------------- 1 | class crosslet.PanelView extends Backbone.View 2 | initialize: (el, config,parent) -> 3 | @config=crosslet.createConfig(crosslet.defaultConfig,config) 4 | @parent=parent 5 | @el=el 6 | @ds=parent.ds 7 | @boxes={} 8 | @render() 9 | @width=200 10 | @active= if @config.defaults.active then @config.defaults.active else @config.defaults.order[0] 11 | @numloads=@config.defaults.order.length 12 | for o in @config.defaults.order 13 | #console.log(o) 14 | e=$("
") 15 | @boxes[o]=new crosslet.BoxView(e,@config.dimensions[o],@,o) 16 | $(@el).append(e) 17 | @boxes[@active].setActive(true) 18 | @renderMap=_.debounce(@_renderMap,300) 19 | return @boxes 20 | 21 | loaded: ()-> 22 | @numloads=@numloads-1 23 | #console.log("Loads left: "+@numloads) 24 | @createCube() if @numloads<=0 25 | 26 | getSelection: ()=> 27 | abox=@boxes[@active] 28 | adata=abox.getFilteredData() 29 | keys=@intersection(_.map(_.values(@boxes),(b) ->_.keys(b.getFilteredData()).sort())) 30 | out={} 31 | out[k]=adata[k] for k in keys 32 | return out 33 | 34 | _renderMap: ()=> 35 | abox=@boxes[@active] 36 | out = @getSelection() 37 | f=abox.config.format.long(abox.config) 38 | @parent.renderMap(out,((v) -> abox.config.data.colorscale(abox.config.scale(v))),(data,value) => data.properties[@config.map.geo.name_field] + " - " + f(value)) 39 | return @ 40 | 41 | #@parent.renderMap(abox.getFilteredData(),(v) -> @config.defaults.colorscale(abox.config.scale(v))) 42 | setActive: (activeBox)=> 43 | #console.log("Setting active to "+activeBox) 44 | if activeBox!=@active 45 | @boxes[@active].setActive(false) 46 | @active=activeBox 47 | @boxes[@active].setActive(true) 48 | @renderMap() 49 | 50 | 51 | intersection: (a) -> 52 | intersect_safe = (a,b) -> 53 | ai = bi= 0 54 | result = [] 55 | while ai < a.length and bi < b.length 56 | ai++ if a[ai] < b[bi] 57 | bi++ if a[ai] > b[bi] 58 | if a[ai]==b[bi] 59 | result.push(a[ai]) 60 | ai++ 61 | bi++ 62 | return result 63 | switch a.length 64 | when 0 then a 65 | when 1 then a[0] 66 | when 2 then intersect_safe(a[0],a[1]) 67 | else 68 | out=a[0] 69 | out = intersect_safe(out,o) for o in a[1..] 70 | return out 71 | createCube: () => 72 | @rows=[] 73 | t1=new Date().getTime() 74 | #console.log("Starting intesrsection") 75 | keys=_.map(_.values(@boxes),(b) ->_.keys(b.data).sort()) 76 | t15=new Date().getTime() 77 | #console.log("keys took "+d3.format(",")(t15-t1)+" ms") 78 | int=@intersection(keys) 79 | for key in int 80 | row={} 81 | for bName, box of @boxes 82 | row[bName]=box.data[key] 83 | @rows.push(row) 84 | t2=new Date().getTime() 85 | #console.log("Intersection took "+d3.format(",")(t2-t1)+" ms") 86 | @cube = crossfilter(@rows) 87 | 88 | getRounder=(m1,m2,w,exp) -> 89 | t=5*(m2-m1)/(w); 90 | scale=d3.scale.pow().exponent(exp).range([m1/t,m2/t]).domain([m1/t,m2/t]) 91 | 92 | 93 | return (d) ->t*scale.invert(Math.floor(scale(+d/t))) 94 | #return (d) ->t*Math.floor(+d/t) 95 | groups={} 96 | @charts={} 97 | #renderAll= (method)=> _.each(_.values(@charts),(c)-> c.call(method)); return true 98 | brushevent= (box,ctx) -> 99 | () -> box.event_click(); ctx.renderCubes() 100 | for bName, box of @boxes 101 | `var chart, js_box,js_bName` 102 | js_box=box 103 | js_bName=bName 104 | d=@cube.dimension((dd) -> dd[bName]) 105 | dg=d.group(getRounder(box.config.data.interval[0],box.config.data.interval[1],@width-20,box.config.data.exponent)) 106 | 107 | box.graph.empty() 108 | #if box.config.data.exponent==1 109 | yscale=d3.scale.linear().clamp(true).range([20, 0]) 110 | #else 111 | # scale=d3.scale.pow().exponent(box.config.data.exponent).clamp(true).range([20, 0]) 112 | chart=barChart() 113 | .dimension(d) 114 | .name_id(bName) 115 | .group(dg) 116 | .x(d3.scale.pow().exponent(box.config.data.exponent).domain(box.config.data.interval).rangeRound([0,@width-20])) 117 | .y(yscale.copy()) 118 | .ticks(box.config.data.ticks) 119 | .tickFormat(box.config.format.axis(box.config)) 120 | .fill(box.config.data.colorscale) 121 | chart.on("brush",brushevent(box,@)) 122 | chart.on("brushend",@renderCubes) 123 | box.chart=chart 124 | 125 | @charts[bName]=chart 126 | #debugger; 127 | @renderCubes() if @parent.ds.isGeoLoaded 128 | for o in @config.defaults.order 129 | @boxes[o].setFilter(@config.dimensions[o].filter,true) if @config.dimensions[o].filter 130 | return @ 131 | 132 | renderCubes: () => 133 | #console.log("renderCubes") 134 | for bName, box of @boxes 135 | box.chart(box.graph) 136 | $(box.el).on("mousedown",box.event_click) 137 | box.setFilter(box.chart.filter(), false) 138 | 139 | abox=@boxes[@active] 140 | abox.setFilter(abox.chart.filter(),false) 141 | @renderMap() 142 | return @ 143 | 144 | class crosslet.BoxView extends Backbone.View 145 | initialize: (el,config, parent,name) -> 146 | @el=el 147 | @config=crosslet.createConfig(crosslet.defaultDimensionConfig,config) 148 | @config.id=name 149 | @config.data.field_func = if not _.isFunction(@config.data.field) then ((d) -> d.data.field) else @config.data.field 150 | $(@el).on("mousedown",@event_click) 151 | $(@el).on("tap",@event_click) 152 | $(@el)[0].onmousedown = $(@el)[0].ondblclick = L.DomEvent.stopPropagation; 153 | @legend={} 154 | @legend.all=$("
") 155 | @legend.text=$("
") 156 | @legend.text_p=$("
") 157 | @legend.text_range=$("
") 158 | @legend.text.append(@legend.text_p).append(@legend.text_range) 159 | @legend.form=$("
") 160 | @legend.form_p=$("
") 161 | @legend.form_range=$("
") 162 | @legend.form.append(@legend.form_p).append(@legend.form_range) 163 | @legend.all.append(@legend.text).append(@legend.form) 164 | $(el).append(@legend.all) 165 | 166 | @graph=$("
") 167 | $(el).append(@graph) 168 | @parent=parent 169 | @ds=parent.ds 170 | @active=false 171 | @name=name 172 | @loadData() 173 | #debugger; 174 | loadData: ()-> 175 | if _.isString(@config.data.dataSet) 176 | #console.log("Thats an url") 177 | @parent.ds.loadData(@config.data.dataSet, @dataLoaded,@config.data.method) 178 | else 179 | if _.isFunction(@config.data.dataSet) 180 | #console.log("Thats a function") 181 | @parent.ds.loadData(@config.data.dataSet(@config), @dataLoaded,@config.data.method) 182 | else 183 | #console.log("Thats an array") 184 | @parent.ds.addData @config.data.dataSet, @dataLoaded 185 | 186 | dataLoaded: () => 187 | @data={} 188 | f=@config.data.field_func(@config) 189 | #console.log("Field is "+f) 190 | preformatter=@config.data.preformat(@config) 191 | for id, val of @parent.ds.data 192 | pd=preformatter(val[f]) if _.isNumber(val[f]) 193 | @data[id]=pd if _.isNumber(pd) 194 | @config.data.interval=[_.min(_.values @data), _.max(_.values @data)] if not @config.data.interval 195 | @config.filter=[_.min(_.values @data), _.max(_.values @data)] if not @config.filter 196 | #console.log("Interval is") 197 | #console.log(@interval) 198 | #@config.scale=d3.scale.quantize().domain(@config.data.interval).range([0..20]) if not @config.scale 199 | @config.scale=d3.scale.pow().exponent(@config.data.exponent).domain(@config.data.interval).rangeRound([0,20])# if not @config.scale 200 | @config.scale.name= "yes" 201 | @render() 202 | @parent.loaded() 203 | 204 | setActive: (isActive) => 205 | @active=isActive 206 | if isActive 207 | $(@el).addClass("selected") 208 | else 209 | $(@el).removeClass("selected") 210 | 211 | event_click: (event) => 212 | #console.log("Active") 213 | @parent.setActive(@name) if not @active 214 | return true 215 | 216 | setFilter: (f,redrawCube=false) => 217 | #console.log(@filterElements[0].val()) 218 | if redrawCube 219 | @chart.filter(f) 220 | @parent.renderCubes() 221 | if not f 222 | f=@config.data.interval 223 | @config.filter=f 224 | @filterElements[0].val(@config.format.input(@config)(f[0])) 225 | @filterElements[1].val(@config.format.input(@config)(f[1])) 226 | $(@legend.text_range).find(".m0").text(@config.format.short(@config)(f[0])) 227 | $(@legend.text_range).find(".m1").text(@config.format.short(@config)(f[1])) 228 | return @ 229 | getFilteredData: () -> 230 | return @data if not @chart.filter() 231 | f=@chart.filter() ? @config.data.interval 232 | out={} 233 | out[k]=v for k,v of @data when f[0]<=v<=f[1] 234 | return out 235 | renderRange: () -> 236 | @config.render.range(@config,@legend.text_range) 237 | @config.render.rangeForm(@config,@legend.form_range) 238 | render: () -> 239 | @config.render.legend(@config,@legend.text_p) 240 | @config.render.form(@config,@legend.form_p) 241 | @renderRange() 242 | $(@legend.form_range).find("input").on("change",()=> 243 | 244 | f=[+@filterElements[0].val(),+@filterElements[1].val()] 245 | f.reverse() if f[0]>f[1] 246 | f[0]=_.max([@config.data.interval[0],f[0]]) 247 | f[1]=_.min([@config.data.interval[1],f[1]]) 248 | f=null if _.isEqual(f,@config.data.interval) 249 | @setFilter(f,true) 250 | ) 251 | $(@legend.form_p).find("input, select").on("change", () => 252 | @config.data.interval=null 253 | @config.scale=null 254 | @config.filter=null 255 | p= @config.submitter(@config,@legend.form_p) 256 | @config.p=p 257 | console.log(p) 258 | @loadData() 259 | ) 260 | @filterElements=[$(@legend.form_range).find("input[name=m0]"),$(@legend.form_range).find("input[name=m1]")] 261 | 262 | #console.log(@filterElements) 263 | -------------------------------------------------------------------------------- /src/coffee/views/mapView.coffee: -------------------------------------------------------------------------------- 1 | class crosslet.MapView extends Backbone.View 2 | initialize: (el,config) -> 3 | @config=crosslet.createConfig(crosslet.defaultConfig,config) 4 | @geoURL=@config.map.geo.url 5 | @version="1.1" 6 | #@config.data.id_field = "id" if not @config.data.id_field 7 | #@config.map.geo.id_field = "id" if not @config.map.geo.id_field 8 | 9 | @opacity=@config.defaults.opacity 10 | @ds=new crosslet.DataStore(@config) 11 | @el=el 12 | @hoverFunc=@default_hover 13 | $(@el).attr("class","crosslet") 14 | @map= L.map(el[0]).setView(@config.map.view.center, @config.map.view.zoom) 15 | 16 | L.tileLayer(@config.map.leaflet.url, @config.map.leaflet).addTo(@map); 17 | @control=$("
") 18 | 19 | @info = L.Control.extend( 20 | options: { position: 'topright' }, 21 | onAdd : (map) => 22 | #@control[0].onmousedown = @control[0].ondblclick = L.DomEvent.stopPropagation; 23 | return @control[0]; 24 | ) 25 | #$(".leaflet-map-pane").css("-webkit-transform","") 26 | @map.addControl(new @info()) 27 | @panel=new crosslet.PanelView(@control,@config,@) 28 | @renderMap=@_renderMap #_.debounce(@_renderMap,200) 29 | #console.log(@panel) 30 | #debugger; 31 | #console.log 32 | @ds.loadGeo(@geoURL, @config.map.geo.id_field, (ds) => 33 | @bounds = @ds.bounds 34 | @path = d3.geo.path().projection(@project) 35 | @svg = d3.select(@map.getPanes().overlayPane).append("svg") 36 | @g = @svg.append("g") 37 | @g.attr("class","crosslet_geometry") 38 | #@g.style("fill-opacity",@opacity) 39 | @feature = @g.selectAll("path") 40 | .data(ds.geometries).enter() 41 | .append("path") 42 | .attr("id",(d) => "path_"+d.properties[@config.map.geo.id_field]) 43 | .on("mouseover",(d) => @hover(d)) 44 | .on("mousemove",@mouseMove) 45 | @reset() 46 | @map.on("viewreset", @reset) 47 | @map.on("zoomstart", @beforezoom) 48 | @hoverElement=@svg.append("g").attr("class","hover") 49 | @hoverElementRect = @hoverElement.append("svg:rect") 50 | .attr("x", 0) 51 | .attr("y", 0) 52 | .attr("width", 10) 53 | .attr("height", 30) 54 | .attr("rx",5) 55 | .attr("ry",5) 56 | @hoverElementText=@hoverElement.append("text").attr("x",0).attr("y",0) 57 | #@hoverElementTextBB=@hoverElementText.node().getBBox() - firefox will hate this, see https://bugzilla.mozilla.org/show_bug.cgi?id=612118 58 | @hoverElementTextBB={width: 0, height:0, x:0, y:0} 59 | @panel.createCube() if @panel.numloads<=0 60 | , @config.map.geo.topo_object) 61 | 62 | 63 | 64 | project: (x) => 65 | point = @map.latLngToLayerPoint(new L.LatLng(x[1], x[0])) 66 | return [point.x, point.y] 67 | 68 | beforezoom: () => 69 | #console.log("before zoom") 70 | @g.style("display","none") 71 | #debugger; 72 | reset: () => 73 | bottomLeft = @project(@bounds[0]) 74 | topRight = @project(@bounds[1]) 75 | @svg.attr("width", topRight[0] - bottomLeft[0]) 76 | .attr("height", bottomLeft[1] - topRight[1]) 77 | .style("margin-left", bottomLeft[0] + "px") 78 | .style("margin-top", topRight[1] + "px") 79 | @g.attr("transform", "translate(" + -bottomLeft[0] + "," + -topRight[1] + ")") 80 | @feature.attr("d", @path) 81 | @g.style("display","inline") 82 | # @path_done=true 83 | return true 84 | mouseMove: () => 85 | br=jQuery.browser 86 | pos=d3.mouse(@svg.node()) 87 | if br.mozilla 88 | trp=@svg.node().parentNode.parentNode.parentNode 89 | matrix=$(trp).css("transform").split('(')[1].split(')')[0].split(','); 90 | #console.log(matrix) 91 | dx=+matrix[4] 92 | dy=+matrix[5] 93 | pos[0]-=dx 94 | pos[1]-=dy 95 | #console.log(pos) 96 | pos[0]+=30 97 | pos[1]+=30 98 | #console.log() 99 | if @hoverElementTextBB.width+pos[0]>=@svg.attr("width") 100 | pos[0]-=@hoverElementTextBB.width+60 101 | if @hoverElementTextBB.height+pos[1]>=@svg.attr("height") 102 | pos[1]-=@hoverElementTextBB.height+60 103 | #console.log(d3.mouse(@svg[0][0])) 104 | @hoverElement.attr("transform","translate(" + pos[0] + "," + pos[1] + ")") 105 | hover: (data) => 106 | text=@hoverFunc(data,data.properties.value) 107 | @hoverElementText.text(text) 108 | @hoverElementTextBB=@hoverElementText.node().getBBox() 109 | @hoverElementRect.attr("width",@hoverElementTextBB.width+10) 110 | .attr("height",@hoverElementTextBB.height+10) 111 | .attr("x",@hoverElementTextBB.x-5) 112 | .attr("y",@hoverElementTextBB.y-5) 113 | #console.log(text) 114 | 115 | getSelection: () => 116 | return @panel.getSelection() 117 | default_hover: (data,value) -> 118 | ##console.log(@config.map.geo.name_field) 119 | data.properties[@config.map.geo.name_field] + " - " + value 120 | 121 | _renderMap: (data,formatter,hoverFunc) => 122 | #console.log("Rendering map") 123 | @hoverFunc=hoverFunc if hoverFunc 124 | @feature.attr("style",(d) => 125 | id=d.properties[@config.map.geo.id_field] 126 | d.properties.value=data[id] 127 | if _.isNumber(data[id]) 128 | "fill: "+formatter(d.properties.value) 129 | else 130 | "display:none" 131 | ) 132 | return this 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /src/js/barChart.js: -------------------------------------------------------------------------------- 1 | barChart=function() { 2 | if (!barChart.id) barChart.id = 0; 3 | 4 | var margin = {top: 5, right: 10, bottom: 20, left: 10}, 5 | x, 6 | //y = d3.scale.log().clamp(true).range([20, 0]), 7 | y = d3.scale.pow().exponent(0.01).clamp(true).range([20, 0]), 8 | id = barChart.id++, 9 | axis = d3.svg.axis().orient("bottom"), 10 | brush = d3.svg.brush(), 11 | brushDirty, 12 | dimension, 13 | group, 14 | round, 15 | tickFormat, 16 | tickSize, 17 | filter=null, 18 | name_id, 19 | status, 20 | fill; 21 | 22 | function chart(div) { 23 | 24 | //debugger; 25 | var width = x.range()[1], 26 | height = y.range()[0]; 27 | //debugger; 28 | y.domain([group.top(1)[0].value/100, group.top(1)[0].value]); 29 | 30 | div.each(function() { 31 | var div = d3.select(this), 32 | g = div.select("g"); 33 | 34 | // Create the skeletal chart. 35 | if (g.empty()) { 36 | var svg = div.append("svg") 37 | .attr("width", width + margin.left + margin.right) 38 | .attr("height", height + margin.top + margin.bottom) 39 | .attr("id",name_id) 40 | if(fill) 41 | { 42 | fill_svg=svg.append("defs").append("linearGradient").attr("id","lg-"+id) 43 | .attr("x1","0%").attr("y1","0%").attr("x2","100%").attr("y2","0%") 44 | var rr=x.copy().domain([0,20]).range(x.range) 45 | for(var i=0;i<20;i++) 46 | { 47 | fill_svg.append("stop").attr("stop-color",fill(i)).attr("offset",i*5+"%").attr("stop-opacity","1") 48 | } 49 | } 50 | /* 51 | 52 | 56 | 57 | 58 | 59 | 60 | */ 61 | g=svg.append("g") 62 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 63 | 64 | /*status=svg.append("text").attr("class","title").attr("x",width-margin.left).attr("y",10) 65 | .attr("width",150) 66 | .attr("height",20).text("")*/ 67 | if(filter) 68 | status.text(axis.tickFormat()(filter[0])+" - "+axis.tickFormat()(filter[1])) 69 | g.append("clipPath") 70 | .attr("id", "clip-" + id) 71 | .append("rect") 72 | .attr("width", width) 73 | .attr("height", height); 74 | 75 | g.selectAll(".bar") 76 | .data(["background", "foreground"]) 77 | .enter().append("path") 78 | .attr("class", function(d) { return d + " bar"; }) 79 | .datum(group.all()); 80 | 81 | g.selectAll(".foreground.bar") 82 | .attr("clip-path", "url(#clip-" + id + ")") 83 | .attr("fill","url(#lg-"+id+")"); 84 | 85 | g.append("g") 86 | .attr("class", "axis") 87 | .attr("transform", "translate(0," + height + ")") 88 | .call(axis); 89 | 90 | // Initialize the brush component with pretty resize handles. 91 | var gBrush = g.append("g").attr("class", "brush").call(brush); 92 | gBrush.selectAll("rect").attr("height", height); 93 | gBrush.selectAll(".resize").append("path").attr("d", resizePath); 94 | } 95 | 96 | // Only redraw the brush if set externally. 97 | if (brushDirty) { 98 | brushDirty = false; 99 | g.selectAll(".brush").call(brush); 100 | div.select(".title a").style("display", brush.empty() ? "none" : null); 101 | if (brush.empty()) { 102 | g.selectAll("#clip-" + id + " rect") 103 | .attr("x", 0) 104 | .attr("width", width); 105 | } else { 106 | var extent = brush.extent(); 107 | g.selectAll("#clip-" + id + " rect") 108 | .attr("x", x(extent[0])) 109 | .attr("width", x(extent[1]) - x(extent[0])); 110 | } 111 | } 112 | 113 | g.selectAll(".bar").attr("d", barPath); 114 | }); 115 | 116 | function barPath(groups) { 117 | var path = [], 118 | i = -1, 119 | n = groups.length, 120 | d; 121 | //console.log("ha") 122 | while (++i < n) { 123 | d = groups[i]; 124 | //console.log(d.value +" - "+ y(d.value)) 125 | //debugger; 126 | path.push("M", x(d.key), ",", height, "V", y(d.value), "h4.5V", height); 127 | } 128 | return path.join(""); 129 | } 130 | 131 | function resizePath(d) { 132 | var e = +(d == "e"), 133 | x = e ? 1 : -1, 134 | y = height / 3; 135 | return "M" + (.5 * x) + "," + y 136 | + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) 137 | + "V" + (2 * y - 6) 138 | + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) 139 | + "Z" 140 | + "M" + (2.5 * x) + "," + (y + 8) 141 | + "V" + (2 * y - 8) 142 | + "M" + (4.5 * x) + "," + (y + 8) 143 | + "V" + (2 * y - 8); 144 | } 145 | } 146 | 147 | brush.on("brushstart.chart", function() { 148 | var div = d3.select(this.parentNode.parentNode.parentNode); 149 | //div.select(".title a").style("display", null); 150 | }); 151 | 152 | brush.on("brush.chart", function() { 153 | var g = d3.select(this.parentNode), 154 | extent = brush.extent(); 155 | if (round) g.select(".brush") 156 | .call(brush.extent(extent = extent.map(round))) 157 | .selectAll(".resize") 158 | .style("display", null); 159 | g.select("#clip-" + id + " rect") 160 | .attr("x", x(extent[0])) 161 | .attr("width", x(extent[1]) - x(extent[0])); 162 | 163 | dimension.filterRange(extent); 164 | filter=extent 165 | if(extent[1]-extent[0]>0) 166 | { 167 | if(status) 168 | status.text(axis.tickFormat()(extent[0])+" - "+axis.tickFormat()(extent[1])) 169 | } 170 | else 171 | { 172 | if(status) 173 | status.text("") 174 | } 175 | }); 176 | 177 | brush.on("brushend.chart", function() { 178 | if (brush.empty()) { 179 | var div = d3.select(this.parentNode.parentNode.parentNode); 180 | //div.select(".title a").style("display", "none"); 181 | div.select("#clip-" + id + " rect").attr("x", null).attr("width", "100%"); 182 | dimension.filterAll(); 183 | filter=null 184 | } 185 | }); 186 | 187 | chart.margin = function(_) { 188 | if (!arguments.length) return margin; 189 | margin = _; 190 | return chart; 191 | }; 192 | 193 | chart.x = function(_) { 194 | if (!arguments.length) return x; 195 | x = _; 196 | axis.scale(x); 197 | brush.x(x); 198 | return chart; 199 | }; 200 | 201 | chart.tickFormat = function(_) { 202 | if (!arguments.length) return tickFormat; 203 | tickFormat = _; 204 | axis.tickFormat(tickFormat) 205 | return chart; 206 | }; 207 | 208 | chart.name_id = function(_) { 209 | if (!arguments.length) return name_id; 210 | name_id = _; 211 | return chart; 212 | }; 213 | 214 | chart.ticks = function(a) { 215 | if (!arguments.length) return tickSize; 216 | ticks = a; 217 | if(a.length){ 218 | axis.tickValues(ticks); 219 | //console.log(ticks); 220 | } 221 | else 222 | axis.ticks(ticks); 223 | return chart; 224 | }; 225 | 226 | chart.fill = function(_) { 227 | if (!arguments.length) return fill; 228 | fill = _; 229 | return chart; 230 | }; 231 | 232 | 233 | chart.y = function(_) { 234 | if (!arguments.length) return y; 235 | y = _; 236 | return chart; 237 | }; 238 | 239 | chart.dimension = function(_) { 240 | if (!arguments.length) return dimension; 241 | dimension = _; 242 | return chart; 243 | }; 244 | 245 | chart.filter = function(_) { 246 | if (!arguments.length) return filter; 247 | if (_) { 248 | filter=_ 249 | brush.extent(_); 250 | dimension.filterRange(_); 251 | if(status) 252 | status.text(axis.tickFormat()(filter[0])+" - "+axis.tickFormat()(filter[1])) 253 | } else { 254 | brush.clear(); 255 | filter=null 256 | dimension.filterAll(); 257 | } 258 | brushDirty = true; 259 | return chart; 260 | }; 261 | 262 | chart.group = function(_) { 263 | if (!arguments.length) return group; 264 | group = _; 265 | return chart; 266 | }; 267 | 268 | chart.round = function(_) { 269 | if (!arguments.length) return round; 270 | round = _; 271 | return chart; 272 | }; 273 | 274 | return d3.rebind(chart, brush, "on"); 275 | }; 276 | -------------------------------------------------------------------------------- /src/less/crosslet.less: -------------------------------------------------------------------------------- 1 | @inactive: #EFEFEF; 2 | @inactive-border: darken(@inactive,10%); 3 | @panel-text: darken(@inactive,60%); 4 | 5 | @active: white; 6 | @active-border: darken(@active,30%); 7 | 8 | .transition(@prop,@time: 0.2s) 9 | { 10 | transition: @prop @time; 11 | -moz-transition: @prop @time; /* Firefox 4 */ 12 | -webkit-transition: @prop @time; /* Safari and Chrome */ 13 | -o-transition: @prop @time; /* Opera */ 14 | } 15 | 16 | .crosslet, .crosslet *{ 17 | font-family: georgia, "times new roman", times, serif; 18 | 19 | .crosslet_panel{ 20 | /*display: none;*/ 21 | /*width: 950px;*/ 22 | color: @panel-text; 23 | //position: relative; 24 | top: -10px; 25 | //z-index: 1000; 26 | .box{ 27 | /*float:left;*/ 28 | display: inline-block; 29 | vertical-align: top; 30 | width: 215px; 31 | margin-left: 5px; 32 | background-color: @inactive; 33 | .transition(background-color); 34 | /*background: -webkit-linear-gradient(left top, white, darken(white,5%));*/ 35 | border-bottom-right-radius: 15px; 36 | /*opacity: 0.9;*/ 37 | border-bottom-left-radius: 15px; 38 | 39 | border: 1px solid @inactive-border; 40 | border-top: none; 41 | box-shadow: 0 10px 14px -10px rgba(0, 0, 0, .8); 42 | padding: 5px; 43 | font-size: 11px; 44 | text-align: center; 45 | line-height: 10px; 46 | 47 | .legendForm{ 48 | display:none; 49 | } 50 | .legendText, .legendForm{ 51 | 52 | h2{ 53 | font-size: 1.1em; 54 | margin: 0px; 55 | margin-bottom: 4px; 56 | text-align: center; 57 | line-height:1.3em; 58 | } 59 | p{ 60 | margin: 0px; 61 | } 62 | select, input[type="text"] { 63 | background-color: @inactive; 64 | width: auto; 65 | padding: 0px; 66 | padding-left: 4px; 67 | height: 12px; 68 | line-height: 13px; 69 | font-size: 12px; 70 | //border: none; 71 | text-align: center; 72 | border: 1px solid @inactive; 73 | border-radius: 6px; 74 | font-weight: bold; 75 | margin: 0px; 76 | .transition(background-color); 77 | /*text-align: center;*/ 78 | } 79 | } 80 | 81 | .graph{ 82 | /*.transition(height);*/ 83 | display: none; 84 | 85 | } 86 | 87 | 88 | 89 | .graph { 90 | display: inline-block; 91 | margin-bottom: 0px; 92 | } 93 | 94 | .background.bar { 95 | fill: darken(@inactive,10%); 96 | } 97 | 98 | 99 | .axis{ 100 | display: none; 101 | } 102 | .axis path, .axis line { 103 | fill: none; 104 | stroke: #000; 105 | shape-rendering: crispEdges; 106 | 107 | } 108 | 109 | .axis text { 110 | font: 10px sans-serif; 111 | } 112 | 113 | .brush rect.extent { 114 | fill: steelblue; 115 | fill-opacity: .125; 116 | } 117 | .brush .resize{ 118 | display: none; 119 | } 120 | .brush .resize path { 121 | fill: #eee; 122 | stroke: #666; 123 | } 124 | 125 | svg{ 126 | height: 25px; 127 | .transition(height); 128 | } 129 | } 130 | .box.selected, .box:hover{ 131 | opacity: 1; 132 | //background: -webkit-linear-gradient(left top, white, white); 133 | background: @active; 134 | 135 | 136 | border-color: @active-border; 137 | .transition(background-color); 138 | /*min-height: 110px;*/ 139 | color: black; 140 | 141 | .legendForm{ 142 | display:block; 143 | } 144 | .legendText{ 145 | display:none; 146 | } 147 | 148 | select, input[type="text"]{ 149 | background-color: @active; 150 | border: 1px solid @active-border; 151 | .transition(background-color); 152 | 153 | 154 | } 155 | 156 | .graph{ 157 | /*border: 1px dotted @inactive-border;*/ 158 | /*height: 55px;*/ 159 | margin: 5px; 160 | margin-bottom: 2px; 161 | display: block; 162 | 163 | svg{ 164 | height: 45px; 165 | .transition(height); 166 | } 167 | .axis{ 168 | display: inline; 169 | .transition(display); 170 | } 171 | .brush .resize{ 172 | display: inline; 173 | } 174 | .background.bar { 175 | fill: darken(@active,20%); 176 | } 177 | /* 178 | 179 | 180 | }*/ 181 | 182 | 183 | } 184 | } 185 | 186 | 187 | } 188 | 189 | .box:not(.selected):hover{ 190 | .foreground.bar { 191 | fill: darken(@active,50%); 192 | 193 | } 194 | } 195 | .box:not(.selected) .foreground.bar { 196 | fill: darken(@inactive,20%); 197 | /*fill: steelblue;*/ 198 | } 199 | .box.selected #imd .foreground.bar{ 200 | /* fill: inherit; */ 201 | } 202 | 203 | } 204 | 205 | 206 | 207 | .crosslet{ 208 | 209 | svg { 210 | g.crosslet_geometry 211 | { 212 | fill-opacity: 0.5; 213 | path{ 214 | fill: white; 215 | stroke: none; 216 | /*stroke: black; */ 217 | } 218 | path:hover{ 219 | fill-opacity: 0.2; 220 | stroke-width: 2px; 221 | stroke: white; 222 | box-shadow: -5px -5px -5px -5px rgba(0, 0, 0, .8); 223 | } 224 | } 225 | .hover{ 226 | display: none; 227 | rect{ 228 | stroke:none; 229 | fill-opacity:0.5; 230 | fill: @inactive; 231 | border-radius: 5px; 232 | 233 | } 234 | text{ 235 | font-size: 12px; 236 | fill: black; 237 | font-weight: bold; 238 | } 239 | } 240 | } 241 | svg:hover{ 242 | .hover { 243 | display: inline; 244 | 245 | } 246 | } 247 | 248 | } 249 | 250 | -------------------------------------------------------------------------------- /test/1/coffee/config.coffee: -------------------------------------------------------------------------------- 1 | config= 2 | map: 3 | leaflet: 4 | key: "fe623ce312234f8f9333bbee72d4a176" 5 | styleId: 64657 6 | attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade' 7 | view: 8 | center: [51.505, -0.09] 9 | zoom: 11 10 | geo: 11 | url: "data/lsoa.json" 12 | name_field: "ward" 13 | id_field: "code" 14 | data: 15 | version: "1.0" 16 | id_field: "id" 17 | 18 | dimensions: 19 | imd: 20 | title: "Index of Multiple Deprivation" 21 | data: 22 | dataSet: "data/imd.tsv" 23 | field: "imd" 24 | format: 25 | short: (data) -> return ((f) -> Math.round(f*100)/100) 26 | axis: (data) -> Math.round 27 | #render: (data,container) -> $(container).html($("#templates .imd").html()) 28 | crime: 29 | filter: [-1,0] 30 | title: "Crime figures" 31 | data: 32 | dataSet: "data/imd.tsv" 33 | field: "crime" 34 | format: 35 | short: (data) -> return ((f) -> Math.round(f*100)/100) 36 | 37 | income: 38 | title: "Income Deprivation" 39 | data: 40 | dataSet: "data/imd.tsv" 41 | field: "income" 42 | format: 43 | short: (data) -> return ((f) -> Math.round(f*100)/100) 44 | price: 45 | p: 46 | bedrooms: 1 47 | type: "rent" 48 | data: 49 | dataSet: "data/prices.tsv" 50 | field: (d) -> d.p.type+"_"+d.p.bedrooms 51 | preformat: (d) -> if d.p.type=='rent' then ((dd) -> +dd*12/52) else ((dd) -> +dd) 52 | render: 53 | form: (data,container) -> 54 | $(container).html($("#templates .price").html()) 55 | crosslet.changeSelect($(container).find("[name=type]"),data.p.type) 56 | crosslet.changeSelect($(container).find("[name=bedrooms]"),data.p.bedrooms) 57 | legend: (data,c)-> 58 | type=if data.p.type=='rent' then "Weekly rental" else "Sale" 59 | $(c).html("

"+type+" price of "+data.p.bedrooms+" bed flat

") 60 | format: 61 | short: (data) -> 62 | if data.p.type=='sale' 63 | return (v) -> "£"+d3.format(",.0f")(v/1000)+"k" 64 | else 65 | return (v) -> "£"+d3.format(",.0f")(v)+" pw" 66 | input: (data) -> return Math.round 67 | axis: (data) -> 68 | if data.p.type=='sale' 69 | return (v) -> "£"+d3.format(",.0f")(v/1000)+"k" 70 | else 71 | return (v) -> "£"+d3.format(",.0f")(v) 72 | defaults: 73 | colorscale: d3.scale.linear().domain([1,12,20]).range(["green","yellow", "red"]).interpolate(d3.cie.interpolateLab); 74 | opacity: 0.7 75 | order: ["imd"]#,"crime","income","price"] 76 | active: "imd" 77 | -------------------------------------------------------------------------------- /test/1/coffee/config.js: -------------------------------------------------------------------------------- 1 | var config; 2 | 3 | config = { 4 | map: { 5 | leaflet: { 6 | key: "fe623ce312234f8f9333bbee72d4a176", 7 | styleId: 64657, 8 | attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade' 9 | }, 10 | view: { 11 | center: [51.505, -0.09], 12 | zoom: 11 13 | }, 14 | geo: { 15 | url: "data/lsoa.json", 16 | name_field: "ward", 17 | id_field: "code" 18 | } 19 | }, 20 | data: { 21 | version: "1.0", 22 | id_field: "id" 23 | }, 24 | dimensions: { 25 | imd: { 26 | title: "Index of Multiple Deprivation", 27 | data: { 28 | dataSet: "data/imd.tsv", 29 | field: "imd" 30 | }, 31 | format: { 32 | short: function(data) { 33 | return (function(f) { 34 | return Math.round(f * 100) / 100; 35 | }); 36 | }, 37 | axis: function(data) { 38 | return Math.round; 39 | } 40 | } 41 | }, 42 | crime: { 43 | filter: [-1, 0], 44 | title: "Crime figures", 45 | data: { 46 | dataSet: "data/imd.tsv", 47 | field: "crime" 48 | }, 49 | format: { 50 | short: function(data) { 51 | return (function(f) { 52 | return Math.round(f * 100) / 100; 53 | }); 54 | } 55 | } 56 | }, 57 | income: { 58 | title: "Income Deprivation", 59 | data: { 60 | dataSet: "data/imd.tsv", 61 | field: "income" 62 | }, 63 | format: { 64 | short: function(data) { 65 | return (function(f) { 66 | return Math.round(f * 100) / 100; 67 | }); 68 | } 69 | } 70 | }, 71 | price: { 72 | p: { 73 | bedrooms: 1, 74 | type: "rent" 75 | }, 76 | data: { 77 | dataSet: "data/prices.tsv", 78 | field: function(d) { 79 | return d.p.type + "_" + d.p.bedrooms; 80 | }, 81 | preformat: function(d) { 82 | if (d.p.type === 'rent') { 83 | return function(dd) { 84 | return +dd * 12 / 52; 85 | }; 86 | } else { 87 | return function(dd) { 88 | return +dd; 89 | }; 90 | } 91 | } 92 | }, 93 | render: { 94 | form: function(data, container) { 95 | $(container).html($("#templates .price").html()); 96 | crosslet.changeSelect($(container).find("[name=type]"), data.p.type); 97 | return crosslet.changeSelect($(container).find("[name=bedrooms]"), data.p.bedrooms); 98 | }, 99 | legend: function(data, c) { 100 | var type; 101 | type = data.p.type === 'rent' ? "Weekly rental" : "Sale"; 102 | return $(c).html("

" + type + " price of " + data.p.bedrooms + " bed flat

"); 103 | } 104 | }, 105 | format: { 106 | short: function(data) { 107 | if (data.p.type === 'sale') { 108 | return function(v) { 109 | return "£" + d3.format(",.0f")(v / 1000) + "k"; 110 | }; 111 | } else { 112 | return function(v) { 113 | return "£" + d3.format(",.0f")(v) + " pw"; 114 | }; 115 | } 116 | }, 117 | input: function(data) { 118 | return Math.round; 119 | }, 120 | axis: function(data) { 121 | if (data.p.type === 'sale') { 122 | return function(v) { 123 | return "£" + d3.format(",.0f")(v / 1000) + "k"; 124 | }; 125 | } else { 126 | return function(v) { 127 | return "£" + d3.format(",.0f")(v); 128 | }; 129 | } 130 | } 131 | } 132 | } 133 | }, 134 | defaults: { 135 | colorscale: d3.scale.linear().domain([1, 12, 20]).range(["green", "yellow", "red"]).interpolate(d3.cie.interpolateLab), 136 | opacity: 0.7, 137 | order: ["imd"], 138 | active: "imd" 139 | } 140 | }; 141 | -------------------------------------------------------------------------------- /test/1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Crosslet test 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 |

Commute time to

24 | 25 |

between and minutes

26 |
27 |
28 |
29 |

price of 33 | 40 | flat

41 |
42 |
43 | 44 |
45 | 46 |
47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /test/1/js/barChart.js: -------------------------------------------------------------------------------- 1 | ../../../src/js/barChart.js -------------------------------------------------------------------------------- /test/1/js/coffee: -------------------------------------------------------------------------------- 1 | ../../../src/coffee -------------------------------------------------------------------------------- /test/1/js/data.js: -------------------------------------------------------------------------------- 1 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 2 | __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 3 | 4 | crosslet.DataStore = (function() { 5 | 6 | DataStore.prototype.data = {}; 7 | 8 | DataStore.prototype.geometries = null; 9 | 10 | DataStore.prototype.isGeoLoaded = false; 11 | 12 | DataStore.prototype.isDataLoaded = false; 13 | 14 | function DataStore(initData) { 15 | this.loadGeo = __bind(this.loadGeo, this); 16 | var _ref, _ref2; 17 | this.geoURL = initData.map.geo.url; 18 | this.version = initData.data.version; 19 | this.idField = (_ref = initData.data.id_field) != null ? _ref : "id"; 20 | this.geoIdField = (_ref2 = initData.map.geo.id_field) != null ? _ref2 : "id"; 21 | if (!window.dataloader) window.dataloader = new crosslet.DataLoader(); 22 | this.l = window.dataloader; 23 | } 24 | 25 | DataStore.prototype.addData = function(data, callback) { 26 | var d, k, v, _i, _len; 27 | for (_i = 0, _len = data.length; _i < _len; _i++) { 28 | d = data[_i]; 29 | if (!this.data[d[this.idField]]) this.data[d[this.idField]] = {}; 30 | for (k in d) { 31 | v = d[k]; 32 | if (!_.isNaN(+v)) this.data[d[this.idField]][k] = +v; 33 | } 34 | } 35 | this.isDataLoaded = true; 36 | if (callback) return callback(data); 37 | }; 38 | 39 | DataStore.prototype.loadData = function(url, callback, method) { 40 | var _this = this; 41 | if (!method) method = d3.tsv; 42 | this.l.load(url, method, function(data) { 43 | return _this.addData(data, callback); 44 | }); 45 | return this; 46 | }; 47 | 48 | DataStore.prototype.get_bounds_topo = function(c) { 49 | var a, f, i, o, _i, _j, _len, _len2, _ref, _ref2; 50 | o = []; 51 | _ref = [_.min, _.max]; 52 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 53 | f = _ref[_i]; 54 | a = []; 55 | _ref2 = [0, 1]; 56 | for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { 57 | i = _ref2[_j]; 58 | a.push(f(_.map(c, function(d) { 59 | return f(_.map(d.coordinates[0], function(dd) { 60 | return dd[i]; 61 | })); 62 | }))); 63 | } 64 | o.push(a); 65 | } 66 | return o; 67 | }; 68 | 69 | DataStore.prototype.loadGeo = function(url, geoIdField, callback, topo_objectName) { 70 | var _this = this; 71 | return this.l.load(url, d3.json, function(t) { 72 | var f, _i, _len, _ref; 73 | if (t.arcs) { 74 | t = topojson.object(t, t.objects[topo_objectName]); 75 | _this.geometries = t.geometries; 76 | } else { 77 | _this.geometries = t.features; 78 | } 79 | _this.bounds = d3.geo.bounds(t); 80 | _ref = _this.geometries; 81 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 82 | f = _ref[_i]; 83 | if (f.properties) { 84 | _this.data[f.properties[_this.geoIdField]] = f.properties; 85 | _this.data[f.properties[_this.geoIdField]].bbox = d3.geo.bounds(f); 86 | } 87 | } 88 | _this.isGeoLoaded = true; 89 | if (callback) callback(_this); 90 | return _this; 91 | }); 92 | }; 93 | 94 | return DataStore; 95 | 96 | })(); 97 | 98 | crosslet.DataLoader = (function() { 99 | 100 | DataLoader.prototype.cache = {}; 101 | 102 | DataLoader.prototype.status = {}; 103 | 104 | DataLoader.prototype.callbackList = {}; 105 | 106 | function DataLoader(version) { 107 | if (!version) version = 1 + ".0"; 108 | this.version = version; 109 | this.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB; 110 | } 111 | 112 | DataLoader.prototype.load = function(url, method, callback) { 113 | var urlv, 114 | _this = this; 115 | urlv = url + this.version; 116 | if (!this.callbackList[urlv]) this.callbackList[urlv] = []; 117 | if (!this.status[urlv]) this.status[urlv] = "init"; 118 | if (callback) this.callbackList[urlv].push(callback); 119 | if (__indexOf.call(this.cache, urlv) >= 0) { 120 | this.executeCallbacks(this.callbackList[urlv], this.cache[urlv]); 121 | return this; 122 | } else { 123 | if (this.status[urlv] !== "loading") { 124 | this.status[urlv] = "loading"; 125 | method(url, function(data) { 126 | _this.cache[urlv] = data; 127 | _this.executeCallbacks(_this.callbackList[urlv], _this.cache[urlv]); 128 | _this.status[urlv] = "done"; 129 | return _this; 130 | }); 131 | } 132 | } 133 | return this; 134 | }; 135 | 136 | DataLoader.prototype.executeCallbacks = function(list, data) { 137 | var _results; 138 | _results = []; 139 | while (list.length > 0) { 140 | _results.push(list.pop()(data)); 141 | } 142 | return _results; 143 | }; 144 | 145 | return DataLoader; 146 | 147 | })(); 148 | -------------------------------------------------------------------------------- /test/1/js/init.js: -------------------------------------------------------------------------------- 1 | var crosslet; 2 | 3 | crosslet = {}; 4 | 5 | if (!_) console.log("Please include underscore.js"); 6 | 7 | crosslet.createConfig = function(defaultConfig, config) { 8 | var c; 9 | return c = jQuery.extend(true, jQuery.extend(true, {}, defaultConfig), config); 10 | }; 11 | 12 | crosslet.id = function(d) { 13 | return d; 14 | }; 15 | 16 | crosslet.idf = function(d) { 17 | return id; 18 | }; 19 | 20 | crosslet.notimplemented = function() { 21 | throw "This function is not set. Please check your config."; 22 | }; 23 | 24 | crosslet.changeSelect = function(select, val) { 25 | return $(select).find("option").filter(function() { 26 | return $(this).val() === val; 27 | }).attr('selected', true); 28 | }; 29 | 30 | crosslet.defaultConfig = { 31 | map: { 32 | leaflet: { 33 | key: "--your key--", 34 | styleId: 64657, 35 | attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade' 36 | }, 37 | view: { 38 | center: [51.505, -0.09], 39 | zoom: 11 40 | }, 41 | geo: { 42 | url: "please specify correct location of your geojson", 43 | name_field: "name", 44 | id_field: "code", 45 | topo_object: "please specify correct object name" 46 | } 47 | } 48 | }; 49 | 50 | ({ 51 | data: { 52 | version: "1.0", 53 | id_field: "id" 54 | }, 55 | dimensions: {}, 56 | defaults: { 57 | colorscale: d3.scale.linear().domain([1, 10, 20]).range(["green", "yellow", "red"]).interpolate(d3.cie.interpolateLab), 58 | opacity: 0.75, 59 | order: [] 60 | } 61 | }); 62 | 63 | crosslet.defaultDimensionConfig = { 64 | p: {}, 65 | filter: null, 66 | data: { 67 | interval: null, 68 | filter: null, 69 | field: function(d) { 70 | return d.id; 71 | }, 72 | dataSet: crosslet.notimplemented, 73 | method: d3.tsv, 74 | preformat: function(dd) { 75 | return function(d) { 76 | return +d; 77 | }; 78 | }, 79 | tickSize: 5, 80 | colorscale: d3.scale.linear().domain([1, 10, 20]).range(["green", "yellow", "red"]).interpolate(d3.cie.interpolateLab) 81 | }, 82 | format: { 83 | short: function(d) { 84 | return d3.format(",.2f"); 85 | }, 86 | long: function(d) { 87 | return d.format.short(d); 88 | }, 89 | input: function(d) { 90 | return d.format.short(d); 91 | }, 92 | axis: function(d) { 93 | return d.format.short(d); 94 | } 95 | }, 96 | render: { 97 | legend: function(d, el) { 98 | var f, html; 99 | f = d.title ? d.title : d.data.field_func(d); 100 | html = '

' + f + '

'; 101 | return el.html(html); 102 | }, 103 | range: function(d, el) { 104 | var html; 105 | html = "

" + d.format.short(d)(d.filter[0]) + "" + d.format.short(d)(d.filter[1]) + "

"; 106 | return el.html(html); 107 | }, 108 | form: function(d, el) { 109 | return d.render.legend(d, el); 110 | }, 111 | rangeForm: function(d, el) { 112 | var html, size; 113 | size = _.max(_.map(d.data.interval, function(dd) { 114 | return ("_" + d.format.input(d)(dd)).length - 1; 115 | })); 116 | html = "Range: "; 117 | return el.html(html); 118 | } 119 | }, 120 | submitter: function(d, el) { 121 | var out; 122 | out = {}; 123 | $(el).find("input, select").each(function(index, el) { 124 | return out[$(el).attr("name")] = $(el).val(); 125 | }); 126 | return out; 127 | } 128 | }; 129 | -------------------------------------------------------------------------------- /test/1/js/views/datasetsView.js: -------------------------------------------------------------------------------- 1 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 2 | __hasProp = Object.prototype.hasOwnProperty, 3 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; 4 | 5 | crosslet.PanelView = (function(_super) { 6 | 7 | __extends(PanelView, _super); 8 | 9 | function PanelView() { 10 | this.renderCubes = __bind(this.renderCubes, this); 11 | this.createCube = __bind(this.createCube, this); 12 | this.setActive = __bind(this.setActive, this); 13 | this._renderMap = __bind(this._renderMap, this); 14 | PanelView.__super__.constructor.apply(this, arguments); 15 | } 16 | 17 | PanelView.prototype.initialize = function(el, config, parent) { 18 | var e, o, _i, _len, _ref; 19 | this.config = crosslet.createConfig(crosslet.defaultConfig, config); 20 | this.parent = parent; 21 | this.el = el; 22 | this.ds = parent.ds; 23 | this.boxes = {}; 24 | this.render(); 25 | this.width = 200; 26 | this.active = this.config.defaults.active ? this.config.defaults.active : this.config.defaults.order[0]; 27 | this.numloads = this.config.defaults.order.length; 28 | _ref = this.config.defaults.order; 29 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 30 | o = _ref[_i]; 31 | e = $("
"); 32 | this.boxes[o] = new crosslet.BoxView(e, this.config.dimensions[o], this, o); 33 | $(this.el).append(e); 34 | } 35 | this.boxes[this.active].setActive(true); 36 | this.renderMap = _.debounce(this._renderMap, 200); 37 | return this.boxes; 38 | }; 39 | 40 | PanelView.prototype.loaded = function() { 41 | this.numloads = this.numloads - 1; 42 | if (this.numloads <= 0) return this.createCube(); 43 | }; 44 | 45 | PanelView.prototype._renderMap = function() { 46 | var abox, adata, f, k, keys, out, _i, _len, 47 | _this = this; 48 | abox = this.boxes[this.active]; 49 | adata = abox.getFilteredData(); 50 | keys = this.intersection(_.map(_.values(this.boxes), function(b) { 51 | return _.keys(b.getFilteredData()).sort(); 52 | })); 53 | out = {}; 54 | for (_i = 0, _len = keys.length; _i < _len; _i++) { 55 | k = keys[_i]; 56 | out[k] = adata[k]; 57 | } 58 | f = abox.config.format.long(abox.config); 59 | this.parent.renderMap(out, (function(v) { 60 | return abox.config.data.colorscale(abox.config.scale(v)); 61 | }), function(data, value) { 62 | return data.properties[_this.config.map.geo.name_field] + " - " + f(value); 63 | }); 64 | return this; 65 | }; 66 | 67 | PanelView.prototype.setActive = function(activeBox) { 68 | if (activeBox !== this.active) { 69 | this.boxes[this.active].setActive(false); 70 | this.active = activeBox; 71 | this.boxes[this.active].setActive(true); 72 | return this.renderMap(); 73 | } 74 | }; 75 | 76 | PanelView.prototype.intersection = function(a) { 77 | var intersect_safe, o, out, _i, _len, _ref; 78 | intersect_safe = function(a, b) { 79 | var ai, bi, result; 80 | ai = bi = 0; 81 | result = []; 82 | while (ai < a.length && bi < b.length) { 83 | if (a[ai] < b[bi]) ai++; 84 | if (a[ai] > b[bi]) bi++; 85 | if (a[ai] === b[bi]) { 86 | result.push(a[ai]); 87 | ai++; 88 | bi++; 89 | } 90 | } 91 | return result; 92 | }; 93 | switch (a.length) { 94 | case 0: 95 | return a; 96 | case 1: 97 | return a[0]; 98 | case 2: 99 | return intersect_safe(a[0], a[1]); 100 | default: 101 | out = a[0]; 102 | _ref = a.slice(1); 103 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 104 | o = _ref[_i]; 105 | out = intersect_safe(out, o); 106 | } 107 | return out; 108 | } 109 | }; 110 | 111 | PanelView.prototype.createCube = function() { 112 | var bName, box, brushevent, chart, d, dg, getRounder, groups, int, js_bName, js_box, key, keys, o, row, t1, t15, t2, _i, _j, _len, _len2, _ref, _ref2, _ref3; 113 | this.rows = []; 114 | t1 = new Date().getTime(); 115 | keys = _.map(_.values(this.boxes), function(b) { 116 | return _.keys(b.data).sort(); 117 | }); 118 | t15 = new Date().getTime(); 119 | int = this.intersection(keys); 120 | for (_i = 0, _len = int.length; _i < _len; _i++) { 121 | key = int[_i]; 122 | row = {}; 123 | _ref = this.boxes; 124 | for (bName in _ref) { 125 | box = _ref[bName]; 126 | row[bName] = box.data[key]; 127 | } 128 | this.rows.push(row); 129 | } 130 | t2 = new Date().getTime(); 131 | this.cube = crossfilter(this.rows); 132 | getRounder = function(m1, m2, w) { 133 | var t; 134 | t = 10 * (m2 - m1) / w; 135 | return function(d) { 136 | return t * Math.floor(+d / t); 137 | }; 138 | }; 139 | groups = {}; 140 | this.charts = {}; 141 | brushevent = function(box, ctx) { 142 | return function() { 143 | box.event_click(); 144 | return ctx.renderCubes(); 145 | }; 146 | }; 147 | _ref2 = this.boxes; 148 | for (bName in _ref2) { 149 | box = _ref2[bName]; 150 | var chart, js_box,js_bName; 151 | js_box = box; 152 | js_bName = bName; 153 | d = this.cube.dimension(function(dd) { 154 | return dd[bName]; 155 | }); 156 | dg = d.group(getRounder(box.config.data.interval[0], box.config.data.interval[1], this.width - 20)); 157 | box.graph.empty(); 158 | chart = barChart().dimension(d).name_id(bName).group(dg).x(d3.scale.linear().domain(box.config.data.interval).rangeRound([0, this.width - 20])).tickSize(box.config.data.tickSize).tickFormat(box.config.format.axis(box.config)).fill(box.config.data.colorscale); 159 | chart.on("brush", brushevent(box, this)); 160 | chart.on("brushend", this.renderCubes); 161 | box.chart = chart; 162 | this.charts[bName] = chart; 163 | } 164 | this.renderCubes(); 165 | _ref3 = this.config.defaults.order; 166 | for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) { 167 | o = _ref3[_j]; 168 | if (this.config.dimensions[o].filter) { 169 | this.boxes[o].setFilter(this.config.dimensions[o].filter, true); 170 | } 171 | } 172 | return this; 173 | }; 174 | 175 | PanelView.prototype.renderCubes = function() { 176 | var abox, bName, box, _ref; 177 | _ref = this.boxes; 178 | for (bName in _ref) { 179 | box = _ref[bName]; 180 | box.chart(box.graph); 181 | $(box.el).on("mousedown", box.event_click); 182 | box.setFilter(box.chart.filter(), false); 183 | } 184 | abox = this.boxes[this.active]; 185 | abox.setFilter(abox.chart.filter(), false); 186 | this.renderMap(); 187 | return this; 188 | }; 189 | 190 | return PanelView; 191 | 192 | })(Backbone.View); 193 | 194 | crosslet.BoxView = (function(_super) { 195 | 196 | __extends(BoxView, _super); 197 | 198 | function BoxView() { 199 | this.setFilter = __bind(this.setFilter, this); 200 | this.event_click = __bind(this.event_click, this); 201 | this.setActive = __bind(this.setActive, this); 202 | this.dataLoaded = __bind(this.dataLoaded, this); 203 | BoxView.__super__.constructor.apply(this, arguments); 204 | } 205 | 206 | BoxView.prototype.initialize = function(el, config, parent, name) { 207 | this.el = el; 208 | this.config = crosslet.createConfig(crosslet.defaultDimensionConfig, config); 209 | this.config.id = name; 210 | this.config.data.field_func = !_.isFunction(this.config.data.field) ? (function(d) { 211 | return d.data.field; 212 | }) : this.config.data.field; 213 | $(this.el).on("mousedown", this.event_click); 214 | $(this.el).on("tap", this.event_click); 215 | $(this.el)[0].onmousedown = $(this.el)[0].ondblclick = L.DomEvent.stopPropagation; 216 | this.legend = {}; 217 | this.legend.all = $("
"); 218 | this.legend.text = $("
"); 219 | this.legend.text_p = $("
"); 220 | this.legend.text_range = $("
"); 221 | this.legend.text.append(this.legend.text_p).append(this.legend.text_range); 222 | this.legend.form = $("
"); 223 | this.legend.form_p = $("
"); 224 | this.legend.form_range = $("
"); 225 | this.legend.form.append(this.legend.form_p).append(this.legend.form_range); 226 | this.legend.all.append(this.legend.text).append(this.legend.form); 227 | $(el).append(this.legend.all); 228 | this.graph = $("
"); 229 | $(el).append(this.graph); 230 | this.parent = parent; 231 | this.ds = parent.ds; 232 | this.active = false; 233 | this.name = name; 234 | return this.loadData(); 235 | }; 236 | 237 | BoxView.prototype.loadData = function() { 238 | if (_.isString(this.config.data.dataSet)) { 239 | return this.parent.ds.loadData(this.config.data.dataSet, this.dataLoaded, this.config.data.method); 240 | } else { 241 | if (_.isFunction(this.config.data.dataSet)) { 242 | return this.parent.ds.loadData(this.config.data.dataSet(this.config), this.dataLoaded, this.config.data.method); 243 | } else { 244 | return this.parent.ds.addData(this.config.data.dataSet, this.dataLoaded); 245 | } 246 | } 247 | }; 248 | 249 | BoxView.prototype.dataLoaded = function() { 250 | var f, id, preformatter, val, _ref; 251 | this.data = {}; 252 | f = this.config.data.field_func(this.config); 253 | preformatter = this.config.data.preformat(this.config); 254 | _ref = this.parent.ds.data; 255 | for (id in _ref) { 256 | val = _ref[id]; 257 | if (val[f]) this.data[id] = preformatter(val[f]); 258 | } 259 | if (!this.config.data.interval) { 260 | this.config.data.interval = [_.min(_.values(this.data)), _.max(_.values(this.data))]; 261 | } 262 | if (!this.config.filter) { 263 | this.config.filter = [_.min(_.values(this.data)), _.max(_.values(this.data))]; 264 | } 265 | if (!this.config.scale) { 266 | this.config.scale = d3.scale.quantize().domain(this.config.data.interval).range([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]); 267 | } 268 | this.render(); 269 | return this.parent.loaded(); 270 | }; 271 | 272 | BoxView.prototype.setActive = function(isActive) { 273 | this.active = isActive; 274 | if (isActive) { 275 | return $(this.el).addClass("selected"); 276 | } else { 277 | return $(this.el).removeClass("selected"); 278 | } 279 | }; 280 | 281 | BoxView.prototype.event_click = function(event) { 282 | if (!this.active) this.parent.setActive(this.name); 283 | return true; 284 | }; 285 | 286 | BoxView.prototype.setFilter = function(f, redrawCube) { 287 | if (redrawCube == null) redrawCube = false; 288 | if (redrawCube) { 289 | this.chart.filter(f); 290 | this.parent.renderCubes(); 291 | } 292 | if (!f) f = this.config.data.interval; 293 | this.config.filter = f; 294 | this.filterElements[0].val(this.config.format.input(this.config)(f[0])); 295 | this.filterElements[1].val(this.config.format.input(this.config)(f[1])); 296 | $(this.legend.text_range).find(".m0").text(this.config.format.short(this.config)(f[0])); 297 | $(this.legend.text_range).find(".m1").text(this.config.format.short(this.config)(f[1])); 298 | return this; 299 | }; 300 | 301 | BoxView.prototype.getFilteredData = function() { 302 | var f, k, out, v, _ref, _ref2; 303 | if (!this.chart.filter()) return this.data; 304 | f = (_ref = this.chart.filter()) != null ? _ref : this.config.data.interval; 305 | out = {}; 306 | _ref2 = this.data; 307 | for (k in _ref2) { 308 | v = _ref2[k]; 309 | if ((f[0] <= v && v <= f[1])) out[k] = v; 310 | } 311 | return out; 312 | }; 313 | 314 | BoxView.prototype.renderRange = function() { 315 | this.config.render.range(this.config, this.legend.text_range); 316 | return this.config.render.rangeForm(this.config, this.legend.form_range); 317 | }; 318 | 319 | BoxView.prototype.render = function() { 320 | var _this = this; 321 | this.config.render.legend(this.config, this.legend.text_p); 322 | this.config.render.form(this.config, this.legend.form_p); 323 | this.renderRange(); 324 | $(this.legend.form_range).find("input").on("change", function() { 325 | var f; 326 | f = [+_this.filterElements[0].val(), +_this.filterElements[1].val()]; 327 | if (f[0] > f[1]) f.reverse(); 328 | f[0] = _.max([_this.config.data.interval[0], f[0]]); 329 | f[1] = _.min([_this.config.data.interval[1], f[1]]); 330 | if (_.isEqual(f, _this.config.data.interval)) f = null; 331 | return _this.setFilter(f, true); 332 | }); 333 | $(this.legend.form_p).find("input, select").on("change", function() { 334 | var p; 335 | _this.config.data.interval = null; 336 | _this.config.scale = null; 337 | _this.config.filter = null; 338 | p = _this.config.submitter(_this.config, _this.legend.form_p); 339 | _this.config.p = p; 340 | console.log(p); 341 | return _this.loadData(); 342 | }); 343 | return this.filterElements = [$(this.legend.form_range).find("input[name=m0]"), $(this.legend.form_range).find("input[name=m1]")]; 344 | }; 345 | 346 | return BoxView; 347 | 348 | })(Backbone.View); 349 | -------------------------------------------------------------------------------- /test/1/js/views/mapView.js: -------------------------------------------------------------------------------- 1 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 2 | __hasProp = Object.prototype.hasOwnProperty, 3 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; 4 | 5 | crosslet.MapView = (function(_super) { 6 | 7 | __extends(MapView, _super); 8 | 9 | function MapView() { 10 | this._renderMap = __bind(this._renderMap, this); 11 | this.hover = __bind(this.hover, this); 12 | this.moveMove = __bind(this.moveMove, this); 13 | this.reset = __bind(this.reset, this); 14 | this.beforezoom = __bind(this.beforezoom, this); 15 | this.project = __bind(this.project, this); 16 | MapView.__super__.constructor.apply(this, arguments); 17 | } 18 | 19 | MapView.prototype.initialize = function(el, config) { 20 | var _this = this; 21 | this.config = crosslet.createConfig(crosslet.defaultConfig, config); 22 | this.geoURL = this.config.map.geo.url; 23 | this.opacity = this.config.defaults.opacity; 24 | this.ds = new crosslet.DataStore(this.config); 25 | this.el = el; 26 | this.hoverFunc = this.default_hover; 27 | $(this.el).attr("class", "crosslet"); 28 | this.map = L.map(el[0]).setView(this.config.map.view.center, this.config.map.view.zoom); 29 | L.tileLayer("http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png", this.config.map.leaflet).addTo(this.map); 30 | this.control = $("
"); 31 | this.info = L.Control.extend({ 32 | options: { 33 | position: 'topright' 34 | }, 35 | onAdd: function(map) { 36 | return _this.control[0]; 37 | } 38 | }); 39 | this.map.addControl(new this.info()); 40 | this.panel = new crosslet.PanelView(this.control, this.config, this); 41 | this.renderMap = this._renderMap; 42 | return this.ds.loadGeo(this.geoURL, this.config.map.geo.id_field, function(ds) { 43 | _this.bounds = _this.ds.bounds; 44 | _this.path = d3.geo.path().projection(_this.project); 45 | _this.svg = d3.select(_this.map.getPanes().overlayPane).append("svg"); 46 | _this.g = _this.svg.append("g"); 47 | _this.g.attr("class", "crosslet_geometry"); 48 | _this.feature = _this.g.selectAll("path").data(ds.geometries).enter().append("path").attr("id", function(d) { 49 | return "path_" + d.properties[_this.config.map.geo.id_field]; 50 | }).on("mouseover", function(d) { 51 | return _this.hover(d); 52 | }).on("mousemove", _this.moveMove); 53 | _this.reset(); 54 | _this.map.on("viewreset", _this.reset); 55 | _this.map.on("zoomstart", _this.beforezoom); 56 | _this.hoverElement = _this.svg.append("g").attr("class", "hover"); 57 | _this.hoverElementRect = _this.hoverElement.append("svg:rect").attr("x", 0).attr("y", 0).attr("width", 10).attr("height", 30).attr("rx", 5).attr("ry", 5); 58 | _this.hoverElementText = _this.hoverElement.append("text").attr("x", 0).attr("y", 0); 59 | return _this.hoverElementTextBB = _this.hoverElementText.node().getBBox(); 60 | }, this.config.map.geo.topo_object); 61 | }; 62 | 63 | MapView.prototype.project = function(x) { 64 | var point; 65 | point = this.map.latLngToLayerPoint(new L.LatLng(x[1], x[0])); 66 | return [point.x, point.y]; 67 | }; 68 | 69 | MapView.prototype.beforezoom = function() { 70 | return this.g.style("display", "none"); 71 | }; 72 | 73 | MapView.prototype.reset = function() { 74 | var bottomLeft, topRight; 75 | bottomLeft = this.project(this.bounds[0]); 76 | topRight = this.project(this.bounds[1]); 77 | this.svg.attr("width", topRight[0] - bottomLeft[0]).attr("height", bottomLeft[1] - topRight[1]).style("margin-left", bottomLeft[0] + "px").style("margin-top", topRight[1] + "px"); 78 | this.g.attr("transform", "translate(" + -bottomLeft[0] + "," + -topRight[1] + ")"); 79 | this.feature.attr("d", this.path); 80 | this.g.style("display", "inline"); 81 | return true; 82 | }; 83 | 84 | MapView.prototype.moveMove = function() { 85 | var pos; 86 | pos = d3.mouse(this.svg.node()); 87 | pos[0] += 30; 88 | pos[1] += 30; 89 | if (this.hoverElementTextBB.width + pos[0] >= this.svg.attr("width")) { 90 | pos[0] -= this.hoverElementTextBB.width + 60; 91 | } 92 | if (this.hoverElementTextBB.height + pos[1] >= this.svg.attr("height")) { 93 | pos[1] -= this.hoverElementTextBB.height + 60; 94 | } 95 | return this.hoverElement.attr("transform", "translate(" + pos[0] + "," + pos[1] + ")"); 96 | }; 97 | 98 | MapView.prototype.hover = function(data) { 99 | var text; 100 | text = this.hoverFunc(data, data.properties.value); 101 | this.hoverElementText.text(text); 102 | this.hoverElementTextBB = this.hoverElementText.node().getBBox(); 103 | return this.hoverElementRect.attr("width", this.hoverElementTextBB.width + 10).attr("height", this.hoverElementTextBB.height + 10).attr("x", this.hoverElementTextBB.x - 5).attr("y", this.hoverElementTextBB.y - 5); 104 | }; 105 | 106 | MapView.prototype.default_hover = function(data, value) { 107 | return data.properties[this.config.map.geo.name_field] + " - " + value; 108 | }; 109 | 110 | MapView.prototype._renderMap = function(data, formatter, hoverFunc) { 111 | var _this = this; 112 | if (hoverFunc) this.hoverFunc = hoverFunc; 113 | this.feature.attr("style", function(d) { 114 | var id; 115 | id = d.properties[_this.config.map.geo.id_field]; 116 | d.properties.value = data[id]; 117 | if (data[id]) { 118 | return "fill: " + formatter(d.properties.value); 119 | } else { 120 | return "display:none"; 121 | } 122 | }); 123 | return this; 124 | }; 125 | 126 | return MapView; 127 | 128 | })(Backbone.View); 129 | -------------------------------------------------------------------------------- /test/1/less/crosslet.less: -------------------------------------------------------------------------------- 1 | ../../../src/less/crosslet.less -------------------------------------------------------------------------------- /test/1/less/styles.less: -------------------------------------------------------------------------------- 1 | @import "crosslet.less"; 2 | 3 | html{ 4 | height: 100%; 5 | } 6 | body{ 7 | margin: 0px; 8 | padding: 0px; 9 | height: 100%; 10 | } 11 | 12 | #content{ 13 | margin-right: auto; 14 | margin-left: auto; 15 | height: 100%; 16 | 17 | //width: 1324px; 18 | } 19 | 20 | #map{ 21 | 22 | height: 100%; 23 | } 24 | 25 | #templates{ 26 | display: none; 27 | } -------------------------------------------------------------------------------- /test/1/lib: -------------------------------------------------------------------------------- 1 | ../../lib --------------------------------------------------------------------------------