| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
| <meta name="viewport" content="width=1024, user-scalable=no"> | |
| <style> | |
| html { height: 100% } | |
| body { height: 100%; margin: 0; padding: 0;} | |
| #map{ height: 80%;width:60%; position:absolute;cursor: auto;} | |
| #fullscreen:hover { cursor: pointer; } | |
| #circle { | |
| border-width:0.2px; | |
| border-style:solid; | |
| border-radius: 50%;; | |
| } | |
| </style> | |
| <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.css" /> | |
| <link rel="stylesheet" href="tipsy.css"></script> | |
| <title>Following circles</title> | |
| <div id="fullscreen">Click me to fullscreeen</div> | |
| <div id="map"></div> | |
| <script src="http://d3js.org/d3.v3.js"></script> | |
| <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> | |
| <script src="jquery.tipsy_mod.js"></script> | |
| <script src="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js"></script> | |
| <script src="http://lully.snv.jussieu.fr/gbif/mapping/test_maps/wax.leaf.min.js"></script> | |
| <script type="text/javascript" src="jquery.fullscreen-min.js"></script> | |
| <script> | |
| var map = L.map("map").setView([24, 0.4],3); | |
| map._initPathRoot() | |
| svg = d3.select("#map").select("svg") | |
| g = svg.append("g"); | |
| var latlng=new L.LatLng(-8,52) | |
| var mouseover_circle = g.selectAll("mouseover_circle").data(function () | |
| { | |
| return [latlng]; | |
| }) | |
| mouseover_circle.enter().append("circle").attr('class','mouseover_circle') | |
| mouseover_circle.attr("cx",function(d) { return map.latLngToLayerPoint(d).x}) | |
| mouseover_circle.attr("cy",function(d) { return map.latLngToLayerPoint(d).y}).attr("stroke", "#005eff") | |
| mouseover_circle.attr("r", 10).attr('fill','#4ceb76') | |
| $('circle.mouseover_circle').tipsy({fade: true, opacity:1,gravity: 'n', html: true, container: $('#map'), | |
| title: 'title' | |
| }); | |
| url='http://a.tiles.mapbox.com/v3/pereion.map-fr0rgo1u.jsonp'; | |
| var basemap; | |
| wax.tilejson(url, function(tilejson) { | |
| basemap = new wax.leaf.connector(tilejson); | |
| map.addLayer(basemap,true); | |
| }); | |
| //add a tileset | |
| var simple_datapublisher_url='http://www.gbif.fr/mbtiles/datapublishers/simple_datapublisher_4/metadata.jsonp'; | |
| wax.tilejson(simple_datapublisher_url, function(tilejson) { | |
| this_datapublisher = new wax.leaf.connector(tilejson); | |
| map.addLayer(this_datapublisher,false); | |
| this_datapublisher.bringToFront() | |
| interaction= wax.leaf.interaction(this_datapublisher) | |
| .map(map) | |
| .tilejson(tilejson) | |
| .on({ | |
| on: function(o) { | |
| // console.warn(map.mouseEventToLatLng(o.e)) | |
| // console.info(o.data) | |
| if (o.e.type !== 'mousemove') | |
| { | |
| alert('clicking over a feature') | |
| } | |
| else | |
| { | |
| console.warn('mouse moving over a feature') | |
| var obj=o.data; | |
| var latlng=map.mouseEventToLatLng(o.e) | |
| var this_y=map.latLngToLayerPoint(latlng).y | |
| var this_x=map.latLngToLayerPoint(latlng).x | |
| mouseover_circle.attr("cx",this_x) | |
| mouseover_circle.attr("cy",this_y) | |
| var point_id=obj.point_id; | |
| var count_occurrences=obj.count_occurrences; | |
| var content='<div class="hoverbox" style="z-index:10000"><div id="point_centroid" class="'+obj.point_id+'"/></br><b>'+obj.count_occurrences+'</b> occurrences</br>'; | |
| console.warn(content) | |
| $('circle.mouseover_circle').attr('title', content); | |
| } | |
| } | |
| }) | |
| }) | |
| $('#fullscreen').click(function () | |
| { | |
| $('#map').width('100%').height('100%').fullScreen(true) | |
| map.invalidateSize(true); | |
| }) | |
| </script> |
| /** | |
| * @preserve jquery.fullscreen 1.1.4 | |
| * https://github.com/kayahr/jquery-fullscreen-plugin | |
| * Copyright (C) 2012 Klaus Reimer <k@ailis.de> | |
| * Licensed under the MIT license | |
| * (See http://www.opensource.org/licenses/mit-license) | |
| */ | |
| (function() { | |
| /** | |
| * Sets or gets the fullscreen state. | |
| * | |
| * @param {boolean=} state | |
| * True to enable fullscreen mode, false to disable it. If not | |
| * specified then the current fullscreen state is returned. | |
| * @return {boolean|Element|jQuery|null} | |
| * When querying the fullscreen state then the current fullscreen | |
| * element (or true if browser doesn't support it) is returned | |
| * when browser is currently in full screen mode. False is returned | |
| * if browser is not in full screen mode. Null is returned if | |
| * browser doesn't support fullscreen mode at all. When setting | |
| * the fullscreen state then the current jQuery selection is | |
| * returned for chaining. | |
| * @this {jQuery} | |
| */ | |
| function fullScreen(state) | |
| { | |
| var e, func, doc; | |
| // Do nothing when nothing was selected | |
| if (!this.length) return this; | |
| // We only use the first selected element because it doesn't make sense | |
| // to fullscreen multiple elements. | |
| e = (/** @type {Element} */ this[0]); | |
| // Find the real element and the document (Depends on whether the | |
| // document itself or a HTML element was selected) | |
| if (e.ownerDocument) | |
| { | |
| doc = e.ownerDocument; | |
| } | |
| else | |
| { | |
| doc = e; | |
| e = doc.documentElement; | |
| } | |
| // When no state was specified then return the current state. | |
| if (state == null) | |
| { | |
| // When fullscreen mode is not supported then return null | |
| if (!((/** @type {?Function} */ doc["cancelFullScreen"]) | |
| || (/** @type {?Function} */ doc["webkitCancelFullScreen"]) | |
| || (/** @type {?Function} */ doc["mozCancelFullScreen"]))) | |
| { | |
| return null; | |
| } | |
| // Check fullscreen state | |
| state = !!doc["fullScreen"] | |
| || !!doc["webkitIsFullScreen"] | |
| || !!doc["mozFullScreen"]; | |
| if (!state) return state; | |
| // Return current fullscreen element or "true" if browser doesn't | |
| // support this | |
| return (/** @type {?Element} */ doc["fullScreenElement"]) | |
| || (/** @type {?Element} */ doc["webkitCurrentFullScreenElement"]) | |
| || (/** @type {?Element} */ doc["mozFullScreenElement"]) | |
| || state; | |
| } | |
| // When state was specified then enter or exit fullscreen mode. | |
| if (state) | |
| { | |
| // Enter fullscreen | |
| func = (/** @type {?Function} */ e["requestFullScreen"]) | |
| || (/** @type {?Function} */ e["webkitRequestFullScreen"]) | |
| || (/** @type {?Function} */ e["mozRequestFullScreen"]); | |
| if (func) | |
| { | |
| if (Element["ALLOW_KEYBOARD_INPUT"]) | |
| func.call(e, Element["ALLOW_KEYBOARD_INPUT"]); | |
| else | |
| func.call(e); | |
| } | |
| return this; | |
| } | |
| else | |
| { | |
| // Exit fullscreen | |
| func = (/** @type {?Function} */ doc["cancelFullScreen"]) | |
| || (/** @type {?Function} */ doc["webkitCancelFullScreen"]) | |
| || (/** @type {?Function} */ doc["mozCancelFullScreen"]); | |
| if (func) func.call(doc); | |
| return this; | |
| } | |
| } | |
| /** | |
| * Toggles the fullscreen mode. | |
| * | |
| * @return {!jQuery} | |
| * The jQuery selection for chaining. | |
| * @this {jQuery} | |
| */ | |
| function toggleFullScreen() | |
| { | |
| return (/** @type {!jQuery} */ fullScreen.call(this, | |
| !fullScreen.call(this))); | |
| } | |
| /** | |
| * Handles the browser-specific fullscreenchange event and triggers | |
| * a jquery event for it. | |
| * | |
| * @param {?Event} event | |
| * The fullscreenchange event. | |
| */ | |
| function fullScreenChangeHandler(event) | |
| { | |
| jQuery(document).trigger(new jQuery.Event("fullscreenchange")); | |
| } | |
| /** | |
| * Handles the browser-specific fullscreenerror event and triggers | |
| * a jquery event for it. | |
| * | |
| * @param {?Event} event | |
| * The fullscreenerror event. | |
| */ | |
| function fullScreenErrorHandler(event) | |
| { | |
| jQuery(document).trigger(new jQuery.Event("fullscreenerror")); | |
| } | |
| /** | |
| * Installs the fullscreenchange event handler. | |
| */ | |
| function installFullScreenHandlers() | |
| { | |
| var e, change, error; | |
| // Determine event name | |
| e = document; | |
| if (e["webkitCancelFullScreen"]) | |
| { | |
| change = "webkitfullscreenchange"; | |
| error = "webkitfullscreenerror"; | |
| } | |
| else if (e["mozCancelFullScreen"]) | |
| { | |
| change = "mozfullscreenchange"; | |
| error = "mozfullscreenerror"; | |
| } | |
| else | |
| { | |
| change = "fullscreenchange"; | |
| error = "fullscreenerror"; | |
| } | |
| // Install the event handlers | |
| jQuery(document).bind(change, fullScreenChangeHandler); | |
| jQuery(document).bind(error, fullScreenErrorHandler); | |
| } | |
| jQuery.fn["fullScreen"] = fullScreen; | |
| jQuery.fn["toggleFullScreen"] = toggleFullScreen; | |
| installFullScreenHandlers(); | |
| })(); |
| // tipsy, facebook style tooltips for jquery | |
| // version 1.0.0a | |
| // (c) 2008-2010 jason frame [jason@onehackoranother.com] | |
| // released under the MIT license | |
| (function($) { | |
| function maybeCall(thing, ctx) { | |
| return (typeof thing == 'function') ? (thing.call(ctx)) : thing; | |
| } | |
| function Tipsy(element, options) { | |
| this.$element = $(element); | |
| this.options = options; | |
| this.enabled = true; | |
| this.fixTitle(); | |
| } | |
| Tipsy.prototype = { | |
| show: function() { | |
| var title = this.getTitle(); | |
| if (title && this.enabled) { | |
| var $tip = this.tip(); | |
| $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title); | |
| var container=this.options.container; | |
| $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity | |
| $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(container); | |
| console.warn(this.$element.offset()) | |
| console.warn(this.$element.offsetParent().offset()) | |
| var pos = $.extend({}, this.$element.offset(), { | |
| width: this.$element[0].offsetWidth || 0, | |
| height: this.$element[0].offsetHeight || 0 | |
| }); | |
| if (typeof this.$element[0].nearestViewportElement == 'object') { | |
| // SVG | |
| var el = this.$element[0]; | |
| var rect = el.getBoundingClientRect(); | |
| pos.width = rect.width; | |
| pos.height = rect.height; | |
| } | |
| var actualWidth = $tip[0].offsetWidth, | |
| actualHeight = $tip[0].offsetHeight, | |
| gravity = maybeCall(this.options.gravity, this.$element[0]); | |
| var tp; | |
| switch (gravity.charAt(0)) { | |
| case 'n': | |
| tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; | |
| break; | |
| case 's': | |
| tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; | |
| break; | |
| case 'e': | |
| tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}; | |
| break; | |
| case 'w': | |
| tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}; | |
| break; | |
| } | |
| if (gravity.length == 2) { | |
| if (gravity.charAt(1) == 'w') { | |
| tp.left = pos.left + pos.width / 2 - 15; | |
| } else { | |
| tp.left = pos.left + pos.width / 2 - actualWidth + 15; | |
| } | |
| } | |
| $tip.css(tp).addClass('tipsy-' + gravity); | |
| $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0); | |
| if (this.options.className) { | |
| $tip.addClass(maybeCall(this.options.className, this.$element[0])); | |
| } | |
| if (this.options.fade) { | |
| $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}); | |
| } else { | |
| $tip.css({visibility: 'visible', opacity: this.options.opacity}); | |
| } | |
| var t = this; | |
| var set_hovered = function(set_hover){ | |
| return function(){ | |
| t.$tip.stop(); | |
| t.tipHovered = set_hover; | |
| if (!set_hover){ | |
| if (t.options.delayOut === 0) { | |
| t.hide(); | |
| } else { | |
| setTimeout(function() { | |
| if (t.hoverState == 'out') t.hide(); }, t.options.delayOut); | |
| } | |
| } | |
| }; | |
| }; | |
| $tip.hover(set_hovered(true), set_hovered(false)); | |
| } | |
| }, | |
| hide: function() { | |
| if (this.options.fade) { | |
| this.tip().stop().fadeOut(function() { $(this).remove(); }); | |
| } else { | |
| this.tip().remove(); | |
| } | |
| }, | |
| fixTitle: function() { | |
| var $e = this.$element; | |
| if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') { | |
| $e.attr('original-title', $e.attr('title') || '').removeAttr('title'); | |
| } | |
| if (typeof $e.context.nearestViewportElement == 'object'){ | |
| if ($e.children('title').length){ | |
| console.warn('fix title') | |
| $e.append('<original-title>' + ($e.children('title').text() || '') + '</original-title>') | |
| .children('title').remove(); | |
| } | |
| } | |
| }, | |
| getTitle: function() { | |
| var title, $e = this.$element, o = this.options; | |
| this.fixTitle(); | |
| if (typeof o.title == 'string') { | |
| var title_name = o.title == 'title' ? 'original-title' : o.title; | |
| if ($e.children(title_name).length){ | |
| title = $e.children(title_name).html(); | |
| } else{ | |
| title = $e.attr(title_name); | |
| } | |
| } else if (typeof o.title == 'function') { | |
| title = o.title.call($e[0]); | |
| } | |
| title = ('' + title).replace(/(^\s*|\s*$)/, ""); | |
| return title || o.fallback; | |
| }, | |
| tip: function() { | |
| if (!this.$tip) { | |
| this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>'); | |
| } | |
| return this.$tip; | |
| }, | |
| validate: function() { | |
| if (!this.$element[0].parentNode) { | |
| this.hide(); | |
| this.$element = null; | |
| this.options = null; | |
| } | |
| }, | |
| enable: function() { this.enabled = true; }, | |
| disable: function() { this.enabled = false; }, | |
| toggleEnabled: function() { this.enabled = !this.enabled; } | |
| }; | |
| $.fn.tipsy = function(options) { | |
| if (options === true) { | |
| return this.data('tipsy'); | |
| } else if (typeof options == 'string') { | |
| var tipsy = this.data('tipsy'); | |
| if (tipsy) tipsy[options](); | |
| return this; | |
| } | |
| options = $.extend({}, $.fn.tipsy.defaults, options); | |
| if (options.hoverlock && options.delayOut === 0) { | |
| options.delayOut = 100; | |
| } | |
| function get(ele) { | |
| var tipsy = $.data(ele, 'tipsy'); | |
| if (!tipsy) { | |
| tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options)); | |
| $.data(ele, 'tipsy', tipsy); | |
| } | |
| return tipsy; | |
| } | |
| function enter() { | |
| var tipsy = get(this); | |
| tipsy.hoverState = 'in'; | |
| if (options.delayIn === 0) { | |
| tipsy.show(); | |
| } else { | |
| tipsy.fixTitle(); | |
| setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn); | |
| } | |
| } | |
| function leave() { | |
| var tipsy = get(this); | |
| tipsy.hoverState = 'out'; | |
| if (options.delayOut === 0) { | |
| tipsy.hide(); | |
| } else { | |
| var to = function() { | |
| if (!tipsy.tipHovered || !options.hoverlock){ | |
| if (tipsy.hoverState == 'out') tipsy.hide(); | |
| } | |
| }; | |
| setTimeout(to, options.delayOut); | |
| } | |
| } | |
| if (options.trigger != 'manual') { | |
| var binder = options.live ? 'live' : 'bind', | |
| eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus', | |
| eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'; | |
| this[binder](eventIn, enter)[binder](eventOut, leave); | |
| } | |
| return this; | |
| }; | |
| $.fn.tipsy.defaults = { | |
| className: null, | |
| container:document.body, | |
| delayIn: 0, | |
| delayOut: 0, | |
| fade: false, | |
| fallback: '', | |
| gravity: 'n', | |
| html: false, | |
| live: false, | |
| offset: 0, | |
| opacity: 0.8, | |
| title: 'title', | |
| trigger: 'hover', | |
| hoverlock: false | |
| }; | |
| // Overwrite this method to provide options on a per-element basis. | |
| // For example, you could store the gravity in a 'tipsy-gravity' attribute: | |
| // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' }); | |
| // (remember - do not modify 'options' in place!) | |
| $.fn.tipsy.elementOptions = function(ele, options) { | |
| return $.metadata ? $.extend({}, options, $(ele).metadata()) : options; | |
| }; | |
| $.fn.tipsy.autoNS = function() { | |
| return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; | |
| }; | |
| $.fn.tipsy.autoWE = function() { | |
| return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; | |
| }; | |
| /** | |
| * yields a closure of the supplied parameters, producing a function that takes | |
| * no arguments and is suitable for use as an autogravity function like so: | |
| * | |
| * @param margin (int) - distance from the viewable region edge that an | |
| * element should be before setting its tooltip's gravity to be away | |
| * from that edge. | |
| * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer | |
| * if there are no viewable region edges effecting the tooltip's | |
| * gravity. It will try to vary from this minimally, for example, | |
| * if 'sw' is preferred and an element is near the right viewable | |
| * region edge, but not the top edge, it will set the gravity for | |
| * that element's tooltip to be 'se', preserving the southern | |
| * component. | |
| */ | |
| $.fn.tipsy.autoBounds = function(margin, prefer) { | |
| return function() { | |
| var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)}, | |
| boundTop = $(document).scrollTop() + margin, | |
| boundLeft = $(document).scrollLeft() + margin, | |
| $this = $(this); | |
| if ($this.offset().top < boundTop) dir.ns = 'n'; | |
| if ($this.offset().left < boundLeft) dir.ew = 'w'; | |
| if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e'; | |
| if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's'; | |
| return dir.ns + (dir.ew ? dir.ew : ''); | |
| }; | |
| }; | |
| })(jQuery); |
| .tipsy { font-size: 15px; position: absolute; padding: 5px; z-index: 100000; } | |
| .tipsy-inner { background-color: #000; color: #FFF; max-width: 300px; padding: 5px 8px 4px 8px; text-align: center; } | |
| .tipsy-inner a { color: #FFF;} | |
| /* Rounded corners */ | |
| .tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; } | |
| /* Uncomment for shadow */ | |
| /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/ | |
| .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; } | |
| /* Rules to colour arrows */ | |
| .tipsy-arrow-n { border-bottom-color: #000; } | |
| .tipsy-arrow-s { border-top-color: #000; } | |
| .tipsy-arrow-e { border-left-color: #000; } | |
| .tipsy-arrow-w { border-right-color: #000; } | |
| .tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } | |
| .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} | |
| .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} | |
| .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |
| .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |
| .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |
| .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } | |
| .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment