├── .gitignore ├── .project ├── README.md ├── bootstrap.min.css ├── build ├── README.txt ├── build.py ├── buildUncompressed.py ├── full.cfg ├── library.cfg ├── license.txt ├── lite.cfg ├── matrix.cfg ├── osmatrix.min.js └── tools │ ├── BeautifulSoup.py │ ├── README.txt │ ├── exampleparser.py │ ├── jsmin.c │ ├── jsmin.py │ ├── jsmin.pyc │ ├── mergejs.py │ ├── mergejs.pyc │ ├── minimize.py │ ├── oldot.py │ ├── release.sh │ ├── shrinksafe.py │ ├── toposort.py │ ├── toposort.pyc │ └── update_dev_dir.sh ├── img ├── ajax-loader.gif ├── ajax-loader_head.gif ├── giscience_logo.png └── icons.png ├── index.html ├── js ├── control.js ├── event.js ├── geocoder.js ├── geolocator.js ├── lib │ ├── d3.v3.min.js │ ├── leaflet-0.5.1.css │ ├── leaflet-0.5.1.ie.css │ └── leaflet-0.5.1.js ├── map.js ├── osmatrix.js ├── permalink.js └── ui.js ├── license.txt └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | .project -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | osmatrix-client 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repository is no longer maintained! 2 | 3 | # OSMatrix 4 | 5 | OSMatrix is a web-based application to visualize characteristics of OpenStreetMap, which are usually not displayed in cartographic representations of the data. The characteristics include information on the topicality of data, user contributions and the presence (or absence) of certain feature types. 6 | 7 | OSMatrix is based on an idea of Alexander Zipf has been brought to life by Lukas Loos and Oliver Roick at [GIScience Research Group](http://giscience.uni-hd.de) at Heidelberg University. 8 | 9 | ## Licence 10 | 11 | (The MIT Licence) 12 | 13 | Copyright (c) 2013 Oliver Roick 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /bootstrap.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v2.3.1 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | .clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;} 11 | .clearfix:after{clear:both;} 12 | .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;} 13 | .input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} 14 | form{margin:0 0 20px;} 15 | fieldset{padding:0;margin:0;border:0;} 16 | legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:19.5px;line-height:40px;color:#333333;border:0;border-bottom:1px solid #e5e5e5;}legend small{font-size:15px;color:#999999;} 17 | label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:20px;} 18 | input,button,select,textarea{font-family:'Droid Sans','Helvetica Neue',Helvetica,Arial,sans-serif;} 19 | label{display:block;margin-bottom:5px;} 20 | select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:13px;line-height:20px;color:#555555;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;vertical-align:middle;} 21 | input,textarea,.uneditable-input{width:206px;} 22 | textarea{height:auto;} 23 | textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#ffffff;border:1px solid #cccccc;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear .2s, box-shadow linear .2s;-moz-transition:border linear .2s, box-shadow linear .2s;-o-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82, 168, 236, 0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);} 24 | input[type="radio"],input[type="checkbox"]{margin:4px 0 0;*margin-top:0;margin-top:1px \9;line-height:normal;} 25 | input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto;} 26 | select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px;} 27 | select{width:220px;border:1px solid #cccccc;background-color:#ffffff;} 28 | select[multiple],select[size]{height:auto;} 29 | select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} 30 | .uneditable-input,.uneditable-textarea{color:#999999;background-color:#fcfcfc;border-color:#cccccc;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;} 31 | .uneditable-input{overflow:hidden;white-space:nowrap;} 32 | .uneditable-textarea{width:auto;height:auto;} 33 | input:-moz-placeholder,textarea:-moz-placeholder{color:#999999;} 34 | input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999999;} 35 | input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999999;} 36 | .radio,.checkbox{min-height:20px;padding-left:20px;} 37 | .radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px;} 38 | .controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;} 39 | .radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle;} 40 | .radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;} 41 | .input-mini{width:60px;} 42 | .input-small{width:90px;} 43 | .input-medium{width:150px;} 44 | .input-large{width:210px;} 45 | .input-xlarge{width:270px;} 46 | .input-xxlarge{width:530px;} 47 | input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0;} 48 | .input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block;} 49 | input,textarea,.uneditable-input{margin-left:0;} 50 | .controls-row [class*="span"]+[class*="span"]{margin-left:20px;} 51 | input.span12,textarea.span12,.uneditable-input.span12{width:926px;} 52 | input.span11,textarea.span11,.uneditable-input.span11{width:846px;} 53 | input.span10,textarea.span10,.uneditable-input.span10{width:766px;} 54 | input.span9,textarea.span9,.uneditable-input.span9{width:686px;} 55 | input.span8,textarea.span8,.uneditable-input.span8{width:606px;} 56 | input.span7,textarea.span7,.uneditable-input.span7{width:526px;} 57 | input.span6,textarea.span6,.uneditable-input.span6{width:446px;} 58 | input.span5,textarea.span5,.uneditable-input.span5{width:366px;} 59 | input.span4,textarea.span4,.uneditable-input.span4{width:286px;} 60 | input.span3,textarea.span3,.uneditable-input.span3{width:206px;} 61 | input.span2,textarea.span2,.uneditable-input.span2{width:126px;} 62 | input.span1,textarea.span1,.uneditable-input.span1{width:46px;} 63 | .controls-row{*zoom:1;}.controls-row:before,.controls-row:after{display:table;content:"";line-height:0;} 64 | .controls-row:after{clear:both;} 65 | .controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left;} 66 | .controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px;} 67 | input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eeeeee;} 68 | input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent;} 69 | .control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;} 70 | .control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;} 71 | .control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;} 72 | .control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853;} 73 | .control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;} 74 | .control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;} 75 | .control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;} 76 | .control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48;} 77 | .control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;} 78 | .control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;} 79 | .control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;} 80 | .control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847;} 81 | .control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad;} 82 | .control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad;} 83 | .control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7ab5d3;} 84 | .control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad;} 85 | input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;} 86 | .form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1;}.form-actions:before,.form-actions:after{display:table;content:"";line-height:0;} 87 | .form-actions:after{clear:both;} 88 | .help-block,.help-inline{color:#595959;} 89 | .help-block{display:block;margin-bottom:10px;} 90 | .help-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding-left:5px;} 91 | .input-append,.input-prepend{display:inline-block;margin-bottom:10px;vertical-align:middle;font-size:0;white-space:nowrap;}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:13px;} 92 | .input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2;} 93 | .input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:13px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#eeeeee;border:1px solid #ccc;} 94 | .input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} 95 | .input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546;} 96 | .input-prepend .add-on,.input-prepend .btn{margin-right:-1px;} 97 | .input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;} 98 | .input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;} 99 | .input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px;} 100 | .input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;} 101 | .input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;} 102 | .input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;} 103 | .input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;} 104 | .input-prepend.input-append .btn-group:first-child{margin-left:0;} 105 | input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;} 106 | .form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} 107 | .form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;} 108 | .form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;} 109 | .form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;} 110 | .form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;} 111 | .form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;*zoom:1;margin-bottom:0;vertical-align:middle;} 112 | .form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none;} 113 | .form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block;} 114 | .form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0;} 115 | .form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle;} 116 | .form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0;} 117 | .control-group{margin-bottom:10px;} 118 | legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate;} 119 | .form-horizontal .control-group{margin-bottom:20px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";line-height:0;} 120 | .form-horizontal .control-group:after{clear:both;} 121 | .form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right;} 122 | .form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0;}.form-horizontal .controls:first-child{*padding-left:180px;} 123 | .form-horizontal .help-block{margin-bottom:0;} 124 | .form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px;} 125 | .form-horizontal .form-actions{padding-left:180px;} 126 | .btn{display:inline-block;*display:inline;*zoom:1;padding:4px 12px;margin-bottom:0;font-size:13px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#333333;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #ffffff, #e6e6e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(top, #ffffff, #e6e6e6);background-image:-o-linear-gradient(top, #ffffff, #e6e6e6);background-image:linear-gradient(to bottom, #ffffff, #e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #cccccc;*border:0;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333333;background-color:#e6e6e6;*background-color:#d9d9d9;} 127 | .btn:active,.btn.active{background-color:#cccccc \9;} 128 | .btn:first-child{*margin-left:0;} 129 | .btn:hover,.btn:focus{color:#333333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;} 130 | .btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} 131 | .btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);} 132 | .btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} 133 | .btn-large{padding:11px 19px;font-size:16.25px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;} 134 | .btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px;} 135 | .btn-small{padding:2px 10px;font-size:11.049999999999999px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} 136 | .btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0;} 137 | .btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px;} 138 | .btn-mini{padding:0 6px;font-size:9.75px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} 139 | .btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} 140 | .btn-block+.btn-block{margin-top:5px;} 141 | input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;} 142 | .btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255, 255, 255, 0.75);} 143 | .btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(to bottom, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#0044cc;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#ffffff;background-color:#0044cc;*background-color:#003bb3;} 144 | .btn-primary:active,.btn-primary.active{background-color:#003399 \9;} 145 | .btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#ffffff;background-color:#f89406;*background-color:#df8505;} 146 | .btn-warning:active,.btn-warning.active{background-color:#c67605 \9;} 147 | .btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(to bottom, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#ffffff;background-color:#bd362f;*background-color:#a9302a;} 148 | .btn-danger:active,.btn-danger.active{background-color:#942a25 \9;} 149 | .btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(to bottom, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#ffffff;background-color:#51a351;*background-color:#499249;} 150 | .btn-success:active,.btn-success.active{background-color:#408140 \9;} 151 | .btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(to bottom, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#ffffff;background-color:#2f96b4;*background-color:#2a85a0;} 152 | .btn-info:active,.btn-info.active{background-color:#24748c \9;} 153 | .btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#363636;background-image:-moz-linear-gradient(top, #444444, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));background-image:-webkit-linear-gradient(top, #444444, #222222);background-image:-o-linear-gradient(top, #444444, #222222);background-image:linear-gradient(to bottom, #444444, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#222222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#ffffff;background-color:#222222;*background-color:#151515;} 154 | .btn-inverse:active,.btn-inverse.active{background-color:#080808 \9;} 155 | button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;} 156 | button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px;} 157 | button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px;} 158 | button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px;} 159 | .btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} 160 | .btn-link{border-color:transparent;cursor:pointer;color:#0088cc;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} 161 | .btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent;} 162 | .btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333333;text-decoration:none;} 163 | .btn-group{position:relative;display:inline-block;*display:inline;*zoom:1;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em;}.btn-group:first-child{*margin-left:0;} 164 | .btn-group+.btn-group{margin-left:5px;} 165 | .btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px;}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px;} 166 | .btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} 167 | .btn-group>.btn+.btn{margin-left:-1px;} 168 | .btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:13px;} 169 | .btn-group>.btn-mini{font-size:9.75px;} 170 | .btn-group>.btn-small{font-size:11.049999999999999px;} 171 | .btn-group>.btn-large{font-size:16.25px;} 172 | .btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;} 173 | .btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;} 174 | .btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;} 175 | .btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;} 176 | .btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2;} 177 | .btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;} 178 | .btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);*padding-top:5px;*padding-bottom:5px;} 179 | .btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px;} 180 | .btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px;} 181 | .btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px;} 182 | .btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);} 183 | .btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6;} 184 | .btn-group.open .btn-primary.dropdown-toggle{background-color:#0044cc;} 185 | .btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406;} 186 | .btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f;} 187 | .btn-group.open .btn-success.dropdown-toggle{background-color:#51a351;} 188 | .btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4;} 189 | .btn-group.open .btn-inverse.dropdown-toggle{background-color:#222222;} 190 | .btn .caret{margin-top:8px;margin-left:0;} 191 | .btn-large .caret{margin-top:6px;} 192 | .btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px;} 193 | .btn-mini .caret,.btn-small .caret{margin-top:8px;} 194 | .dropup .btn-large .caret{border-bottom-width:5px;} 195 | .btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;} 196 | .btn-group-vertical{display:inline-block;*display:inline;*zoom:1;} 197 | .btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} 198 | .btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px;} 199 | .btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;} 200 | .btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;} 201 | .btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0;} 202 | .btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;} -------------------------------------------------------------------------------- /build/README.txt: -------------------------------------------------------------------------------- 1 | 2 | ## HowTo: Build & deploy "Shrunk" Single File Library version of OpenLayers ## 3 | 4 | * Build: 5 | 6 | cd build 7 | ./build.py 8 | cd .. 9 | 10 | * Upload the result to the server: e.g. 11 | 12 | scp build/OpenLayers.js openlayers@openlayers.org:openlayers.org/htdocs/code/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /build/build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | sys.path.append("tools") 5 | import mergejs 6 | 7 | def build(): 8 | have_compressor = None 9 | try: 10 | import jsmin 11 | have_compressor = "jsmin" 12 | except ImportError: 13 | try: 14 | import minimize 15 | have_compressor = "minimize" 16 | except Exception, E: 17 | print E 18 | pass 19 | 20 | sourceDirectory = "../js" 21 | configFilename = "matrix.cfg" 22 | outputFilename = "osmatrix.min.js" 23 | 24 | if len(sys.argv) > 1: 25 | configFilename = sys.argv[1] 26 | extension = configFilename[-4:] 27 | 28 | if extension != ".cfg": 29 | configFilename = sys.argv[1] + ".cfg" 30 | 31 | if len(sys.argv) > 2: 32 | outputFilename = sys.argv[2] 33 | 34 | print "Merging libraries." 35 | merged = mergejs.run(sourceDirectory, None, configFilename) 36 | if have_compressor == "jsmin": 37 | print "Compressing using jsmin." 38 | minimized = jsmin.jsmin(merged) 39 | elif have_compressor == "minimize": 40 | print "Compressing using minimize." 41 | minimized = minimize.minimize(merged) 42 | else: # fallback 43 | print "Not compressing." 44 | minimized = merged 45 | # print "Adding license file." 46 | # minimized = file("license.txt").read() + minimized 47 | 48 | print "Writing to %s." % outputFilename 49 | file(outputFilename, "w").write(minimized) 50 | 51 | print "Done." 52 | 53 | if __name__ == '__main__': 54 | build() -------------------------------------------------------------------------------- /build/buildUncompressed.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | sys.path.append("../tools") 5 | 6 | import jsmin, mergejs 7 | 8 | sourceDirectory = "../lib" 9 | configFilename = "full.cfg" 10 | outputFilename = "OpenLayers.js" 11 | 12 | if len(sys.argv) > 1: 13 | configFilename = sys.argv[1] + ".cfg" 14 | if len(sys.argv) > 2: 15 | outputFilename = sys.argv[2] 16 | 17 | print "Merging libraries." 18 | merged = mergejs.run(sourceDirectory, None, configFilename) 19 | print "Adding license file." 20 | merged = file("license.txt").read() + merged 21 | 22 | print "Writing to %s." % outputFilename 23 | file(outputFilename, "w").write(merged) 24 | 25 | print "Done." 26 | -------------------------------------------------------------------------------- /build/full.cfg: -------------------------------------------------------------------------------- 1 | # This is the full build with all files: this includes the vector-related files 2 | # like Renderers and Formats. 3 | 4 | [first] 5 | OpenLayers/SingleFile.js 6 | OpenLayers.js 7 | OpenLayers/BaseTypes.js 8 | OpenLayers/BaseTypes/Class.js 9 | OpenLayers/Util.js 10 | Rico/Corner.js 11 | 12 | [last] 13 | 14 | [include] 15 | 16 | [exclude] 17 | Firebug/firebug.js 18 | Firebug/firebugx.js 19 | OpenLayers/Lang/ca.js 20 | OpenLayers/Lang/cs-CZ.js 21 | OpenLayers/Lang/da-DK.js 22 | OpenLayers/Lang/de.js 23 | OpenLayers/Lang/en-CA.js 24 | OpenLayers/Lang/es.js 25 | OpenLayers/Lang/fr.js 26 | OpenLayers/Lang/it.js 27 | OpenLayers/Lang/nb.js 28 | OpenLayers/Lang/nl.js 29 | OpenLayers/Lang/pt-BR.js 30 | OpenLayers/Lang/sv-SE.js 31 | OpenLayers/Lang/zh-TW.js 32 | OpenLayers/Lang/zh-CN.js 33 | -------------------------------------------------------------------------------- /build/library.cfg: -------------------------------------------------------------------------------- 1 | # This file includes the OpenLayers code to create a build for everything that 2 | # does not require vector support. build.py uses this profile if no other one 3 | # is specified. 4 | 5 | [first] 6 | OpenLayers/SingleFile.js 7 | OpenLayers.js 8 | OpenLayers/BaseTypes.js 9 | OpenLayers/BaseTypes/Class.js 10 | OpenLayers/Util.js 11 | Rico/Corner.js 12 | 13 | [last] 14 | 15 | [include] 16 | 17 | [exclude] 18 | Firebug/firebug.js 19 | Firebug/firebugx.js 20 | OpenLayers/Format/GeoRSS.js 21 | OpenLayers/Format/GML.js 22 | OpenLayers/Format/WKT.js 23 | OpenLayers/Format/KML.js 24 | OpenLayers/Format/WFS.js 25 | OpenLayers/Format.js 26 | OpenLayers/Handler/Path.js 27 | OpenLayers/Handler/Point.js 28 | OpenLayers/Handler/Polygon.js 29 | OpenLayers/Handler/Select.js 30 | OpenLayers/Geometry/Collection.js 31 | OpenLayers/Geometry/Curve.js 32 | OpenLayers/Geometry/LinearRing.js 33 | OpenLayers/Geometry/LineString.js 34 | OpenLayers/Geometry/MultiLineString.js 35 | OpenLayers/Geometry/MultiPoint.js 36 | OpenLayers/Geometry/MultiPolygon.js 37 | OpenLayers/Geometry/Point.js 38 | OpenLayers/Geometry/Polygon.js 39 | OpenLayers/Geometry/Rectangle.js 40 | OpenLayers/Geometry/Surface.js 41 | OpenLayers/Geometry.js 42 | OpenLayers/Layer/GML.js 43 | OpenLayers/Layer/Vector.js 44 | OpenLayers/Control/DrawFeature.js 45 | OpenLayers/Control/EditingToolbar.js 46 | OpenLayers/Control/SelectFeature.js 47 | OpenLayers/Feature/Vector.js 48 | OpenLayers/Renderer 49 | OpenLayers/Renderer/Elements.js 50 | OpenLayers/Renderer/SVG.js 51 | OpenLayers/Renderer/VML.js 52 | OpenLayers/Renderer.js 53 | OpenLayers/Lang/ca.js 54 | OpenLayers/Lang/cs-CZ.js 55 | OpenLayers/Lang/da-DK.js 56 | OpenLayers/Lang/de.js 57 | OpenLayers/Lang/en-CA.js 58 | OpenLayers/Lang/es.js 59 | OpenLayers/Lang/fr.js 60 | OpenLayers/Lang/it.js 61 | OpenLayers/Lang/nb.js 62 | OpenLayers/Lang/nl.js 63 | OpenLayers/Lang/pt-BR.js 64 | OpenLayers/Lang/sv-SE.js 65 | OpenLayers/Lang/zh-TW.js 66 | OpenLayers/Lang/zh-CN.js 67 | 68 | 69 | -------------------------------------------------------------------------------- /build/license.txt: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | OpenLayers.js -- OpenLayers Map Viewer Library 4 | 5 | Copyright 2005-2010 OpenLayers Contributors, released under the Clear BSD 6 | license. Please see http://svn.openlayers.org/trunk/openlayers/license.txt 7 | for the full text of the license. 8 | 9 | Includes compressed code under the following licenses: 10 | 11 | (For uncompressed versions of the code used please see the 12 | OpenLayers SVN repository: ) 13 | 14 | */ 15 | 16 | /* Contains portions of Prototype.js: 17 | * 18 | * Prototype JavaScript framework, version 1.4.0 19 | * (c) 2005 Sam Stephenson 20 | * 21 | * Prototype is freely distributable under the terms of an MIT-style license. 22 | * For details, see the Prototype web site: http://prototype.conio.net/ 23 | * 24 | *--------------------------------------------------------------------------*/ 25 | 26 | /** 27 | * 28 | * Contains portions of Rico 29 | * 30 | * Copyright 2005 Sabre Airline Solutions 31 | * 32 | * Licensed under the Apache License, Version 2.0 (the "License"); you 33 | * may not use this file except in compliance with the License. You 34 | * may obtain a copy of the License at 35 | * 36 | * http://www.apache.org/licenses/LICENSE-2.0 37 | * 38 | * Unless required by applicable law or agreed to in writing, software 39 | * distributed under the License is distributed on an "AS IS" BASIS, 40 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 41 | * implied. See the License for the specific language governing 42 | * permissions and limitations under the License. 43 | * 44 | **/ 45 | 46 | /** 47 | * Contains XMLHttpRequest.js 48 | * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com) 49 | * 50 | * Licensed under the Apache License, Version 2.0 (the "License"); 51 | * you may not use this file except in compliance with the License. 52 | * You may obtain a copy of the License at 53 | * http://www.apache.org/licenses/LICENSE-2.0 54 | */ 55 | 56 | /** 57 | * Contains portions of Gears 58 | * 59 | * Copyright 2007, Google Inc. 60 | * 61 | * Redistribution and use in source and binary forms, with or without 62 | * modification, are permitted provided that the following conditions are met: 63 | * 64 | * 1. Redistributions of source code must retain the above copyright notice, 65 | * this list of conditions and the following disclaimer. 66 | * 2. Redistributions in binary form must reproduce the above copyright notice, 67 | * this list of conditions and the following disclaimer in the documentation 68 | * and/or other materials provided with the distribution. 69 | * 3. Neither the name of Google Inc. nor the names of its contributors may be 70 | * used to endorse or promote products derived from this software without 71 | * specific prior written permission. 72 | * 73 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 74 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 75 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 76 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 77 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 78 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 79 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 80 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 81 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 82 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 83 | * 84 | * Sets up google.gears.*, which is *the only* supported way to access Gears. 85 | * 86 | * Circumvent this file at your own risk! 87 | * 88 | * In the future, Gears may automatically define google.gears.* without this 89 | * file. Gears may use these objects to transparently fix bugs and compatibility 90 | * issues. Applications that use the code below will continue to work seamlessly 91 | * when that happens. 92 | */ 93 | -------------------------------------------------------------------------------- /build/lite.cfg: -------------------------------------------------------------------------------- 1 | # This file includes a small subset of OpenLayers code, designed to be 2 | # integrated into another application. It includes only the Layer types 3 | # neccesary to create tiled or untiled WMS, and does not include any Controls. 4 | # This is the result of what was at the time called "Webmap.js" at the FOSS4G 5 | # Web Mapping BOF. 6 | 7 | [first] 8 | OpenLayers/SingleFile.js 9 | OpenLayers.js 10 | OpenLayers/BaseTypes.js 11 | OpenLayers/BaseTypes/Class.js 12 | OpenLayers/Util.js 13 | 14 | [last] 15 | 16 | [include] 17 | OpenLayers/Map.js 18 | OpenLayers/Layer/WMS.js 19 | 20 | [exclude] 21 | 22 | 23 | -------------------------------------------------------------------------------- /build/matrix.cfg: -------------------------------------------------------------------------------- 1 | # This is the full build with all files: this includes the vector-related files 2 | # like Renderers and Formats. 3 | 4 | [first] 5 | osmatrix.js 6 | event.js 7 | permalink.js 8 | geolocator.js 9 | geocoder.js 10 | map.js 11 | ui.js 12 | control.js 13 | 14 | [last] 15 | 16 | [include] 17 | 18 | [exclude] 19 | lib/d3.v3.min.js 20 | lib/leaflet-0.5.1.js 21 | -------------------------------------------------------------------------------- /build/osmatrix.min.js: -------------------------------------------------------------------------------- 1 | var OSMatrix=(function(w){"use strict";var $=w.jQuery,PROXY_URL="/cgi-bin/proxy.cgi?url=",API_URL="http://lemberg.geog.uni-heidelberg.de:50684/osmatrix/",MODE={timestamp:1,diff:2};function Osmatrix(){} 2 | function get(url,callback){$.getJSON(PROXY_URL+encodeURIComponent(url),null,callback);} 3 | function getCapabilities(callback){get(API_URL+'api',callback);} 4 | function getLegend(mode,layer,callback){get(API_URL+'map/'+layer+'/'+mode+'/legend',callback);} 5 | function getLayerUrl(mode,layer,times){if(MODE[mode]===MODE.timestamp){return API_URL+'map/'+layer+'/timestamp/'+times[0]+'/{z}/{x}/{y}';}else{return API_URL+'map/'+layer+'/diff/{z}/{x}/{y}?start='+times[0]+'&end='+times[1];}} 6 | function getFeatureInfoFromPoint(attribute,latlng,callback){get(API_URL+'api/attributes/'+attribute+'?proj=4326&lat='+latlng.lat+'&lon='+latlng.lng,callback);} 7 | Osmatrix.prototype.getCapabilities=getCapabilities;Osmatrix.prototype.getLegend=getLegend;Osmatrix.prototype.getLayerUrl=getLayerUrl;Osmatrix.prototype.getFeatureInfoFromPoint=getFeatureInfoFromPoint;return new Osmatrix();}(window));var EventEmitter=(function(){"use strict";function eventEmitter(){this.events={};} 8 | function register(ev,callback){if(!this.events[ev]){this.events[ev]=[];} 9 | this.events[ev].push(callback);} 10 | function emit(ev,eventObj){if(this.events[ev]){for(var i=0,len=this.events[ev].length;i button').not('#'+tool+' > button').removeClass('active');$('.tool > .content').not('#'+tool+' > .content').removeClass('active');$('#sidebar').removeClass('active');$('#'+tool).toggleClass('active');$('#'+tool+' > button').toggleClass('active');$('#'+tool+' > .content').toggleClass('active');if($('#'+tool).parent().attr('id')==='sidebar'&&$('#'+tool+' > button').hasClass('active')){$('#sidebar').addClass('active');}} 40 | function handleButtonClick(e){var toolId=$(e.currentTarget).parent().attr('id');if(toolId===TOOLS.geolocate){setLoadingState(true,TOOLS.geolocate);theInterface.emit('ui:geolocationRequest');}else{toggleActiveState(toolId);}} 41 | function hideMessage(){$('#'+TOOLS.message).hide();} 42 | function displayMessage(type,text){$('#'+TOOLS.message).removeClass().addClass(type);$('#'+TOOLS.message+' h3').text(type.charAt(0).toUpperCase()+type.slice(1));$('#'+TOOLS.message+' p').text(text);$('#'+TOOLS.message+' > #actions > button').click(hideMessage);$('#'+TOOLS.message).show();} 43 | function stopGeolocation(text){setLoadingState(false,TOOLS.geolocate);if(text){displayMessage('error',text);}} 44 | function deactivateGeolocation(text){stopGeolocation();$('#'+TOOLS.geolocate).hide();if(text){displayMessage('error',text);}} 45 | function handleFormType(e){var key=e.which||e.keyCode;if(key===13){setLoadingState(true,TOOLS.geocode);theInterface.emit('ui:geocodeRequest',$(e.currentTarget).val());return false;}} 46 | function handleGeocodeLinkClick(e){theInterface.emit('ui:geocodeLinkClick',$(e.currentTarget).attr('href'));if($('#'+TOOLS.geocode+' > button').hasClass('active')){$('#'+TOOLS.geocode+' > button').click();} 47 | return false;} 48 | function updateGeocodeResultList(permaLink,results){var queryParams=permaLink.split('?')[1],linkBase=((permaLink.indexOf('?')!==-1)?permaLink.substring(0,permaLink.indexOf('?')):permaLink.substring(0)).split('#')[0],mapState=((permaLink.indexOf('?')!==-1)?permaLink.substring(0,permaLink.indexOf('?')):permaLink.substring(0)).split('#')[1].split('/');if(results){$('#'+TOOLS.geocode+' ul.resultList').children().remove();if(results.length>0){for(var i=0,len=results.length;i'+address.display_name+'');}}else{$('#'+TOOLS.geocode+' ul.resultList').append('
  • No results matching your query have been found.
  • ');} 49 | $('#'+TOOLS.geocode+' ul.resultList li a').click(handleGeocodeLinkClick);}else{} 50 | setLoadingState(false,TOOLS.geocode);} 51 | function handleLayerModeToogle(e){$(e.currentTarget).siblings().removeClass('btn-success active');$(e.currentTarget).addClass('btn-success active');var timeElements=$('#'+TOOLS.layer+' input[name="timestamp"]');for(var i=0,len=timeElements.length;i2)||mode==='timestamp'){for(var i=0,len=timeElements.length;i'+c.attributes[i].title+'');} 54 | for(var i=0,len=c.timestamps.length;i'+c.timestamps[i].timestamp+'');} 55 | $('#'+TOOLS.layer+' input[name="timestamp"]').change(handleTimeStampChange);} 56 | function setLayerSwitcherToMode(state){if(state){$('#'+TOOLS.layer+' .btn-group button[value="'+state.mode+'"]').click();$('#'+TOOLS.layer+' #characteristics').val(state.layer);var times=$('#'+TOOLS.layer+' input[name="timestamp"]');for(var i=0,len=times.length;i button').hasClass('active')){$('#'+TOOLS.layer+' > button').click();} 61 | return false;} 62 | function setLayerLoadingState(state){setLoadingState(state,TOOLS.layer);} 63 | function updateLegend(l){$('#toolbox > h2').text(l.attribute.title);$('#'+TOOLS.legend+' .content #labels').children().remove();$('#'+TOOLS.legend+' .content h3').text(l.attribute.title);$('#'+TOOLS.legend+' .content p.desc').text(l.attribute.description);for(var i=0,len=l.labels.length;i'+l.labels[i].label+'');}} 64 | function updateFeatureInfo(info,colors){$('#'+TOOLS.featureInfo+' #chart').empty();if(info&&colors){$('#'+TOOLS.featureInfo+' h3').text(info.attribute.title);$('#'+TOOLS.featureInfo+' p').text(info.attribute.description);var chartArea,WIDTH=$('#'+TOOLS.featureInfo+' #chart').width(),HEIGHT=$('#'+TOOLS.featureInfo+' #chart').height(),MARGIN_TOP=10,MARGIN_LEFT=60,MARGIN_BOTTOM=60,min,max,xScale,yScale,xDomain=[],line=d3.svg.line().x(function(d){return xScale(d.timestamp);}).y(function(d){return yScale(d.value);}).interpolate("linear"),stddevArea=d3.svg.area().x(function(d){return xScale(d.timestamp);}).y0(function(d){return yScale(d.lower);}).y1(function(d){return yScale(d.upper);}),averages=[],stddev=[];for(var key in info.stats){min=d3.min([info.stats[key].min,min]);max=d3.max([info.stats[key].max,max]);} 65 | if(info.attribute==='DateOfLatestEdit'||info.attribute==='dateOfEldestEdit'){MARGIN_LEFT+=20;} 66 | else{min=0;} 67 | for(var i=0,len=info.timestamps.length;i .content').hasClass('active')){$('#'+TOOLS.featureInfo+' button').click();}}else{$('#'+TOOLS.featureInfo+' h3').text('');$('#'+TOOLS.featureInfo+' p').text('Click on the map to get information on the temporal evolution of the selected characteristic in the area of interest.');} 72 | setLoadingState(false,TOOLS.featureInfo);} 73 | function setFeatureInfoLoadingState(state){setLoadingState(state,TOOLS.featureInfo);} 74 | function Ui(){$('.tool > button').click(handleButtonClick);$('#'+TOOLS.layer+' .btn-group button').click(handleLayerModeToogle);$('#'+TOOLS.geocode+' input[type="text"]').keypress(handleFormType);$('#'+TOOLS.layer+' form').submit(handleLayerSubmit);hideMessage();} 75 | Ui.prototype=new EventEmitter();Ui.prototype.constructor=Ui;Ui.prototype.updateGeocodeResultList=updateGeocodeResultList;Ui.prototype.initializeLayerSwitcher=initializeLayerSwitcher;Ui.prototype.setLayerSwitcherToMode=setLayerSwitcherToMode;Ui.prototype.stopGeolocation=stopGeolocation;Ui.prototype.deactivateGeolocation=deactivateGeolocation;Ui.prototype.updateLegend=updateLegend;Ui.prototype.updateFeatureInfo=updateFeatureInfo;Ui.prototype.setLayerLoadingState=setLayerLoadingState;Ui.prototype.setFeatureInfoLoadingState=setFeatureInfoLoadingState;theInterface=new Ui();return theInterface;}(window));var Controller=(function(w){'use strict';var $=w.jQuery,ui=w.Ui,perma=w.Permalink,geolocator=w.Geolocator,geocoder=w.Geocoder,osmatrix=w.OSMatrix,Map=w.Map,HIGHLIGHT_COLORS=['#E41A1C','#377EB8','#4DAF4A','#984EA3','#FF7F00','#FFFF33','#A65628'],map;function handleGeolocateSuccess(position){map.moveTo([position.coords.latitude,position.coords.longitude]);ui.stopGeolocation();} 76 | function handleGeolocateError(error){switch(error.code){case error.UNKNOWN_ERROR:ui.stopGeolocation('The location acquisition process failed');break;case error.PERMISSION_DENIED:ui.deactivateGeolocation();break;case error.POSITION_UNAVAILABLE:ui.stopGeolocation('The position of the device could not be determined. One or more of the location providers used in the location acquisition process reported an internal error that caused the process to fail entirely.');break;case error.TIMEOUT:ui.stopGeolocation('The location acquisition timed out');break;}} 77 | function handleGeolocateNoSupport(){ui.deactivateGeolocation('Geolocation API is not supported by your browser.');} 78 | function handleGeocodeResults(results){ui.updateGeocodeResultList(w.document.URL,results);} 79 | function handleGeolocationRequest(){geolocator.locate(handleGeolocateSuccess,handleGeolocateError,handleGeolocateNoSupport);} 80 | function handleGeocodeRequest(address){geocoder.find(address,handleGeocodeResults);} 81 | function handleGeocodeLink(link){var permaLinkState=perma.parse(link);map.moveTo([permaLinkState.lat,permaLinkState.lng]);} 82 | function handleLayerUpdate(layerInfo){osmatrix.getLegend(layerInfo.mode,layerInfo.layer,handleLegend);map.updateMatrixLayer(layerInfo,osmatrix.getLayerUrl(layerInfo.mode,layerInfo.layer,layerInfo.times));ui.updateFeatureInfo();} 83 | function handleMapLoadStart(){ui.setLayerLoadingState(true);} 84 | function handleMapLoadEnd(){ui.setLayerLoadingState(false);} 85 | function handleMapChanged(mapState){perma.update(mapState.mode,mapState.layer,mapState.times,mapState.zoom,mapState.lon,mapState.lat);} 86 | function handleUserMapClick(latlng){ui.setFeatureInfoLoadingState(true);var layer=perma.parse(w.document.URL).layer;osmatrix.getFeatureInfoFromPoint(layer,latlng,handleFeatureInfoResult);} 87 | function handleMatrixCapabilities(capabilities){ui.initializeLayerSwitcher(capabilities);initializeTheMap();} 88 | function handleLegend(results){ui.updateLegend(results);} 89 | function initializeTheMatrix(){osmatrix.getCapabilities(handleMatrixCapabilities);} 90 | function initializeTheMap(){var permaLink=perma.parse(w.document.URL);if(permaLink){map.moveTo([permaLink.lat,permaLink.lng],permaLink.zoom);}else{handleGeolocationRequest();} 91 | ui.setLayerSwitcherToMode(permaLink);} 92 | function handleFeatureInfoResult(result){map.updateFeatureInfoLayer(result,HIGHLIGHT_COLORS);ui.updateFeatureInfo(result,HIGHLIGHT_COLORS);} 93 | function initialize(){map=new Map('map');map.register('layer:loadStart',handleMapLoadStart);map.register('layer:loadEnd',handleMapLoadEnd);map.register('map:changed',handleMapChanged);map.register('user:click',handleUserMapClick);ui.register('ui:geolocationRequest',handleGeolocationRequest);ui.register('ui:geocodeRequest',handleGeocodeRequest);ui.register('ui:geocodeLinkClick',handleGeocodeLink);ui.register('ui:layerUpdate',handleLayerUpdate);initializeTheMatrix();} 94 | function Controller(){} 95 | Controller.prototype.initialize=initialize;return new Controller();}(window));window.onload=Controller.initialize; -------------------------------------------------------------------------------- /build/tools/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains tools used in the packaging or deployment of OpenLayers. 2 | 3 | Javascript minimizing tools: 4 | 5 | * jsmin.c, jsmin.py: 6 | jsmin.py is a direct translation of the jsmin.c code into Python. jsmin.py 7 | will therefore run anyplace Python runs... but at significantly slower speed. 8 | 9 | * shrinksafe.py 10 | shrinksafe.py calls out to a third party javascript shrinking service. This 11 | creates file sizes about 4% smaller (as of commit 501) of the OpenLayers 12 | code. However, this also has the side effect of making you dependant on the 13 | web service -- and since that service sometimes goes dead, it's risky to 14 | depend on it. 15 | -------------------------------------------------------------------------------- /build/tools/exampleparser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import os 5 | import re 6 | import urllib2 7 | import time 8 | from xml.dom.minidom import Document 9 | 10 | try: 11 | import xml.etree.ElementTree as ElementTree 12 | except ImportError: 13 | try: 14 | import cElementTree as ElementTree 15 | except ImportError: 16 | try: 17 | import elementtree.ElementTree as ElementTree 18 | except ImportError: 19 | import lxml.etree as ElementTree 20 | 21 | missing_deps = False 22 | try: 23 | import simplejson 24 | from BeautifulSoup import BeautifulSoup 25 | except ImportError, E: 26 | missing_deps = E 27 | 28 | feedName = "example-list.xml" 29 | feedPath = "http://openlayers.org/dev/examples/" 30 | 31 | def getListOfOnlineExamples(baseUrl): 32 | """ 33 | useful if you want to get a list of examples a url. not used by default. 34 | """ 35 | html = urllib2.urlopen(baseUrl) 36 | soup = BeautifulSoup(html) 37 | examples = soup.findAll('li') 38 | examples = [example.find('a').get('href') for example in examples] 39 | examples = [example for example in examples if example.endswith('.html')] 40 | examples = [example for example in examples] 41 | return examples 42 | 43 | def getListOfExamples(relPath): 44 | """ 45 | returns list of .html filenames within a given path - excludes example-list.html 46 | """ 47 | examples = os.listdir(relPath) 48 | examples = [example for example in examples if example.endswith('.html') and example != "example-list.html"] 49 | return examples 50 | 51 | 52 | def getExampleHtml(location): 53 | """ 54 | returns html of a specific example that is available online or locally 55 | """ 56 | print '.', 57 | if location.startswith('http'): 58 | return urllib2.urlopen(location).read() 59 | else: 60 | f = open(location) 61 | html = f.read() 62 | f.close() 63 | return html 64 | 65 | 66 | def extractById(soup, tagId, value=None): 67 | """ 68 | returns full contents of a particular tag id 69 | """ 70 | beautifulTag = soup.find(id=tagId) 71 | if beautifulTag: 72 | if beautifulTag.contents: 73 | value = str(beautifulTag.renderContents()).strip() 74 | value = value.replace('\t','') 75 | value = value.replace('\n','') 76 | return value 77 | 78 | def getRelatedClasses(html): 79 | """ 80 | parses the html, and returns a list of all OpenLayers Classes 81 | used within (ie what parts of OL the javascript uses). 82 | """ 83 | rawstr = r'''(?POpenLayers\..*?)\(''' 84 | return re.findall(rawstr, html) 85 | 86 | def parseHtml(html,ids): 87 | """ 88 | returns dictionary of items of interest 89 | """ 90 | soup = BeautifulSoup(html) 91 | d = {} 92 | for tagId in ids: 93 | d[tagId] = extractById(soup,tagId) 94 | #classes should eventually be parsed from docs - not automatically created. 95 | classes = getRelatedClasses(html) 96 | d['classes'] = classes 97 | return d 98 | 99 | def getSvnInfo(path): 100 | h = os.popen("svn info %s --xml" % path) 101 | tree = ElementTree.fromstring(h.read()) 102 | h.close() 103 | d = { 104 | 'url': tree.findtext('entry/url'), 105 | 'author': tree.findtext('entry/commit/author'), 106 | 'date': tree.findtext('entry/commit/date') 107 | } 108 | return d 109 | 110 | def createFeed(examples): 111 | doc = Document() 112 | atomuri = "http://www.w3.org/2005/Atom" 113 | feed = doc.createElementNS(atomuri, "feed") 114 | feed.setAttribute("xmlns", atomuri) 115 | title = doc.createElementNS(atomuri, "title") 116 | title.appendChild(doc.createTextNode("OpenLayers Examples")) 117 | feed.appendChild(title) 118 | link = doc.createElementNS(atomuri, "link") 119 | link.setAttribute("rel", "self") 120 | link.setAttribute("href", feedPath + feedName) 121 | 122 | modtime = time.strftime("%Y-%m-%dT%I:%M:%SZ", time.gmtime()) 123 | id = doc.createElementNS(atomuri, "id") 124 | id.appendChild(doc.createTextNode("%s%s#%s" % (feedPath, feedName, modtime))) 125 | feed.appendChild(id) 126 | 127 | updated = doc.createElementNS(atomuri, "updated") 128 | updated.appendChild(doc.createTextNode(modtime)) 129 | feed.appendChild(updated) 130 | 131 | examples.sort(key=lambda x:x["modified"]) 132 | for example in sorted(examples, key=lambda x:x["modified"], reverse=True): 133 | entry = doc.createElementNS(atomuri, "entry") 134 | 135 | title = doc.createElementNS(atomuri, "title") 136 | title.appendChild(doc.createTextNode(example["title"] or example["example"])) 137 | entry.appendChild(title) 138 | 139 | link = doc.createElementNS(atomuri, "link") 140 | link.setAttribute("href", "%s%s" % (feedPath, example["example"])) 141 | entry.appendChild(link) 142 | 143 | summary = doc.createElementNS(atomuri, "summary") 144 | summary.appendChild(doc.createTextNode(example["shortdesc"] or example["example"])) 145 | entry.appendChild(summary) 146 | 147 | updated = doc.createElementNS(atomuri, "updated") 148 | updated.appendChild(doc.createTextNode(example["modified"])) 149 | entry.appendChild(updated) 150 | 151 | author = doc.createElementNS(atomuri, "author") 152 | name = doc.createElementNS(atomuri, "name") 153 | name.appendChild(doc.createTextNode(example["author"])) 154 | author.appendChild(name) 155 | entry.appendChild(author) 156 | 157 | id = doc.createElementNS(atomuri, "id") 158 | id.appendChild(doc.createTextNode("%s%s#%s" % (feedPath, example["example"], example["modified"]))) 159 | entry.appendChild(id) 160 | 161 | feed.appendChild(entry) 162 | 163 | doc.appendChild(feed) 164 | return doc 165 | 166 | def wordIndex(examples): 167 | """ 168 | Create an inverted index based on words in title and shortdesc. Keys are 169 | lower cased words. Values are dictionaries with example index keys and 170 | count values. 171 | """ 172 | index = {} 173 | unword = re.compile("\\W+") 174 | keys = ["shortdesc", "title"] 175 | for i in range(len(examples)): 176 | for key in keys: 177 | text = examples[i][key] 178 | if text: 179 | words = unword.split(text) 180 | for word in words: 181 | if word: 182 | word = word.lower() 183 | if index.has_key(word): 184 | if index[word].has_key(i): 185 | index[word][i] += 1 186 | else: 187 | index[word][i] = 1 188 | else: 189 | index[word] = {i: 1} 190 | return index 191 | 192 | if __name__ == "__main__": 193 | 194 | if missing_deps: 195 | print "This script requires simplejson and BeautifulSoup. You don't have them. \n(%s)" % E 196 | sys.exit() 197 | 198 | if len(sys.argv) > 1: 199 | outFile = open(sys.argv[1],'w') 200 | else: 201 | outFile = open('../examples/example-list.js','w') 202 | 203 | examplesLocation = '../examples' 204 | print 'Reading examples from %s and writing out to %s' % (examplesLocation, outFile.name) 205 | 206 | exampleList = [] 207 | docIds = ['title','shortdesc'] 208 | 209 | #comment out option to create docs from online resource 210 | #examplesLocation = 'http://svn.openlayers.org/sandbox/docs/examples/' 211 | #examples = getListOfOnlineExamples(examplesLocation) 212 | 213 | examples = getListOfExamples(examplesLocation) 214 | 215 | modtime = time.strftime("%Y-%m-%dT%I:%M:%SZ", time.gmtime()) 216 | 217 | for example in examples: 218 | url = os.path.join(examplesLocation,example) 219 | html = getExampleHtml(url) 220 | tagvalues = parseHtml(html,docIds) 221 | tagvalues['example'] = example 222 | # add in svn info 223 | d = getSvnInfo(url) 224 | tagvalues["modified"] = d["date"] or modtime 225 | tagvalues["author"] = d["author"] or "anonymous" 226 | tagvalues['link'] = example 227 | 228 | exampleList.append(tagvalues) 229 | 230 | print 231 | 232 | exampleList.sort(key=lambda x:x['example'].lower()) 233 | 234 | index = wordIndex(exampleList) 235 | 236 | json = simplejson.dumps({"examples": exampleList, "index": index}) 237 | #give the json a global variable we can use in our js. This should be replaced or made optional. 238 | json = 'var info=' + json 239 | outFile.write(json) 240 | outFile.close() 241 | 242 | print "writing feed to ../examples/%s " % feedName 243 | atom = open('../examples/%s' % feedName, 'w') 244 | doc = createFeed(exampleList) 245 | atom.write(doc.toxml()) 246 | atom.close() 247 | 248 | 249 | print 'complete' 250 | 251 | 252 | -------------------------------------------------------------------------------- /build/tools/jsmin.c: -------------------------------------------------------------------------------- 1 | /* jsmin.c 2 | 2006-05-04 3 | 4 | Copyright (c) 2002 Douglas Crockford (www.crockford.com) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | The Software shall be used for Good, not Evil. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | static int theA; 31 | static int theB; 32 | static int theLookahead = EOF; 33 | 34 | 35 | /* isAlphanum -- return true if the character is a letter, digit, underscore, 36 | dollar sign, or non-ASCII character. 37 | */ 38 | 39 | static int 40 | isAlphanum(int c) 41 | { 42 | return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || 43 | (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' || 44 | c > 126); 45 | } 46 | 47 | 48 | /* get -- return the next character from stdin. Watch out for lookahead. If 49 | the character is a control character, translate it to a space or 50 | linefeed. 51 | */ 52 | 53 | static int 54 | get() 55 | { 56 | int c = theLookahead; 57 | theLookahead = EOF; 58 | if (c == EOF) { 59 | c = getc(stdin); 60 | } 61 | if (c >= ' ' || c == '\n' || c == EOF) { 62 | return c; 63 | } 64 | if (c == '\r') { 65 | return '\n'; 66 | } 67 | return ' '; 68 | } 69 | 70 | 71 | /* peek -- get the next character without getting it. 72 | */ 73 | 74 | static int 75 | peek() 76 | { 77 | theLookahead = get(); 78 | return theLookahead; 79 | } 80 | 81 | 82 | /* next -- get the next character, excluding comments. peek() is used to see 83 | if a '/' is followed by a '/' or '*'. 84 | */ 85 | 86 | static int 87 | next() 88 | { 89 | int c = get(); 90 | if (c == '/') { 91 | switch (peek()) { 92 | case '/': 93 | for (;;) { 94 | c = get(); 95 | if (c <= '\n') { 96 | return c; 97 | } 98 | } 99 | case '*': 100 | get(); 101 | for (;;) { 102 | switch (get()) { 103 | case '*': 104 | if (peek() == '/') { 105 | get(); 106 | return ' '; 107 | } 108 | break; 109 | case EOF: 110 | fprintf(stderr, "Error: JSMIN Unterminated comment.\n"); 111 | exit(1); 112 | } 113 | } 114 | default: 115 | return c; 116 | } 117 | } 118 | return c; 119 | } 120 | 121 | 122 | /* action -- do something! What you do is determined by the argument: 123 | 1 Output A. Copy B to A. Get the next B. 124 | 2 Copy B to A. Get the next B. (Delete A). 125 | 3 Get the next B. (Delete B). 126 | action treats a string as a single character. Wow! 127 | action recognizes a regular expression if it is preceded by ( or , or =. 128 | */ 129 | 130 | static void 131 | action(int d) 132 | { 133 | switch (d) { 134 | case 1: 135 | putc(theA, stdout); 136 | case 2: 137 | theA = theB; 138 | if (theA == '\'' || theA == '"') { 139 | for (;;) { 140 | putc(theA, stdout); 141 | theA = get(); 142 | if (theA == theB) { 143 | break; 144 | } 145 | if (theA <= '\n') { 146 | fprintf(stderr, 147 | "Error: JSMIN unterminated string literal: %c\n", theA); 148 | exit(1); 149 | } 150 | if (theA == '\\') { 151 | putc(theA, stdout); 152 | theA = get(); 153 | } 154 | } 155 | } 156 | case 3: 157 | theB = next(); 158 | if (theB == '/' && (theA == '(' || theA == ',' || theA == '=' || 159 | theA == ':' || theA == '[' || theA == '!' || theA == '&' || 160 | theA == '|')) { 161 | putc(theA, stdout); 162 | putc(theB, stdout); 163 | for (;;) { 164 | theA = get(); 165 | if (theA == '/') { 166 | break; 167 | } else if (theA =='\\') { 168 | putc(theA, stdout); 169 | theA = get(); 170 | } else if (theA <= '\n') { 171 | fprintf(stderr, 172 | "Error: JSMIN unterminated Regular Expression literal.\n", theA); 173 | exit(1); 174 | } 175 | putc(theA, stdout); 176 | } 177 | theB = next(); 178 | } 179 | } 180 | } 181 | 182 | 183 | /* jsmin -- Copy the input to the output, deleting the characters which are 184 | insignificant to JavaScript. Comments will be removed. Tabs will be 185 | replaced with spaces. Carriage returns will be replaced with linefeeds. 186 | Most spaces and linefeeds will be removed. 187 | */ 188 | 189 | static void 190 | jsmin() 191 | { 192 | theA = '\n'; 193 | action(3); 194 | while (theA != EOF) { 195 | switch (theA) { 196 | case ' ': 197 | if (isAlphanum(theB)) { 198 | action(1); 199 | } else { 200 | action(2); 201 | } 202 | break; 203 | case '\n': 204 | switch (theB) { 205 | case '{': 206 | case '[': 207 | case '(': 208 | case '+': 209 | case '-': 210 | action(1); 211 | break; 212 | case ' ': 213 | action(3); 214 | break; 215 | default: 216 | if (isAlphanum(theB)) { 217 | action(1); 218 | } else { 219 | action(2); 220 | } 221 | } 222 | break; 223 | default: 224 | switch (theB) { 225 | case ' ': 226 | if (isAlphanum(theA)) { 227 | action(1); 228 | break; 229 | } 230 | action(3); 231 | break; 232 | case '\n': 233 | switch (theA) { 234 | case '}': 235 | case ']': 236 | case ')': 237 | case '+': 238 | case '-': 239 | case '"': 240 | case '\'': 241 | action(1); 242 | break; 243 | default: 244 | if (isAlphanum(theA)) { 245 | action(1); 246 | } else { 247 | action(3); 248 | } 249 | } 250 | break; 251 | default: 252 | action(1); 253 | break; 254 | } 255 | } 256 | } 257 | } 258 | 259 | 260 | /* main -- Output any command line arguments as comments 261 | and then minify the input. 262 | */ 263 | extern int 264 | main(int argc, char* argv[]) 265 | { 266 | int i; 267 | for (i = 1; i < argc; i += 1) { 268 | fprintf(stdout, "// %s\n", argv[i]); 269 | } 270 | jsmin(); 271 | return 0; 272 | } 273 | -------------------------------------------------------------------------------- /build/tools/jsmin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # This code is original from jsmin by Douglas Crockford, it was translated to 4 | # Python by Baruch Even. The original code had the following copyright and 5 | # license. 6 | # 7 | # /* jsmin.c 8 | # 2007-01-08 9 | # 10 | # Copyright (c) 2002 Douglas Crockford (www.crockford.com) 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 13 | # this software and associated documentation files (the "Software"), to deal in 14 | # the Software without restriction, including without limitation the rights to 15 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16 | # of the Software, and to permit persons to whom the Software is furnished to do 17 | # so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in all 20 | # copies or substantial portions of the Software. 21 | # 22 | # The Software shall be used for Good, not Evil. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # */ 32 | 33 | from StringIO import StringIO 34 | 35 | def jsmin(js): 36 | ins = StringIO(js) 37 | outs = StringIO() 38 | JavascriptMinify().minify(ins, outs) 39 | str = outs.getvalue() 40 | if len(str) > 0 and str[0] == '\n': 41 | str = str[1:] 42 | return str 43 | 44 | def isAlphanum(c): 45 | """return true if the character is a letter, digit, underscore, 46 | dollar sign, or non-ASCII character. 47 | """ 48 | return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or 49 | (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126)); 50 | 51 | class UnterminatedComment(Exception): 52 | pass 53 | 54 | class UnterminatedStringLiteral(Exception): 55 | pass 56 | 57 | class UnterminatedRegularExpression(Exception): 58 | pass 59 | 60 | class JavascriptMinify(object): 61 | 62 | def _outA(self): 63 | self.outstream.write(self.theA) 64 | def _outB(self): 65 | self.outstream.write(self.theB) 66 | 67 | def _get(self): 68 | """return the next character from stdin. Watch out for lookahead. If 69 | the character is a control character, translate it to a space or 70 | linefeed. 71 | """ 72 | c = self.theLookahead 73 | self.theLookahead = None 74 | if c == None: 75 | c = self.instream.read(1) 76 | if c >= ' ' or c == '\n': 77 | return c 78 | if c == '': # EOF 79 | return '\000' 80 | if c == '\r': 81 | return '\n' 82 | return ' ' 83 | 84 | def _peek(self): 85 | self.theLookahead = self._get() 86 | return self.theLookahead 87 | 88 | def _next(self): 89 | """get the next character, excluding comments. peek() is used to see 90 | if a '/' is followed by a '/' or '*'. 91 | """ 92 | c = self._get() 93 | if c == '/': 94 | p = self._peek() 95 | if p == '/': 96 | c = self._get() 97 | while c > '\n': 98 | c = self._get() 99 | return c 100 | if p == '*': 101 | c = self._get() 102 | while 1: 103 | c = self._get() 104 | if c == '*': 105 | if self._peek() == '/': 106 | self._get() 107 | return ' ' 108 | if c == '\000': 109 | raise UnterminatedComment() 110 | 111 | return c 112 | 113 | def _action(self, action): 114 | """do something! What you do is determined by the argument: 115 | 1 Output A. Copy B to A. Get the next B. 116 | 2 Copy B to A. Get the next B. (Delete A). 117 | 3 Get the next B. (Delete B). 118 | action treats a string as a single character. Wow! 119 | action recognizes a regular expression if it is preceded by ( or , or =. 120 | """ 121 | if action <= 1: 122 | self._outA() 123 | 124 | if action <= 2: 125 | self.theA = self.theB 126 | if self.theA == "'" or self.theA == '"': 127 | while 1: 128 | self._outA() 129 | self.theA = self._get() 130 | if self.theA == self.theB: 131 | break 132 | if self.theA <= '\n': 133 | raise UnterminatedStringLiteral() 134 | if self.theA == '\\': 135 | self._outA() 136 | self.theA = self._get() 137 | 138 | 139 | if action <= 3: 140 | self.theB = self._next() 141 | if self.theB == '/' and (self.theA == '(' or self.theA == ',' or 142 | self.theA == '=' or self.theA == ':' or 143 | self.theA == '[' or self.theA == '?' or 144 | self.theA == '!' or self.theA == '&' or 145 | self.theA == '|'): 146 | self._outA() 147 | self._outB() 148 | while 1: 149 | self.theA = self._get() 150 | if self.theA == '/': 151 | break 152 | elif self.theA == '\\': 153 | self._outA() 154 | self.theA = self._get() 155 | elif self.theA <= '\n': 156 | raise UnterminatedRegularExpression() 157 | self._outA() 158 | self.theB = self._next() 159 | 160 | 161 | def _jsmin(self): 162 | """Copy the input to the output, deleting the characters which are 163 | insignificant to JavaScript. Comments will be removed. Tabs will be 164 | replaced with spaces. Carriage returns will be replaced with linefeeds. 165 | Most spaces and linefeeds will be removed. 166 | """ 167 | self.theA = '\n' 168 | self._action(3) 169 | 170 | while self.theA != '\000': 171 | if self.theA == ' ': 172 | if isAlphanum(self.theB): 173 | self._action(1) 174 | else: 175 | self._action(2) 176 | elif self.theA == '\n': 177 | if self.theB in ['{', '[', '(', '+', '-']: 178 | self._action(1) 179 | elif self.theB == ' ': 180 | self._action(3) 181 | else: 182 | if isAlphanum(self.theB): 183 | self._action(1) 184 | else: 185 | self._action(2) 186 | else: 187 | if self.theB == ' ': 188 | if isAlphanum(self.theA): 189 | self._action(1) 190 | else: 191 | self._action(3) 192 | elif self.theB == '\n': 193 | if self.theA in ['}', ']', ')', '+', '-', '"', '\'']: 194 | self._action(1) 195 | else: 196 | if isAlphanum(self.theA): 197 | self._action(1) 198 | else: 199 | self._action(3) 200 | else: 201 | self._action(1) 202 | 203 | def minify(self, instream, outstream): 204 | self.instream = instream 205 | self.outstream = outstream 206 | self.theA = None 207 | self.thaB = None 208 | self.theLookahead = None 209 | 210 | self._jsmin() 211 | self.instream.close() 212 | 213 | if __name__ == '__main__': 214 | import sys 215 | jsm = JavascriptMinify() 216 | jsm.minify(sys.stdin, sys.stdout) 217 | -------------------------------------------------------------------------------- /build/tools/jsmin.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GIScience/osmatrix-client/39b564a91aa00de467128449977f322515cc5b4f/build/tools/jsmin.pyc -------------------------------------------------------------------------------- /build/tools/mergejs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Merge multiple JavaScript source code files into one. 4 | # 5 | # Usage: 6 | # This script requires source files to have dependencies specified in them. 7 | # 8 | # Dependencies are specified with a comment of the form: 9 | # 10 | # // @requires 11 | # 12 | # e.g. 13 | # 14 | # // @requires Geo/DataSource.js 15 | # 16 | # This script should be executed like so: 17 | # 18 | # mergejs.py [...] 19 | # 20 | # e.g. 21 | # 22 | # mergejs.py openlayers.js Geo/ CrossBrowser/ 23 | # 24 | # This example will cause the script to walk the `Geo` and 25 | # `CrossBrowser` directories--and subdirectories thereof--and import 26 | # all `*.js` files encountered. The dependency declarations will be extracted 27 | # and then the source code from imported files will be output to 28 | # a file named `openlayers.js` in an order which fulfils the dependencies 29 | # specified. 30 | # 31 | # 32 | # Note: This is a very rough initial version of this code. 33 | # 34 | # -- Copyright 2005-2010 OpenLayers contributors / OpenLayers project -- 35 | # 36 | 37 | # TODO: Allow files to be excluded. e.g. `Crossbrowser/DebugMode.js`? 38 | # TODO: Report error when dependency can not be found rather than KeyError. 39 | 40 | import re 41 | import os 42 | import sys 43 | 44 | SUFFIX_JAVASCRIPT = ".js" 45 | 46 | RE_REQUIRE = "@requires:? (.*)\n" # TODO: Ensure in comment? 47 | class SourceFile: 48 | """ 49 | Represents a Javascript source code file. 50 | """ 51 | 52 | def __init__(self, filepath, source): 53 | """ 54 | """ 55 | self.filepath = filepath 56 | self.source = source 57 | 58 | self.requiredBy = [] 59 | 60 | 61 | def _getRequirements(self): 62 | """ 63 | Extracts the dependencies specified in the source code and returns 64 | a list of them. 65 | """ 66 | # TODO: Cache? 67 | return re.findall(RE_REQUIRE, self.source) 68 | 69 | requires = property(fget=_getRequirements, doc="") 70 | 71 | 72 | 73 | def usage(filename): 74 | """ 75 | Displays a usage message. 76 | """ 77 | print "%s [-c ] [...]" % filename 78 | 79 | 80 | class Config: 81 | """ 82 | Represents a parsed configuration file. 83 | 84 | A configuration file should be of the following form: 85 | 86 | [first] 87 | 3rd/prototype.js 88 | core/application.js 89 | core/params.js 90 | # A comment 91 | 92 | [last] 93 | core/api.js # Another comment 94 | 95 | [exclude] 96 | 3rd/logger.js 97 | 98 | All headings are required. 99 | 100 | The files listed in the `first` section will be forced to load 101 | *before* all other files (in the order listed). The files in `last` 102 | section will be forced to load *after* all the other files (in the 103 | order listed). 104 | 105 | The files list in the `exclude` section will not be imported. 106 | 107 | Any text appearing after a # symbol indicates a comment. 108 | 109 | """ 110 | 111 | def __init__(self, filename): 112 | """ 113 | Parses the content of the named file and stores the values. 114 | """ 115 | lines = [re.sub("#.*?$", "", line).strip() # Assumes end-of-line character is present 116 | for line in open(filename) 117 | if line.strip() and not line.strip().startswith("#")] # Skip blank lines and comments 118 | 119 | self.forceFirst = lines[lines.index("[first]") + 1:lines.index("[last]")] 120 | 121 | self.forceLast = lines[lines.index("[last]") + 1:lines.index("[include]")] 122 | self.include = lines[lines.index("[include]") + 1:lines.index("[exclude]")] 123 | self.exclude = lines[lines.index("[exclude]") + 1:] 124 | 125 | def run (sourceDirectory, outputFilename = None, configFile = None): 126 | cfg = None 127 | if configFile: 128 | cfg = Config(configFile) 129 | 130 | allFiles = [] 131 | 132 | ## Find all the Javascript source files 133 | for root, dirs, files in os.walk(sourceDirectory): 134 | for filename in files: 135 | if filename.endswith(SUFFIX_JAVASCRIPT) and not filename.startswith("."): 136 | filepath = os.path.join(root, filename)[len(sourceDirectory)+1:] 137 | filepath = filepath.replace("\\", "/") 138 | if cfg and cfg.include: 139 | if filepath in cfg.include or filepath in cfg.forceFirst: 140 | allFiles.append(filepath) 141 | elif (not cfg) or (filepath not in cfg.exclude): 142 | allFiles.append(filepath) 143 | 144 | ## Header inserted at the start of each file in the output 145 | HEADER = "/* " + "=" * 70 + "\n %s\n" + " " + "=" * 70 + " */\n\n" 146 | 147 | files = {} 148 | 149 | order = [] # List of filepaths to output, in a dependency satisfying order 150 | 151 | ## Import file source code 152 | ## TODO: Do import when we walk the directories above? 153 | for filepath in allFiles: 154 | print "Importing: %s" % filepath 155 | fullpath = os.path.join(sourceDirectory, filepath).strip() 156 | content = open(fullpath, "U").read() # TODO: Ensure end of line @ EOF? 157 | files[filepath] = SourceFile(filepath, content) # TODO: Chop path? 158 | 159 | print 160 | 161 | from toposort import toposort 162 | 163 | complete = False 164 | resolution_pass = 1 165 | 166 | while not complete: 167 | order = [] # List of filepaths to output, in a dependency satisfying order 168 | nodes = [] 169 | routes = [] 170 | ## Resolve the dependencies 171 | print "Resolution pass %s... " % resolution_pass 172 | resolution_pass += 1 173 | 174 | for filepath, info in files.items(): 175 | nodes.append(filepath) 176 | for neededFilePath in info.requires: 177 | routes.append((neededFilePath, filepath)) 178 | 179 | for dependencyLevel in toposort(nodes, routes): 180 | for filepath in dependencyLevel: 181 | order.append(filepath) 182 | if not files.has_key(filepath): 183 | print "Importing: %s" % filepath 184 | fullpath = os.path.join(sourceDirectory, filepath).strip() 185 | content = open(fullpath, "U").read() # TODO: Ensure end of line @ EOF? 186 | files[filepath] = SourceFile(filepath, content) # TODO: Chop path? 187 | 188 | 189 | 190 | # Double check all dependencies have been met 191 | complete = True 192 | try: 193 | for fp in order: 194 | if max([order.index(rfp) for rfp in files[fp].requires] + 195 | [order.index(fp)]) != order.index(fp): 196 | complete = False 197 | except: 198 | complete = False 199 | 200 | print 201 | 202 | 203 | ## Move forced first and last files to the required position 204 | if cfg: 205 | print "Re-ordering files..." 206 | order = cfg.forceFirst + [item 207 | for item in order 208 | if ((item not in cfg.forceFirst) and 209 | (item not in cfg.forceLast))] + cfg.forceLast 210 | 211 | print 212 | ## Output the files in the determined order 213 | result = [] 214 | 215 | for fp in order: 216 | f = files[fp] 217 | print "Exporting: ", f.filepath 218 | result.append(HEADER % f.filepath) 219 | source = f.source 220 | result.append(source) 221 | if not source.endswith("\n"): 222 | result.append("\n") 223 | 224 | print "\nTotal files merged: %d " % len(files) 225 | 226 | if outputFilename: 227 | print "\nGenerating: %s" % (outputFilename) 228 | open(outputFilename, "w").write("".join(result)) 229 | return "".join(result) 230 | 231 | if __name__ == "__main__": 232 | import getopt 233 | 234 | options, args = getopt.getopt(sys.argv[1:], "-c:") 235 | 236 | try: 237 | outputFilename = args[0] 238 | except IndexError: 239 | usage(sys.argv[0]) 240 | raise SystemExit 241 | else: 242 | sourceDirectory = args[1] 243 | if not sourceDirectory: 244 | usage(sys.argv[0]) 245 | raise SystemExit 246 | 247 | configFile = None 248 | if options and options[0][0] == "-c": 249 | configFile = options[0][1] 250 | print "Parsing configuration file: %s" % filename 251 | 252 | run( sourceDirectory, outputFilename, configFile ) 253 | -------------------------------------------------------------------------------- /build/tools/mergejs.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GIScience/osmatrix-client/39b564a91aa00de467128449977f322515cc5b4f/build/tools/mergejs.pyc -------------------------------------------------------------------------------- /build/tools/minimize.py: -------------------------------------------------------------------------------- 1 | # Minimal Python Minimizer 2 | # Copyright 2008, Christopher Schmidt 3 | # Released under the MIT License 4 | # 5 | # Taken from: http://svn.crschmidt.net/personal/python/minimize.py 6 | # $Id: minimize.py 6 2008-01-03 06:33:35Z crschmidt $ 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in 16 | # all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | # THE SOFTWARE. 25 | 26 | import re 27 | 28 | def strip_comments_helper(data): 29 | """remove all /* */ format comments and surrounding whitespace.""" 30 | p = re.compile(r'[\s]*/\*.*?\*/[\s]*', re.DOTALL) 31 | return p.sub('',data) 32 | 33 | def minimize(data, exclude=None): 34 | """Central function call. This will call all other compression 35 | functions. To add further compression algorithms, simply add 36 | functions whose names end in _helper which take a string as input 37 | and return a more compressed string as output.""" 38 | for key, item in globals().iteritems(): 39 | if key.endswith("_helper"): 40 | func_key = key[:-7] 41 | if not exclude or not func_key in exclude: 42 | data = item(data) 43 | return data 44 | 45 | if __name__ == "__main__": 46 | import sys 47 | print minimize(open(sys.argv[1]).read()) 48 | -------------------------------------------------------------------------------- /build/tools/oldot.py: -------------------------------------------------------------------------------- 1 | import re 2 | import os 3 | def run(): 4 | sourceDirectory = "../lib/OpenLayers" 5 | allFiles = [] 6 | SUFFIX_JAVASCRIPT = ".js" 7 | ## Find all the Javascript source files 8 | for root, dirs, files in os.walk(sourceDirectory): 9 | for filename in files: 10 | if filename.endswith(SUFFIX_JAVASCRIPT) and not filename.startswith("."): 11 | filepath = os.path.join(root, filename)[len(sourceDirectory)+1:] 12 | filepath = filepath.replace("\\", "/") 13 | data = open(os.path.join(sourceDirectory, filepath)).read() 14 | parents = re.search("OpenLayers.Class\((.*?){", data, 15 | re.DOTALL) 16 | if parents: 17 | parents = [x.strip() for x in parents.group(1).strip().strip(",").split(",")] 18 | else: 19 | parents = [] 20 | cls = "OpenLayers.%s" % filepath.strip(".js").replace("/", ".") 21 | allFiles.append([cls, parents]) 22 | return allFiles 23 | print """ 24 | digraph name { 25 | fontname = "Helvetica" 26 | fontsize = 8 27 | K = 0.6 28 | 29 | node [ 30 | fontname = "Helvetica" 31 | fontsize = 8 32 | shape = "plaintext" 33 | ] 34 | """ 35 | 36 | for i in run(): 37 | print i[0].replace(".", "_") 38 | for item in i[1]: 39 | if not item: continue 40 | print "%s -> %s" % (i[0].replace(".","_"), item.replace(".", "_")) 41 | print "; " 42 | 43 | print """}""" 44 | -------------------------------------------------------------------------------- /build/tools/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | VERSION=$1 4 | 5 | svn export http://svn.openlayers.org/tags/openlayers/release-$VERSION OpenLayers-$VERSION 6 | cd OpenLayers-$VERSION/build 7 | ./build.py full 8 | cp OpenLayers.js .. 9 | 10 | cd .. 11 | 12 | mkdir doc/devdocs 13 | mkdir doc/apidocs 14 | rm tools/*.pyc 15 | 16 | mkdir /www/openlayers/htdocs/api/$VERSION 17 | cp OpenLayers.js /www/openlayers/htdocs/api/$VERSION 18 | cp -a img/ /www/openlayers/htdocs/api/$VERSION 19 | cp -a theme/ /www/openlayers/htdocs/api/$VERSION 20 | 21 | cd .. 22 | 23 | ~/nd/NaturalDocs -i OpenLayers-$VERSION/lib -o HTML OpenLayers-$VERSION/doc/devdocs -p OpenLayers-$VERSION/doc_config -s Small OL 24 | ~/nd/NaturalDocs -i OpenLayers-$VERSION/lib -o HTML OpenLayers-$VERSION/doc/apidocs -p OpenLayers-$VERSION/apidoc_config -s Small OL 25 | 26 | tar cvfz OpenLayers-$VERSION.tar.gz OpenLayers-$VERSION/ 27 | zip -9r OpenLayers-$VERSION.zip OpenLayers-$VERSION/ 28 | 29 | cp OpenLayers-$VERSION.* /www/openlayers/htdocs/download 30 | -------------------------------------------------------------------------------- /build/tools/shrinksafe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Script to provide a wrapper around the ShrinkSafe "web service" 4 | # 5 | # 6 | 7 | # 8 | # We use this script for two reasons: 9 | # 10 | # * This avoids having to install and configure Java and the standalone 11 | # ShrinkSafe utility. 12 | # 13 | # * The current ShrinkSafe standalone utility was broken when we last 14 | # used it. 15 | # 16 | 17 | import sys 18 | 19 | import urllib 20 | import urllib2 21 | 22 | URL_SHRINK_SAFE = "http://shrinksafe.dojotoolkit.org/shrinksafe.php" 23 | 24 | # This would normally be dynamically generated: 25 | BOUNDARY_MARKER = "---------------------------72288400411964641492083565382" 26 | 27 | if __name__ == "__main__": 28 | ## Grab the source code 29 | try: 30 | sourceFilename = sys.argv[1] 31 | except: 32 | print "Usage: %s (|-)" % sys.argv[0] 33 | raise SystemExit 34 | 35 | if sourceFilename == "-": 36 | sourceCode = sys.stdin.read() 37 | sourceFilename = "stdin.js" 38 | else: 39 | sourceCode = open(sourceFilename).read() 40 | 41 | ## Create the request replicating posting of the form from the web page 42 | request = urllib2.Request(url=URL_SHRINK_SAFE) 43 | request.add_header("Content-Type", 44 | "multipart/form-data; boundary=%s" % BOUNDARY_MARKER) 45 | request.add_data(""" 46 | --%s 47 | Content-Disposition: form-data; name="shrinkfile[]"; filename="%s" 48 | Content-Type: application/x-javascript 49 | 50 | %s 51 | """ % (BOUNDARY_MARKER, sourceFilename, sourceCode)) 52 | 53 | ## Deliver the result 54 | print urllib2.urlopen(request).read(), 55 | -------------------------------------------------------------------------------- /build/tools/toposort.py: -------------------------------------------------------------------------------- 1 | # 2 | # According to this file 3 | # is licensed under a BSD-style license. We only use the section 4 | # originally by Tim Peters. 5 | # 6 | # TODO: The use of this code needs to be okayed by someone. 7 | # 8 | 9 | class RecursionError( OverflowError, ValueError ): 10 | '''Unable to calculate result because of recursive structure''' 11 | 12 | 13 | def sort(nodes, routes, noRecursion=1): 14 | '''Passed a list of node IDs and a list of source,dest ID routes 15 | attempt to create a list of stages where each sub list 16 | is one stage in a process. 17 | ''' 18 | children, parents = _buildChildrenLists(routes) 19 | # first stage is those nodes 20 | # having no incoming routes... 21 | stage = [] 22 | stages = [stage] 23 | taken = [] 24 | for node in nodes: 25 | if (not parents.get(node)): 26 | stage.append (node) 27 | if nodes and not stage: 28 | # there is no element which does not depend on 29 | # some other element!!! 30 | stage.append( nodes[0]) 31 | taken.extend( stage ) 32 | nodes = filter ( lambda x, l=stage: x not in l, nodes ) 33 | while nodes: 34 | previousStageChildren = [] 35 | nodelen = len(nodes) 36 | # second stage are those nodes 37 | # which are direct children of the first stage 38 | for node in stage: 39 | for child in children.get (node, []): 40 | if child not in previousStageChildren and child not in taken: 41 | previousStageChildren.append(child) 42 | elif child in taken and noRecursion: 43 | raise RecursionError( (child, node) ) 44 | # unless they are children of other direct children... 45 | # TODO, actually do that... 46 | stage = previousStageChildren 47 | removes = [] 48 | for current in stage: 49 | currentParents = parents.get( current, [] ) 50 | for parent in currentParents: 51 | if parent in stage and parent != current: 52 | # might wind up removing current... 53 | if not current in parents.get(parent, []): 54 | # is not mutually dependent... 55 | removes.append( current ) 56 | for remove in removes: 57 | while remove in stage: 58 | stage.remove( remove ) 59 | stages.append( stage) 60 | taken.extend( stage ) 61 | nodes = filter ( lambda x, l=stage: x not in l, nodes ) 62 | if nodelen == len(nodes): 63 | if noRecursion: 64 | raise RecursionError( nodes ) 65 | else: 66 | stages.append( nodes[:] ) 67 | nodes = [] 68 | return stages 69 | 70 | def _buildChildrenLists (routes): 71 | childrenTable = {} 72 | parentTable = {} 73 | for sourceID,destinationID in routes: 74 | currentChildren = childrenTable.get( sourceID, []) 75 | currentParents = parentTable.get( destinationID, []) 76 | if not destinationID in currentChildren: 77 | currentChildren.append ( destinationID) 78 | if not sourceID in currentParents: 79 | currentParents.append ( sourceID) 80 | childrenTable[sourceID] = currentChildren 81 | parentTable[destinationID] = currentParents 82 | return childrenTable, parentTable 83 | 84 | 85 | def toposort (nodes, routes, noRecursion=1): 86 | '''Topological sort from Tim Peters, fairly efficient 87 | in comparison (it seems).''' 88 | #first calculate the recursion depth 89 | 90 | dependencies = {} 91 | inversedependencies = {} 92 | if not nodes: 93 | return [] 94 | if not routes: 95 | return [nodes] 96 | for node in nodes: 97 | dependencies[ node ] = (0, node) 98 | inversedependencies[ node ] = [] 99 | 100 | 101 | for depended, depends in routes: 102 | # is it a null rule 103 | try: 104 | newdependencylevel, object = dependencies.get ( depends, (0, depends)) 105 | except TypeError: 106 | print depends 107 | raise 108 | dependencies[ depends ] = (newdependencylevel + 1, depends) 109 | # "dependency (existence) of depended-on" 110 | newdependencylevel,object = dependencies.get ( depended, (0, depended) ) 111 | dependencies[ depended ] = (newdependencylevel, depended) 112 | # Inverse dependency set up 113 | dependencieslist = inversedependencies.get ( depended, []) 114 | dependencieslist.append (depends) 115 | inversedependencies[depended] = dependencieslist 116 | ### Now we do the actual sorting 117 | # The first task is to create the sortable 118 | # list of dependency-levels 119 | sortinglist = dependencies.values() 120 | sortinglist.sort () 121 | output = [] 122 | while sortinglist: 123 | deletelist = [] 124 | generation = [] 125 | output.append( generation) 126 | while sortinglist and sortinglist[0][0] == 0: 127 | number, object = sortinglist[0] 128 | generation.append ( object ) 129 | deletelist.append( object ) 130 | for inverse in inversedependencies.get(object, () ): 131 | try: 132 | oldcount, inverse = dependencies [ inverse] 133 | if oldcount > 0: 134 | # will be dealt with on later pass 135 | dependencies [ inverse] = (oldcount-1, inverse) 136 | else: 137 | # will be dealt with on this pass, 138 | # so needs not to be in the sorting list next time 139 | deletelist.append( inverse ) 140 | # just in case a loop comes through 141 | inversedependencies[object] = [] 142 | except KeyError: 143 | # dealing with a recursion-breaking run... 144 | pass 145 | del sortinglist [0] 146 | # if no elements could be deleted, then 147 | # there is something which depends upon itself 148 | if not deletelist: 149 | if noRecursion: 150 | raise RecursionError( sortinglist ) 151 | else: 152 | # hack so that something gets deleted... 153 | ## import pdb 154 | ## pdb.set_trace() 155 | dependencies[sortinglist[0][1]] = (0,sortinglist[0][1]) 156 | # delete the items that were dealt with 157 | for item in deletelist: 158 | try: 159 | del dependencies [ item ] 160 | except KeyError: 161 | pass 162 | # need to recreate the sortinglist 163 | sortinglist = dependencies.values() 164 | if not generation: 165 | output.remove( generation ) 166 | sortinglist.sort () 167 | return output 168 | 169 | 170 | 171 | 172 | 173 | if __name__ == "__main__": 174 | 175 | nodes = ['a', 'b', 'c', 'd', 'e', 'f'] 176 | route = [('a', 'b'), ('b', 'c'), ('b', 'd'), ('e','f')] 177 | 178 | for x in toposort( nodes, route): 179 | for a in x: 180 | print a 181 | 182 | raise SystemExit 183 | 184 | 185 | 186 | import pprint, traceback 187 | nodes= [ 0,1,2,3,4,5 ] 188 | testingValues = [ 189 | [ (0,1),(1,2),(2,3),(3,4),(4,5)], 190 | [ (0,1),(0,2),(1,2),(3,4),(4,5)], 191 | [ 192 | (0,1), 193 | (0,2), 194 | (0,2), 195 | (2,4), 196 | (2,5), 197 | (3,2), 198 | (0,3)], 199 | [ 200 | (0,1), # 3-element cycle test, no orphan nodes 201 | (1,2), 202 | (2,0), 203 | (2,4), 204 | (2,5), 205 | (3,2), 206 | (0,3)], 207 | [ 208 | (0,1), 209 | (1,1), 210 | (1,1), 211 | (1,4), 212 | (1,5), 213 | (1,2), 214 | (3,1), 215 | (2,1), 216 | (2,0)], 217 | [ 218 | (0,1), 219 | (1,0), 220 | (0,2), 221 | (0,3), 222 | ], 223 | [ 224 | (0,1), 225 | (1,0), 226 | (0,2), 227 | (3,1), 228 | ], 229 | ] 230 | print 'sort, no recursion allowed' 231 | for index in range(len(testingValues)): 232 | ## print ' %s -- %s'%( index, testingValues[index]) 233 | try: 234 | print ' ', sort( nodes, testingValues[index] ) 235 | except: 236 | print 'exception raised' 237 | print 'toposort, no recursion allowed' 238 | for index in range(len(testingValues)): 239 | ## print ' %s -- %s'%( index, testingValues[index]) 240 | try: 241 | print ' ', toposort( nodes, testingValues[index] ) 242 | except: 243 | print 'exception raised' 244 | print 'sort, recursion allowed' 245 | for index in range(len(testingValues)): 246 | ## print ' %s -- %s'%( index, testingValues[index]) 247 | try: 248 | print ' ', sort( nodes, testingValues[index],0 ) 249 | except: 250 | print 'exception raised' 251 | print 'toposort, recursion allowed' 252 | for index in range(len(testingValues)): 253 | ## print ' %s -- %s'%( index, testingValues[index]) 254 | try: 255 | print ' ', toposort( nodes, testingValues[index],0 ) 256 | except: 257 | print 'exception raised' 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------- /build/tools/toposort.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GIScience/osmatrix-client/39b564a91aa00de467128449977f322515cc5b4f/build/tools/toposort.pyc -------------------------------------------------------------------------------- /build/tools/update_dev_dir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Used to update http://openlayers.org/dev/ 4 | 5 | svn up /osgeo/openlayers/docs/dev; 6 | 7 | # Get current 'Last Changed Rev' 8 | REV=`svn info /osgeo/openlayers/docs/dev/ | grep 'Revision' | awk '{print $2}'` 9 | 10 | # Get the last svn rev 11 | touch /tmp/ol_svn_rev 12 | OLD_REV="o`cat /tmp/ol_svn_rev`" 13 | 14 | # If they're not equal, do some work. 15 | if [ ! o$REV = $OLD_REV ]; then 16 | 17 | cd /osgeo/openlayers/docs/dev/tools/ 18 | python exampleparser.py 19 | cd /osgeo/openlayers/docs/dev/build 20 | ./build.py 21 | 22 | cp OpenLayers.js .. 23 | cd .. 24 | 25 | sed -i -e 's!../lib/OpenLayers.js!../OpenLayers.js!' examples/*.html 26 | naturaldocs -i /osgeo/openlayers/docs/dev/lib -o HTML /osgeo/openlayers/dev/apidocs -p /osgeo/openlayers/docs/dev/apidoc_config -s Default OL >/dev/null 27 | naturaldocs -i /osgeo/openlayers/docs/dev/lib -o HTML /osgeo/openlayers/dev/docs -p /osgeo/openlayers/docs/dev/doc_config -s Default OL >/dev/null 28 | 29 | svn up /osgeo/openlayers/dev/sandbox/ 30 | # Record the revision 31 | echo -n $REV > /tmp/ol_svn_rev 32 | fi 33 | 34 | svn up /osgeo/openlayers/documentation-checkout 35 | REV=`svn info /osgeo/openlayers/documentation-checkout | grep 'Last Changed Rev' | awk '{print $4}'` 36 | # Get the last svn rev 37 | touch /tmp/ol_doc_rev 38 | OLD_REV="o`cat /tmp/ol_doc_rev`" 39 | # If they're not equal, do some work. 40 | if [ ! o$REV = $OLD_REV ]; then 41 | cd /osgeo/openlayers/documentation-checkout 42 | make html > /dev/null 43 | cp -r _build/html/* /osgeo/openlayers/documentation 44 | 45 | echo -n $REV > /tmp/ol_doc_rev 46 | fi 47 | -------------------------------------------------------------------------------- /img/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GIScience/osmatrix-client/39b564a91aa00de467128449977f322515cc5b4f/img/ajax-loader.gif -------------------------------------------------------------------------------- /img/ajax-loader_head.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GIScience/osmatrix-client/39b564a91aa00de467128449977f322515cc5b4f/img/ajax-loader_head.gif -------------------------------------------------------------------------------- /img/giscience_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GIScience/osmatrix-client/39b564a91aa00de467128449977f322515cc5b4f/img/giscience_logo.png -------------------------------------------------------------------------------- /img/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GIScience/osmatrix-client/39b564a91aa00de467128449977f322515cc5b4f/img/icons.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OSMatrix 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
    42 |

    OSMatrix— visualizing spatio-temporal characteristics of OpenStreetMap

    43 |

    initializing...

    44 |
    45 | 46 |
    47 |
    48 |
    49 | 50 |

    51 | 52 |
    53 |
    54 | 55 |
    56 | 57 |
    58 | 59 |
    60 |
    61 |

    Find place

    62 | 63 |
      64 |
      65 | 66 |
      67 | 68 |
      69 |
      70 | 71 |
      72 |

      Choose Layer

      73 |
      74 |
      75 | Select characteristic 76 | 77 |
      78 | 79 |
      80 | Select display mode 81 |
      82 | 83 | 84 |
      85 | 86 |
      87 | 88 |
      89 | Select timestamps 90 |
      91 | 92 | 93 |
      94 |
      95 | 96 | 97 |
      98 |
      99 | 100 | 101 | 145 | 146 |
      147 |
      148 |

      149 |

      150 |
      151 | 152 |
      153 |
      154 |
      155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /js/control.js: -------------------------------------------------------------------------------- 1 | var Controller = (function (w) { 2 | 'use strict'; 3 | 4 | var $ = w.jQuery, 5 | ui = w.Ui, 6 | perma = w.Permalink, 7 | geolocator = w.Geolocator, 8 | geocoder = w.Geocoder, 9 | osmatrix = w.OSMatrix, 10 | Map = w.Map, 11 | HIGHLIGHT_COLORS = ['#E41A1C', '#377EB8', '#4DAF4A', '#984EA3', '#FF7F00', '#FFFF33', '#A65628'], 12 | map; 13 | 14 | /* ********************************************************************* 15 | * GEOLOCATION 16 | * *********************************************************************/ 17 | 18 | /** 19 | * [handleGeolocateSuccess description] 20 | * @param {[type]} position [description] 21 | * @return {[type]} [description] 22 | */ 23 | function handleGeolocateSuccess(position) { 24 | map.moveTo([position.coords.latitude, position.coords.longitude]); 25 | ui.stopGeolocation(); 26 | } 27 | 28 | /** 29 | * [handleGeolocateError description] 30 | * @param {[type]} error [description] 31 | * @return {[type]} [description] 32 | */ 33 | function handleGeolocateError(error) { 34 | switch (error.code) { 35 | case error.UNKNOWN_ERROR: 36 | ui.stopGeolocation('The location acquisition process failed'); 37 | break; 38 | case error.PERMISSION_DENIED: 39 | ui.deactivateGeolocation(); 40 | break; 41 | case error.POSITION_UNAVAILABLE: 42 | ui.stopGeolocation('The position of the device could not be determined. One or more of the location providers used in the location acquisition process reported an internal error that caused the process to fail entirely.'); 43 | break; 44 | case error.TIMEOUT: 45 | ui.stopGeolocation('The location acquisition timed out'); 46 | break; 47 | } 48 | } 49 | 50 | /** 51 | * [handleGeolocateNoSupport description] 52 | */ 53 | function handleGeolocateNoSupport() { 54 | ui.deactivateGeolocation('Geolocation API is not supported by your browser.'); 55 | } 56 | 57 | /* ********************************************************************* 58 | * GEOCODER 59 | * *********************************************************************/ 60 | 61 | function handleGeocodeResults(results) { 62 | ui.updateGeocodeResultList(w.document.URL, results); 63 | } 64 | 65 | function handleGeolocationRequest() { 66 | geolocator.locate(handleGeolocateSuccess, handleGeolocateError, handleGeolocateNoSupport); 67 | } 68 | 69 | function handleGeocodeRequest(address) { 70 | geocoder.find(address, handleGeocodeResults); 71 | } 72 | 73 | function handleGeocodeLink(link) { 74 | var permaLinkState = perma.parse(link); 75 | map.moveTo([permaLinkState.lat, permaLinkState.lng]); 76 | } 77 | 78 | /* ********************************************************************* 79 | * MAP 80 | * *********************************************************************/ 81 | 82 | function handleLayerUpdate(layerInfo) { 83 | osmatrix.getLegend(layerInfo.mode, layerInfo.layer, handleLegend); 84 | map.updateMatrixLayer(layerInfo, osmatrix.getLayerUrl(layerInfo.mode, layerInfo.layer, layerInfo.times)); 85 | ui.updateFeatureInfo(); 86 | } 87 | 88 | function handleMapLoadStart() { 89 | ui.setLayerLoadingState(true); 90 | } 91 | 92 | function handleMapLoadEnd() { 93 | ui.setLayerLoadingState(false); 94 | } 95 | 96 | function handleMapChanged(mapState) { 97 | perma.update(mapState.mode, mapState.layer, mapState.times, mapState.zoom, mapState.lon, mapState.lat); 98 | } 99 | 100 | function handleUserMapClick(latlng) { 101 | ui.setFeatureInfoLoadingState(true); 102 | var layer = perma.parse(w.document.URL).layer; 103 | osmatrix.getFeatureInfoFromPoint(layer, latlng, handleFeatureInfoResult); 104 | } 105 | 106 | /* ********************************************************************* 107 | * OSMATRIX CONTROLLER 108 | * *********************************************************************/ 109 | 110 | function handleMatrixCapabilities(capabilities) { 111 | ui.initializeLayerSwitcher(capabilities); 112 | initializeTheMap(); 113 | } 114 | 115 | function handleLegend(results) { 116 | ui.updateLegend(results); 117 | } 118 | 119 | function initializeTheMatrix() { 120 | osmatrix.getCapabilities(handleMatrixCapabilities); 121 | } 122 | 123 | /** 124 | * [setInitialMapLocation description] 125 | */ 126 | function initializeTheMap() { 127 | var permaLink = perma.parse(w.document.URL); 128 | if (permaLink) {map.moveTo([permaLink.lat, permaLink.lng], permaLink.zoom); } else {handleGeolocationRequest(); } 129 | 130 | ui.setLayerSwitcherToMode(permaLink); 131 | } 132 | 133 | function handleFeatureInfoResult(result) { 134 | map.updateFeatureInfoLayer(result, HIGHLIGHT_COLORS); 135 | ui.updateFeatureInfo(result, HIGHLIGHT_COLORS); 136 | } 137 | 138 | 139 | /** 140 | * [initialize description] 141 | */ 142 | function initialize() { 143 | map = new Map('map'); 144 | 145 | map.register('layer:loadStart', handleMapLoadStart); 146 | map.register('layer:loadEnd', handleMapLoadEnd); 147 | map.register('map:changed', handleMapChanged); 148 | map.register('user:click', handleUserMapClick); 149 | 150 | ui.register('ui:geolocationRequest', handleGeolocationRequest); 151 | ui.register('ui:geocodeRequest', handleGeocodeRequest); 152 | ui.register('ui:geocodeLinkClick', handleGeocodeLink); 153 | ui.register('ui:layerUpdate', handleLayerUpdate); 154 | 155 | initializeTheMatrix(); 156 | } 157 | 158 | 159 | function Controller() {} 160 | Controller.prototype.initialize = initialize; 161 | return new Controller(); 162 | }(window)); 163 | 164 | window.onload = Controller.initialize; -------------------------------------------------------------------------------- /js/event.js: -------------------------------------------------------------------------------- 1 | var EventEmitter = (function () { 2 | "use strict"; 3 | 4 | /** 5 | * Constructor 6 | */ 7 | function eventEmitter() { 8 | /** 9 | * Registered events and their callbacks 10 | * @type {Object} 11 | */ 12 | this.events = {}; 13 | } 14 | 15 | /** 16 | * Registers a callback function to a given event. 17 | * @param {String} ev The event identifier. 18 | * @param {Function} callback The callback function. 19 | */ 20 | function register(ev, callback) { 21 | if (!this.events[ev]) {this.events[ev] = []; } 22 | this.events[ev].push(callback); 23 | } 24 | 25 | /** 26 | * Emits an event by calling all registered callback functions 27 | * @param {String} ev The event identifier 28 | * @param {Object} eventObj An optional object giving information on the state of the event 29 | */ 30 | function emit(ev, eventObj) { 31 | if (this.events[ev]) { 32 | for (var i = 0, len = this.events[ev].length; i < len; i++) { 33 | this.events[ev][i](eventObj); 34 | } 35 | } 36 | } 37 | 38 | eventEmitter.prototype.register = register; 39 | eventEmitter.prototype.emit = emit; 40 | 41 | return eventEmitter; 42 | })(); -------------------------------------------------------------------------------- /js/geocoder.js: -------------------------------------------------------------------------------- 1 | var Geocoder = (function (window) { 2 | "use strict"; 3 | 4 | var $ = window.jQuery, 5 | NOMINATIM_URL = 'http://nominatim.openstreetmap.org/search?format=json&polygon=0&addressdetails=1&viewbox=5.52,55.26,15.18,47.27&bounded=1'; 6 | 7 | /** 8 | * Constructor 9 | */ 10 | function Geocoder() { 11 | } 12 | 13 | /** 14 | * Sends the request to Nominatim and calls the callback function. 15 | * @param {String} address Address to be geocoded 16 | * @param {Function} callback Callback which is called after the results are returned from Nominatim 17 | */ 18 | function find(address, callback) { 19 | $.getJSON( 20 | //'/cgi-bin/proxy.cgi?url=' + encodeURIComponent(NOMINATIM_URL + '&q=' + address.replace(/\s+/g, '+')), 21 | NOMINATIM_URL+ '&q=' + address.replace(/\s+/g, '+'), 22 | null, 23 | callback 24 | ); 25 | } 26 | 27 | Geocoder.prototype.find = find; 28 | 29 | return new Geocoder(); 30 | }(window)); -------------------------------------------------------------------------------- /js/geolocator.js: -------------------------------------------------------------------------------- 1 | var Geolocator = (function (w) { 2 | "use strict"; 3 | 4 | /** 5 | * Constructor 6 | */ 7 | function Geolocator() { 8 | 9 | } 10 | 11 | function locate(locationSuccess, locationError, locationNotSupported) { 12 | if (w.navigator.geolocation) {w.navigator.geolocation.getCurrentPosition(locationSuccess, locationError); } else {locationNotSupported(); } 13 | } 14 | 15 | Geolocator.prototype.locate = locate; 16 | 17 | return new Geolocator(); 18 | }(window)); -------------------------------------------------------------------------------- /js/lib/leaflet-0.5.1.css: -------------------------------------------------------------------------------- 1 | /* required styles */ 2 | 3 | .leaflet-map-pane, 4 | .leaflet-tile, 5 | .leaflet-marker-icon, 6 | .leaflet-marker-shadow, 7 | .leaflet-tile-pane, 8 | .leaflet-overlay-pane, 9 | .leaflet-shadow-pane, 10 | .leaflet-marker-pane, 11 | .leaflet-popup-pane, 12 | .leaflet-overlay-pane svg, 13 | .leaflet-zoom-box, 14 | .leaflet-image-layer, 15 | .leaflet-layer { 16 | position: absolute; 17 | left: 0; 18 | top: 0; 19 | } 20 | .leaflet-container { 21 | overflow: hidden; 22 | -ms-touch-action: none; 23 | } 24 | .leaflet-tile, 25 | .leaflet-marker-icon, 26 | .leaflet-marker-shadow { 27 | -webkit-user-select: none; 28 | -moz-user-select: none; 29 | user-select: none; 30 | } 31 | .leaflet-marker-icon, 32 | .leaflet-marker-shadow { 33 | display: block; 34 | } 35 | /* map is broken in FF if you have max-width: 100% on tiles */ 36 | .leaflet-container img { 37 | max-width: none !important; 38 | } 39 | /* stupid Android 2 doesn't understand "max-width: none" properly */ 40 | .leaflet-container img.leaflet-image-layer { 41 | max-width: 15000px !important; 42 | } 43 | .leaflet-tile { 44 | filter: inherit; 45 | visibility: hidden; 46 | } 47 | .leaflet-tile-loaded { 48 | visibility: inherit; 49 | } 50 | .leaflet-zoom-box { 51 | width: 0; 52 | height: 0; 53 | } 54 | 55 | .leaflet-tile-pane { z-index: 2; } 56 | .leaflet-objects-pane { z-index: 3; } 57 | .leaflet-overlay-pane { z-index: 4; } 58 | .leaflet-shadow-pane { z-index: 5; } 59 | .leaflet-marker-pane { z-index: 6; } 60 | .leaflet-popup-pane { z-index: 7; } 61 | 62 | 63 | /* control positioning */ 64 | 65 | .leaflet-control { 66 | position: relative; 67 | z-index: 7; 68 | pointer-events: auto; 69 | } 70 | .leaflet-top, 71 | .leaflet-bottom { 72 | position: absolute; 73 | z-index: 1000; 74 | pointer-events: none; 75 | } 76 | .leaflet-top { 77 | top: 0; 78 | } 79 | .leaflet-right { 80 | right: 0; 81 | } 82 | .leaflet-bottom { 83 | bottom: 0; 84 | } 85 | .leaflet-left { 86 | left: 0; 87 | } 88 | .leaflet-control { 89 | float: left; 90 | clear: both; 91 | } 92 | .leaflet-right .leaflet-control { 93 | float: right; 94 | } 95 | .leaflet-top .leaflet-control { 96 | margin-top: 10px; 97 | } 98 | .leaflet-bottom .leaflet-control { 99 | margin-bottom: 10px; 100 | } 101 | .leaflet-left .leaflet-control { 102 | margin-left: 10px; 103 | } 104 | .leaflet-right .leaflet-control { 105 | margin-right: 10px; 106 | } 107 | 108 | 109 | /* zoom and fade animations */ 110 | 111 | .leaflet-fade-anim .leaflet-tile, 112 | .leaflet-fade-anim .leaflet-popup { 113 | opacity: 0; 114 | -webkit-transition: opacity 0.2s linear; 115 | -moz-transition: opacity 0.2s linear; 116 | -o-transition: opacity 0.2s linear; 117 | transition: opacity 0.2s linear; 118 | } 119 | .leaflet-fade-anim .leaflet-tile-loaded, 120 | .leaflet-fade-anim .leaflet-map-pane .leaflet-popup { 121 | opacity: 1; 122 | } 123 | 124 | .leaflet-zoom-anim .leaflet-zoom-animated { 125 | -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); 126 | -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); 127 | -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); 128 | transition: transform 0.25s cubic-bezier(0,0,0.25,1); 129 | } 130 | .leaflet-zoom-anim .leaflet-tile, 131 | .leaflet-pan-anim .leaflet-tile, 132 | .leaflet-touching .leaflet-zoom-animated { 133 | -webkit-transition: none; 134 | -moz-transition: none; 135 | -o-transition: none; 136 | transition: none; 137 | } 138 | 139 | .leaflet-zoom-anim .leaflet-zoom-hide { 140 | visibility: hidden; 141 | } 142 | 143 | 144 | /* cursors */ 145 | 146 | .leaflet-clickable { 147 | cursor: pointer; 148 | } 149 | .leaflet-container { 150 | cursor: -webkit-grab; 151 | cursor: -moz-grab; 152 | } 153 | .leaflet-popup-pane, 154 | .leaflet-control { 155 | cursor: auto; 156 | } 157 | .leaflet-dragging, 158 | .leaflet-dragging .leaflet-clickable, 159 | .leaflet-dragging .leaflet-container { 160 | cursor: move; 161 | cursor: -webkit-grabbing; 162 | cursor: -moz-grabbing; 163 | } 164 | 165 | 166 | /* visual tweaks */ 167 | 168 | .leaflet-container { 169 | background: #ddd; 170 | outline: 0; 171 | } 172 | .leaflet-container a { 173 | color: #0078A8; 174 | } 175 | .leaflet-container a.leaflet-active { 176 | outline: 2px solid orange; 177 | } 178 | .leaflet-zoom-box { 179 | border: 2px dotted #05f; 180 | background: white; 181 | opacity: 0.5; 182 | } 183 | 184 | 185 | /* general typography */ 186 | .leaflet-container { 187 | font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; 188 | } 189 | 190 | 191 | /* general toolbar styles */ 192 | 193 | .leaflet-bar { 194 | box-shadow: 0 0 8px rgba(0,0,0,0.4); 195 | border: 1px solid #888; 196 | -webkit-border-radius: 5px; 197 | border-radius: 5px; 198 | } 199 | .leaflet-bar-part { 200 | background-color: rgba(255, 255, 255, 0.8); 201 | border-bottom: 1px solid #aaa; 202 | } 203 | .leaflet-bar-part-top { 204 | -webkit-border-radius: 4px 4px 0 0; 205 | border-radius: 4px 4px 0 0; 206 | } 207 | .leaflet-bar-part-bottom { 208 | -webkit-border-radius: 0 0 4px 4px; 209 | border-radius: 0 0 4px 4px; 210 | border-bottom: none; 211 | } 212 | 213 | .leaflet-touch .leaflet-bar { 214 | -webkit-border-radius: 10px; 215 | border-radius: 10px; 216 | } 217 | .leaflet-touch .leaflet-bar-part { 218 | border-bottom: 4px solid rgba(0,0,0,0.3); 219 | } 220 | .leaflet-touch .leaflet-bar-part-top { 221 | -webkit-border-radius: 7px 7px 0 0; 222 | border-radius: 7px 7px 0 0; 223 | } 224 | .leaflet-touch .leaflet-bar-part-bottom { 225 | -webkit-border-radius: 0 0 7px 7px; 226 | border-radius: 0 0 7px 7px; 227 | border-bottom: none; 228 | } 229 | 230 | 231 | /* zoom control */ 232 | 233 | .leaflet-container .leaflet-control-zoom { 234 | margin-left: 13px; 235 | margin-top: 12px; 236 | } 237 | .leaflet-control-zoom a { 238 | width: 22px; 239 | height: 22px; 240 | text-align: center; 241 | text-decoration: none; 242 | color: black; 243 | } 244 | .leaflet-control-zoom a, 245 | .leaflet-control-layers-toggle { 246 | background-position: 50% 50%; 247 | background-repeat: no-repeat; 248 | display: block; 249 | } 250 | .leaflet-control-zoom a:hover { 251 | background-color: #fff; 252 | color: #777; 253 | } 254 | .leaflet-control-zoom-in { 255 | font: bold 18px/24px Arial, Helvetica, sans-serif; 256 | } 257 | .leaflet-control-zoom-out { 258 | font: bold 23px/20px Tahoma, Verdana, sans-serif; 259 | } 260 | .leaflet-control-zoom a.leaflet-control-zoom-disabled { 261 | cursor: default; 262 | background-color: rgba(255, 255, 255, 0.8); 263 | color: #bbb; 264 | } 265 | 266 | .leaflet-touch .leaflet-control-zoom a { 267 | width: 30px; 268 | height: 30px; 269 | } 270 | .leaflet-touch .leaflet-control-zoom-in { 271 | font-size: 24px; 272 | line-height: 29px; 273 | } 274 | .leaflet-touch .leaflet-control-zoom-out { 275 | font-size: 28px; 276 | line-height: 24px; 277 | } 278 | 279 | /* layers control */ 280 | 281 | .leaflet-control-layers { 282 | box-shadow: 0 1px 7px rgba(0,0,0,0.4); 283 | background: #f8f8f9; 284 | -webkit-border-radius: 8px; 285 | border-radius: 8px; 286 | } 287 | .leaflet-control-layers-toggle { 288 | background-image: url(images/layers.png); 289 | width: 36px; 290 | height: 36px; 291 | } 292 | .leaflet-touch .leaflet-control-layers-toggle { 293 | width: 44px; 294 | height: 44px; 295 | } 296 | .leaflet-control-layers .leaflet-control-layers-list, 297 | .leaflet-control-layers-expanded .leaflet-control-layers-toggle { 298 | display: none; 299 | } 300 | .leaflet-control-layers-expanded .leaflet-control-layers-list { 301 | display: block; 302 | position: relative; 303 | } 304 | .leaflet-control-layers-expanded { 305 | padding: 6px 10px 6px 6px; 306 | color: #333; 307 | background: #fff; 308 | } 309 | .leaflet-control-layers-selector { 310 | margin-top: 2px; 311 | position: relative; 312 | top: 1px; 313 | } 314 | .leaflet-control-layers label { 315 | display: block; 316 | } 317 | .leaflet-control-layers-separator { 318 | height: 0; 319 | border-top: 1px solid #ddd; 320 | margin: 5px -10px 5px -6px; 321 | } 322 | 323 | 324 | /* attribution and scale controls */ 325 | 326 | .leaflet-container .leaflet-control-attribution { 327 | background-color: rgba(255, 255, 255, 0.7); 328 | box-shadow: 0 0 5px #bbb; 329 | margin: 0; 330 | } 331 | .leaflet-control-attribution, 332 | .leaflet-control-scale-line { 333 | padding: 0 5px; 334 | color: #333; 335 | } 336 | .leaflet-container .leaflet-control-attribution, 337 | .leaflet-container .leaflet-control-scale { 338 | font-size: 11px; 339 | } 340 | .leaflet-left .leaflet-control-scale { 341 | margin-left: 5px; 342 | } 343 | .leaflet-bottom .leaflet-control-scale { 344 | margin-bottom: 5px; 345 | } 346 | .leaflet-control-scale-line { 347 | border: 2px solid #777; 348 | border-top: none; 349 | color: black; 350 | line-height: 1.1; 351 | padding: 2px 5px 1px; 352 | font-size: 11px; 353 | text-shadow: 1px 1px 1px #fff; 354 | background-color: rgba(255, 255, 255, 0.5); 355 | box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.2); 356 | white-space: nowrap; 357 | overflow: hidden; 358 | } 359 | .leaflet-control-scale-line:not(:first-child) { 360 | border-top: 2px solid #777; 361 | border-bottom: none; 362 | margin-top: -2px; 363 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); 364 | } 365 | .leaflet-control-scale-line:not(:first-child):not(:last-child) { 366 | border-bottom: 2px solid #777; 367 | } 368 | 369 | .leaflet-touch .leaflet-control-attribution, 370 | .leaflet-touch .leaflet-control-layers, 371 | .leaflet-touch .leaflet-control-zoom { 372 | box-shadow: none; 373 | } 374 | .leaflet-touch .leaflet-control-layers, 375 | .leaflet-touch .leaflet-control-zoom { 376 | border: 4px solid rgba(0,0,0,0.3); 377 | } 378 | 379 | 380 | /* popup */ 381 | 382 | .leaflet-popup { 383 | position: absolute; 384 | text-align: center; 385 | } 386 | .leaflet-popup-content-wrapper { 387 | padding: 1px; 388 | text-align: left; 389 | -webkit-border-radius: 20px; 390 | border-radius: 20px; 391 | } 392 | .leaflet-popup-content { 393 | margin: 14px 20px; 394 | line-height: 1.4; 395 | } 396 | .leaflet-popup-content p { 397 | margin: 18px 0; 398 | } 399 | .leaflet-popup-tip-container { 400 | margin: 0 auto; 401 | width: 40px; 402 | height: 20px; 403 | position: relative; 404 | overflow: hidden; 405 | } 406 | .leaflet-popup-tip { 407 | width: 15px; 408 | height: 15px; 409 | padding: 1px; 410 | 411 | margin: -8px auto 0; 412 | 413 | -webkit-transform: rotate(45deg); 414 | -moz-transform: rotate(45deg); 415 | -ms-transform: rotate(45deg); 416 | -o-transform: rotate(45deg); 417 | transform: rotate(45deg); 418 | } 419 | .leaflet-popup-content-wrapper, .leaflet-popup-tip { 420 | background: white; 421 | 422 | box-shadow: 0 3px 14px rgba(0,0,0,0.4); 423 | } 424 | .leaflet-container a.leaflet-popup-close-button { 425 | position: absolute; 426 | top: 0; 427 | right: 0; 428 | padding: 4px 5px 0 0; 429 | text-align: center; 430 | width: 18px; 431 | height: 14px; 432 | font: 16px/14px Tahoma, Verdana, sans-serif; 433 | color: #c3c3c3; 434 | text-decoration: none; 435 | font-weight: bold; 436 | background: transparent; 437 | } 438 | .leaflet-container a.leaflet-popup-close-button:hover { 439 | color: #999; 440 | } 441 | .leaflet-popup-scrolled { 442 | overflow: auto; 443 | border-bottom: 1px solid #ddd; 444 | border-top: 1px solid #ddd; 445 | } 446 | 447 | 448 | /* div icon */ 449 | 450 | .leaflet-div-icon { 451 | background: #fff; 452 | border: 1px solid #666; 453 | } 454 | .leaflet-editing-icon { 455 | -webkit-border-radius: 2px; 456 | border-radius: 2px; 457 | } 458 | -------------------------------------------------------------------------------- /js/lib/leaflet-0.5.1.ie.css: -------------------------------------------------------------------------------- 1 | .leaflet-vml-shape { 2 | width: 1px; 3 | height: 1px; 4 | } 5 | .lvml { 6 | behavior: url(#default#VML); 7 | display: inline-block; 8 | position: absolute; 9 | } 10 | 11 | .leaflet-control { 12 | display: inline; 13 | } 14 | 15 | .leaflet-popup-tip { 16 | width: 21px; 17 | _width: 27px; 18 | margin: 0 auto; 19 | _margin-top: -3px; 20 | 21 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); 22 | -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; 23 | } 24 | .leaflet-popup-tip-container { 25 | margin-top: -1px; 26 | } 27 | .leaflet-popup-content-wrapper, .leaflet-popup-tip { 28 | border: 1px solid #999; 29 | } 30 | .leaflet-popup-content-wrapper { 31 | zoom: 1; 32 | } 33 | 34 | .leaflet-control-zoom, 35 | .leaflet-control-layers { 36 | border: 3px solid #999; 37 | } 38 | .leaflet-control-zoom a { 39 | background-color: #eee; 40 | } 41 | .leaflet-control-zoom a:hover { 42 | background-color: #fff; 43 | } 44 | .leaflet-control-layers-toggle { 45 | } 46 | .leaflet-control-attribution, 47 | .leaflet-control-layers, 48 | .leaflet-control-scale-line { 49 | background: white; 50 | } 51 | .leaflet-zoom-box { 52 | filter: alpha(opacity=50); 53 | } 54 | .leaflet-control-attribution { 55 | border-top: 1px solid #bbb; 56 | border-left: 1px solid #bbb; 57 | } 58 | -------------------------------------------------------------------------------- /js/map.js: -------------------------------------------------------------------------------- 1 | var Map = (function () { 2 | "use strict"; 3 | 4 | /** 5 | * Constructor 6 | * @param {[type]} container [description] 7 | */ 8 | function map(container) { 9 | var self = this; 10 | 11 | /** 12 | * [emitMapChangedEvent description] 13 | */ 14 | function emitMapChangedEvent(e) { 15 | self.emit('map:changed', { 16 | zoom: self.theMap.getZoom(), 17 | lat: self.theMap.getCenter().lat, 18 | lon: self.theMap.getCenter().lng 19 | }); 20 | } 21 | 22 | /** 23 | * [emitLayerLoadEvent description] 24 | */ 25 | function emitLayerLoadStartEvent() { 26 | self.emit('layer:loadStart'); 27 | } 28 | 29 | /** 30 | * [emitLayerLoadEndEvent description] 31 | */ 32 | function emitLayerLoadEndEvent() { 33 | self.emit('layer:loadEnd'); 34 | } 35 | 36 | /** 37 | * [handleLayerAddEvent description] 38 | */ 39 | function handleLayerAddEvent(e) { 40 | e.layer.on('loading', emitLayerLoadStartEvent); 41 | e.layer.on('load', emitLayerLoadEndEvent); 42 | } 43 | 44 | function emitUserClickEvent(e) { 45 | self.emit('user:click', e.latlng); 46 | } 47 | 48 | this.theMap = L.map(container, { 49 | center: [49.505, 8.09], 50 | zoom: 9, 51 | // minZoom: 3, 52 | // maxZoom: 18, 53 | maxBounds: new L.LatLngBounds(new L.LatLng(34.66682, -10.53538), new L.LatLng(61.07390, 38.00957)), 54 | zoomControl: false 55 | }); 56 | 57 | var tiledLayer = new L.StamenTileLayer("toner-lite"); 58 | this.theMap.addLayer(tiledLayer); 59 | 60 | this.theMap.on('zoomend', emitMapChangedEvent); 61 | this.theMap.on('moveend', emitMapChangedEvent); 62 | this.theMap.on('layeradd', handleLayerAddEvent); 63 | this.theMap.on('click', emitUserClickEvent); 64 | } 65 | 66 | /** 67 | * [moveTo description] 68 | * @param {[type]} lonlat [description] 69 | * @param {[type]} zoom [description] 70 | */ 71 | function moveTo(lonlat, zoom) { 72 | if (lonlat) {this.theMap.panTo(lonlat); } 73 | if (zoom) {this.theMap.setZoom(zoom); } 74 | } 75 | 76 | function updateMatrixLayer(mode, layerUrl) { 77 | this.updateFeatureInfoLayer(); 78 | if (this.matrixLayer) {this.theMap.removeLayer(this.matrixLayer); } 79 | this.matrixLayer = L.tileLayer(layerUrl, { 80 | maxZoom: 18 81 | }); 82 | this.theMap.addLayer(this.matrixLayer); 83 | 84 | this.emit('map:changed', { 85 | mode: mode.mode, 86 | layer: mode.layer, 87 | times: mode.times, 88 | zoom: this.theMap.getZoom(), 89 | lat: this.theMap.getCenter().lat, 90 | lon: this.theMap.getCenter().lng 91 | }); 92 | } 93 | 94 | function updateFeatureInfoLayer(features, colors) { 95 | if (this.featureInfoLayer) {this.theMap.removeLayer(this.featureInfoLayer); } 96 | 97 | if (features && colors) { 98 | this.featureInfoLayer = L.geoJson(null, { 99 | style: function (feature) { 100 | return { 101 | fillColor: feature.properties.color, 102 | fillOpacity: 0.7, 103 | color: 'white', 104 | opacity: 1, 105 | weight: 2 106 | }; 107 | } 108 | }); 109 | this.theMap.addLayer(this.featureInfoLayer); 110 | 111 | for (var i = 0, len = features.result.length; i < len; i++) { 112 | var color = colors[i]; 113 | this.featureInfoLayer.addData({"type": "Feature", "properties": {"color": color}, "geometry": features.result[i].geometry}); 114 | } 115 | } 116 | } 117 | 118 | map.prototype = new EventEmitter(); 119 | map.prototype.constructor = map; 120 | map.prototype.moveTo = moveTo; 121 | map.prototype.updateMatrixLayer = updateMatrixLayer; 122 | map.prototype.updateFeatureInfoLayer = updateFeatureInfoLayer; 123 | 124 | return map; 125 | }()); -------------------------------------------------------------------------------- /js/osmatrix.js: -------------------------------------------------------------------------------- 1 | var OSMatrix = (function (w) { 2 | "use strict"; 3 | 4 | var $ = w.jQuery, 5 | // PROXY_URL = "/cgi-bin/proxy.cgi?url=", 6 | PROXY_URL = "", 7 | // !!! PLEASE SET YOUR SERVER URL BELOW !!! 8 | API_URL = "http://localhost:50684/osmatrix/", 9 | MODE = { 10 | timestamp: 1, 11 | diff: 2 12 | }; 13 | 14 | function Osmatrix() { 15 | 16 | } 17 | 18 | function get(url, callback) { 19 | $.getJSON( 20 | // PROXY_URL + encodeURIComponent(url), 21 | url, 22 | 23 | null, 24 | callback 25 | ); 26 | } 27 | 28 | function getCapabilities(callback) { 29 | get(API_URL + 'api', callback); 30 | } 31 | 32 | function getLegend(mode, layer, callback) { 33 | get(API_URL + 'map/' + layer + '/' + mode + '/legend', callback); 34 | } 35 | 36 | function getLayerUrl(mode, layer, times) { 37 | if (MODE[mode] === MODE.timestamp) { 38 | return API_URL + 'map/' + layer + '/timestamp/' + times[0] + '/{z}/{x}/{y}'; 39 | } else { 40 | return API_URL + 'map/' + layer + '/diff/{z}/{x}/{y}?start=' + times[0] + '&end=' + times[1]; 41 | } 42 | } 43 | 44 | function getFeatureInfoFromPoint(attribute, latlng, callback) { 45 | get(API_URL + 'api/attributes/' + attribute + '?proj=4326&lat=' + latlng.lat + '&lon=' + latlng.lng, callback); 46 | } 47 | 48 | Osmatrix.prototype.getCapabilities = getCapabilities; 49 | Osmatrix.prototype.getLegend = getLegend; 50 | Osmatrix.prototype.getLayerUrl = getLayerUrl; 51 | Osmatrix.prototype.getFeatureInfoFromPoint = getFeatureInfoFromPoint; 52 | 53 | return new Osmatrix(); 54 | }(window)); -------------------------------------------------------------------------------- /js/permalink.js: -------------------------------------------------------------------------------- 1 | var Permalink = (function (w) { 2 | 'use strict'; 3 | 4 | var state, 5 | history = w.history; 6 | 7 | /** 8 | * Constructor 9 | */ 10 | function Permalink() { 11 | 12 | } 13 | 14 | /** 15 | * [update description] 16 | * @param {[type]} zoom [description] 17 | * @param {[type]} lon [description] 18 | * @param {[type]} lat [description] 19 | */ 20 | function update(mode, layer, times, zoom, lon, lat) { 21 | if (!state) {state = {}; } 22 | if (mode) {state.mode = mode; } 23 | if (layer) {state.layer = layer; } 24 | if (times) {state.times = times; } 25 | if (zoom) {state.zoom = zoom; } 26 | if (lon) {state.lon = lon; } 27 | if (lat) {state.lat = lat; } 28 | 29 | var url = "#" + state.mode + "/" + state.layer + "/" + ((state.times.length === 1) ? state.times[0] + "/" : "") + state.zoom + "/" + state.lon + "/" + state.lat + ((state.times.length === 2) ? "?start=" + state.times[0] + "&end=" + state.times[1] : ""); 30 | 31 | if (history.pushState) {history.pushState(state, null, url); } else {w.location = url; return false; } 32 | } 33 | 34 | /** 35 | * [parse description] 36 | * @param {[type]} url [description] 37 | * @return {[type]} [description] 38 | */ 39 | function parse(url) { 40 | if (url.indexOf('#') !== -1) { 41 | var urlState = url.split('#')[1].split('/'); 42 | 43 | state = {}; 44 | 45 | state.mode = urlState[0]; 46 | state.layer = urlState[1]; 47 | state.times = []; 48 | if (urlState[0] === 'timestamp') { 49 | state.times.push(urlState[2]); 50 | state.zoom = urlState[3]; 51 | state.lng = urlState[4]; 52 | state.lat = urlState[5]; 53 | } else { 54 | var times = urlState[4].split('?')[1].split('&'); 55 | 56 | state.zoom = urlState[2]; 57 | state.lng = urlState[3]; 58 | state.lat = urlState[4].split('?')[0]; 59 | 60 | for (var i = 0, len = times.length; i < len; i++) { 61 | state.times.push(times[i].split('=')[1]); 62 | } 63 | } 64 | } 65 | return state; 66 | } 67 | 68 | Permalink.prototype.update = update; 69 | Permalink.prototype.parse = parse; 70 | 71 | return new Permalink(); 72 | })(window); -------------------------------------------------------------------------------- /js/ui.js: -------------------------------------------------------------------------------- 1 | var Ui = (function (w) { 2 | 'use strict'; 3 | 4 | var $ = w.jQuery, 5 | d3 = w.d3, 6 | TOOLS = {geolocate: 'geolocate', layer: 'layer', geocode: 'searchPlace', legend: 'legend', featureInfo: 'featureInfo', message: 'message' }, 7 | theInterface; 8 | 9 | 10 | 11 | 12 | /* ********************************************************************* 13 | * GENERAL 14 | * *********************************************************************/ 15 | 16 | /** 17 | * [setLoadingState description] 18 | * @param {[type]} state [description] 19 | * @param {[type]} tool [description] 20 | */ 21 | function setLoadingState(state, tool) { 22 | if (state) { 23 | $('#' + tool).addClass('loading'); 24 | $('#' + tool + ' button').addClass('loading'); 25 | $('#' + tool + ' .spinner').addClass('loading'); 26 | } else { 27 | $('#' + tool).removeClass('loading'); 28 | $('#' + tool + ' button').removeClass('loading'); 29 | $('#' + tool + ' .spinner').removeClass('loading'); 30 | } 31 | } 32 | 33 | /** 34 | * [toggleActiveState description] 35 | * @param {[type]} tool [description] 36 | */ 37 | function toggleActiveState(tool) { 38 | $('.tool').not('#' + tool).removeClass('active'); 39 | $('.tool > button').not('#' + tool + ' > button').removeClass('active'); 40 | $('.tool > .content').not('#' + tool + ' > .content').removeClass('active'); 41 | $('#sidebar').removeClass('active'); 42 | 43 | 44 | console.log($('#' + tool)); 45 | $('#' + tool).toggleClass('active'); 46 | $('#' + tool + ' > button').toggleClass('active'); 47 | $('#' + tool + ' > .content').toggleClass('active'); 48 | 49 | if ($('#' + tool).parent().attr('id') === 'sidebar' && $('#' + tool + ' > button').hasClass('active')) { 50 | $('#sidebar').addClass('active'); 51 | } 52 | } 53 | 54 | /** 55 | * [handleButtonClick description] 56 | * @return {[type]} [description] 57 | */ 58 | function handleButtonClick(e) { 59 | var toolId = $(e.currentTarget).parent().attr('id'); 60 | if (toolId === TOOLS.geolocate) { 61 | setLoadingState(true, TOOLS.geolocate); 62 | theInterface.emit('ui:geolocationRequest'); 63 | } else { 64 | toggleActiveState(toolId); 65 | } 66 | } 67 | 68 | 69 | /* ********************************************************************* 70 | * MESSAGE 71 | * *********************************************************************/ 72 | 73 | function hideMessage() { 74 | $('#' + TOOLS.message).hide(); 75 | } 76 | 77 | function displayMessage(type, text) { 78 | $('#' + TOOLS.message).removeClass().addClass(type); 79 | $('#' + TOOLS.message + ' h3').text(type.charAt(0).toUpperCase() + type.slice(1)); 80 | $('#' + TOOLS.message + ' p').text(text); 81 | $('#' + TOOLS.message + ' #actions > button').click(hideMessage); 82 | $('#' + TOOLS.message).show(); 83 | } 84 | 85 | 86 | 87 | 88 | /* ********************************************************************* 89 | * GEOLOCATION 90 | * *********************************************************************/ 91 | 92 | function stopGeolocation(text) { 93 | setLoadingState(false, TOOLS.geolocate); 94 | if (text) {displayMessage('error', text); } 95 | } 96 | 97 | function deactivateGeolocation(text) { 98 | stopGeolocation(); 99 | $('#' + TOOLS.geolocate).hide(); 100 | if (text) {displayMessage('error', text); } 101 | } 102 | 103 | 104 | 105 | /* ********************************************************************* 106 | * GEOCODER 107 | * *********************************************************************/ 108 | 109 | /** 110 | * [handleFormType description] 111 | */ 112 | function handleFormType(e) { 113 | var key = e.which || e.keyCode; 114 | 115 | if (key === 13) { 116 | setLoadingState(true, TOOLS.geocode); 117 | theInterface.emit('ui:geocodeRequest', $(e.currentTarget).val()); 118 | return false; 119 | } 120 | } 121 | 122 | /** 123 | * [handleGeocodeLinkClick description] 124 | */ 125 | function handleGeocodeLinkClick(e) { 126 | theInterface.emit('ui:geocodeLinkClick', $(e.currentTarget).attr('href')); 127 | if ($('#' + TOOLS.geocode + ' > button').hasClass('active')) {$('#' + TOOLS.geocode + ' > button').click(); } 128 | return false; 129 | } 130 | 131 | /** 132 | * [handleGeocodeResults description] 133 | * @param {[type]} results [description] 134 | */ 135 | function updateGeocodeResultList(permaLink, results) { 136 | var queryParams = '?' + permaLink.split('?')[1] || '', 137 | linkBase = ((permaLink.indexOf('?') !== -1) ? permaLink.substring(0, permaLink.indexOf('?')) : permaLink.substring(0)).split('#')[0], 138 | mapState = ((permaLink.indexOf('?') !== -1) ? permaLink.substring(0, permaLink.indexOf('?')) : permaLink.substring(0)).split('#')[1].split('/'); 139 | 140 | if (results) { 141 | $('#' + TOOLS.geocode + ' ul.resultList').children().remove(); 142 | 143 | if (results.length > 0) { 144 | for (var i = 0, len = results.length; i < len; i++) { 145 | var address = results[i]; 146 | mapState[mapState.length - 1] = parseFloat(address.lat); 147 | mapState[mapState.length - 2] = parseFloat(address.lon); 148 | 149 | var address = results[i]; 150 | var link = linkBase + "#" + mapState.join("/") + queryParams; 151 | 152 | $('#' + TOOLS.geocode + ' ul.resultList').append('
    • ' + address.display_name + '
    • '); 153 | } 154 | } else { 155 | $('#' + TOOLS.geocode + ' ul.resultList').append('
    • No results matching your query have been found.
    • '); 156 | } 157 | 158 | $('#' + TOOLS.geocode + ' ul.resultList li a').click(handleGeocodeLinkClick); 159 | } else { 160 | 161 | } 162 | 163 | setLoadingState(false, TOOLS.geocode); 164 | } 165 | 166 | 167 | 168 | 169 | /* ********************************************************************* 170 | * LAYER 171 | * ********************************************************************* 172 | 173 | /** 174 | * [handleLayerModeToogle description] 175 | * @return {[type]} [description] 176 | */ 177 | function handleLayerModeToogle(e) { 178 | $(e.currentTarget).siblings().removeClass('btn-success active'); 179 | $(e.currentTarget).addClass('btn-success active'); 180 | 181 | var timeElements = $('#' + TOOLS.layer + ' input[name="timestamp"]'); 182 | for (var i = 0, len = timeElements.length; i < len; i++) { 183 | if ((i === 0 && this.value === 'diff') || i === len - 1) { 184 | timeElements[i].checked = true; 185 | } else { 186 | timeElements[i].checked = false; 187 | } 188 | } 189 | } 190 | 191 | /** 192 | * [handleTimeStampChange description] 193 | * @return {[type]} [description] 194 | */ 195 | function handleTimeStampChange() { 196 | var mode = $('#' + TOOLS.layer + ' #layerMode button.active').val(); 197 | var timeElements = $('#' + TOOLS.layer + ' input[name="timestamp"]:checked'); 198 | 199 | if ((mode === 'diff' && timeElements.length > 2) || mode === 'timestamp') { 200 | for (var i = 0, len = timeElements.length; i < len; i++) { 201 | if (timeElements[i].value != this.value) {timeElements[i].checked = false; } 202 | } 203 | } 204 | } 205 | 206 | function initializeLayerSwitcher(c) { 207 | for (var i = 0, len = c.attributes.length; i < len; i++) { 208 | $('#' + TOOLS.layer + ' select#characteristics').append(''); 209 | } 210 | 211 | for (var i = 0, len = c.timestamps.length; i < len; i++) { 212 | $('#' + TOOLS.layer + ' fieldset#timestamps').append(''); 213 | } 214 | 215 | $('#' + TOOLS.layer + ' input[name="timestamp"]').change(handleTimeStampChange); 216 | } 217 | 218 | function setLayerSwitcherToMode(state) { 219 | if (state) { 220 | $('#' + TOOLS.layer + ' .btn-group button[value="' + state.mode + '"]').click(); 221 | $('#' + TOOLS.layer + ' #characteristics').val(state.layer); 222 | 223 | var times = $('#' + TOOLS.layer + ' input[name="timestamp"]'); 224 | for (var i = 0, len = times.length; i < len; i++) { 225 | times[i].checked = (state.times.indexOf(times[i].value) != -1); 226 | } 227 | } 228 | 229 | $('#' + TOOLS.layer + ' form').submit(); 230 | $('header').addClass('hide'); 231 | } 232 | 233 | /** 234 | * [handleLayerChange description] 235 | */ 236 | function handleLayerSubmit() { 237 | var layer = $('#' + TOOLS.layer + ' select#characteristics').val(); 238 | var mode = $('#' + TOOLS.layer + ' #layerMode button.active').val(); 239 | 240 | var times = []; 241 | var timeElements = $('#' + TOOLS.layer + ' input[name="timestamp"]'); 242 | for (var i = 0, len = timeElements.length; i < len; i++) { 243 | if (timeElements[i].checked) {times.push(timeElements[i].value)} 244 | } 245 | 246 | if ((mode === 'diff' && times.length === 2) || mode === 'timestamp') { 247 | theInterface.emit('ui:layerUpdate', { 248 | mode: mode, 249 | layer: layer, 250 | times: times 251 | }); 252 | } else { 253 | displayMessage("warning", "Please select two timestamps for comparison."); 254 | } 255 | 256 | if ($('#' + TOOLS.layer + ' > button').hasClass('active')) {$('#' + TOOLS.layer + ' > button').click(); } 257 | 258 | return false; 259 | } 260 | 261 | 262 | 263 | function setLayerLoadingState (state) { 264 | setLoadingState(state, TOOLS.layer); 265 | } 266 | 267 | 268 | 269 | 270 | /* ********************************************************************* 271 | * LEGEND 272 | * *********************************************************************/ 273 | 274 | function updateLegend(l) { 275 | $('#toolbox > h2').text(l.attribute.title); 276 | $('#' + TOOLS.legend + ' .content #labels').children().remove(); 277 | $('#' + TOOLS.legend + ' .content h3').text(l.attribute.title); 278 | $('#' + TOOLS.legend + ' .content p.desc').text(l.attribute.description); 279 | 280 | for (var i = 0, len = l.labels.length; i < len; i++) { 281 | $('#' + TOOLS.legend + ' .content #labels').append('
      ' + l.labels[i].label + '
      '); 282 | } 283 | } 284 | 285 | 286 | 287 | /* ********************************************************************* 288 | * FEATURE INFO 289 | * *********************************************************************/ 290 | 291 | 292 | function updateFeatureInfo(info, colors) { 293 | $('#' + TOOLS.featureInfo + ' #chart').empty(); 294 | 295 | if (info && colors) { 296 | $('#' + TOOLS.featureInfo + ' h3').text(info.attribute.title); 297 | $('#' + TOOLS.featureInfo + ' p').text(info.attribute.description); 298 | 299 | 300 | // var averages = [], 301 | // stddev = [], 302 | // min, max, xScale, yScale, xDomain = []; 303 | // 304 | // 305 | // // iterating through a dataset or arrays 306 | // for (var key in info.stats) { 307 | // min = d3.min([info.stats[key].min, min]); 308 | // max = d3.max([info.stats[key].max, max]); 309 | // console.log("min: " + min + " max: "+ max); 310 | // } 311 | // 312 | // if (info.attribute === 'DateOfLatestEdit' || info.attribute === 'dateOfEldestEdit') 313 | // { 314 | // MARGIN_LEFT += 20; 315 | // } 316 | // else 317 | // { 318 | // min = 0; 319 | // } 320 | // 321 | // for (var i = 0, len = info.timestamps.length; i < len; i++) { 322 | // xDomain.push(info.timestamps[i].timestamp.substring(0, info.timestamps[i].timestamp.lastIndexOf('-'))); 323 | // } 324 | // for (var key in info.stats) 325 | // { 326 | // averages.push({"timestamp": key, "value": info.stats[key].avg}); 327 | // stddev.push({"timestamp": key, "upper": info.stats[key].avg + info.stats[key].std, "lower": info.stats[key].avg - info.stats[key].std}); 328 | // } 329 | // 330 | // ; 331 | 332 | 333 | function convert(info){ 334 | 335 | var out=[]; 336 | 337 | 338 | for (var i = 0; i < info.timestamps.length;i++){ 339 | 340 | var ts = {}; 341 | 342 | 343 | 344 | 345 | 346 | ts["ts"] = info.timestamps[i].timestamp; 347 | 348 | for (var j = 0; j < info.result.length; j++){ 349 | ts["cell_" + j] = info.result[j].values[ts["ts"]]; 350 | } 351 | 352 | 353 | ts["cell_avg"] = (info.stats[ts["ts"]].avg != null) ? parseFloat(info.stats[ts["ts"]].avg.toFixed(2)) : null; 354 | 355 | ts["cell_std"] = (info.stats[ts["ts"]].std != null) ? parseFloat(info.stats[ts["ts"]].std.toFixed(2)) : null; 356 | 357 | 358 | out.push(ts); 359 | } 360 | 361 | 362 | return out; 363 | 364 | } 365 | 366 | 367 | 368 | var chart = c3.generate({ 369 | bindTo:"#chart", 370 | zoom: { 371 | enabled: true 372 | }, 373 | data: { 374 | 375 | json: convert(info), 376 | keys: { 377 | x: 'ts', // it's possible to specify 'x' when category axis 378 | value: ['cell_avg','cell_0', 'cell_1','cell_2', 'cell_3','cell_4', 'cell_5','cell_6'], 379 | }, 380 | names:{ 381 | 'cell_avg': "average", 382 | 'cell_0': " ", 383 | 'cell_1': " ", 384 | 'cell_2': " ", 385 | 'cell_3': " ", 386 | 'cell_4': " ", 387 | 'cell_5': " ", 388 | 'cell_6': " " 389 | }, 390 | colors: { 391 | 'cell_avg': '#000000', 392 | 'cell_0': colors[0], 393 | 'cell_1': colors[1], 394 | 'cell_2': colors[2], 395 | 'cell_3': colors[3], 396 | 'cell_4': colors[4], 397 | 'cell_5': colors[5], 398 | 'cell_6': colors[6] 399 | 400 | }, 401 | }, 402 | 403 | axis: { 404 | x: { 405 | type: 'timeseries', 406 | tick: { 407 | format: '%Y-%m-%d', 408 | rotate: 90 409 | } 410 | } 411 | }, 412 | tooltip: { 413 | position: function (data, width, height, element) { 414 | return {top: 250, left: 40}; 415 | } 416 | } 417 | }); 418 | 419 | 420 | 421 | // ********************** 422 | // OPEN THE THING, YO! 423 | 424 | if (!$('#' + TOOLS.featureInfo + '> .content').hasClass('active')) {$('#' + TOOLS.featureInfo + ' button').click(); } 425 | } else { 426 | $('#' + TOOLS.featureInfo + ' h3').text(''); 427 | $('#' + TOOLS.featureInfo + ' p').text('Click on the map to get information on the temporal evolution of the selected characteristic in the area of interest.'); 428 | 429 | } 430 | setLoadingState(false, TOOLS.featureInfo); 431 | }; 432 | 433 | function setFeatureInfoLoadingState(state) { 434 | setLoadingState(state, TOOLS.featureInfo); 435 | } 436 | 437 | //::::::::::::::::::::::: 438 | 439 | 440 | /* 441 | 442 | 443 | function updateFeatureInfo(info, colors) { 444 | $('#' + TOOLS.featureInfo + ' #chart').empty(); 445 | 446 | if (info && colors) { 447 | $('#' + TOOLS.featureInfo + ' h3').text(info.attribute.title); 448 | $('#' + TOOLS.featureInfo + ' p').text(info.attribute.description); 449 | 450 | // variable declarations 451 | var chartArea, 452 | tooltip, 453 | WIDTH = $('#' + TOOLS.featureInfo + ' #chart').width(), 454 | HEIGHT = $('#' + TOOLS.featureInfo + ' #chart').height(), 455 | MARGIN_TOP = 10, 456 | MARGIN_LEFT = 60, 457 | MARGIN_BOTTOM = 60, 458 | min, max, xScale, yScale, xDomain = [], 459 | line = d3.svg.line() 460 | .x(function(d) {return xScale(d.timestamp); }) 461 | .y(function(d) {return yScale(d.value); }) 462 | .interpolate("linear"), 463 | stddevArea = d3.svg.area() 464 | .x(function(d) {return xScale(d.timestamp); }) 465 | .y0(function(d) {return yScale(d.lower); }) 466 | .y1(function(d) {return yScale(d.upper); }), 467 | 468 | averages = [], 469 | stddev = []; 470 | 471 | 472 | 473 | //:::::::::::::::......................................... 474 | /* var zoom = d3.behavior.zoom() 475 | .x(xScale) 476 | .y(yScale) 477 | .scaleExtent([1, 10]) 478 | .on("zoom", zoomed); 479 | 480 | //zoommmm 481 | // var zoom = d3.behavior.zoom() 482 | // .x(x) 483 | // .y(y) 484 | // .on("zoom", zoomed); 485 | 486 | // iterating through a dataset or arrays 487 | for (var key in info.stats) { 488 | min = d3.min([info.stats[key].min, min]); 489 | max = d3.max([info.stats[key].max, max]); 490 | console.log("min: " + min + " max: "+ max); 491 | } 492 | 493 | if (info.attribute === 'DateOfLatestEdit' || info.attribute === 'dateOfEldestEdit') 494 | { 495 | MARGIN_LEFT += 20; 496 | } 497 | else 498 | { 499 | min = 0; 500 | } 501 | 502 | for (var i = 0, len = info.timestamps.length; i < len; i++) { 503 | xDomain.push(info.timestamps[i].timestamp.substring(0, info.timestamps[i].timestamp.lastIndexOf('-'))); 504 | } 505 | 506 | 507 | /* var zoom = d3.behavior.zoom() 508 | .x(xScale) 509 | .on("zoom", function() { 510 | if (xScale.domain()[0] < xDomain) { 511 | var x = zoom.translate()[0] - xScale(xDomain) + xScale.range()[0]; 512 | zoom.translate([x, 0]); 513 | } else if (xScale.domain()[1] > xDomain) { 514 | var x = zoom.translate()[0] - xScale(xDomain) + xScale.range()[1]; 515 | zoom.translate([x, 0]); 516 | } 517 | redrawChart(); 518 | // updateViewportFromChart(); 519 | }); 520 | 521 | 522 | // scales, domain and ranges to adjust our visualization to match our data.......... 523 | // D3 ...scales are represented using domain and ranges 524 | 525 | 526 | // variable xScale & yScale 527 | xScale = d3.scale.ordinal() 528 | .domain(xDomain) 529 | .rangePoints([MARGIN_LEFT + 10, WIDTH - 20]); 530 | yScale = d3.scale.linear() 531 | .domain([max, min]) 532 | .range([MARGIN_TOP + 10, (HEIGHT - MARGIN_BOTTOM)]); 533 | 534 | 535 | // chartArea .... generate SVG element... 536 | chartArea = d3.select("div#chart") 537 | .append("svg") 538 | .attr("width", WIDTH) 539 | .attr("height", HEIGHT); 540 | 541 | // .append("g") 542 | 543 | 544 | // svg.append("line") 545 | 546 | 547 | //.append("g") 548 | //.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 549 | //.call(zoom); 550 | 551 | /* var zoom = d3.behavior.zoom() 552 | .on("zoom", draw); 553 | 554 | 555 | chartArea.append("clipPath") 556 | .attr("id", "clip") 557 | .append("rect") 558 | .attr("x", x(0)) 559 | .attr("y", y(1)) 560 | .attr("width", x(1) - x(0)) 561 | .attr("height", y(0) - y(1));*/ 562 | /* .call(zoom) 563 | .append("g") 564 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 565 | 566 | 567 | //..................................................................................... 568 | tooltip = d3.select("div#chart") 569 | .append("div") 570 | .style("position", "absolute") 571 | .style("font-family", "'Open Sans', sans-serif") 572 | .style("font-size", "16px") 573 | .style("z-index", "10") 574 | .style("visibility", "hidden"); 575 | //................................................................................ 576 | //::::::::::::::.................................................................................... 577 | 578 | 579 | 580 | 581 | 582 | 583 | // ********************** 584 | // PLOT STATISTICAL MEASURES 585 | 586 | for (var key in info.stats) { 587 | averages.push({"timestamp": key, "value": info.stats[key].avg}); 588 | stddev.push({"timestamp": key, "upper": info.stats[key].avg + info.stats[key].std, "lower": info.stats[key].avg - info.stats[key].std}); 589 | } 590 | 591 | 592 | // svg path to create standard deviation area 593 | chartArea.append("svg:path") 594 | .datum(stddev) 595 | .attr("fill", '#f0f0f0') 596 | .attr("d", stddevArea); 597 | 598 | // svg path to create averages lines 599 | chartArea.append("svg:path") 600 | .attr("d", line(averages)) 601 | .attr("stroke", '#bbb') 602 | .attr("stroke-width", 2) 603 | .attr("fill", "transparent"); 604 | 605 | 606 | 607 | // ********************** 608 | // PREPARE THE CHART AREA 609 | 610 | // dynamic vertical rule 611 | chartArea.selectAll(".yRule") 612 | .data(yScale.ticks(5)) 613 | .enter().append("line") 614 | .attr("class", "yRule") 615 | .attr("x1", MARGIN_LEFT) 616 | .attr("x2", WIDTH) 617 | .attr("y1", yScale) 618 | .attr("y2", yScale) 619 | .style("stroke", "#ccc"); 620 | 621 | // add axes ... svg line element 622 | chartArea.append("svg:line") 623 | .attr("class", "yBase") 624 | .attr("x1", MARGIN_LEFT) 625 | .attr("x2", WIDTH) 626 | .attr("y1", (HEIGHT - MARGIN_BOTTOM)) 627 | .attr("y2", (HEIGHT - MARGIN_BOTTOM)) 628 | .style("stroke", "#000") 629 | .style("stroke-width", "1") 630 | ; 631 | // .append('g') 632 | // .attr("transform", "translate(" + width + ",0)"); 633 | 634 | // add label by adding text elements to SVG element 635 | chartArea.selectAll(".yLabel") 636 | .data(yScale.ticks(5)) 637 | .enter().append("svg:text") 638 | .attr("class", "yLabel") 639 | .text(function (d) { 640 | if (info.attribute == 'DateOfLatestEdit' || info.attribute == 'dateOfEldestEdit') { 641 | var date = new Date(d); 642 | var m = (date.getMonth()+1) < 10 ? "0" + (date.getMonth()+1) : (date.getMonth()+1); 643 | return date.getFullYear() + "-" + m; 644 | } else { 645 | return d; 646 | } 647 | }) 648 | .attr("x", MARGIN_LEFT - 10) 649 | .attr("y", yScale) 650 | .attr("text-anchor", "end") 651 | .attr("font-size", "14"); 652 | 653 | // add axes ... svg line element 654 | chartArea.selectAll(".xTicks") 655 | .data(xDomain) 656 | .enter().append("svg:line") 657 | .attr("class", "xTicks") 658 | .attr("x1", function(d) {return xScale(d);}) 659 | .attr("x2", function(d) {return xScale(d);}) 660 | .attr("y1", HEIGHT - MARGIN_BOTTOM) 661 | .attr("y2", HEIGHT - MARGIN_BOTTOM + 5) 662 | .style("stroke", "#000") 663 | ; 664 | // .append('g') 665 | //.attr("transform", "translate(0," + height + ")"); 666 | 667 | 668 | 669 | // add label by adding text elements to SVG element 670 | chartArea.selectAll(".xLabel") 671 | .data(xDomain) 672 | .enter().append("svg:text") 673 | .attr("class", "xLabel") 674 | .text(function(d) {return d;}) 675 | .attr("x", function(d) {return xScale(d);}) 676 | .attr("y", HEIGHT - MARGIN_BOTTOM + 10) 677 | .attr("text-anchor", "top") 678 | .attr("style", "writing-mode: tb;") 679 | .attr("font-size", "14"); 680 | 681 | 682 | // ********************** 683 | // PLOT THE GRAPH 684 | 685 | for (var i = 0, len = info.result.length; i < len; i++) { 686 | var item = info.result[i], 687 | value = []; 688 | // console.log(info.result); 689 | for (var key in item.values) { 690 | value.push({"timestamp": key, "value": item.values[key]}); 691 | } 692 | // console.log(value); 693 | 694 | 695 | //data bound to line................................................................................................................... 696 | // d3.select("#start").on("click", function() { 697 | var path = chartArea.append("svg:path") // for unrolling line time animation 698 | .attr("d", line(value)) 699 | .attr("stroke", colors[i]) 700 | .attr("fill", "transparent") 701 | ; 702 | 703 | 704 | 705 | // Variable to Hold Total Length 706 | var totalLength = path.node().getTotalLength(); 707 | 708 | // Set Properties of Dash Array and Dash Offset and initiate Transition 709 | path 710 | .attr("stroke-dasharray", totalLength + " " + totalLength) 711 | .attr("stroke-dashoffset", totalLength) 712 | .transition() // Call Transition Method 713 | .duration(4000) // Set Duration timing (ms) 714 | .ease("linear") // Set Easing option 715 | .attr("stroke-dashoffset", 0); // Set final value of dash-offset for transition........................................................... 716 | 717 | 718 | 719 | 720 | 721 | chartArea.selectAll("path" + item.cell_id).data(value) 722 | .enter().append("svg:circle") 723 | .attr("class", "path" + item.cell_id) 724 | .attr("cx", function(d) {return xScale(d.timestamp.substring(0, d.timestamp.lastIndexOf('-'))); }) 725 | .attr("cy", function(d) {return yScale(d.value); }) 726 | .attr("r", 5) 727 | .attr("fill", "#ffffff") 728 | .attr("stroke", colors[i]) 729 | .attr("stroke-width", 2) 730 | 731 | 732 | // testing event listeners................................................................................... 733 | 734 | .on("mouseover", function(d){ 735 | return tooltip.style("visibility", "visible").text(d.timestamp + ": " + d.value); 736 | }) 737 | .on("mousemove", function(d){ 738 | return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px").text(d.timpestamp + ": " + d.value); 739 | }) 740 | .on("mouseout", function(d){ 741 | return tooltip.style("visibility", "hidden"); 742 | }); 743 | 744 | 745 | 746 | // var zoom = d3.behavior.zoom() 747 | //.on("zoom", draw); 748 | 749 | /* var xyzoom = d3.behavior.zoom() 750 | .x(xscale) 751 | .y(yscale) 752 | .on("zoom", zoomable ? draw : null); 753 | var xzoom = d3.behavior.zoom() 754 | .x(xscale) 755 | .on("zoom", zoomable ? draw : null); 756 | var yzoom = d3.behavior.zoom() 757 | .y(yscale) 758 | .on("zoom", zoomable ? draw : null); 759 | 760 | function draw() { 761 | // svg.select("g.x.axis").call(xAxis); 762 | // svg.select("g.y.axis").call(yAxis); 763 | // svg.select("path.area").attr("d", stddevArea); 764 | svg.select("path.line").attr("d", line); 765 | } ; 766 | */ 767 | 768 | // }); 769 | /* // Reset Animation 770 | d3.select("#reset").on("click", function() { 771 | d3.select(".line").remove(); 772 | });........................................................................................................................... 773 | } 774 | 775 | */ 776 | 777 | // ********************** 778 | // OPEN THE THING, YO! 779 | 780 | /* if (!$('#' + TOOLS.featureInfo + '> .content').hasClass('active')) {$('#' + TOOLS.featureInfo + ' button').click(); } 781 | } else { 782 | $('#' + TOOLS.featureInfo + ' h3').text(''); 783 | $('#' + TOOLS.featureInfo + ' p').text('Click on the map to get information on the temporal evolution of the selected characteristic in the area of interest.'); 784 | 785 | } 786 | setLoadingState(false, TOOLS.featureInfo); 787 | } 788 | 789 | function setFeatureInfoLoadingState(state) { 790 | setLoadingState(state, TOOLS.featureInfo); 791 | } 792 | */ 793 | /* ********************************************************************* 794 | * CONSTRUCTOR 795 | * *********************************************************************/ 796 | 797 | function Ui() { 798 | $('.tool > button').click(handleButtonClick); 799 | $('#' + TOOLS.layer + ' .btn-group button').click(handleLayerModeToogle); 800 | $('#' + TOOLS.geocode + ' input[type="text"]').keypress(handleFormType); 801 | $('#' + TOOLS.layer + ' form').submit(handleLayerSubmit); 802 | hideMessage(); 803 | } 804 | 805 | 806 | 807 | Ui.prototype = new EventEmitter(); 808 | Ui.prototype.constructor = Ui; 809 | 810 | Ui.prototype.updateGeocodeResultList = updateGeocodeResultList; 811 | Ui.prototype.initializeLayerSwitcher = initializeLayerSwitcher; 812 | Ui.prototype.setLayerSwitcherToMode = setLayerSwitcherToMode; 813 | Ui.prototype.stopGeolocation = stopGeolocation; 814 | Ui.prototype.deactivateGeolocation = deactivateGeolocation; 815 | Ui.prototype.updateLegend = updateLegend; 816 | Ui.prototype.updateFeatureInfo = updateFeatureInfo; 817 | Ui.prototype.setLayerLoadingState = setLayerLoadingState; 818 | Ui.prototype.setFeatureInfoLoadingState = setFeatureInfoLoadingState; 819 | 820 | 821 | theInterface = new Ui(); 822 | 823 | return theInterface; 824 | }(window)); 825 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2013 Oliver Roick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body, form { 2 | font-family: 'Droid Sans','Helvetica Neue', Helvetica, Arial, sans-serif; 3 | font-size: 13px; 4 | line-height: 15px; 5 | color: #2d3841; 6 | } 7 | 8 | div.tool > button { 9 | color: #fff; 10 | border: 0; 11 | margin: 0; 12 | width: 36px; 13 | height: 36px; 14 | /*padding: 10px; 15 | line-height: 15px;*/ 16 | border: 0 solid rgba(0,0,0,0.4); 17 | font-size: 1em; 18 | z-index: 5000; 19 | 20 | background: #2d3841 url(img/icons.png) no-repeat; 21 | 22 | transition: background-color 0.05s ease; 23 | -moz-transition: background-color 0.05s ease; /* Firefox 4 */ 24 | -webkit-transition: background-color 0.05s ease; /* Safari and Chrome */ 25 | -o-transition: background-color 0.05s ease; 26 | } 27 | 28 | div.tool > button:hover { 29 | cursor:pointer; 30 | background-color: #3f4f5a; 31 | } 32 | 33 | div.tool > button.loading, 34 | div.tool > button.active { 35 | background-color: #fff; 36 | color: #2d3841; 37 | margin-left: -1px; 38 | } 39 | 40 | div.tool > div.spinner { 41 | background: #fff url(img/ajax-loader.gif) no-repeat 50% 50%; 42 | z-index: 5000; 43 | border: 0 solid rgba(0,0,0,0.4); 44 | } 45 | 46 | /* @group head */ 47 | 48 | header { 49 | position: absolute; 50 | top: 0; 51 | left: 0; 52 | bottom: 0; 53 | right: 0; 54 | color: #fff; 55 | z-index: 10000; 56 | 57 | background-color: #2d3841; 58 | transition: right 0.5s; 59 | -moz-transition: right 0.5s; /* Firefox 4 */ 60 | -webkit-transition: right 0.5s; /* Safari and Chrome */ 61 | -o-transition: right 0.5s; /* Opera */ 62 | } 63 | 64 | header.hide { 65 | right: 100%; 66 | overflow: hidden; 67 | } 68 | 69 | h1 { 70 | position: absolute; 71 | left: 3em; 72 | bottom: 6em; 73 | 74 | z-index: 10000; 75 | line-height: 1; 76 | 77 | margin: 0; 78 | 79 | font-size: 52px; 80 | font-weight: normal; 81 | } 82 | 83 | header > h1 > span { 84 | display: block; 85 | font-size: 26px; 86 | } 87 | 88 | header > p { 89 | display: block; 90 | font-size: 26px; 91 | 92 | position: absolute; 93 | left: 6em; 94 | bottom: 8em; 95 | padding-left: 60px; 96 | background: url(img/ajax-loader_head.gif) no-repeat 0 50%; 97 | } 98 | 99 | h2 { 100 | font-size: 15px; 101 | font-weight: normal; 102 | margin: 0 0 10px 0; 103 | padding: 4px 0 7px 0; 104 | border-bottom: 1px solid rgba(0,0,0,0.4); 105 | } 106 | 107 | 108 | 109 | h3 { 110 | font-size: 15px; 111 | margin-bottom: 7px; 112 | line-height: 30px; 113 | font-weight: normal; 114 | } 115 | 116 | p { 117 | margin: 0 0 15px 0; 118 | } 119 | 120 | /* @end */ 121 | 122 | /* @group map */ 123 | 124 | section#map { 125 | position: absolute; 126 | top: 0; 127 | right: 0; 128 | bottom: 0; 129 | left: 0; 130 | z-index: 500; 131 | 132 | transition: left 0.5s ease; 133 | -moz-transition: left 0.5s ease; /* Firefox 4 */ 134 | -webkit-transition: left 0.5s ease; /* Safari and Chrome */ 135 | -o-transition: left 0.5s ease; /* Opera */ 136 | 137 | } 138 | 139 | /*section#map.showSidebar { 140 | left: 380px; 141 | }*/ 142 | 143 | /* @end */ 144 | 145 | 146 | /* @group toolbox */ 147 | 148 | div#toolbox { 149 | position: absolute; 150 | top: 0; 151 | right: 1em; 152 | z-index: 1000; 153 | height: 0; 154 | overflow: visible; 155 | } 156 | 157 | div#toolbox > h2 { 158 | position: relative; 159 | float: left; 160 | margin-left: 10px; 161 | border-radius: 0 0 5px 5px; 162 | border: 0; 163 | background-color: rgba(45,56,65,0.75); 164 | color: #fff; 165 | font-weight: normal; 166 | padding: 10px 10px 11px 10px; 167 | } 168 | 169 | 170 | div#toolbox div.tool { 171 | position: relative; 172 | float: left; 173 | margin-left: 10px; 174 | overflow: hidden; 175 | padding: 0 3px 3px 3px; 176 | height: 0; 177 | overflow: visible; 178 | width: 35px; 179 | 180 | transition: width 0.6s ease; 181 | -moz-transition: width 0.6s ease; /* Firefox 4 */ 182 | -webkit-transition: width 0.6s ease; /* Safari and Chrome */ 183 | -o-transition: left 0.6s ease; /* Opera */ 184 | } 185 | 186 | div#toolbox div.tool.loading { 187 | width: 74px; 188 | 189 | transition: width 0.4s ease; 190 | -moz-transition: width 0.4s ease; /* Firefox 4 */ 191 | -webkit-transition: width 0.4s ease; /* Safari and Chrome */ 192 | -o-transition: left 0.4s ease; /* Opera */ 193 | } 194 | 195 | div#toolbox div.tool.active { 196 | width: 369px; 197 | 198 | transition: width 0.4s ease; 199 | -moz-transition: width 0.4s ease; /* Firefox 4 */ 200 | -webkit-transition: width 0.4s ease; /* Safari and Chrome */ 201 | -o-transition: left 0.4s ease; /* Opera */ 202 | } 203 | 204 | div#toolbox div.tool.active.loading { 205 | width: 406px; 206 | 207 | transition: width 0.4s ease; 208 | -moz-transition: width 0.4s ease; /* Firefox 4 */ 209 | -webkit-transition: width 0.4s ease; /* Safari and Chrome */ 210 | -o-transition: left 0.4s ease; /* Opera */ 211 | } 212 | 213 | div#toolbox div.tool > button { 214 | float: left; 215 | border-width: 0 1px 1px 1px; 216 | -webkit-border-radius: 0 0 5px 5px; 217 | border-radius: 0 0 5px 5px; 218 | position: relative; 219 | } 220 | 221 | div#toolbox div#geolocate > button, 222 | div#toolbox div#geolocate > button:hover { 223 | background-position: -106px -35px; 224 | } 225 | 226 | div#toolbox div#geolocate > button.active, 227 | div#toolbox div#geolocate > button.loading { 228 | background-position: -106px 0; 229 | } 230 | 231 | div#toolbox div#searchPlace > button, 232 | div#toolbox div#searchPlace > button:hover { 233 | background-position: -35px -35px; 234 | } 235 | 236 | div#toolbox div#searchPlace > button.active, 237 | div#toolbox div#searchPlace > button.loading { 238 | background-position: -35px 0; 239 | } 240 | 241 | div#toolbox div#layer > button, 242 | div#toolbox div#layer > button:hover { 243 | background-position: 0 -35px; 244 | } 245 | 246 | div#toolbox div#layer > button.active, 247 | div#toolbox div#layer > button.loading { 248 | background-position: 0 0; 249 | } 250 | 251 | div#toolbox div.tool > button.loading, 252 | div#toolbox div.tool > button.active { 253 | border-width: 0 1px 1px 0; 254 | -webkit-border-radius: 0 0 5px 0; 255 | border-radius: 0 0 5px 0; 256 | } 257 | 258 | div#toolbox div.tool div.spinner, 259 | div#toolbox div.tool div.content { 260 | position: relative; 261 | width: 0; 262 | float: left; 263 | overflow: hidden; 264 | margin-right: 0px; 265 | 266 | transition: width 0.5s ease, padding 0.5s ease, height 0.5s ease, border 0.5s ease; 267 | -moz-transition: width 0.5s ease, padding 0.5s ease, height 0.5s ease, border 0.5s ease; /* Firefox 4 */ 268 | -webkit-transition: width 0.5s ease, padding 0.5s ease, height 0.5s ease, border 0.5s ease; /* Safari and Chrome */ 269 | -o-transition: width 0.5s ease, padding 0.5s ease, height 0.5s ease, border 0.5s ease; /* Opera */ 270 | } 271 | 272 | div#toolbox div.tool div.spinner { 273 | width: 0; 274 | height: 35px; 275 | -webkit-border-radius: 0 0 0 5px; 276 | border-radius: 0 0 0 5px; 277 | margin-right: -1px; 278 | } 279 | 280 | div#toolbox div.tool div.spinner.loading { 281 | width: 35px; 282 | border-width: 0 0 1px 1px; 283 | } 284 | 285 | 286 | /** 287 | * ACTIVE 288 | */ 289 | div#toolbox div.tool div.content { 290 | width: 0; 291 | height: 0; 292 | padding: 0; 293 | background-color: #fff; 294 | color: #2d3841; 295 | z-index: 4000; 296 | border: 0 solid rgba(0,0,0,0.4); 297 | } 298 | 299 | div#toolbox div.tool div.content.active { 300 | width: 300px; 301 | height: auto; 302 | max-height: 700px; 303 | padding: 10px 15px; 304 | -webkit-border-radius: 0 0 5px 5px; 305 | border-radius: 0 0 5px 5px; 306 | border-width: 0 1px 1px 1px; 307 | overflow-y: scroll; 308 | } 309 | 310 | /* @group Search Place */ 311 | 312 | div#searchPlace > div.content > input[type="text"] { 313 | width: 288px; 314 | padding: 5px; 315 | font-size: 12px; 316 | color: #2d3841; 317 | } 318 | 319 | div#searchPlace > div.content > ul.resultList { 320 | margin: 0; 321 | padding: 0; 322 | list-style: none; 323 | height: auto; 324 | max-height: 550px; 325 | overflow-y: auto; 326 | } 327 | 328 | div#searchPlace > div.content > ul.resultList li { 329 | 330 | } 331 | 332 | div#searchPlace > div.content > ul.resultList li.noResult, 333 | div#searchPlace > div.content > ul.resultList li a { 334 | display: block; 335 | color: #2d3841; 336 | text-decoration: none; 337 | padding: 7px 5px; 338 | line-height: 1.2; 339 | background-color: #fff; 340 | 341 | -webkit-border-radius: 3px; 342 | border-radius: 3px; 343 | 344 | transition: background-color 0.1s ease; 345 | -moz-transition: background-color 0.1s ease; /* Firefox 4 */ 346 | -webkit-transition: background-color 0.1s ease; /* Safari and Chrome */ 347 | -o-transition: background-color 0.1s ease; /* Opera */ 348 | } 349 | 350 | div#searchPlace > div.content > ul.resultList li a:hover { 351 | background-color: #2d3841; 352 | color: #fff; 353 | } 354 | 355 | /* @end */ 356 | 357 | 358 | /* @group Layer Switcher */ 359 | 360 | #layer fieldset { 361 | margin-bottom: 30px; 362 | } 363 | 364 | #layer fieldset legend { 365 | font-size: 15px; 366 | margin-bottom: 15px; 367 | line-height: 30px; 368 | } 369 | 370 | #layer select { 371 | width: 298px; 372 | font-size: 13px; 373 | } 374 | 375 | #layer fieldset .btn-group button { 376 | margin-right: 0; 377 | width: 150px; 378 | font-size: 13px; 379 | } 380 | 381 | #layer fieldset label { 382 | font-size: 13px; 383 | } 384 | 385 | #layer fieldset label:hover { 386 | cursor: pointer; 387 | } 388 | 389 | #layer #timestamps { 390 | -moz-columns: 3 auto; 391 | -webkit-columns: 3 auto; 392 | columns: 3 auto; 393 | overflow-y: auto; 394 | max-height: 360px; 395 | } 396 | 397 | 398 | /* @end */ 399 | 400 | /* @end */ 401 | 402 | 403 | /* @group Sidebar */ 404 | 405 | #sidebar { 406 | z-index: 750; 407 | position: absolute; 408 | top: 0; 409 | left: 0; 410 | bottom: 0; 411 | width: 480px; 412 | left: -480px; 413 | 414 | border-right: 1px solid rgba(0,0,0,0.4); 415 | background-color: #fff; 416 | 417 | transition: left 0.5s ease, padding 0.5s ease; 418 | -moz-transition: left 0.5s ease, padding 0.5s ease; /* Firefox 4 */ 419 | -webkit-transition: left 0.5s ease, padding 0.5s ease; /* Safari and Chrome */ 420 | -o-transition: left 0.5s ease, padding 0.5s ease; /* Opera */ 421 | } 422 | 423 | #sidebar.active { 424 | left: 0; 425 | } 426 | 427 | div#sidebar p, 428 | div#sidebar ul > li { 429 | line-height: 1.5; 430 | } 431 | 432 | div#sidebar a:link, 433 | div#sidebar a:visited { 434 | color: #ed2d1c; 435 | } 436 | 437 | div#sidebar a:hover, 438 | div#sidebar a:active { 439 | text-decoration: none; 440 | } 441 | 442 | div#sidebar > div#about h3 { 443 | margin-top: 36px; 444 | margin-bottom: 9px; 445 | } 446 | 447 | div#sidebar ul { 448 | padding: 0 0 0 15px; 449 | } 450 | 451 | #sidebar .content { 452 | width: 450px; 453 | padding: 10px 15px; 454 | position: absolute; 455 | top: 0; 456 | left: -480px; 457 | bottom: 0; 458 | overflow: hidden; 459 | 460 | transition: left 0.1s ease; 461 | -moz-transition: left 0.1s ease; /* Firefox 4 */ 462 | -webkit-transition: left 0.1s ease; /* Safari and Chrome */ 463 | -o-transition: left 0.1s ease; /* Opera */ 464 | } 465 | 466 | #sidebar .content.active { 467 | left: 0; 468 | transition: left 0.5s ease; 469 | -moz-transition: left 0.5s ease; /* Firefox 4 */ 470 | -webkit-transition: left 0.5s ease; /* Safari and Chrome */ 471 | -o-transition: left 0.5s ease; /* Opera */ 472 | } 473 | 474 | div#sidebar div.tool > button, 475 | div#sidebar div.tool > div.spinner { 476 | float: left; 477 | -webkit-border-radius: 0 0 5px 5px; 478 | border-radius: 0 5px 5px 0; 479 | position: absolute; 480 | left: 481px; 481 | margin-left: -1px; 482 | 483 | border-width: 1px 1px 1px 0; 484 | 485 | transition: left 0.5s ease, background-color 0.05s ease; 486 | -moz-transition: left 0.5s ease, background-color 0.05s ease; /* Firefox 4 */ 487 | -webkit-transition: left 0.5s ease, background-color 0.05s ease; /* Safari and Chrome */ 488 | -o-transition: left 0.5s ease, background-color 0.05s ease; /* Opera */ 489 | } 490 | 491 | div#sidebar div#about > button, 492 | div#sidebar div#about > button:hover { 493 | bottom: 100px; 494 | background-position: -175px -35px; 495 | } 496 | 497 | div#sidebar div#about > button.active, 498 | div#sidebar div#about > button.loading { 499 | background-position: -175px 0; 500 | } 501 | 502 | div#sidebar div#legend > button, 503 | div#sidebar div#legend > button:hover { 504 | bottom: 50px; 505 | background-position: -70px -35px; 506 | } 507 | 508 | div#sidebar div#legend > button.active, 509 | div#sidebar div#legend > button.loading { 510 | background-position: -70px 0; 511 | } 512 | 513 | div#sidebar div#featureInfo > button, 514 | div#sidebar div#featureInfo > button:hover { 515 | bottom: 150px; 516 | background-position: -140px -35px; 517 | } 518 | 519 | div#sidebar div#featureInfo > button.active, 520 | div#sidebar div#featureInfo > button.loading { 521 | background-position: -140px 0; 522 | } 523 | 524 | div#sidebar div#featureInfo > button.loading { 525 | -webkit-border-radius: 0 0 5px 0; 526 | border-radius: 0 0 5px 0; 527 | border-top-width: 0; 528 | } 529 | 530 | div#sidebar div.tool > div.spinner { 531 | bottom: 185px; 532 | height: 0; 533 | width: 35px; 534 | border-width: 0; 535 | z-index: 5001; 536 | 537 | transition: height 0.5s ease; 538 | -moz-transition: height 0.5s ease; /* Firefox 4 */ 539 | -webkit-transition: height 0.5s ease; /* Safari and Chrome */ 540 | -o-transition: height 0.5s ease; /* Opera */ 541 | } 542 | 543 | div#sidebar.active div.tool > div.spinner { 544 | left: 481px; 545 | } 546 | 547 | div#sidebar div.tool > div.spinner.loading { 548 | height: 35px; 549 | -webkit-border-radius: 0 5px 0 0; 550 | border-radius: 0 5px 0 0; 551 | border-width: 1px 1px 0 0; 552 | } 553 | 554 | div#sidebar > div#about ul.publications { 555 | padding: 0; 556 | } 557 | 558 | div#sidebar > div#about ul.publications li { 559 | text-indent: -30px; 560 | margin-left: 30px; 561 | list-style: none; 562 | } 563 | 564 | /* @group Legend */ 565 | 566 | #labels .legendItem { 567 | padding: 5px 0; 568 | height: 17px; 569 | /*line-height: 17px;*/ 570 | vertical-align: top; 571 | } 572 | 573 | #labels .legendItem span.graphic { 574 | display: inline-block; 575 | width: 15px; 576 | height: 15px; 577 | border: 1px solid #ddd; 578 | margin-right: 15px; 579 | } 580 | 581 | p.desc { 582 | border-bottom: 1px solid #e5e5e5; 583 | padding-bottom: 15px; 584 | } 585 | 586 | /* @end */ 587 | 588 | /* @group Feature Info */ 589 | 590 | div#chart { 591 | height: 240px; 592 | width: 350px; 593 | } 594 | 595 | /* @end */ 596 | 597 | /* @end */ 598 | 599 | /* @group Message */ 600 | 601 | div#message { 602 | position: absolute; 603 | top: 0; 604 | bottom: 0; 605 | left: 0; 606 | right: 0; 607 | z-index: 9999; 608 | background-color: rgba(0,0,0,0.7); 609 | } 610 | 611 | div#message > div#msgContainer { 612 | position: absolute; 613 | top: 50%; 614 | min-height: 250px; 615 | margin-top: -125px; 616 | 617 | left: 50%; 618 | width: 500px; 619 | margin-left: -250px; 620 | 621 | background-color: #fff; 622 | border: 1px solid #e5e5e5; 623 | box-shadow: 0 0 4px rgba(0,0,0,0.4); 624 | } 625 | 626 | div#message > div#msgContainer > h3 { 627 | padding: 0 30px 15px; 628 | border-bottom: 1px solid #e5e5e5; 629 | } 630 | 631 | div#message.error > div#msgContainer > h3 { 632 | color: #ae3825; 633 | } 634 | 635 | div#message.warning > div#msgContainer > h3 { 636 | color: #fba400; 637 | } 638 | 639 | div#message.info > div#msgContainer > h3 { 640 | color: #00ace2; 641 | } 642 | 643 | div#message > div#msgContainer > p { 644 | padding: 0 30px; 645 | line-height: 1.5; 646 | } 647 | 648 | div#message > div#msgContainer > div#actions { 649 | padding: 15px 30px; 650 | position: absolute; 651 | left: 0; 652 | bottom: 0; 653 | right: 0; 654 | border-top: 1px solid #e5e5e5; 655 | text-align: right; 656 | } 657 | 658 | /* @end */ 659 | --------------------------------------------------------------------------------