├── .gitignore ├── README.md ├── assets ├── css │ ├── bootstrap.css │ ├── custom.css │ ├── foundation-datepicker.min.css │ ├── foundation.min.css │ ├── i-con.css │ └── style.css ├── fonts │ ├── georgia.woff │ ├── georgiab.woff │ ├── georgiai.woff │ ├── georgiaz.woff │ └── style.css ├── images │ ├── Givaudan-Globe-Logo.png │ ├── Givaudan-textile-Logo.png │ └── nav.png └── js │ ├── bootstrap-timepicker.js │ ├── bootstrap.min.js │ ├── custom.js │ ├── foundation-datepicker.js │ ├── google-spreadsheet.coffee │ ├── google-spreadsheet.js │ ├── infobox.js │ ├── jquery.min.js │ ├── markercluster.js │ └── popper.min.js ├── favicon.ico ├── index.html ├── index2.html └── places.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | node_modules/ 3 | npm-debug.log 4 | yarn-error.log 5 | 6 | # Laravel 4 specific 7 | bootstrap/compiled.php 8 | app/storage/ 9 | 10 | # Laravel 5 & Lumen specific 11 | public/storage 12 | public/hot 13 | 14 | # Laravel 5 & Lumen specific with changed public path 15 | public_html/storage 16 | public_html/hot 17 | 18 | storage/*.key 19 | .env 20 | Homestead.yaml 21 | Homestead.json 22 | /.vagrant 23 | .phpunit.result.cache 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Map-View 2 | Show map with levels 3 | -------------------------------------------------------------------------------- /assets/css/custom.css: -------------------------------------------------------------------------------- 1 | .sidenav { 2 | height: 95%; 3 | width: 20%; 4 | position: fixed; 5 | z-index: 1; 6 | top: 60px; 7 | left: 500px; 8 | background-color: white; 9 | overflow-x: hidden; 10 | transition: 0.5s; 11 | } 12 | .nav-title { 13 | font-size: 30px; 14 | font-weight: bold; 15 | } 16 | 17 | .chk-filter { 18 | font-size: 20px; 19 | font-weight: bold; 20 | } 21 | 22 | #propertymap .gm-style-iw{ 23 | box-shadow:none; 24 | background: rgb(39, 48, 49)!important; 25 | color:#515151; 26 | font-family: "Georgia", "Open Sans", Sans-serif; 27 | text-align: center; 28 | width: 100% !important; 29 | border-radius: 0; 30 | left: 0 !important; 31 | top: 20px !important; 32 | } 33 | .gm-style .gm-style-iw-t::after { 34 | background: rgb(39,48,49); 35 | box-shadow: -2px 2px 2px 0 rgb(178 178 178 / 40%); 36 | content: ""; 37 | height: 30px; 38 | left: 0; 39 | position: absolute; 40 | top: -20px; 41 | transform: translate(-50%,-50%) rotate(-45deg); 42 | width: 30px; 43 | box-shadow: -9px 8px 7px 0px rgb(196 242 247 / 60%) 44 | } 45 | .gm-style-iw-d { 46 | overflow: hidden !important; 47 | } 48 | .gm-style .gm-style-iw-c { 49 | position: absolute; 50 | box-sizing: border-box; 51 | overflow: hidden; 52 | top: -20px; 53 | left: 0; 54 | /* transform: translate(-50%,-100%); */ 55 | background-color: rgb(39,48,49); 56 | box-shadow: 0px 0px 9px 9px rgb(196 242 247 / 60%); 57 | border-radius: 0px; 58 | padding: 0px; 59 | max-width: 300px !important; 60 | min-width: 300px !important; 61 | max-height: fit-content !important; 62 | margin-left: 50px; 63 | } 64 | 65 | .property_title { 66 | padding-top: 2rem; 67 | padding-left: 1rem; 68 | font-size: 23px; 69 | font-family: auto; 70 | color: rgb(103 222 235); 71 | } 72 | 73 | .property_content { 74 | font-family: auto; 75 | color: white; 76 | font-size: 15px; 77 | padding-top: 1rem; 78 | flex-wrap: wrap; 79 | padding-left: 1rem; 80 | padding-right: 1rem; 81 | } 82 | 83 | .property_activity { 84 | padding-top: 2rem; 85 | padding-left: 1rem; 86 | font-size: 20px; 87 | font-family: auto; 88 | color: rgb(103 222 235); 89 | } 90 | 91 | .property_detail { 92 | font-family: auto; 93 | color: white; 94 | font-size: 15px; 95 | padding-top: 1rem; 96 | flex-wrap: wrap; 97 | padding-left: 1rem; 98 | padding-right: 1rem; 99 | padding-bottom: 2rem; 100 | } 101 | 102 | @media (max-width : 700px) { 103 | .responsive-title { 104 | font-size: 20px; 105 | } 106 | } 107 | @media (min-width : 700px) { 108 | .responsive-title { 109 | font-size: 28px; 110 | } 111 | } 112 | 113 | #logo-image:hover { 114 | cursor: pointer; 115 | } 116 | 117 | .gmnoprint { 118 | display: none; 119 | } 120 | 121 | .gm-ui-hover-effect { 122 | display: none !important; 123 | } -------------------------------------------------------------------------------- /assets/css/foundation-datepicker.min.css: -------------------------------------------------------------------------------- 1 | .datepicker{display:none;position:absolute;padding:4px;margin-top:1px;direction:ltr}.datepicker.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;list-style:none;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;color:#333;font-size:13px;line-height:18px}.datepicker.dropdown-menu td,.datepicker.dropdown-menu th{padding:4px 5px}.datepicker table{border:0;margin:0;width:auto}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;border:0;font-size:12px;padding:4px 8px;cursor:pointer}.datepicker td{background:#fff}.datepicker td span.active,.datepicker td.active.day,.datepicker td.active.year{background:#2ba6cb}.datepicker td.new,.datepicker td.old{color:#999}.datepicker td span.month.disabled,.datepicker td span.year.disabled,.datepicker td.day.disabled{color:#eee}.datepicker th{background:#fff}.datepicker th span.active,.datepicker th.active.day,.datepicker th.active.year{background:#2ba6cb}.datepicker th.date-switch{width:145px}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker.days div.datepicker-days,.datepicker.months div.datepicker-months,.datepicker.years div.datepicker-years{display:block}.datepicker-dropdown:after,.datepicker-dropdown:before{content:'';display:inline-block;position:absolute}.datepicker thead tr:first-child th{cursor:pointer}.datepicker thead tr:first-child th.cw{cursor:default;background-color:transparent}.datepicker tfoot tr:first-child th{cursor:pointer}.datepicker-inline{width:220px}.datepicker-rtl{direction:rtl}.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:1px solid rgba(0,0,0,.2);top:-7px;left:6px}.datepicker-dropdown:after{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;top:-6px;left:7px}.datepicker-dropdown::after,.datepicker-dropdown::before,.datepicker>div{display:none}.datepicker-close{position:absolute;top:-30px;right:0;width:15px;height:30px;padding:0;display:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent} -------------------------------------------------------------------------------- /assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Custom css 3 | */ 4 | 5 | .setting-menu .list-item { 6 | cursor: pointer; 7 | padding: 0.5rem 0.625rem; 8 | } 9 | 10 | .setting-menu .list-item:hover span, 11 | .setting-menu .list-item:hover i { 12 | color: #137eff; 13 | } 14 | 15 | .setting-menu .item a, 16 | .setting-menu .item span { 17 | color: inherit; 18 | } 19 | 20 | .setting-menu .list-item:active { 21 | background: rgba(135, 150, 165, 0.075); 22 | } 23 | 24 | .setting-menu .list-item.active { 25 | background: rgba(135, 150, 165, 0.075); 26 | } 27 | 28 | .setting-menu .list-item:active * { 29 | color: gray; 30 | } 31 | 32 | .setting-menu .list-item * { 33 | color: grey; 34 | } 35 | 36 | .setting-menu .active span { 37 | color: #137eff !important; 38 | } 39 | 40 | tbody { 41 | cursor: pointer; 42 | } 43 | 44 | tbody tr:hover { 45 | background: #ffffff !important; 46 | } 47 | 48 | .bg-success-lt:hover { 49 | background: #e5f5e1 !important; 50 | color: #479f35 !important; 51 | } 52 | 53 | .bg-warning-lt:hover { 54 | background: #fff8e3 !important; 55 | color: #ffc41a !important; 56 | } 57 | 58 | .bg-primary-lt:hover { 59 | color: #0065df !important; 60 | background-color: #d9eaff !important; 61 | } 62 | 63 | .bg-danger-lt:hover { 64 | color: #fe1a35 !important; 65 | background-color: #ffe3e6 !important; 66 | } 67 | 68 | .bg-secondary-lt:hover { 69 | color: #657380 !important; 70 | background-color: #eaedef !important; 71 | } 72 | 73 | .modal .process-bar { 74 | transition: 1s; 75 | } 76 | 77 | #accordion .row:hover { 78 | background: rgba(135, 150, 165, 0.075); 79 | cursor: pointer; 80 | } 81 | 82 | .animation-icon img { 83 | width: 16px; 84 | height: 16px; 85 | } 86 | 87 | .animation-icon img.icon-lg { 88 | width: 30px; 89 | height: 30px; 90 | } 91 | 92 | .animation-icon img.stop { 93 | display: block; 94 | } 95 | 96 | .animation-icon img.play { 97 | display: none; 98 | } 99 | 100 | .animation-icon:hover img.play { 101 | display: block; 102 | } 103 | 104 | .animation-icon:hover img.stop { 105 | display: none; 106 | } 107 | 108 | footer { 109 | width: 100%; 110 | z-index: 1010; 111 | height: 100px; 112 | position: fixed; 113 | bottom: 0; 114 | background: white; 115 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05), 0 -1px 0px rgba(0, 0, 0, 0.015); 116 | padding: 20px 50px 20px 50px; 117 | } 118 | 119 | .alert-container { 120 | display: flex; 121 | justify-content: flex-end; 122 | align-items: center; 123 | } 124 | 125 | .alert { 126 | cursor: pointer; 127 | margin-bottom: 0px; 128 | } 129 | 130 | #accordion .row { 131 | border-bottom: 1px solid rgba(135, 150, 165, 0.075); 132 | } 133 | 134 | #accordion .collapse .row { 135 | background: #fbfbfd; 136 | } 137 | 138 | #accordion .collapse .row:hover { 139 | background: rgba(135, 150, 165, 0.075); 140 | } 141 | 142 | img.icon { 143 | width: 16px; 144 | height: 16px; 145 | margin-right: 5px; 146 | } 147 | 148 | .badge { 149 | font-weight: normal; 150 | } 151 | 152 | #content-aside { 153 | z-index: 1005; 154 | } 155 | 156 | table td { 157 | vertical-align: middle!important; 158 | } 159 | 160 | .scroll-container { 161 | overflow-x: hidden; 162 | overflow-y: scroll; 163 | } 164 | 165 | 166 | /* .scroll-container:hover { 167 | overflow-y: overlay; 168 | } */ 169 | 170 | body.modal-open .setting-menu { 171 | border-radius: 0px!important; 172 | } 173 | 174 | .margin-bottom-80 { 175 | margin-bottom: 80px; 176 | } 177 | 178 | input::-webkit-outer-spin-button, 179 | input::-webkit-inner-spin-button { 180 | -webkit-appearance: none; 181 | margin: 0; 182 | } 183 | 184 | .period-table-td { 185 | border-top: 0.5px solid rgba(135, 150, 165, 0.1) !important; 186 | } 187 | .supplier-dropdwon:hover{ 188 | color:#4D7CFE !important; 189 | } 190 | .import-icon-check{ 191 | width: 16px; 192 | height: 16px; 193 | } 194 | -------------------------------------------------------------------------------- /assets/fonts/georgia.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-free89/Map-View/b80f5b3ec0d7e4dd355704cf4f8a28e5d836cbef/assets/fonts/georgia.woff -------------------------------------------------------------------------------- /assets/fonts/georgiab.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-free89/Map-View/b80f5b3ec0d7e4dd355704cf4f8a28e5d836cbef/assets/fonts/georgiab.woff -------------------------------------------------------------------------------- /assets/fonts/georgiai.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-free89/Map-View/b80f5b3ec0d7e4dd355704cf4f8a28e5d836cbef/assets/fonts/georgiai.woff -------------------------------------------------------------------------------- /assets/fonts/georgiaz.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-free89/Map-View/b80f5b3ec0d7e4dd355704cf4f8a28e5d836cbef/assets/fonts/georgiaz.woff -------------------------------------------------------------------------------- /assets/fonts/style.css: -------------------------------------------------------------------------------- 1 | /* #### Generated By: http://www.cufonfonts.com #### */ 2 | 3 | @font-face { 4 | font-family: 'Georgia Regular'; 5 | font-style: normal; 6 | font-weight: normal; 7 | src: local('Georgia Regular'), url('georgia.woff') format('woff'); 8 | } 9 | 10 | 11 | @font-face { 12 | font-family: 'Georgia Italic'; 13 | font-style: normal; 14 | font-weight: normal; 15 | src: local('Georgia Italic'), url('georgiai.woff') format('woff'); 16 | } 17 | 18 | 19 | @font-face { 20 | font-family: 'Georgia Bold'; 21 | font-style: normal; 22 | font-weight: normal; 23 | src: local('Georgia Bold'), url('georgiab.woff') format('woff'); 24 | } 25 | 26 | 27 | @font-face { 28 | font-family: 'Georgia Bold Italic'; 29 | font-style: normal; 30 | font-weight: normal; 31 | src: local('Georgia Bold Italic'), url('georgiaz.woff') format('woff'); 32 | } -------------------------------------------------------------------------------- /assets/images/Givaudan-Globe-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-free89/Map-View/b80f5b3ec0d7e4dd355704cf4f8a28e5d836cbef/assets/images/Givaudan-Globe-Logo.png -------------------------------------------------------------------------------- /assets/images/Givaudan-textile-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-free89/Map-View/b80f5b3ec0d7e4dd355704cf4f8a28e5d836cbef/assets/images/Givaudan-textile-Logo.png -------------------------------------------------------------------------------- /assets/images/nav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-free89/Map-View/b80f5b3ec0d7e4dd355704cf4f8a28e5d836cbef/assets/images/nav.png -------------------------------------------------------------------------------- /assets/js/bootstrap-timepicker.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Timepicker Component for Twitter Bootstrap 3 | * 4 | * Copyright 2013 Joris de Wit and bootstrap-timepicker contributors 5 | * 6 | * Contributors https://github.com/jdewit/bootstrap-timepicker/graphs/contributors 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | (function($, window, document) { 12 | 'use strict'; 13 | 14 | // TIMEPICKER PUBLIC CLASS DEFINITION 15 | var Timepicker = function(element, options) { 16 | this.widget = ''; 17 | this.$element = $(element); 18 | this.defaultTime = options.defaultTime; 19 | this.disableFocus = options.disableFocus; 20 | this.disableMousewheel = options.disableMousewheel; 21 | this.isOpen = options.isOpen; 22 | this.minuteStep = options.minuteStep; 23 | this.modalBackdrop = options.modalBackdrop; 24 | this.orientation = options.orientation; 25 | this.secondStep = options.secondStep; 26 | this.snapToStep = options.snapToStep; 27 | this.showInputs = options.showInputs; 28 | this.showMeridian = options.showMeridian; 29 | this.showSeconds = options.showSeconds; 30 | this.template = options.template; 31 | this.appendWidgetTo = options.appendWidgetTo; 32 | this.showWidgetOnAddonClick = options.showWidgetOnAddonClick; 33 | this.icons = options.icons; 34 | this.maxHours = options.maxHours; 35 | this.explicitMode = options.explicitMode; // If true 123 = 1:23, 12345 = 1:23:45, else invalid. 36 | 37 | this.handleDocumentClick = function (e) { 38 | var self = e.data.scope; 39 | // This condition was inspired by bootstrap-datepicker. 40 | // The element the timepicker is invoked on is the input but it has a sibling for addon/button. 41 | if (!(self.$element.parent().find(e.target).length || 42 | self.$widget.is(e.target) || 43 | self.$widget.find(e.target).length)) { 44 | self.hideWidget(); 45 | } 46 | }; 47 | 48 | this._init(); 49 | }; 50 | 51 | Timepicker.prototype = { 52 | 53 | constructor: Timepicker, 54 | _init: function() { 55 | var self = this; 56 | 57 | if (this.showWidgetOnAddonClick && (this.$element.parent().hasClass('input-group') && this.$element.parent().hasClass('bootstrap-timepicker'))) { 58 | this.$element.parent('.input-group.bootstrap-timepicker').find('.input-group-addon').on({ 59 | 'click.timepicker': $.proxy(this.showWidget, this) 60 | }); 61 | this.$element.on({ 62 | 'focus.timepicker': $.proxy(this.highlightUnit, this), 63 | 'click.timepicker': $.proxy(this.highlightUnit, this), 64 | 'keydown.timepicker': $.proxy(this.elementKeydown, this), 65 | 'blur.timepicker': $.proxy(this.blurElement, this), 66 | 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this) 67 | }); 68 | } else { 69 | if (this.template) { 70 | this.$element.on({ 71 | 'focus.timepicker': $.proxy(this.showWidget, this), 72 | 'click.timepicker': $.proxy(this.showWidget, this), 73 | 'blur.timepicker': $.proxy(this.blurElement, this), 74 | 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this) 75 | }); 76 | } else { 77 | this.$element.on({ 78 | 'focus.timepicker': $.proxy(this.highlightUnit, this), 79 | 'click.timepicker': $.proxy(this.highlightUnit, this), 80 | 'keydown.timepicker': $.proxy(this.elementKeydown, this), 81 | 'blur.timepicker': $.proxy(this.blurElement, this), 82 | 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this) 83 | }); 84 | } 85 | } 86 | 87 | if (this.template !== false) { 88 | this.$widget = $(this.getTemplate()).on('click', $.proxy(this.widgetClick, this)); 89 | } else { 90 | this.$widget = false; 91 | } 92 | 93 | if (this.showInputs && this.$widget !== false) { 94 | this.$widget.find('input').each(function() { 95 | $(this).on({ 96 | 'click.timepicker': function() { $(this).select(); }, 97 | 'keydown.timepicker': $.proxy(self.widgetKeydown, self), 98 | 'keyup.timepicker': $.proxy(self.widgetKeyup, self) 99 | }); 100 | }); 101 | } 102 | 103 | this.setDefaultTime(this.defaultTime); 104 | }, 105 | 106 | blurElement: function() { 107 | this.highlightedUnit = null; 108 | this.updateFromElementVal(); 109 | }, 110 | 111 | clear: function() { 112 | this.hour = ''; 113 | this.minute = ''; 114 | this.second = ''; 115 | this.meridian = ''; 116 | 117 | this.$element.val(''); 118 | }, 119 | 120 | decrementHour: function() { 121 | if (this.showMeridian) { 122 | if (this.hour === 1) { 123 | this.hour = 12; 124 | } else if (this.hour === 12) { 125 | this.hour--; 126 | 127 | return this.toggleMeridian(); 128 | } else if (this.hour === 0) { 129 | this.hour = 11; 130 | 131 | return this.toggleMeridian(); 132 | } else { 133 | this.hour--; 134 | } 135 | } else { 136 | if (this.hour <= 0) { 137 | this.hour = this.maxHours - 1; 138 | } else { 139 | this.hour--; 140 | } 141 | } 142 | }, 143 | 144 | decrementMinute: function(step) { 145 | var newVal; 146 | 147 | if (step) { 148 | newVal = this.minute - step; 149 | } else { 150 | newVal = this.minute - this.minuteStep; 151 | } 152 | 153 | if (newVal < 0) { 154 | this.decrementHour(); 155 | this.minute = newVal + 60; 156 | } else { 157 | this.minute = newVal; 158 | } 159 | }, 160 | 161 | decrementSecond: function() { 162 | var newVal = this.second - this.secondStep; 163 | 164 | if (newVal < 0) { 165 | this.decrementMinute(true); 166 | this.second = newVal + 60; 167 | } else { 168 | this.second = newVal; 169 | } 170 | }, 171 | 172 | elementKeydown: function(e) { 173 | switch (e.which) { 174 | case 9: //tab 175 | if (e.shiftKey) { 176 | if (this.highlightedUnit === 'hour') { 177 | this.hideWidget(); 178 | break; 179 | } 180 | this.highlightPrevUnit(); 181 | } else if ((this.showMeridian && this.highlightedUnit === 'meridian') || (this.showSeconds && this.highlightedUnit === 'second') || (!this.showMeridian && !this.showSeconds && this.highlightedUnit ==='minute')) { 182 | this.hideWidget(); 183 | break; 184 | } else { 185 | this.highlightNextUnit(); 186 | } 187 | e.preventDefault(); 188 | this.updateFromElementVal(); 189 | break; 190 | case 27: // escape 191 | this.updateFromElementVal(); 192 | break; 193 | case 37: // left arrow 194 | e.preventDefault(); 195 | this.highlightPrevUnit(); 196 | this.updateFromElementVal(); 197 | break; 198 | case 38: // up arrow 199 | e.preventDefault(); 200 | switch (this.highlightedUnit) { 201 | case 'hour': 202 | this.incrementHour(); 203 | this.highlightHour(); 204 | break; 205 | case 'minute': 206 | this.incrementMinute(); 207 | this.highlightMinute(); 208 | break; 209 | case 'second': 210 | this.incrementSecond(); 211 | this.highlightSecond(); 212 | break; 213 | case 'meridian': 214 | this.toggleMeridian(); 215 | this.highlightMeridian(); 216 | break; 217 | } 218 | this.update(); 219 | break; 220 | case 39: // right arrow 221 | e.preventDefault(); 222 | this.highlightNextUnit(); 223 | this.updateFromElementVal(); 224 | break; 225 | case 40: // down arrow 226 | e.preventDefault(); 227 | switch (this.highlightedUnit) { 228 | case 'hour': 229 | this.decrementHour(); 230 | this.highlightHour(); 231 | break; 232 | case 'minute': 233 | this.decrementMinute(); 234 | this.highlightMinute(); 235 | break; 236 | case 'second': 237 | this.decrementSecond(); 238 | this.highlightSecond(); 239 | break; 240 | case 'meridian': 241 | this.toggleMeridian(); 242 | this.highlightMeridian(); 243 | break; 244 | } 245 | 246 | this.update(); 247 | break; 248 | } 249 | }, 250 | 251 | getCursorPosition: function() { 252 | var input = this.$element.get(0); 253 | 254 | if ('selectionStart' in input) {// Standard-compliant browsers 255 | 256 | return input.selectionStart; 257 | } else if (document.selection) {// IE fix 258 | input.focus(); 259 | var sel = document.selection.createRange(), 260 | selLen = document.selection.createRange().text.length; 261 | 262 | sel.moveStart('character', - input.value.length); 263 | 264 | return sel.text.length - selLen; 265 | } 266 | }, 267 | 268 | getTemplate: function() { 269 | var template, 270 | hourTemplate, 271 | minuteTemplate, 272 | secondTemplate, 273 | meridianTemplate, 274 | templateContent; 275 | 276 | if (this.showInputs) { 277 | hourTemplate = ''; 278 | minuteTemplate = ''; 279 | secondTemplate = ''; 280 | meridianTemplate = ''; 281 | } else { 282 | hourTemplate = ''; 283 | minuteTemplate = ''; 284 | secondTemplate = ''; 285 | meridianTemplate = ''; 286 | } 287 | 288 | templateContent = '
8 | * An InfoBox behaves like a google.maps.InfoWindow, but it supports several 9 | * additional properties for advanced styling. An InfoBox can also be used as a map label. 10 | *
11 | * An InfoBox also fires the same events as a google.maps.InfoWindow.
12 | */
13 |
14 | /*!
15 | *
16 | * Licensed under the Apache License, Version 2.0 (the "License");
17 | * you may not use this file except in compliance with the License.
18 | * You may obtain a copy of the License at
19 | *
20 | * http://www.apache.org/licenses/LICENSE-2.0
21 | *
22 | * Unless required by applicable law or agreed to in writing, software
23 | * distributed under the License is distributed on an "AS IS" BASIS,
24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 | * See the License for the specific language governing permissions and
26 | * limitations under the License.
27 | */
28 |
29 | /*jslint browser:true */
30 | /*global google */
31 |
32 | /**
33 | * @name InfoBoxOptions
34 | * @class This class represents the optional parameter passed to the {@link InfoBox} constructor.
35 | * @property {string|Node} content The content of the InfoBox (plain text or an HTML DOM node).
36 | * @property {boolean} [disableAutoPan=false] Disable auto-pan on open.
37 | * @property {number} maxWidth The maximum width (in pixels) of the InfoBox. Set to 0 if no maximum.
38 | * @property {Size} pixelOffset The offset (in pixels) from the top left corner of the InfoBox
39 | * (or the bottom left corner if the Google Sheets API QuickstartalignBottom
property is true
)
40 | * to the map pixel corresponding to position.
41 | * @property {LatLng} position The geographic location at which to display the InfoBox.
42 | * @property {number} zIndex The CSS z-index style value for the InfoBox.
43 | * Note: This value overrides a zIndex setting specified in the boxStyle property.
44 | * @property {string} [boxClass="infoBox"] The name of the CSS class defining the styles for the InfoBox container.
45 | * @property {Object} [boxStyle] An object literal whose properties define specific CSS
46 | * style values to be applied to the InfoBox. Style values defined here override those that may
47 | * be defined in the boxClass
style sheet. If this property is changed after the
48 | * InfoBox has been created, all previously set styles (except those defined in the style sheet)
49 | * are removed from the InfoBox before the new style values are applied.
50 | * @property {string} closeBoxMargin The CSS margin style value for the close box.
51 | * The default is "2px" (a 2-pixel margin on all sides).
52 | * @property {string} closeBoxURL The URL of the image representing the close box.
53 | * Note: The default is the URL for Google's standard close box.
54 | * Set this property to "" if no close box is required.
55 | * @property {Size} infoBoxClearance Minimum offset (in pixels) from the InfoBox to the
56 | * map edge after an auto-pan.
57 | * @property {boolean} [isHidden=false] Hide the InfoBox on open.
58 | * [Deprecated in favor of the visible property.]
59 | * @property {boolean} [visible=true] Show the InfoBox on open.
60 | * @property {boolean} alignBottom Align the bottom left corner of the InfoBox to the position
61 | * location (default is false which means that the top left corner of the InfoBox is aligned).
62 | * @property {string} pane The pane where the InfoBox is to appear (default is "floatPane").
63 | * Set the pane to "mapPane" if the InfoBox is being used as a map label.
64 | * Valid pane names are the property names for the google.maps.MapPanes object.
65 | * @property {boolean} enableEventPropagation Propagate mousedown, mousemove, mouseover, mouseout,
66 | * mouseup, click, dblclick, touchstart, touchend, touchmove, and contextmenu events in the InfoBox
67 | * (default is false to mimic the behavior of a google.maps.InfoWindow). Set
68 | * this property to true if the InfoBox is being used as a map label.
69 | */
70 |
71 | /**
72 | * Creates an InfoBox with the options specified in {@link InfoBoxOptions}.
73 | * Call InfoBox.open to add the box to the map.
74 | * @constructor
75 | * @param {InfoBoxOptions} [opt_opts]
76 | */
77 | function InfoBox(opt_opts) {
78 |
79 | opt_opts = opt_opts || {};
80 |
81 | google.maps.OverlayView.apply(this, arguments);
82 |
83 | // Standard options (in common with google.maps.InfoWindow):
84 | //
85 | this.content_ = opt_opts.content || "";
86 | this.disableAutoPan_ = opt_opts.disableAutoPan || false;
87 | this.maxWidth_ = opt_opts.maxWidth || 0;
88 | this.pixelOffset_ = opt_opts.pixelOffset || new google.maps.Size(0, 0);
89 | this.position_ = opt_opts.position || new google.maps.LatLng(0, 0);
90 | this.zIndex_ = opt_opts.zIndex || null;
91 |
92 | // Additional options (unique to InfoBox):
93 | //
94 | this.boxClass_ = opt_opts.boxClass || "infoBox";
95 | this.boxStyle_ = opt_opts.boxStyle || {};
96 | this.closeBoxMargin_ = opt_opts.closeBoxMargin || "2px";
97 | this.closeBoxURL_ = opt_opts.closeBoxURL || "http://www.google.com/intl/en_us/mapfiles/close.gif";
98 | if (opt_opts.closeBoxURL === "") {
99 | this.closeBoxURL_ = "";
100 | }
101 | this.infoBoxClearance_ = opt_opts.infoBoxClearance || new google.maps.Size(1, 1);
102 |
103 | if (typeof opt_opts.visible === "undefined") {
104 | if (typeof opt_opts.isHidden === "undefined") {
105 | opt_opts.visible = true;
106 | } else {
107 | opt_opts.visible = !opt_opts.isHidden;
108 | }
109 | }
110 | this.isHidden_ = !opt_opts.visible;
111 |
112 | this.alignBottom_ = opt_opts.alignBottom || false;
113 | this.pane_ = opt_opts.pane || "floatPane";
114 | this.enableEventPropagation_ = opt_opts.enableEventPropagation || false;
115 |
116 | this.div_ = null;
117 | this.closeListener_ = null;
118 | this.moveListener_ = null;
119 | this.contextListener_ = null;
120 | this.eventListeners_ = null;
121 | this.fixedWidthSet_ = null;
122 | }
123 |
124 | /* InfoBox extends OverlayView in the Google Maps API v3.
125 | */
126 | InfoBox.prototype = new google.maps.OverlayView();
127 |
128 | /**
129 | * Creates the DIV representing the InfoBox.
130 | * @private
131 | */
132 | InfoBox.prototype.createInfoBoxDiv_ = function () {
133 |
134 | var i;
135 | var events;
136 | var bw;
137 | var me = this;
138 |
139 | // This handler prevents an event in the InfoBox from being passed on to the map.
140 | //
141 | var cancelHandler = function (e) {
142 | e.cancelBubble = true;
143 | if (e.stopPropagation) {
144 | e.stopPropagation();
145 | }
146 | };
147 |
148 | // This handler ignores the current event in the InfoBox and conditionally prevents
149 | // the event from being passed on to the map. It is used for the contextmenu event.
150 | //
151 | var ignoreHandler = function (e) {
152 |
153 | e.returnValue = false;
154 |
155 | if (e.preventDefault) {
156 |
157 | e.preventDefault();
158 | }
159 |
160 | if (!me.enableEventPropagation_) {
161 |
162 | cancelHandler(e);
163 | }
164 | };
165 |
166 | if (!this.div_) {
167 |
168 | this.div_ = document.createElement("div");
169 |
170 | this.setBoxStyle_();
171 |
172 | if (typeof this.content_.nodeType === "undefined") {
173 | this.div_.innerHTML = this.getCloseBoxImg_() + this.content_;
174 | } else {
175 | this.div_.innerHTML = this.getCloseBoxImg_();
176 | this.div_.appendChild(this.content_);
177 | }
178 |
179 | // Add the InfoBox DIV to the DOM
180 | this.getPanes()[this.pane_].appendChild(this.div_);
181 |
182 | this.addClickHandler_();
183 |
184 | if (this.div_.style.width) {
185 |
186 | this.fixedWidthSet_ = true;
187 |
188 | } else {
189 |
190 | if (this.maxWidth_ !== 0 && this.div_.offsetWidth > this.maxWidth_) {
191 |
192 | this.div_.style.width = this.maxWidth_;
193 | this.div_.style.overflow = "auto";
194 | this.fixedWidthSet_ = true;
195 |
196 | } else { // The following code is needed to overcome problems with MSIE
197 |
198 | bw = this.getBoxWidths_();
199 |
200 | this.div_.style.width = (this.div_.offsetWidth - bw.left - bw.right) + "px";
201 | this.fixedWidthSet_ = false;
202 | }
203 | }
204 |
205 | this.panBox_(this.disableAutoPan_);
206 |
207 | if (!this.enableEventPropagation_) {
208 |
209 | this.eventListeners_ = [];
210 |
211 | // Cancel event propagation.
212 | //
213 | // Note: mousemove not included (to resolve Issue 152)
214 | events = ["mousedown", "mouseover", "mouseout", "mouseup",
215 | "click", "dblclick", "touchstart", "touchend", "touchmove"];
216 |
217 | for (i = 0; i < events.length; i++) {
218 |
219 | this.eventListeners_.push(google.maps.event.addDomListener(this.div_, events[i], cancelHandler));
220 | }
221 |
222 | // Workaround for Google bug that causes the cursor to change to a pointer
223 | // when the mouse moves over a marker underneath InfoBox.
224 | this.eventListeners_.push(google.maps.event.addDomListener(this.div_, "mouseover", function (e) {
225 | this.style.cursor = "default";
226 | }));
227 | }
228 |
229 | this.contextListener_ = google.maps.event.addDomListener(this.div_, "contextmenu", ignoreHandler);
230 |
231 | /**
232 | * This event is fired when the DIV containing the InfoBox's content is attached to the DOM.
233 | * @name InfoBox#domready
234 | * @event
235 | */
236 | google.maps.event.trigger(this, "domready");
237 | }
238 | };
239 |
240 | /**
241 | * Returns the HTML tag for the close box.
242 | * @private
243 | */
244 | InfoBox.prototype.getCloseBoxImg_ = function () {
245 |
246 | var img = "";
247 |
248 | if (this.closeBoxURL_ !== "") {
249 |
250 | img = "
";
258 | }
259 |
260 | return img;
261 | };
262 |
263 | /**
264 | * Adds the click handler to the InfoBox close box.
265 | * @private
266 | */
267 | InfoBox.prototype.addClickHandler_ = function () {
268 |
269 | var closeBox;
270 |
271 | if (this.closeBoxURL_ !== "") {
272 |
273 | closeBox = this.div_.firstChild;
274 | this.closeListener_ = google.maps.event.addDomListener(closeBox, "click", this.getCloseClickHandler_());
275 |
276 | } else {
277 |
278 | this.closeListener_ = null;
279 | }
280 | };
281 |
282 | /**
283 | * Returns the function to call when the user clicks the close box of an InfoBox.
284 | * @private
285 | */
286 | InfoBox.prototype.getCloseClickHandler_ = function () {
287 |
288 | var me = this;
289 |
290 | return function (e) {
291 |
292 | // 1.0.3 fix: Always prevent propagation of a close box click to the map:
293 | e.cancelBubble = true;
294 |
295 | if (e.stopPropagation) {
296 |
297 | e.stopPropagation();
298 | }
299 |
300 | /**
301 | * This event is fired when the InfoBox's close box is clicked.
302 | * @name InfoBox#closeclick
303 | * @event
304 | */
305 | google.maps.event.trigger(me, "closeclick");
306 |
307 | me.close();
308 | };
309 | };
310 |
311 | /**
312 | * Pans the map so that the InfoBox appears entirely within the map's visible area.
313 | * @private
314 | */
315 | InfoBox.prototype.panBox_ = function (disablePan) {
316 |
317 | var map;
318 | var bounds;
319 | var xOffset = 0, yOffset = 0;
320 |
321 | if (!disablePan) {
322 |
323 | map = this.getMap();
324 |
325 | if (map instanceof google.maps.Map) { // Only pan if attached to map, not panorama
326 |
327 | if (!map.getBounds().contains(this.position_)) {
328 | // Marker not in visible area of map, so set center
329 | // of map to the marker position first.
330 | map.setCenter(this.position_);
331 | }
332 |
333 | bounds = map.getBounds();
334 |
335 | var mapDiv = map.getDiv();
336 | var mapWidth = mapDiv.offsetWidth;
337 | var mapHeight = mapDiv.offsetHeight;
338 | var iwOffsetX = this.pixelOffset_.width;
339 | var iwOffsetY = this.pixelOffset_.height;
340 | var iwWidth = this.div_.offsetWidth;
341 | var iwHeight = this.div_.offsetHeight;
342 | var padX = this.infoBoxClearance_.width;
343 | var padY = this.infoBoxClearance_.height;
344 | var pixPosition = this.getProjection().fromLatLngToContainerPixel(this.position_);
345 |
346 | if (pixPosition.x < (-iwOffsetX + padX)) {
347 | xOffset = pixPosition.x + iwOffsetX - padX;
348 | } else if ((pixPosition.x + iwWidth + iwOffsetX + padX) > mapWidth) {
349 | xOffset = pixPosition.x + iwWidth + iwOffsetX + padX - mapWidth;
350 | }
351 | if (this.alignBottom_) {
352 | if (pixPosition.y < (-iwOffsetY + padY + iwHeight)) {
353 | yOffset = pixPosition.y + iwOffsetY - padY - iwHeight;
354 | } else if ((pixPosition.y + iwOffsetY + padY) > mapHeight) {
355 | yOffset = pixPosition.y + iwOffsetY + padY - mapHeight;
356 | }
357 | } else {
358 | if (pixPosition.y < (-iwOffsetY + padY)) {
359 | yOffset = pixPosition.y + iwOffsetY - padY;
360 | } else if ((pixPosition.y + iwHeight + iwOffsetY + padY) > mapHeight) {
361 | yOffset = pixPosition.y + iwHeight + iwOffsetY + padY - mapHeight;
362 | }
363 | }
364 |
365 | if (!(xOffset === 0 && yOffset === 0)) {
366 |
367 | // Move the map to the shifted center.
368 | //
369 | var c = map.getCenter();
370 | map.panBy(xOffset, yOffset);
371 | }
372 | }
373 | }
374 | };
375 |
376 | /**
377 | * Sets the style of the InfoBox by setting the style sheet and applying
378 | * other specific styles requested.
379 | * @private
380 | */
381 | InfoBox.prototype.setBoxStyle_ = function () {
382 |
383 | var i, boxStyle;
384 |
385 | if (this.div_) {
386 |
387 | // Apply style values from the style sheet defined in the boxClass parameter:
388 | this.div_.className = this.boxClass_;
389 |
390 | // Clear existing inline style values:
391 | this.div_.style.cssText = "";
392 |
393 | // Apply style values defined in the boxStyle parameter:
394 | boxStyle = this.boxStyle_;
395 | for (i in boxStyle) {
396 |
397 | if (boxStyle.hasOwnProperty(i)) {
398 |
399 | this.div_.style[i] = boxStyle[i];
400 | }
401 | }
402 |
403 | // Fix for iOS disappearing InfoBox problem.
404 | // See http://stackoverflow.com/questions/9229535/google-maps-markers-disappear-at-certain-zoom-level-only-on-iphone-ipad
405 | this.div_.style.WebkitTransform = "translateZ(0)";
406 |
407 | // Fix up opacity style for benefit of MSIE:
408 | //
409 | if (typeof this.div_.style.opacity !== "undefined" && this.div_.style.opacity !== "") {
410 | // See http://www.quirksmode.org/css/opacity.html
411 | this.div_.style.MsFilter = "\"progid:DXImageTransform.Microsoft.Alpha(Opacity=" + (this.div_.style.opacity * 100) + ")\"";
412 | this.div_.style.filter = "alpha(opacity=" + (this.div_.style.opacity * 100) + ")";
413 | }
414 |
415 | // Apply required styles:
416 | //
417 | this.div_.style.position = "absolute";
418 | this.div_.style.visibility = 'hidden';
419 | if (this.zIndex_ !== null) {
420 |
421 | this.div_.style.zIndex = this.zIndex_;
422 | }
423 | }
424 | };
425 |
426 | /**
427 | * Get the widths of the borders of the InfoBox.
428 | * @private
429 | * @return {Object} widths object (top, bottom left, right)
430 | */
431 | InfoBox.prototype.getBoxWidths_ = function () {
432 |
433 | var computedStyle;
434 | var bw = {top: 0, bottom: 0, left: 0, right: 0};
435 | var box = this.div_;
436 |
437 | if (document.defaultView && document.defaultView.getComputedStyle) {
438 |
439 | computedStyle = box.ownerDocument.defaultView.getComputedStyle(box, "");
440 |
441 | if (computedStyle) {
442 |
443 | // The computed styles are always in pixel units (good!)
444 | bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0;
445 | bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
446 | bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0;
447 | bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0;
448 | }
449 |
450 | } else if (document.documentElement.currentStyle) { // MSIE
451 |
452 | if (box.currentStyle) {
453 |
454 | // The current styles may not be in pixel units, but assume they are (bad!)
455 | bw.top = parseInt(box.currentStyle.borderTopWidth, 10) || 0;
456 | bw.bottom = parseInt(box.currentStyle.borderBottomWidth, 10) || 0;
457 | bw.left = parseInt(box.currentStyle.borderLeftWidth, 10) || 0;
458 | bw.right = parseInt(box.currentStyle.borderRightWidth, 10) || 0;
459 | }
460 | }
461 |
462 | return bw;
463 | };
464 |
465 | /**
466 | * Invoked when close is called. Do not call it directly.
467 | */
468 | InfoBox.prototype.onRemove = function () {
469 |
470 | if (this.div_) {
471 |
472 | this.div_.parentNode.removeChild(this.div_);
473 | this.div_ = null;
474 | }
475 | };
476 |
477 | /**
478 | * Draws the InfoBox based on the current map projection and zoom level.
479 | */
480 | InfoBox.prototype.draw = function () {
481 |
482 | this.createInfoBoxDiv_();
483 |
484 | var pixPosition = this.getProjection().fromLatLngToDivPixel(this.position_);
485 |
486 | this.div_.style.left = (pixPosition.x + this.pixelOffset_.width) + "px";
487 |
488 | if (this.alignBottom_) {
489 | this.div_.style.bottom = -(pixPosition.y + this.pixelOffset_.height) + "px";
490 | } else {
491 | this.div_.style.top = (pixPosition.y + this.pixelOffset_.height) + "px";
492 | }
493 |
494 | if (this.isHidden_) {
495 |
496 | this.div_.style.visibility = "hidden";
497 |
498 | } else {
499 |
500 | this.div_.style.visibility = "visible";
501 | }
502 | };
503 |
504 | /**
505 | * Sets the options for the InfoBox. Note that changes to the maxWidth,
506 | * closeBoxMargin, closeBoxURL, and enableEventPropagation
507 | * properties have no affect until the current InfoBox is closed and a new one
508 | * is opened.
509 | * @param {InfoBoxOptions} opt_opts
510 | */
511 | InfoBox.prototype.setOptions = function (opt_opts) {
512 | if (typeof opt_opts.boxClass !== "undefined") { // Must be first
513 |
514 | this.boxClass_ = opt_opts.boxClass;
515 | this.setBoxStyle_();
516 | }
517 | if (typeof opt_opts.boxStyle !== "undefined") { // Must be second
518 |
519 | this.boxStyle_ = opt_opts.boxStyle;
520 | this.setBoxStyle_();
521 | }
522 | if (typeof opt_opts.content !== "undefined") {
523 |
524 | this.setContent(opt_opts.content);
525 | }
526 | if (typeof opt_opts.disableAutoPan !== "undefined") {
527 |
528 | this.disableAutoPan_ = opt_opts.disableAutoPan;
529 | }
530 | if (typeof opt_opts.maxWidth !== "undefined") {
531 |
532 | this.maxWidth_ = opt_opts.maxWidth;
533 | }
534 | if (typeof opt_opts.pixelOffset !== "undefined") {
535 |
536 | this.pixelOffset_ = opt_opts.pixelOffset;
537 | }
538 | if (typeof opt_opts.alignBottom !== "undefined") {
539 |
540 | this.alignBottom_ = opt_opts.alignBottom;
541 | }
542 | if (typeof opt_opts.position !== "undefined") {
543 |
544 | this.setPosition(opt_opts.position);
545 | }
546 | if (typeof opt_opts.zIndex !== "undefined") {
547 |
548 | this.setZIndex(opt_opts.zIndex);
549 | }
550 | if (typeof opt_opts.closeBoxMargin !== "undefined") {
551 |
552 | this.closeBoxMargin_ = opt_opts.closeBoxMargin;
553 | }
554 | if (typeof opt_opts.closeBoxURL !== "undefined") {
555 |
556 | this.closeBoxURL_ = opt_opts.closeBoxURL;
557 | }
558 | if (typeof opt_opts.infoBoxClearance !== "undefined") {
559 |
560 | this.infoBoxClearance_ = opt_opts.infoBoxClearance;
561 | }
562 | if (typeof opt_opts.isHidden !== "undefined") {
563 |
564 | this.isHidden_ = opt_opts.isHidden;
565 | }
566 | if (typeof opt_opts.visible !== "undefined") {
567 |
568 | this.isHidden_ = !opt_opts.visible;
569 | }
570 | if (typeof opt_opts.enableEventPropagation !== "undefined") {
571 |
572 | this.enableEventPropagation_ = opt_opts.enableEventPropagation;
573 | }
574 |
575 | if (this.div_) {
576 |
577 | this.draw();
578 | }
579 | };
580 |
581 | /**
582 | * Sets the content of the InfoBox.
583 | * The content can be plain text or an HTML DOM node.
584 | * @param {string|Node} content
585 | */
586 | InfoBox.prototype.setContent = function (content) {
587 | this.content_ = content;
588 |
589 | if (this.div_) {
590 |
591 | if (this.closeListener_) {
592 |
593 | google.maps.event.removeListener(this.closeListener_);
594 | this.closeListener_ = null;
595 | }
596 |
597 | // Odd code required to make things work with MSIE.
598 | //
599 | if (!this.fixedWidthSet_) {
600 |
601 | this.div_.style.width = "";
602 | }
603 |
604 | if (typeof content.nodeType === "undefined") {
605 | this.div_.innerHTML = this.getCloseBoxImg_() + content;
606 | } else {
607 | this.div_.innerHTML = this.getCloseBoxImg_();
608 | this.div_.appendChild(content);
609 | }
610 |
611 | // Perverse code required to make things work with MSIE.
612 | // (Ensures the close box does, in fact, float to the right.)
613 | //
614 | if (!this.fixedWidthSet_) {
615 | this.div_.style.width = this.div_.offsetWidth + "px";
616 | if (typeof content.nodeType === "undefined") {
617 | this.div_.innerHTML = this.getCloseBoxImg_() + content;
618 | } else {
619 | this.div_.innerHTML = this.getCloseBoxImg_();
620 | this.div_.appendChild(content);
621 | }
622 | }
623 |
624 | this.addClickHandler_();
625 | }
626 |
627 | /**
628 | * This event is fired when the content of the InfoBox changes.
629 | * @name InfoBox#content_changed
630 | * @event
631 | */
632 | google.maps.event.trigger(this, "content_changed");
633 | };
634 |
635 | /**
636 | * Sets the geographic location of the InfoBox.
637 | * @param {LatLng} latlng
638 | */
639 | InfoBox.prototype.setPosition = function (latlng) {
640 |
641 | this.position_ = latlng;
642 |
643 | if (this.div_) {
644 |
645 | this.draw();
646 | }
647 |
648 | /**
649 | * This event is fired when the position of the InfoBox changes.
650 | * @name InfoBox#position_changed
651 | * @event
652 | */
653 | google.maps.event.trigger(this, "position_changed");
654 | };
655 |
656 | /**
657 | * Sets the zIndex style for the InfoBox.
658 | * @param {number} index
659 | */
660 | InfoBox.prototype.setZIndex = function (index) {
661 |
662 | this.zIndex_ = index;
663 |
664 | if (this.div_) {
665 |
666 | this.div_.style.zIndex = index;
667 | }
668 |
669 | /**
670 | * This event is fired when the zIndex of the InfoBox changes.
671 | * @name InfoBox#zindex_changed
672 | * @event
673 | */
674 | google.maps.event.trigger(this, "zindex_changed");
675 | };
676 |
677 | /**
678 | * Sets the visibility of the InfoBox.
679 | * @param {boolean} isVisible
680 | */
681 | InfoBox.prototype.setVisible = function (isVisible) {
682 |
683 | this.isHidden_ = !isVisible;
684 | if (this.div_) {
685 | this.div_.style.visibility = (this.isHidden_ ? "hidden" : "visible");
686 | }
687 | };
688 |
689 | /**
690 | * Returns the content of the InfoBox.
691 | * @returns {string}
692 | */
693 | InfoBox.prototype.getContent = function () {
694 |
695 | return this.content_;
696 | };
697 |
698 | /**
699 | * Returns the geographic location of the InfoBox.
700 | * @returns {LatLng}
701 | */
702 | InfoBox.prototype.getPosition = function () {
703 |
704 | return this.position_;
705 | };
706 |
707 | /**
708 | * Returns the zIndex for the InfoBox.
709 | * @returns {number}
710 | */
711 | InfoBox.prototype.getZIndex = function () {
712 |
713 | return this.zIndex_;
714 | };
715 |
716 | /**
717 | * Returns a flag indicating whether the InfoBox is visible.
718 | * @returns {boolean}
719 | */
720 | InfoBox.prototype.getVisible = function () {
721 |
722 | var isVisible;
723 |
724 | if ((typeof this.getMap() === "undefined") || (this.getMap() === null)) {
725 | isVisible = false;
726 | } else {
727 | isVisible = !this.isHidden_;
728 | }
729 | return isVisible;
730 | };
731 |
732 | /**
733 | * Shows the InfoBox. [Deprecated; use setVisible instead.]
734 | */
735 | InfoBox.prototype.show = function () {
736 |
737 | this.isHidden_ = false;
738 | if (this.div_) {
739 | this.div_.style.visibility = "visible";
740 | }
741 | };
742 |
743 | /**
744 | * Hides the InfoBox. [Deprecated; use setVisible instead.]
745 | */
746 | InfoBox.prototype.hide = function () {
747 |
748 | this.isHidden_ = true;
749 | if (this.div_) {
750 | this.div_.style.visibility = "hidden";
751 | }
752 | };
753 |
754 | /**
755 | * Adds the InfoBox to the specified map or Street View panorama. If anchor
756 | * (usually a google.maps.Marker) is specified, the position
757 | * of the InfoBox is set to the position of the anchor. If the
758 | * anchor is dragged to a new location, the InfoBox moves as well.
759 | * @param {Map|StreetViewPanorama} map
760 | * @param {MVCObject} [anchor]
761 | */
762 | InfoBox.prototype.open = function (map, anchor) {
763 |
764 | var me = this;
765 |
766 | if (anchor) {
767 |
768 | this.position_ = anchor.getPosition();
769 | this.moveListener_ = google.maps.event.addListener(anchor, "position_changed", function () {
770 | me.setPosition(this.getPosition());
771 | });
772 | }
773 |
774 | this.setMap(map);
775 |
776 | if (this.div_) {
777 |
778 | this.panBox_();
779 | }
780 | };
781 |
782 | /**
783 | * Removes the InfoBox from the map.
784 | */
785 | InfoBox.prototype.close = function () {
786 |
787 | var i;
788 |
789 | if (this.closeListener_) {
790 |
791 | google.maps.event.removeListener(this.closeListener_);
792 | this.closeListener_ = null;
793 | }
794 |
795 | if (this.eventListeners_) {
796 |
797 | for (i = 0; i < this.eventListeners_.length; i++) {
798 |
799 | google.maps.event.removeListener(this.eventListeners_[i]);
800 | }
801 | this.eventListeners_ = null;
802 | }
803 |
804 | if (this.moveListener_) {
805 |
806 | google.maps.event.removeListener(this.moveListener_);
807 | this.moveListener_ = null;
808 | }
809 |
810 | if (this.contextListener_) {
811 |
812 | google.maps.event.removeListener(this.contextListener_);
813 | this.contextListener_ = null;
814 | }
815 |
816 | this.setMap(null);
817 | };
--------------------------------------------------------------------------------
/assets/js/markercluster.js:
--------------------------------------------------------------------------------
1 | // ==ClosureCompiler==
2 | // @compilation_level ADVANCED_OPTIMIZATIONS
3 | // @externs_url https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/maps/google_maps_api_v3.js
4 | // ==/ClosureCompiler==
5 |
6 | /**
7 | * @name MarkerClusterer for Google Maps v3
8 | * @version version 1.0
9 | * @author Luke Mahe
10 | * @fileoverview
11 | * The library creates and manages per-zoom-level clusters for large amounts of
12 | * markers.
13 | *
14 | * This is a v3 implementation of the
15 | * v2 MarkerClusterer.
17 | */
18 |
19 | /**
20 | * @license
21 | * Copyright 2010 Google Inc. All Rights Reserved.
22 | *
23 | * Licensed under the Apache License, Version 2.0 (the "License");
24 | * you may not use this file except in compliance with the License.
25 | * You may obtain a copy of the License at
26 | *
27 | * http://www.apache.org/licenses/LICENSE-2.0
28 | *
29 | * Unless required by applicable law or agreed to in writing, software
30 | * distributed under the License is distributed on an "AS IS" BASIS,
31 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32 | * See the License for the specific language governing permissions and
33 | * limitations under the License.
34 | */
35 |
36 |
37 | /**
38 | * A Marker Clusterer that clusters markers.
39 | *
40 | * @param {google.maps.Map} map The Google map to attach to.
41 | * @param {Array.s[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f],10),E=parseFloat(w['border'+f+'Width'],10),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},le(n,m,$(v)),le(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ge.FLIP:p=[n,i];break;case ge.CLOCKWISE:p=G(n);break;case ge.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)
37 | > Givaudan's Virtual Tours
38 |
41 |
45 |
46 |
86 |