My project is with a react and I don't want to use jquery plugins, tell me is there any possibility
Your post is not very descriptive, but you can always use an event listener to adjust your map like
state = {
windowHeight: undefined,
windowWidth: undefined
}
handleResize = () => this.setState({
windowHeight: window.innerHeight,
windowWidth: window.innerWidth
});
componentDidMount() {
this.handleResize();
window.addEventListener('resize', this.handleResize)
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
}
Then just use the height and width from state to style your map, make sure to remove it when the page unmounts.
Related
I want to restrict the drag of an element to only horizontal or vertical direction. I am using HTML5 drag and drop API and not Jquery UI. Here is simplified code I am using to move an element:
$("#movedElem").on("dragstart", (event) => {
event.originalEvent.dataTransfer.effectAllowed= "move";
return true;
});
$("#targetElem").on("dragenter", (event) => {
//...
});
$("#targetElem").on("dragover", (event) => {
//
event.preventDefault();
});
$("#targetElem").on("drop", (event) => {
event.preventDefault();
event.stopPropagation();
$('#targetElem').append($('#movedElem'));
});
I am not looking for code, though that would be good too, but some direction would be enough... I think this must be a common requirement but could not find any example.
So I need to track time-watched etc of a youtube embed in our app, I figured best way was to use the YouTube iframe API and listen for events, but using (onReady) in the template, then assigning it to a method in controller - the obvious way doesn't seem to work:
The docs show this method(https://developers.google.com/youtube/iframe_api_reference), but it's including script tags in the template, I need an angular way of doing it without putting much ts in your html, and breaking the overall consistency of the project, plus the docs don't show how to do it in Angular2,
Since then I found a way by taking a reference from a stackoverflow answer
In your tempelate:
<div #ytPlayer id="ytPlayer"></div>
In ts ngAfterViewinit:
ngAfterViewInit() {
const doc = (<any>window).document;
const playerApiScript = doc.createElement('script');
playerApiScript.type = 'text/javascript';
playerApiScript.src = 'https://www.youtube.com/iframe_api';
doc.body.appendChild(playerApiScript);
}
And then listen for the event iFrame fires on window when it's completed loading api:
(<any>window).onYouTubeIframeAPIReady = () => {
this.player = new (<any>window).YT.Player('ytPlayer', {
height: '500px',
width: '100%',
videoId: 'hHMyZR87VvQ',
playerVars: { 'autoplay': 0, 'rel': 0, 'controls': 2 },
events: {
'onReady': (event) => {
console.log('Player is ready');
},
'onStateChange': (event) => {
}
}
});
};
Then you can call methods like getCurrentTime() on player or whichever variable you assign it to.
Edit: It still uses the document and window object instead of the angular element ref though, I will update this answer once I find a way to do it using window/document.
Is there a way to detect when the user clicks the default fullscreen mode button?
These are the map options I'm using:
var mapOptions = {
center: {
lat: 40.907192,
lng: 20.036871
},
zoom: 2,
fullscreenControl: true
};
I'm not sure if you want to detect the actual click event or just the state change between full screen and not. I needed to do the latter. The two things you need to know are that a) when the map size changes, the map will fire the bounds_changed event and b) within your event handler for that, you need to compare the map div's size with the size of the entire screen. Do this like so:
google.maps.event.addListener( map, 'bounds_changed', onBoundsChanged );
function onBoundsChanged() {
if ( $(map.getDiv()).children().eq(0).height() == window.innerHeight &&
$(map.getDiv()).children().eq(0).width() == window.innerWidth ) {
console.log( 'FULL SCREEN' );
}
else {
console.log ('NOT FULL SCREEN');
}
}
Note that getDiv() returns your own div that you passed to the Map() constructor. That div doesn't get resized for full screen - its child does. So that part where I'm getting the child of the map's div is correct but a little unwieldy. You could also rewrite that more briefly like this and it will work but this could break in the future if Google changes the map div's class name:
if ( $( '.gm-style' ).height() == window.innerHeight &&
$( '.gm-style' ).width() == window.innerWidth ) {
DaveBurns answer worked with some modifications because I don't use jQuery. Also I needed to use clientHeight and clientWidth
window.google.maps.event.addListener(
map,
'bounds_changed',
onBoundsChanged,
);
function onBoundsChanged() {
if (
map.getDiv().firstChild.clientHeight === window.innerHeight &&
map.getDiv().firstChild.clientWidth === window.innerWidth
) {
console.log('FULL SCREEN');
} else {
console.log('NOT FULL SCREEN');
}
}
This solution it is working for me:
/** Full Screen event */
$(document).bind('webkitfullscreenchange mozfullscreenchange fullscreenchange', function() {
var isFullScreen = document.fullScreen ||
document.mozFullScreen ||
document.webkitIsFullScreen;
if (isFullScreen) {
console.log('fullScreen!');
} else {
console.log('NO fullScreen!');
}
});
You can use HTML5 Fullscreen API which has the fullscreenchange event:
"When fullscreen mode is successfully engaged, the document which
contains the element receives a fullscreenchange event. When
fullscreen mode is exited, the document again receives a
fullscreenchange event".
Please note that
"For the moment not all browsers are using the unprefixed version of the API".
So, for instance, in Mozilla Firefox the event handler would look like this
document.onmozfullscreenchange = function(event) {
console.log("Full screen change")
}
I'm using Ember.js to implement a lightbox containing a Google Map. The problem is that when the map is in the lightbox it renders shifted up and to the left of where I expected it to be. The left over space on the bottom and right is just a blank area where you cannot drag the map. When I render the same map view in the main page, there is no problem. I also noticed that if I open the developer tools (in Chrome and Firefox), the map becomes correct. I have no idea why that is.
Here's the JSFiddle: http://jsfiddle.net/hekevintran/qt5k4/9/.
Screenshot (the bottom map is in the lightbox):
HTML:
<script src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>
<script type="text/x-handlebars" data-template-name="buttons">
<button {{action "openBox" }}>Open Box</button>
<button {{action "closeBox" }}>Close Box</button>
{{view App.MapView}}
</script>
<script type="text/x-handlebars" data-template-name="lightbox">
<div style="
background-color: lightgray;
border: 2px solid #000000;">
{{view App.MapView}}
</div>
</script>
JavaScript:
App = Ember.Application.create({});
App.MapView = Ember.View.extend({
installMap: function () {
var mapOptions = {
// San Francisco
center: new google.maps.LatLng(37.773429,-122.424774),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
new google.maps.Map(this.$()[0], mapOptions);
},
didInsertElement: function () {
this.$().css(
{'height': '350px',
'width': '350px'}
);
this.installMap();
}
});
Lightbox = Ember.Object.extend({
isVisible: false,
open: function () {
this.set('isVisible', true);
},
close: function () {
this.set('isVisible', false);
},
view: function () {
var controller = this;
return Ember.View.extend({
templateName: 'lightbox',
controller: controller,
isVisibleBinding: 'controller.isVisible'
})
}.property()
});
lightbox = Lightbox.create();
Ember.View.create({
templateName: 'buttons',
controller: Ember.Object.create({
openBox: function () {
lightbox.open();
},
closeBox: function () {
lightbox.close();
}
})
}).append();
lightbox.get('view').create().append();
The problem is that you are creating the map in the lightbox when you first load your page. This happens when you call lightbox.get('view').create().append(); at the end of your JavaScript page.
But the lightbox is not visible yet, and that confuses the Maps API. You could probably work around the problem by triggering a resize event on the map after opening the lightbox, but it's better by far to avoid creating the map and the lightbox view until you need them.
That fixes the problem, and as a bonus your page loads faster because you avoid creating the second map at load time.
To do this, I replaced the last part of your code with:
var lightbox;
Ember.View.create({
templateName: 'buttons',
controller: Ember.Object.create({
openBox: function () {
if( ! lightbox ) {
lightbox = Lightbox.create();
lightbox.get('view').create().append();
}
lightbox.open();
},
closeBox: function () {
if( lightbox ) {
lightbox.close();
}
}
})
}).append();
As you can see, I moved the lightbox = Lightbox.create(); and lightbox.get('view').create().append(); calls inside openBox(), but only calling them the first time this function is called.
I also added a guard in closeBox() so it doesn't try to close the nonexistent lightbox if it hasn't been created yet.
Here is an updated fiddle with the working code.
here is my code:
$('myButton').addEvents({
mouseenter: function(){
$('myImage').setStyle('display','block');
$('myImage').morph({
'duration': 500,
'transition': Fx.Transitions.Sine.in,
'opacity': 1,
'top': -205
});
},
mouseleave: function(){
$('myImage').morph({
'opacity': 0,
'top': -175,
'onComplete': hidemyImage
});
}
});
function hidemyImage() {
$('myImage').setStyle('display','none')
}
the onComplete inside the mouseleave does not work as expected... it hides the image immediately when i move away from myButton instead of hiding it after the morph has finished... i tried several solutions but none worked so far. any idea / help? thanks in advance!
you need to work with the instance and not pass on things in the morph function directly, that takes properties to morph and it probably runs your function immediately in the hope it will return a property value. you can do el.set('morph', {onComplete: hideImagefn}) before that and it will work but read on...
one way to do it is to set your morph options/instance once and work with it afterwards like so:
(function() {
var img = document.id('myImage').set('morph', {
duration: 500,
transition: Fx.Transitions.Sine.in,
link: 'cancel',
onStart: function() {
this.element.setStyle('display', 'block');
}
}), fx = img.get('morph');
// of you can just do var fx = new Fx.Morph(img, { options});
document.id('myButton').addEvents({
mouseenter: function(){
fx.start({
opacity: 1,
top: -205
});
},
mouseleave: function(){
fx.addEvent('complete', function() {
this.element.setStyle('display', 'none');
this.removeEvents('complete');
}).start({
opacity: 0,
top: -175
});
}
});
})();
the start ensures its always visible when mouseovered, the link is cancel which means it will stop execution if you mouse out too early and if you do mouseout, it will then hide the image and remove the onComplete event so that if you show it once more, it stays visible when it comes into view.
if you don't plan on being able to bring it back you can clean-up better and even use event pseudos like onComplete:once etc - though thats part of Event.Pseudos from mootools-more.
in general - .get/.set morph is your setup. el.morph() passes values to morphInstance.start()
play here: http://jsfiddle.net/dimitar/NkNHX/