Create jumping effect, do not allow animation to stack up - jquery-animate

I have been trying to create something like simple game in jQuery, and i want to have a div that can simulate jumpping. So i've written the following code
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(document).keydown(function(e){
$(".box").stop(true);
if (e.which == 37) {
if(parseInt($(".box").position().left)>49){
$(".box").css("left", parseInt($(".box").position().left)-50);
}
return false;
}
if (e.which == 38) {
$(".box").animate({
bottom: "+=50px",
},function(){
$(".box").animate({bottom: "-=50px"});
});
return false;
}
if (e.which == 39) {
return false;
}
if (e.which == 40) {
return false;
}
});
});
</script>
<div style="width:500;margin:0px auto;">
<div class="main" style="width:500px;height:500px;border:1px solid #ccc;position:relative;">
<div class="box" style="border:1px solid #ccc;width:50px;height:50px;box-sizing:border-box;position:absolute;left:100px;bottom:0px;"></div>
</div>
</div>
So this code allows the box to move left and jump, with animated effect. The question is how to not just stop the animation (as in the code stop()) but to simply not allow the div class Box to jump further untill the animation is complete and the box is down to position bottom 0. Currently the code just stops the animation if you try to jump while the animation is running.

Actually I was able to find a solution. You simply add a variable false,and then on checking for arrow up key pressing you add codeto check if it is false, then add true when is animating, and after animation make it false again, so:
$(document).ready(function(){
var isAnimating = false;
$(document).keydown(function(e){
if (e.which == 37) {
if(parseInt($(".box").position().left)>49){
$(".box").css("left", parseInt($(".box").position().left)-50);
}
return false;
}
if (!isAnimating && e.which == 38) {
isAnimating = true;
$(".box").animate({
bottom: "50px",
},function(){
$(".box").animate({bottom: "0px"},function(){
isAnimating = false;
});
});
return false;
}
if (e.which == 39) {
return false;
}
if (e.which == 40) {
return false;
}
});
});

Related

ArcGIS Javascript API 4.14 popup field attributes not showing

