mooTools Binding All Classes - mootools

I am not used to using mooTools, it looks a lot like Prototype JS. Can anyone tell me how to bind this to every class?
// This grabs all the classes
var mousy = $$('.hf-item-images');
// I don't think this is correct to apply this scroller to all the above classes
var scroll = new Scroller(mousy, {area: 100, velocity: 1});
// Mousemove
mousy.addEvent('mouseover', scroll.start.bind(scroll));
mousy.addEvent('mouseout', scroll.stop.bind(scroll));

you need to be smarter about this, looping through nnnn items to make scollers can be expensive. so is attaching pairs of events on each one.
given markup like so:
<div id="container">
<div class="hf-item-images">...</div>
<div class="hf-item-images">...</div>
</div>
you can delegate stuff on the parent and only instantiate a scroller instance on elements that need it, reusing it afterwards.
var container = document.id('container'),
settings = {
area: 100,
velocity: 1
};
container.addEvents({
'mouseover:relay(.hf-item-images)': function(e, el){
var scroll = el.retrieve('scroller');
if (!scroll){
// create instance the first mouseenter and store for later
scroll = new Scroller(el, settings);
el.store('scroller', scroll);
}
scroll.start();
},
'mouseout:relay(.hf-item-images)': function(e, el){
el.retrieve('scroller').stop();
}
});

Related

Wrong code in tutorial for event listeners

I am following this tutorial to build a store locator page with a Mapbox map.
I don't want to add custom markers because I already have custom map labels (symbols?), which means I don't need the optional last section of the tutorial and stop right after Add Event Listeners.
Once this is completed, the page should react to clicks in the side panel list, as well as on the map (2 event listeners). However, in the demo provided in the tutorial for that particular step, you can tell the code for the second event listener, the one making the map clickable, is not functioning, which makes me believe there is a mistake in the provided code:
// Add an event listener for when a user clicks on the map
map.on('click', function(e) {
// Query all the rendered points in the view
var features = map.queryRenderedFeatures(e.point, { layers: ['locations'] });
if (features.length) {
var clickedPoint = features[0];
// 1. Fly to the point
flyToStore(clickedPoint);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedPoint);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
// Find the index of the store.features that corresponds to the clickedPoint that fired the event listener
var selectedFeature = clickedPoint.properties.address;
for (var i = 0; i < stores.features.length; i++) {
if (stores.features[i].properties.address === selectedFeature) {
selectedFeatureIndex = i;
}
}
// Select the correct list item using the found index and add the active class
var listing = document.getElementById('listing-' + selectedFeatureIndex);
listing.classList.add('active');
}
});
Would anyone be able to tell what is wrong with this code?
Turns out the code is incomplete in that the cursor doesn't change to a pointer as you hover over a map label/marker so it doesn't clue you into realising you can click on it, hence my assumption it wasn't working at all. I assume the general users who would then face the map would be equally deceived unless the pointer shows up. So in the tutorial, if you do go ahead and click the marker, it will have the expected behaviour and display the popup, although no pointer is shown.
Here is how to create the pointer, based on this fiddle: https://jsfiddle.net/Twalsh88/5j70wm8n/25/
map.on('mouseenter', 'locations', function(e) {
// Change the cursor style as a UI indicator.
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'locations', function() {
map.getCanvas().style.cursor = '';
});

PhaserJS collision tilemap not working

I have a tilemap that only 1 layer is correctly colliding with the player. Been through all the examples, but i can't seem to get it working on multiple layers.
I have 1 tilemap that contains all the json data for a total of 13 layers, but for the example i have only included 3.
I would like for the player to collide with different layers and have different callbacks, e.g. cannot walk through, pick up item if within range etc. but all using 1 spritemap/tilemap.
var game = new Phaser.Game(1200, 780, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
this.load.tilemap('main_map', 'img here', null, Phaser.Tilemap.TILED_JSON);
this.load.image('sprite_map', 'img here');
this.load.image('player_image', 'img here');
}
var map;
var tileset;
var bLayer;
var wLayer;
var player;
var sLayer;
var cursors;
function create() {
game.physics.startSystem(Phaser.Physics.ARCADE);
// initiallize the tilemap
map = game.add.tilemap('main_map');
map.addTilesetImage('otherNew', 'sprite_map');
//draw the layers
bLayer = map.createLayer(0);
wLayer = map.createLayer(1);
sLayer = map.createLayer(2);
wLayer.resizeWorld();
player = game.add.sprite(600, 600, 'player_image');
game.physics.arcade.enable(player);
player.body.collideWorldBounds = true; // works
//game camera and movment keys here
}
function update() {
game.physics.arcade.collide(player, wLayer); // DOES NOT WORK
game.physics.arcade.collide(player, sLayer); // THIS WORKS
map.setCollision(1, true, wLayer); // DOES NOT WORK
map.setCollision(2, true, sLayer); // THIS WORKS
//movement here already works so didn't include
}
I'm thinking that your wLayer.resizeWorld(); function makes your tilemap's width/height the size of the world. Looks like this is the only difference between wLayer and sLayer.
Setting width/height in Phaser does not automatically resize the collision body. To do that, use the setSize function.
To view your current body, use Phaser's debug methods
this.game.debug.body(someSprite, 'rgba(255,0,0,0.5)');
The answer is that each layer has its own set of tilemaps, and as i was using a spritesheet to generate each layer, those layers had some value that needed to be set. I didn't have the patience to check what actual collision layer I needed, but as I had split them all up into separate logical layers I just set between 0, 100 for each.
// In the create section
map.setCollisionBetween(0, 100,true, wLayer,true);
map.setCollisionBetween(0, 100,true, sLayer,true);

How to wait a while before adding elements in css? javascript?

I have a problem that I will explain.
I'm doing an animation in HTML5 and CSS3. My idea is that a plane is flying around and it launches a missile after a while. What I want to do is to make the missile appear after that time. I thought about doing that changing the z-Index property of my div (because I have the missile image into a div container) using javascript after a while (any time I choose). For doing that I found the sleep function at the bottom. I created the "appear" function that I know it works because It changes my zIndex value but it doesn't wait the 2 seconds I want.
I also thought I had the solution by using the visibility property, but I have the same problem, sleep function doesn't wait at all.
Any suggestions? Thanks
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function appear(object){
sleep(200000);
var objective = document.getElementById(object);
objective.style.zIndex=1;
You can pass a function to the setTimeout function which will call that function in x milliseconds.
function waitForMe() {
alert('triggered!');
}
// Call waitForMe in 200000ms
setTimeout(waitForMe, 200000);
So for your example, you would want to use 2000 (2 seconds), not 200000 (200 seconds):
function appear(object) {
setTimeout(function () {
var objective = document.getElementById(object);
objective.style.zIndex=1;
}, 2000);
}
Hiding and showing an element
You can hide and show a method in a few ways:
Use z-index as you suggest, probably not the best way as we can actually hide it instead of sending it to the back of the page.
objective.style.zIndex = 1;
Use display, this hide the object completely.
// hide
objective.style.display = 'none';
// show
objective.style.display = 'block';
Use visibility, this will hide the object but it will still take up space in the page. This wouldn't matter if you're using position:fixed or position:absolute.
// hide
objective.style.visibility = 'hidden';
// show
objective.style.visibility = 'visible';
You can either create a div around the objective, and add it in with javascript like this
document.getElementById('objectivespan').innerHTML=imagehere;
Other than that, you can use
objective.style.visibility='hidden';
and change it to
objective.style.visibility='visible';
for the delay, use
function sleep(){
alert('slept');
}
SetTimeout('sleep', 10000);

Is there a function or property like css-zIndex in actionscript?

I want to control which DisplayObject is displayed on the front or on the back.
I can control that with zIndex style in css.
How can I do that in as?
Look at setChildIndex()
Here's a quick function that will let you place something at the highest depth:
function toTop(child:DisplayObject):void
{
if(child.parent)
{
child.setChildIndex(
child.parent.numChildren - 1
);
}
}
To control the z-order of the displayObjects use setChildIndex().
Lowest indexed children are displayed at the bottom.
Highest indexed children are displayed at the top.
To change the zorder of the children, use setChildIndex, to illustrate:
var container:Sprite = new Sprite();
var child1:Sprite = new Sprite();
var child2:Sprite = new Sprite();
var child3:Sprite = new Sprite();
container.addChild(child1); // bottom
container.addChild(child2); // middle
container.addChild(child3); // top
container.setChildIndex(child3,0); // child3 would now be at the bottom
There are even more options than only setting the 'z-index', you have full control on the layers:
getChildAt(index:int):DisplayObject
Gets an object from certain index
getChildIndex(child:DisplayObject):int
Gets a index from certain object
addChild(child:DisplayObject):DisplayObject
addChildAt(child:DisplayObject, index:int):DisplayObject
Adds a object on top (addChild) or at certain index (addChildAt)
swapChildren(child1:DisplayObject, child2:DisplayObject):DisplayObject
swapChildrenAt(index1:int, index2:int):void
Swap objects with eachother of by its 'z-index'

How to access Google Maps API v3 marker's DIV and its pixel position?

Instead of Google Maps API's default info window, I'm going to use other jQuery tooltip plugin over marker. So I need to get marker's DIV and its pixel position.
But couldn't get it because there are no id or class for certain marker. Only I can access map canvas div from marker object and undocumented pixelBounds object.
How can I access marker's DIV?
Where can I get DIV's pixel position? Can I convert lat-lng position to pixel values?
==
appended:
I also tried with below code, but it doesn't change when I scroll the map.
var marker = new google.maps.Marker({...});
google.maps.event.addListener(marker, 'click', function() {
var px = this.getMap().getProjection().fromLatLngToPoint(this.getPosition());
console.log("(" + px.x + "," + px.y + ")");
});
I don't really get why would you want to get specific div for marker? If you want to display tooltip then all you need is pixel position of markers anchor (and knowledge about size of marker and placement of anchor), not div element. You can always trigger opening and closing tooltip by hand when event occurs on google.maps side.
For getting pixel position of anchor of given marker you can use this code:
var scale = Math.pow(2, map.getZoom());
var nw = new google.maps.LatLng(
map.getBounds().getNorthEast().lat(),
map.getBounds().getSouthWest().lng()
);
var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
var worldCoordinate = map.getProjection().fromLatLngToPoint(marker.getPosition());
var pixelOffset = new google.maps.Point(
Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale),
Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale)
);
In pixelDistance you get offset of specific marker anchor counted from left upper corner of the map (and you can get it's position from map.getDiv() div). Why it works like this (or is there a better way?) you can read in documentation of google maps overlays.
var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
var proj = overlay.getProjection();
var pos = marker.getPosition();
var p = proj.fromLatLngToContainerPixel(pos);
You can now access your pixel coordinates through p.x and p.y.
FOLLOWING ADDED POST COMMENT:
The downfall of the overlay projection is that until it your map canvas finishes loading it isn't initialized. I have the following listener that will force whatever method I need to trigger when the map does finish loading.
google.maps.event.addListener(map, 'idle', functionName());
In the mean time I use the following check to avoid any errors before it does draw.
if(overlay.getProjection()) {
// code here
}
One thing to remember when using MBO's code:
When the map tiles are repeated, map.getBounds().getSouthWest() returns "-180" independent of the map's position. A fallback I'm using in this case is calculating the pixel distance to the center instead of the upper left corner, since map.getCenter() seems to return the currently centered point in any case. E.g. (using jQuery):
// Calculate marker position in pixels form upper left corner
var pixelCoordsCenter = map.getProjection().fromLatLngToPoint(map.getCenter());
pixelOffset = new google.maps.Point(
Math.floor((pixelCoordsMarker.x - pixelCoordsCenter.x) * scale + $(container).width()/2),
Math.floor((pixelCoordsMarker.y - pixelCoordsCenter.y) * scale + $(container).height()/2)
);
anyone still looking for an answer to this, have a look here: http://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries
among some other useful google maps stuff there's RichMarker which allows you to add DOM elements of your choice as draggable markers. just add class/id to handle with jQuery.
Rene's answer only gives you the "world coordinates" (that is, coords independent of zoom level and viewport). MBO's answer seems right, though, so that's the one you should accept and vote up (I can't as I just registered) as the solution might easily be overlooked otherwise.
As for an "easier" version, you can use the methods in MapCanvasProjection instead, but that means you'll have to make your own overlay. See here for an example. :P
MapCanvasProjection's fromLatLngToContainerPixel() is probably what the author's after. It will give you the pixel offset relative to the map's container. I did some experiments and found the "simplest" working solution. (I wish Google makes this feature more accessible!)
First you declare a subclass of OverlayView somewhere like so:
function CanvasProjectionOverlay() {}
CanvasProjectionOverlay.prototype = new google.maps.OverlayView();
CanvasProjectionOverlay.prototype.constructor = CanvasProjectionOverlay;
CanvasProjectionOverlay.prototype.onAdd = function(){};
CanvasProjectionOverlay.prototype.draw = function(){};
CanvasProjectionOverlay.prototype.onRemove = function(){};
Then somewhere else in your code where you instantiate the map, you also instantiate this OverlayView and set its map, like so:
var map = new google.maps.Map(document.getElementById('google-map'), mapOptions);
// Add canvas projection overlay so we can use the LatLng to pixel converter
var canvasProjectionOverlay = new CanvasProjectionOverlay();
canvasProjectionOverlay.setMap(map);
Then, whenever you need to use fromLatLngToContainerPixel, you just do this:
canvasProjectionOverlay.getProjection().fromLatLngToContainerPixel(myLatLng);
Note that because the MapCanvasProjection object will only be available once draw() is called, which is sometime before the map's idle, I suggest creating a boolean "mapInitialized" flag, set it to true on the first map idle callback. And then do what you need to do only after that.
Well, if you MUST access the DIV, here's some code. Beware that this will only work with the standard marker (20x34px), and it'll find all markers. You might want to improve this hack to suit your needs...
BEWARE! THIS IS A HACK
var a=document.getElementById('map_canvas');
var b=a.getElementsByTagName('img');
var i, j=b.length;
for (i=0; i<j; i++) {
if(b[i].src.match('marker_sprite.png')){
if(b[i].style.width=='20px' && b[i].style.height=='34px') {
c=b[i].parentElement;
console.log(c.style.top+":"+c.style.left);
// this is a marker's enclosing div
}
}
}
A working snippet jQuery style ready to copy/paste:
step 1 - initialize your map and options
<html>
<head>
<script src="get-your-jQuery" type="text/javascript"></script>
<script src="get-your-maps.API" type="text/javascript"></script>
<script type="text/javascript">
<!--
$(document).ready(function(){
var bucharest = new google.maps.LatLng(44.43552, 26.10250);
var options = {
zoom: 14,
center: bucharest,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
As you can see, lower, the variable map is not preceded by VAR, because it should be Global as we use another function to get the fromLatLngToContainerPixel. For more details check closures.
map = new google.maps.map($("#map_canvas")[0], options);
var marker = new google.maps.Marker({
position: google.maps.LatLng(44.4407,26.0864),
map: map
});
new google.maps.event.addListener(marker, 'mouseover', function(){
placeMarker( marker.getPosition(),'#tooltip');//param1: latlng, param2: container to place result
});
new google.maps.event.addListener(map, 'bounds_changed', function(){
$("#tooltip").css({display:'none'}); //this is just so you can see that all goes well ;)
});
overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
}); //here ends jQuery.ready
function placeMarker(location, ID){
var containerPixel = overlay.getProjection().fromLatLngToContainerPixel(location);
var divPixel = overlay.getProjection().fromLatLngToDivPixel(location);
$(ID).css({top:containerPixel.y, left:containerPixel.x, 'dislay':'block'});
}
//-->
</script>
</head>
<body>
<div id="tooltip" style="width:100px; height:100px; position:absolute; z-index:1; background:#fff">Here I am!</div>
<div id="map_canvas" style="width:300px; height:300px"></div>
</body>
</html>
I found it's easiest to assign a custom icon and use the img src attribute to get to the element. You can still use the default google maps icon, just save it locally.
$("#map img[src='my_marker.png']").getBoundingClientRect();
For many circumstances the complex math used the calculate and change the pin position in the accepted answer may be appropriate.
For my particular use I just created a transparent PNG with a canvas significantly larger than I needed for the icon. Then I just experimented moving the pin around within the transparent background and applying the new image to the map.
Here is the spec for adding the custom pin image, with examples:
https://developers.google.com/maps/documentation/javascript/examples/icon-simple
This method will definitely scale as an offset in pixels instead of an actual different long/lat even when you zoom in.
Try this way, got div by event.
marker.addListener("click", markerClicked);
function markerClicked(event) {
// here you can get the marker div by event.currentTarget
}