I am using webamp to show the map created in ArcGIS (Javascript API in PHP website). In the map, a popup also appears when clicking on the layer's points. Recently I have updated the version 4.14 from 4.13. After updating it, the popup is not working properly. I have a custom popup template. After research in the documentation, I came to know there required a return function to show the custom div on the popup. The below code I have added to show my custom popups.
var template = { content: function(){ var div = document.createElement("div"); div.className = "myClass"; div.innerHTML = "<span>My custom content!</span>"; return div; } }
layers[layerIndex].popupTemplate = template;
Now the popup appears fine. But I have to show the field values on the popup. I have used the required field attributes in double brackets eg: {Name}. But in the latest version, the field values are not appearing when I used the same.
The code I have used in version 4.13 and it was working,
popupTemplate = {
title: "{Name}",
content: '<div id="popup_address">{Address}</div><div class="right"><div href="#" id="popupRight" class="toggle"><p onClick="openPopupDetails({FACILITYID})">+</p></div></div>' };
layers[layerIndex].popupTemplate = popupTemplate;
Please help me to fix this issue.
Thanks.
The complete code for the Webmap and custom popup
map.js
// The map classes and includ1a65d527bfd04cc180c87edf0908907bes
require([
"esri/views/MapView",
"esri/WebMap",
"esri/widgets/Search",
"esri/widgets/Zoom",
"esri/widgets/Locate"
], function(MapView, WebMap, Search, Zoom, Locate) {
var webmap = new WebMap({
portalItem: {
id: "d1ca798d8c7d4afab8983d911df8326b"
}
});
var view = new MapView({
map: webmap,
container: "map",
center: [-95.9406, 41.26],
zoom: 16,
maxZoom: 21,
minZoom: 13,
basemap: "topo",
ui: {
components: ["attribution"]
}
});
webmap
.load()
.then(function() {
return webmap.basemap.load();
})
.then(function() {
let allLayers = webmap.allLayers;
console.log(allLayers);
var promises = allLayers.map(function(layer) {
return layer.load();
});
return Promise.all(promises.toArray());
})
.then(function(layers) {
// Position of the popup in relation to the selected feature.
view.popup.alignment = "top-center";
// To disable the collapse functionality
view.popup.collapseEnabled = false;
// A spinner appear at the pointer
view.popup.spinnerEnabled = false;
// To disable the dock (The popup will be appear in bottom or any corner of the window)
view.popup.dockEnabled = false;
// Disable the pagination
view.popup.featureNavigationEnabled = false;
// Popup template details, Keep only name and address in the popup and avoid all other details
view.popup.viewModel.actions.getItemAt(0).visible = false;
// view.on("click", function(event) {
// keep a delay to align the popup and the pointer together positioned to the map center
// Add animation only if the browser not IE
// });
layers.forEach(function(popupLayers, layerIndex) {
console.log(popupLayers);
var template = {
title: "{Name}",
content: function() {
var div = document.createElement("div");
div.className = "myClass";
div.innerHTML = "<span>{Address}</span>";
return div;
}
};
layers[layerIndex].popupTemplate = template;
// popupTemplate = {
// title: "{Name}",
// content:
// '<div id="popup_address">{Address}</div><div class="right"><div href="#" id="popupRight" class="toggle"><p onClick="openPopupDetails({FACILITYID})">+</p></div></div>'
// };
// layers[layerIndex].popupTemplate = popupTemplate;
});
// To close the popup when hit on esc button
document.onkeyup = function(evt) {
var key = evt.keyCode;
if (key == 27) {
view.popup.close();
}
};
})
.catch(function(error) {
// console.log(error);
});
});
Index.php
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>Load a basic WebMap - 4.14</title>
<style>
html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.14/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.14/"></script>
<script src="map.js"></script>
</head>
<body>
<div id="map"></div>
</body>
</html>
I have modified the code,
for (let i = 2; i < layers.length; i++) {
var template = {
title: "{Name}",
content: function() {
var div = document.createElement("div");
div.innerHTML =
'<div id="popup_address">{Address}</div><div class="right"><div href="#" id="popupRight" class="toggle"><p onClick="openPopupDetails({FACILITYID})">+</p></div></div>';
return div;
}
};
layers[i].popupTemplate = template;
console.log(layer[i]);
}
When I apply custom div, the {Address} part is not rendering. It appears like {Address} itself.
I think you are a bit confuse, you still can use a string, or you can use a function for the content of the popup template. So if you want to use a function, you can use something like this,
popupTemplate = {
title: "{Name}",
content: popupContentChange
}
layers[layerIndex].popupTemplate = template;
function popupContentChange(feature) {
let div = document.createElement("div");
div.className = "myClass";
div.innerHTML = "<span>"+feature.graphic.attributes.Address+"</span>";
return div;
}
There are several examples in the API documentation, take a look there. Just to reference one, ArcGIS JavaScript API Examples - Intro to Popups
Here an example I made for you taking your code as base adding some fixes to display what you want.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>Sketch Feature Coords</title>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.14/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.14/"></script>
<style>
html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
require([
"esri/views/MapView",
"esri/WebMap",
"esri/widgets/Search",
"esri/widgets/Zoom",
"esri/widgets/Locate"
], function(MapView, WebMap, Search, Zoom, Locate) {
var webmap = new WebMap({
portalItem: {
id: "d1ca798d8c7d4afab8983d911df8326b"
}
});
var view = new MapView({
map: webmap,
container: "map",
center: [-95.9406, 41.26],
zoom: 16,
maxZoom: 21,
minZoom: 13,
basemap: "topo",
ui: {
components: ["attribution"]
}
});
webmap
.load()
.then(function() {
return webmap.basemap.load();
})
.then(function() {
let allLayers = webmap.allLayers;
console.log(allLayers);
var promises = allLayers.map(function(layer) {
return layer.load();
});
return Promise.all(promises.toArray());
})
.then(function(layers) {
// Position of the popup in relation to the selected feature.
view.popup.alignment = "top-center";
// To disable the collapse functionality
view.popup.collapseEnabled = false;
// A spinner appear at the pointer
view.popup.spinnerEnabled = false;
// To disable the dock (The popup will be appear in bottom or any corner of the window)
view.popup.dockEnabled = false;
// Disable the pagination
view.popup.featureNavigationEnabled = false;
// Popup template details, Keep only name and address in the popup and avoid all other details
view.popup.viewModel.actions.getItemAt(0).visible = false;
// it is only going to work on the last two layers
// those are the one that have fields: Name and Address
for (let i = 2; i < layers.length; i++) {
var template = {
title: "{Name}",
content: "<span>Address: {Address}</span>"
};
layers[i].popupTemplate = template;
console.log(layer[i]);
}
// To close the popup when hit on esc button
document.onkeyup = function(evt) {
var key = evt.keyCode;
if (key == 27) {
view.popup.close();
}
};
})
.catch(function(error) {
console.log(error);
});
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
If you want to use a function as content, you have to set the outFields parameter to include the fields you want to use in the function. The selected feature is pass as a parameter to the function, and inside you use feature.graphic.attributes to access the attributes. This should work,
var template = {
title: "{Name}",
// content: "<span>Address: {Address}</span>"
content: function(feature) {
console.log(feature);
var div = document.createElement("div");
div.className = "myClass";
div.innerHTML = "<span>Address:"+feature.graphic.attributes.Address+"</span>";
return div;
},
outFields: ["Name", "Address"]
};
featureNavigationEnabled is deprecated as of version 4.15. Use Popup.visibleElements.featureNavigation instead.
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Popup.html#featureNavigationEnabled

How to trigger function on viewport visible with Vue viewport plugin

I am using an counter to display some numbers, but they load up when the page loads, so it loads unless I do some button to trigger it.
Found this viewport plugin (https://github.com/BKWLD/vue-in-viewport-mixin) but I weren't able to use it. That's what I need to do, trigger a function when I reach some element (entirely), how to achieve it?
You don't necessarily need a package to do this. Add an event listener to listen to the scroll event, and check if the element is in the viewport every time there's a scroll event. Example code below - note that I've added an animation to emphasize the "appear if in viewport" effect.
Codepen here.
new Vue({
el: '#app',
created () {
window.addEventListener('scroll', this.onScroll);
},
destroyed () {
window.removeEventListener('scroll', this.onScroll);
},
data () {
return {
items: [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12
],
offsetTop: 0
}
},
watch: {
offsetTop (val) {
this.callbackFunc()
}
},
methods: {
onScroll (e) {
console.log('scrolling')
this.offsetTop = window.pageYOffset || document.documentElement.scrollTop
},
isElementInViewport(el) {
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
},
callbackFunc() {
let items = document.querySelectorAll(".card");
for (var i = 0; i < items.length; i++) {
if (this.isElementInViewport(items[i])) {
items[i].classList.add("in-view");
}
}
}
}
})
.card {
height: 100px;
border: 1px solid #000;
visibility: hidden;
opacity: 0
}
.in-view {
visibility: visible;
opacity: 1;
animation: bounce-appear .5s ease forwards;
}
#keyframes bounce-appear {
0% {
transform: translateY(-50%) translateX(-50%) scale(0);
}
90% {
transform: translateY(-50%) translateX(-50%) scale(1.1);
}
100% {
tranform: translateY(-50%) translateX(-50%) scale(1);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" onscroll="onScroll">
<div v-for="item in items" class="card">
{{item}}
</div>
</div>
Another option is to use an intersection observer - I haven't explored this yet but this tutorial seems good: alligator.io/vuejs/lazy-image. Note that you will need a polyfill for IE.

disable mouse events on click for (this) and re-enable them for ('.class').not(this) - jquery

I need to keep the color of the clicked div until another div of the same class gets clicked. Right now I have this code:
$('.aaa').mouseenter(function () {
$(this).css('background', '#dddddd');
});
$('.aaa').mouseleave(function () {
$(this).css('background', '#888888');
});
$('.aaa').click(function () {
$(this).css('background', '#555555');
$('.aaa').not(this).css('background', '#111111');
$(this).off('mouseenter mouseleave');
$('.aaa').not(this).on('mouseenter mouseleave');
});
http://jsfiddle.net/5jUP7/
Only problem here is that I can't re-enable previously disabled events (for previously clicked elements).
How can this be achieved?
Put your handlers in functions, to make it easy to refer to them in multiple places.
$(".aaa").on({
mouseenter: mouseEnter,
mouseleave: mouseLeave
});
function mouseEnter() {
$(this).css('background', '#dddddd');
}
function mouseLeave() {
$(this).css('background', '#888888');
}
$(".aaa").click(function() {
$(this).css('background', '#555555');
$(".aaa").not(this).css('background', '#111111');
$(this).off('mouseenter mouseleave');
$(".aaa").not(this).on({
mouseenter: mouseEnter,
mouseleave: mouseLeave
});
});
FIDDLE
Have a look at this fiddle
You can do most of your work using simple CSS
HTML
<div class="aaa"></div>
<div class="aaa"></div>
<div class="aaa"></div>
<div class="aaa"></div>
<div class="aaa"></div>
<div class="aaa"></div>
<div class="aaa"></div>
CSS
.aaa {
display:block;
background:#888;
width: 300px;
height: 30px;
border: 1px solid #000;
}
.aaa:hover,
.aaa.disabled:hover{
display:block;
background:#ddd;
}
.aaa.active {
background:#111;
}
.aaa.disabled {
background:#555;
}
JAVASCRIPT
$('.aaa').click(function () {
$('.aaa').removeClass('active disabled');
$(this).addClass('active');
$('.aaa').not($(this)).addClass('disabled');
});
Don't disable anything. Just keep track of the previously clicked element.
var lastObjClicked;
function clicked(this){
var thisClass = this.className;
if( lastObjClicked.className == thisClass){
document.getElementById(lastObjClicked.id).style.color = '#FF0000';
document.getElementById(this.id).style.color = '#FF0000';
}else{
lastObjClicked = this;
}
}

Changing slider width from px to %

I've built a slider using css, javascript and html. I have a bit of javascript which controls the width and height of the div which contains the slider, as well as the slide speed. However, I want to make the width of the slider 100% of the screen, no matter what size screen. It is currently defined in pixels, but whenever i define it as % it simply disappears. Any ideas or suggestions?
Here is the code
<script type="text/javascript">
$(function() {
$('#one').ContentSlider({
width:1600,
heigth:400,
speed : 800,
easing : 'easeInOutBack'
});
});
</script>
HTML CODE
<title> </title>
<body>
<div id="one" class="contentslider">
<div class="cs_wrapper">
<div class="cs_slider">
<div class="cs_article">
Insert Images Here
</div><!-- End cs_article -->
</div><!-- End cs_slider -->
</div><!-- End cs_wrapper -->
</div><!-- End contentslider -->
<!-- Site JavaScript -->
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="ContentSlider.js"></script>
<script type="text/javascript" src="ContentSlider.js"></script>
<script type="text/javascript">
$(function() {
$('#one').ContentSlider({
width:1600,
heigth:600,
speed : 800,
easing : 'easeInOutBack'
});
});
</script>
<script src="ContentSlider.js" type="text/javascript"></script>
<script src="ContentSlider.js" type="text/javascript"></script>
</body>
CSS CODE
body {
font:80%/1.25em arial, sans-serif;
letter-spacing:.1em;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: 0px;
width:100%;
height:100%
}
h1, h2, p, pre {
display:block;
width:99%;
}
.contentslider {
padding:10px; /* This acts as a border for the content slider */
background:#333; /* This is the color of said border */
}
.contentslider {
position:relative;
display:block;
width:100%;
height:100%;
margin:0 auto;
overflow:hidden
}
.cs_wrapper {
position:relative;
display:block;
width:100%;
height:100%;
margin:0;
padding:0;
overflow:hidden;
}
.cs_slider {
position:absolute;
width:10000px;
height:100%;
margin:0;
padding:0;
}
JAVASCRIPT CODE
(function($) {
$.fn.ContentSlider = function(options)
{
var defaults = {
leftBtn : 'cs_leftImg.jpg',
rightBtn : 'cs_rightImg.jpg',
width : '900px',
height : '400px',
speed : 400,
easing : 'easeOutQuad',
textResize : false,
IE_h2 : '26px',
IE_p : '11px'
}
var defaultWidth = defaults.width;
var o = $.extend(defaults, options);
var w = parseInt(o.width);
var n = this.children('.cs_wrapper').children('.cs_slider').children('.cs_article').length;
var x = -1*w*n+w; // Minimum left value
var p = parseInt(o.width)/parseInt(defaultWidth);
var thisInstance = this.attr('id');
var inuse = false; // Prevents colliding animations
function moveSlider(d, b)
{
var l = parseInt(b.siblings('.cs_wrapper').children('.cs_slider').css('left'));
if(isNaN(l)) {
var l = 0;
}
var m = (d=='left') ? l-w : l+w;
if(m<=0&&m>=x) {
b
.siblings('.cs_wrapper')
.children('.cs_slider')
.animate({ 'left':m+'px' }, o.speed, o.easing, function() {
inuse=false;
});
if(b.attr('class')=='cs_leftBtn') {
var thisBtn = $('#'+thisInstance+' .cs_leftBtn');
var otherBtn = $('#'+thisInstance+' .cs_rightBtn');
} else {
var thisBtn = $('#'+thisInstance+' .cs_rightBtn');
var otherBtn = $('#'+thisInstance+' .cs_leftBtn');
}
if(m==0||m==x) {
thisBtn.animate({ 'opacity':'0' }, o.speed, o.easing, function() { thisBtn.hide(); });
}
if(otherBtn.css('opacity')=='0') {
otherBtn.show().animate({ 'opacity':'1' }, { duration:o.speed, easing:o.easing });
}
}
}
function vCenterBtns(b)
{
// Safari and IE don't seem to like the CSS used to vertically center
// the buttons, so we'll force it with this function
var mid = parseInt(o.height)/2;
b
.find('.cs_leftBtn img').css({ 'top':mid+'px', 'padding':0 }).end()
.find('.cs_rightBtn img').css({ 'top':mid+'px', 'padding':0 });
}
return this.each(function() {
$(this)
// Set the width and height of the div to the defined size
.css({
width:o.width,
height:o.height
})
// Add the buttons to move left and right
.prepend('<img src="'+o.leftBtn+'" />')
.append('<img src="'+o.rightBtn+'" />')
// Dig down to the article div elements
.find('.cs_article')
// Set the width and height of the div to the defined size
.css({
width:o.width,
height:o.height
})
.end()
.find('.cs_leftBtn')
.css('opacity','0')
.hide()
.end()
.find('.cs_rightBtn')
.hide()
.animate({ 'width':'show' });
if(o.textResize===true) {
var h2FontSize = $(this).find('h2').css('font-size');
var pFontSize = $(this).find('p').css('font-size');
$.each(jQuery.browser, function(i) {
if($.browser.msie) {
h2FontSize = o.IE_h2;
pFontSize = o.IE_p;
}
});
$(this).find('h2').css({ 'font-size' : parseFloat(h2FontSize)*p+'px', 'margin-left' : '66%' });
$(this).find('p').css({ 'font-size' : parseFloat(pFontSize)*p+'px', 'margin-left' : '66%' });
$(this).find('.readmore').css({ 'font-size' : parseFloat(pFontSize)*p+'px', 'margin-left' : '66%' });
}
var leftBtn = $(this).children('.cs_leftBtn');
leftBtn.bind('click', function() {
if(inuse===false) {
inuse = true;
moveSlider('right', leftBtn);
}
return false;
});
var rightBtn = $(this).children('.cs_rightBtn');
rightBtn.bind('click', function() {
if(inuse===false) {
inuse=true;
moveSlider('left', rightBtn);
}
return false;
});
vCenterBtns($(this));
});
}
})(jQuery)
You could change width to $(this).parent().innerWidth(), but that will only work on init, if the user resizes it will not change. This is because the plugin only sets a size on init
Might be a better idea to search for a fullwidth slider, these often fix some issues which arrise with fullwidths and resizing

Sticky navigation which appears on scroll

I am trying to create a menu which is hidden but appears, fixed to the top, once the user begins scrolling down the page. So far I have managed to create a menu which sticks to the top upon scrolling but am stuck on how to hide this menu initially.
This is the code I am using so far:
(I am using wordpress-headway)
JQuery:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($) {
//STICKY NAV
var isMobile = {
Android: function() {
return navigator.userAgent.match(/Android/i) ? true : false;
},
BlackBerry: function() {
return navigator.userAgent.match(/BlackBerry/i) ? true : false;
},
iOS: function() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
},
Windows: function() {
return navigator.userAgent.match(/IEMobile/i) ? true : false;
},
any: function() {
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
}
};
//Calculate the height of <header>
//Use outerHeight() instead of height() if have padding
var aboveHeight = $('.top-row').outerHeight();
//when scroll
$(window).scroll(function(){
//if scrolled down more than the header’s height but this isn't mobile
if ($(window).scrollTop() > aboveHeight && !isMobile.any()){
// if yes, add “fixed” class to the <nav>
// add padding top to the #content
// (value is same as the height of the nav)
$('.block-type-navigation').addClass('fixed').css('top','0').next()
.css('padding-top','42px');
} else {
// when scroll up or less than aboveHeight,
// remove the “fixed” class, and the padding-top
$('.block-type-navigation').removeClass('fixed').next()
.css('padding-top','0');
}
});
});
</script>
CSS:
.fixed {
position:fixed !important;
left: 0;
text-align: center;
}
.fixed .block-content {
display: inline-block;
text-align: left;
width: 940px; /* This should be the width of your grid!!! */
float:none;
}
.fixed {
position:fixed !important;
left: 0;
text-align: center;
display: block !important;
}
It's driving me crazy so I'd appreciate ANY help!
Thank you!
If you don't want the nav to show unless the user has scrolled passed a certain point then couldn't it always be fixed just off the top of the screen:
.menu {
position:fixed;
top:-42px;
}
then shown or hidden by toggling a class
.menu.is-visible {
top:0;
}
using a scroll listener.
$win = $(window);
$win.on('scroll', function() {
$(".menu").toggleClass('is-visible', $win.scrollTop() > 42);
});
You could even add some CSS animation to the top property
.menu {
-webkit-transition: top 0.2s ease-in-out;
}
to get a cool transition.
Note: All this code is typed out right in here and not tested.
Note: You should definitely put a throttle on the scroll handler too.