Button in update panel will not fire from javascript - javascript

If the function is called and the button is inside an update panel it will not fire (although it works if clicked directly) - place it outside the update panel and the script works.
Any ideas?
<div>
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:Button ID="GridViewLBClicked" runat="server" />
</ContentTemplate>
<%--
<Triggers>
<asp:AsyncPostBackTrigger ControlID="GridViewLBClicked" EventName="Click" />
</Triggers>--%>
</asp:UpdatePanel>
</div>
<script>
function RaiseEvent_Click() {
document.getElementById('<%=GridViewLBClicked.ClientID%>').click();
alert('It was clicked');
}
</script>
Re Joce
I suspect that some other loaded javascript may be causing the problem as I have had the same thing working before - here is the other loaded script
function LinkButtonClick(){ alert('This was clicked'); __doPostBack('ContentPlaceHolder1_GridViewLBClicked', ''); } var sessionTimeoutWarning = '18'; var sessionTimeout = '20'; var timeOnPageLoad = new Date(); var sessionWarningTimer = null; var redirectToWelcomePageTimer = null; var sessionWarningTimer = setTimeout('SessionWarning()', parseInt(sessionTimeoutWarning) * 60 * 1000); var redirectToWelcomePageTimer = setTimeout('RedirectToWelcomePage()', parseInt(sessionTimeout) * 60 * 1000); function SessionWarning() { var minutesForExpiry = (parseInt(sessionTimeout) - parseInt(sessionTimeoutWarning)); var message = 'Your session will expire in another ' + minutesForExpiry + ' mins. Do you want to extend the session?'; $('#SessionModal').modal('show'); var currentTime = new Date(); var timeForExpiry = timeOnPageLoad.setMinutes(timeOnPageLoad.getMinutes() + parseInt(sessionTimeout)); if (Date.parse(currentTime) > timeForExpiry) { window.location = 'http://localhost:53818/Logout_Landing/SessionEnded'; } } function RedirectToWelcomePage() { window.location = 'http://localhost:53818/Logout_Landing/SessionEnded'; } $(document).ready(function(){ var divWidth = document.getElementById('imageHeader').clientWidth; var imagePadding = 75; var imageOneWidth = document.getElementById('TopImage_1').width; var imageTwoWidth = document.getElementById('TopImage_2').width; var imageThreeWidth = document.getElementById('TopImage_3').width; var imageFourWidth = document.getElementById('TopImage_4').width; var imageFiveWidth = document.getElementById('TopImage_5').width; var totalImageWidth = imagePadding + imageOneWidth + imageTwoWidth + imageThreeWidth + imageFourWidth + imageFiveWidth; var widthDifference = divWidth - totalImageWidth; var percentDifference = Math.round(widthDifference / divWidth * 100); var imageOne = document.getElementById('TopImage_1'); var imageTwo = document.getElementById('TopImage_2'); var imageThree = document.getElementById('TopImage_3'); var imageFour = document.getElementById('TopImage_4'); var imageFive = document.getElementById('TopImage_5'); var currentHeight = imageOne.height; imageOne.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageTwo.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageThree.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageFour.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageFive.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; }); window.onresize = function () { var divWidth = document.getElementById('imageHeader').clientWidth; var imagePadding = 75; var imageOneWidth = document.getElementById('TopImage_1').width; var imageTwoWidth = document.getElementById('TopImage_2').width; var imageThreeWidth = document.getElementById('TopImage_3').width; var imageFourWidth = document.getElementById('TopImage_4').width; var imageFiveWidth = document.getElementById('TopImage_5').width; var totalImageWidth = imagePadding + imageOneWidth + imageTwoWidth + imageThreeWidth + imageFourWidth + imageFiveWidth; var widthDifference = divWidth - totalImageWidth; var percentDifference = Math.round(widthDifference / divWidth * 100); var imageOne = document.getElementById('TopImage_1'); var imageTwo = document.getElementById('TopImage_2'); var imageThree = document.getElementById('TopImage_3'); var imageFour = document.getElementById('TopImage_4'); var imageFive = document.getElementById('TopImage_5'); var currentHeight = imageOne.height; imageOne.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageTwo.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageThree.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageFour.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; imageFive.style.height = Math.round(currentHeight + (currentHeight / 100 * percentDifference)) + "px"; }; $(document).ready(function(){ $('body').append("<style>#media (max-width: 1025px) { .navbar-header { float: none; } .navbar-left, .navbar-right { float: none !important; } .navbar-toggle { display: block; } .navbar-collapse { border-top: 1px solid transparent; box-shadow: inset 0 1px 0 rgba(255,255,255,0.1); } .navbar-fixed-top { top: 0; border-width: 0 0 1px; } .navbar-collapse.collapse { display: none !important; } .navbar-nav { float: none !important; margin-top: 7.5px; } .navbar-nav > li { float: none; } .navbar-nav > li > a { padding-top: 10px; padding-bottom: 10px; } .collapse.in { display: block !important; } .navbar-collapse.in { overflow-y: auto !important; } .navbar-nav .open .dropdown-menu { position: static; float: none; width: auto; margin-top: 0; background-color: transparent; border: 0; box-shadow: none; } .navbar-nav .open .dropdown-menu > li > a, .navbar-nav .open .dropdown-menu .dropdown-header { padding: 5px 15px 5px 25px; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { color: #999; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { color: #fff; background-color: transparent; background-image: none; } } </style>"); });
UPDATE
This is odd - if I run this
Dim SB As New StringBuilder
SB.Append("function LinkButtonClick(){ ")
SB.Append("$get('" & GridViewLBClicked.ClientID & "').click(); ")
SB.Append("} ")
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "LoadLinkButton", SB.ToString, True)
It won't work - but if I add an alert it runs fine
Dim SB As New StringBuilder
SB.Append("function LinkButtonClick(){ ")
SB.Append("$get('" & GridViewLBClicked.ClientID & "').click(); ")
SB.Append("alert('it was clicked'); ")
SB.Append("} ")
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "LoadLinkButton", SB.ToString, True)
FURTHER UPDATE
This works - I tried document.ready but that didn't - don't like using setTimeout as who knows what will happen out in the wild, so I would welcome a more robust solution
Private Sub LoadLinkButtonClick()
Try
Dim SB As New StringBuilder
SB.Append("function LinkButtonClick(){ ")
SB.Append("setTimeout(function() { ")
SB.Append("$get('" & GridViewLBClicked.ClientID & "').click(); ")
SB.Append(" }, 300); ")
SB.Append("} ")
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "LoadLinkButton", SB.ToString, True)
Catch ex As Exception
Dim vError As New SendError
vError.MailError("1229", PageName, ex)
End Try
End Sub

You could try to call __doPostBack() by sending the UniqueID of the button.
function RaiseEvent_Click() {
__doPostBack('<%=GridViewLBClicked.UniqueID%>', '');
alert('It was clicked');
}
Edit:
I tried this code snippet and it works fine:
<input type="button" id="btnClickMe" value="Click me" />
<asp:UpdatePanel runat="server" ID="uPanel1">
<ContentTemplate>
<asp:TextBox runat="server" ID="txtInside"></asp:TextBox>
<asp:Button runat="server" ID="btnPostInside" />
</ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
$("#btnClickMe").on("click", function() {
$get("<%=btnPostInside.ClientID %>").click();
});
</script>
Can you give us more of your code?

Related

How to drag images in JS

I have a large background image and some much smaller images for the user to drag around on the background. I need this to be efficient in terms of performance, so i'm trying to avoid libraries. I'm fine with drag 'n' drop if it work's well, but im trying to get drag.
Im pretty much trying to do this. But after 8 years there must be a cleaner way to do this right?
I currently have a drag 'n' drop system that almost works, but when i drop the smaller images, they are just a little off and it's very annoying. Is there a way to fix my code, or do i need to take a whole different approach?
This is my code so far:
var draggedPoint;
function dragStart(event) {
draggedPoint = event.target; // my global var
}
function drop(event) {
event.preventDefault();
let xDiff = draggedPoint.x - event.pageX;
let yDiff = draggedPoint.y - event.pageY;
let left = draggedPoint.style.marginLeft; // get margins
let top = draggedPoint.style.marginTop;
let leftNum = Number(left.substring(0, left.length - 2)); // cut off px from the end
let topNum = Number(top.substring(0, top.length - 2));
let newLeft = leftNum - xDiff + "px" // count new margins and put px back to the end
let newTop = topNum - yDiff + "px"
draggedPoint.style.marginLeft = newLeft;
draggedPoint.style.marginTop = newTop;
}
function allowDrop(event) {
event.preventDefault();
}
let imgs = [
"https://upload.wikimedia.org/wikipedia/commons/6/67/Orange_juice_1_edit1.jpg",
"https://upload.wikimedia.org/wikipedia/commons/f/ff/Solid_blue.svg",
"https://upload.wikimedia.org/wikipedia/commons/b/b4/Litoria_infrafrenata_-_Julatten.jpg"
]
/* my smaller images: */
for (let i = 0; i < 6; i++) {
let sensor = document.createElement("img");
sensor.src = imgs[i % imgs.length];
sensor.alt = i;
sensor.draggable = true;
sensor.classList.add("sensor");
sensor.style.marginLeft = `${Math.floor(Math.random() * 900)}px`
sensor.style.marginTop = `${Math.floor(Math.random() * 500)}px`
sensor.onclick = function() {
sensorClick(logs[i].id)
};
sensor.addEventListener("dragstart", dragStart, null);
let parent = document.getElementsByClassName("map")[0];
parent.appendChild(sensor);
}
<!-- my html: -->
<style>
.map {
width: 900px;
height: 500px;
align-content: center;
margin: 150px auto 150px auto;
}
.map .base {
position: absolute;
width: inherit;
height: inherit;
}
.map .sensor {
position: absolute;
width: 50px;
height: 50px;
}
</style>
<div class="map" onDrop="drop(event)" ondragover="allowDrop(event)">
<img src='https://upload.wikimedia.org/wikipedia/commons/f/f7/Plan-Oum-el-Awamid.jpg' alt="pohja" class="base" draggable="false">
<div>
With the answers from here and some time i was able to get a smooth drag and click with pure js.
Here is a JSFiddle to see it in action.
let maxLeft;
let maxTop;
const minLeft = 0;
const minTop = 0;
let timeDelta;
let imgs = [
"https://upload.wikimedia.org/wikipedia/commons/6/67/Orange_juice_1_edit1.jpg",
"https://upload.wikimedia.org/wikipedia/commons/f/ff/Solid_blue.svg",
"https://upload.wikimedia.org/wikipedia/commons/b/b4/Litoria_infrafrenata_-_Julatten.jpg"
]
var originalX;
var originalY;
window.onload = function() {
document.onmousedown = startDrag;
document.onmouseup = stopDrag;
}
function sensorClick () {
if (Date.now() - timeDelta < 150) { // check that we didn't drag
createPopup(this);
}
}
// create a popup when we click
function createPopup(parent) {
let p = document.getElementById("popup");
if (p) {
p.parentNode.removeChild(p);
}
let popup = document.createElement("div");
popup.id = "popup";
popup.className = "popup";
popup.style.top = parent.y - 110 + "px";
popup.style.left = parent.x - 75 + "px";
let text = document.createElement("span");
text.textContent = parent.id;
popup.appendChild(text);
var map = document.getElementsByClassName("map")[0];
map.appendChild(popup);
}
// when our base is loaded
function baseOnLoad() {
var map = document.getElementsByClassName("map")[0];
let base = document.getElementsByClassName("base")[0];
maxLeft = base.width - 50;
maxTop = base.height - 50;
/* my smaller images: */
for (let i = 0; i < 6; i++) {
let sensor = document.createElement("img");
sensor.src = imgs[i % imgs.length];
sensor.alt = i;
sensor.id = i;
sensor.draggable = true;
sensor.classList.add("sensor");
sensor.classList.add("dragme");
sensor.style.left = `${Math.floor(Math.random() * 900)}px`
sensor.style.top = `${Math.floor(Math.random() * 500)}px`
sensor.onclick = sensorClick;
let parent = document.getElementsByClassName("map")[0];
parent.appendChild(sensor);
}
}
function startDrag(e) {
timeDelta = Date.now(); // get current millis
// determine event object
if (!e) var e = window.event;
// prevent default event
if(e.preventDefault) e.preventDefault();
// IE uses srcElement, others use target
targ = e.target ? e.target : e.srcElement;
originalX = targ.style.left;
originalY = targ.style.top;
// check that this is a draggable element
if (!targ.classList.contains('dragme')) return;
// calculate event X, Y coordinates
offsetX = e.clientX;
offsetY = e.clientY;
// calculate integer values for top and left properties
coordX = parseInt(targ.style.left);
coordY = parseInt(targ.style.top);
drag = true;
document.onmousemove = dragDiv; // move div element
return false; // prevent default event
}
function dragDiv(e) {
if (!drag) return;
if (!e) var e = window.event;
// move div element and check for borders
let newLeft = coordX + e.clientX - offsetX;
if (newLeft < maxLeft && newLeft > minLeft) targ.style.left = newLeft + 'px'
let newTop = coordY + e.clientY - offsetY;
if (newTop < maxTop && newTop > minTop) targ.style.top = newTop + 'px'
return false; // prevent default event
}
function stopDrag() {
if (typeof drag == "undefined") return;
if (drag) {
if (Date.now() - timeDelta > 150) { // we dragged
let p = document.getElementById("popup");
if (p) {
p.parentNode.removeChild(p);
}
} else {
targ.style.left = originalX;
targ.style.top = originalY;
}
}
drag = false;
}
.map {
width: 900px;
height: 500px;
margin: 50px
position: relative;
}
.map .base {
position: absolute;
width: inherit;
height: inherit;
}
.map .sensor {
display: inline-block;
position: absolute;
width: 50px;
height: 50px;
}
.dragme {
cursor: move;
left: 0px;
top: 0px;
}
.popup {
position: absolute;
display: inline-block;
width: 200px;
height: 100px;
background-color: #9FC990;
border-radius: 10%;
}
.popup::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -10px;
border-width: 10px;
border-style: solid;
border-color: #9FC990 transparent transparent transparent;
}
.popup span {
width: 90%;
margin: 10px;
display: inline-block;
text-align: center;
}
<div class="map" width="950px" height="500px">
<img src='https://upload.wikimedia.org/wikipedia/commons/f/f7/Plan-Oum-el-Awamid.jpg' alt="pohja" class="base" draggable="false" onload="baseOnLoad()">
<div>

Draw a line from one element to multiple elements on click

I'm trying to draw a line from an element [.identifier] to the clicked element [ A, B, C series ]. I'm able to display the line but in the other direction, not sure why it is displaying in such a direction.
Here is my fiddle: https://jsfiddle.net/SampathPerOxide/u2afymxs/11/
Can someone help me to display a line between ".identifier" and the respective series element?
Expected result on clicking A series:
on clicking B series:
$('.seriesli').click(function() {
function adjustLine(from, to, line) {
var fT = from.offsetTop + from.offsetHeight / 2;
var tT = to.offsetTop + to.offsetHeight / 2;
var fL = from.offsetLeft + from.offsetWidth / 2;
var tL = to.offsetLeft + to.offsetWidth / 2;
var CA = Math.abs(tT - fT);
var CO = Math.abs(tL - fL);
var H = Math.sqrt(CA * CA + CO * CO);
var ANG = 180 / Math.PI * Math.acos(CA / H);
if (tT > fT) {
var top = (tT - fT) / 2 + fT;
} else {
var top = (fT - tT) / 2 + tT;
}
if (tL > fL) {
var left = (tL - fL) / 2 + fL;
} else {
var left = (fL - tL) / 2 + tL;
}
if ((fT < tT && fL < tL) || (tT < fT && tL < fL) || (fT > tT && fL > tL) || (tT > fT && tL > fL)) {
ANG *= -1;
}
top -= H / 2;
line.style["-webkit-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-moz-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-ms-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-o-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-transform"] = 'rotate(' + ANG + 'deg)';
line.style.top = top + 'px';
line.style.left = left + 'px';
line.style.height = H + 'px';
}
adjustLine(
document.getElementById('div1'),
document.getElementById('div2'),
document.getElementById('line')
);
});
.identifier {
width: 10px;
height: 10px;
background-color: red;
position: absolute;
right: 45%;
top: 50%;
}
.series-div {
position: absolute;
right: 5%;
bottom: 30%;
}
.series-ul li {
list-style: none;
color: grey;
font-size: 1em;
font-weight: 600;
border: 2px solid grey;
display: table;
padding: 0.3em 0.1em;
text-align: center;
margin: 0.5em;
cursor: pointer;
}
#line {
position: absolute;
width: 2px;
margin-top: -1px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="position;relative;">
<div class="identifier" id="div2"></div>
<div class="series-div">
<ul class="series-ul">
<li class="seriesli" id="div1">A series</li>
<li class="seriesli">B series</li>
<li class="seriesli">C series</li>
</ul>
</div>
<div id="line"></div>
<img src="https://stat.overdrive.in/wp-content/odgallery/2020/06/57263_2020_Mercedes_Benz_GLS.jpg" class="img-responsive firstcar-detail" style="width: 100%;">
</div>
I fixed your fiddle: https://jsfiddle.net/c4ju6a0p/
Code changes:
// Get actual position relative to viewport.
// See https://stackoverflow.com/a/11396681/117030
fromBCR = from.getBoundingClientRect();
toBCR = to.getBoundingClientRect();
var fT = fromBCR.top + from.offsetHeight / 2;
var tT = toBCR.top + to.offsetHeight / 2;
// Don't add offsetWidth. This connects to the middle, not the left edge.
var fL = fromBCR.left //+ from.offsetWidth / 2;
var tL = toBCR.left + to.offsetWidth / 2;
The problem was the line was being calculated with the incorrect position due to relative positioning. This can be seen more clearly when the relative CSS is commented out: https://jsfiddle.net/vust5nxf/
Also, don't add the offsetWidth if you want the line to go to the left edge.
update: didn't notice the code snippet... applied changes there, too. I also made one more change:
You need to pass the element that was clicked to adjustLine(), otherwise currently the line is drawn between the same two elements every time because the elements are hardcoded with ids.
As a style note: I would move the definition of function adjustLine() outside the click handler. This will make the code easier to read, and the function will only be created once, instead of every time a click is handled.
adjustLine(
this, // Element that was clicked.
document.getElementById('div2'),
document.getElementById('line')
);
$('.seriesli').click(function() {
function adjustLine(from, to, line) {
// Get actual position relative to viewport.
// See https://stackoverflow.com/a/11396681/117030
fromBCR = from.getBoundingClientRect();
toBCR = to.getBoundingClientRect();
var fT = fromBCR.top + from.offsetHeight / 2;
var tT = toBCR.top + to.offsetHeight / 2;
// Don't add offsetWidth. This connects to the middle, not the left edge.
var fL = fromBCR.left //+ from.offsetWidth / 2;
var tL = toBCR.left + to.offsetWidth / 2;
var CA = Math.abs(tT - fT);
var CO = Math.abs(tL - fL);
var H = Math.sqrt(CA * CA + CO * CO);
var ANG = 180 / Math.PI * Math.acos(CA / H);
if (tT > fT) {
var top = (tT - fT) / 2 + fT;
} else {
var top = (fT - tT) / 2 + tT;
}
if (tL > fL) {
var left = (tL - fL) / 2 + fL;
} else {
var left = (fL - tL) / 2 + tL;
}
if ((fT < tT && fL < tL) || (tT < fT && tL < fL) || (fT > tT && fL > tL) || (tT > fT && tL > fL)) {
ANG *= -1;
}
top -= H / 2;
line.style["-webkit-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-moz-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-ms-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-o-transform"] = 'rotate(' + ANG + 'deg)';
line.style["-transform"] = 'rotate(' + ANG + 'deg)';
line.style.top = top + 'px';
line.style.left = left + 'px';
line.style.height = H + 'px';
}
adjustLine(
this, // Element that was clicked.
document.getElementById('div2'),
document.getElementById('line')
);
});
.identifier {
width: 10px;
height: 10px;
background-color: red;
position: absolute;
right: 45%;
top: 50%;
}
.series-div {
position: absolute;
right: 5%;
bottom: 30%;
}
.series-ul li {
list-style: none;
color: grey;
font-size: 1em;
font-weight: 600;
border: 2px solid grey;
display: table;
padding: 0.3em 0.1em;
text-align: center;
margin: 0.5em;
cursor: pointer;
}
#line {
position: absolute;
width: 2px;
margin-top: -1px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="position;relative;">
<div class="identifier" id="div2"></div>
<div class="series-div">
<ul class="series-ul">
<li class="seriesli" id="div1">A series</li>
<li class="seriesli">B series</li>
<li class="seriesli">C series</li>
</ul>
</div>
<div id="line"></div>
<img src="https://stat.overdrive.in/wp-content/odgallery/2020/06/57263_2020_Mercedes_Benz_GLS.jpg" class="img-responsive firstcar-detail" style="width: 100%;">
</div>

JavaScript: array values are automatically getting deleted

I am making an image slider/ carousel. If you drag it, the images will get momentum and will keep on moving for sometime. There are few issues, one of them is getting the following error frequently: "glide.js:104 Uncaught TypeError: Cannot read property '1' of undefined". JavaScript here is supposed to access a value that is inside an array, but since the array is empty, i'm getting this error. However, the array shouldn't be empty, as the code that empties the array, comes later. Project
var projectContainer = document.querySelector(".project-container")
var projects = document.querySelectorAll(".project")
// exProject is declared so that every project has same transalte to refer to instead of referring to their individual transalations
var exProject = projects[0]
var style = window.getComputedStyle(exProject)
exProject.currentTranslationX = (new WebKitCSSMatrix(style.webkitTransform)).m41
// after dragging, do not add force if mouse has not been moved for pauseTime milliseconds
pauseTime = 40
lastMousePositions = []
//this will set margin to 80, i thought this is better than hardcoding
elementAOffset = projects[0].offsetLeft;
elementBOffset = projects[1].offsetLeft;
elementAWidth = parseInt(getComputedStyle(projects[0]).width)
margin = (elementBOffset - (elementAOffset + elementAWidth))
//projects will teleport to other side if they hit either of the boundary
LeftSideBoundary = -(elementAWidth)
RightSideBoundary = (elementAWidth * (projects.length)) + (margin * (projects.length))
RightSidePosition = RightSideBoundary - elementAWidth;
//how often to update speed (in milliseconds)
intervalTime = 15
//how much speed is lost at every interTime milliseconds
frictionPerMilliseconds = (20 / 1000);
frictionPerMilliseconds *= intervalTime * 5;
mouseInitialPosition = 0;
mouseIsDown = false
startTime = 0;
speed = 0;
mousemoving = false
projectContainer.addEventListener("mousedown", e => {
mouseInitialPosition = e.clientX
mouseIsDown = true;
startDate = new Date();
startTime = startDate.getTime();
lastMousePositions.push(e.clientX)
speed = 0
})
projectContainer.addEventListener("mousemove", e => {
if (!mouseIsDown) return;
distanceTravelled = e.clientX - mouseInitialPosition
if (speed === 0) {
projects.forEach(project => {
project.style.transform = 'translateX(' + ((exProject.currentTranslationX) + ((distanceTravelled))) + 'px)';
shiftPosition(project, distanceTravelled)
})
}
if ((new Date()).getTime() - lastMousePositions[lastMousePositions.length - 1][1] > 50) {
lastMousePositions = []
}
pushToMousePositions(e.clientX)
})
projectContainer.addEventListener("mouseup", e => {
dragEnd(e);
})
projectContainer.addEventListener("mouseleave", e => {
dragEnd(e);
})
function dragEnd(e) {
finalPosition = e.clientX;
distanceTravelled = finalPosition - mouseInitialPosition
endDate = new Date();
endTime = endDate.getTime();
timeElapsed = (endTime - startTime) / 1000
mouseIsDown = false;
tempSpeed = distanceTravelled / timeElapsed
tempSpeed = (tempSpeed / 1000) * 15
if (tempSpeed < 0 && speed < 0) {
if (tempSpeed < speed) {
speed = tempSpeed
}
} else if (tempSpeed > 0 && speed > 0) {
if (tempSpeed > speed) {
speed = tempSpeed
}
} else {
speed = tempSpeed
}
if (lastMousePositions.length === 0) {
console.log("error gonna pop up")
}
if (endTime - (lastMousePositions[lastMousePositions.length - 1])[1] >= pauseTime) {
speed = 0
}
mouseExit(e)
intervalFunction = setInterval(move, intervalTime)
}
function mouseExit(e) {
mouseIsDown = false
lastMousePositions = []
var style = window.getComputedStyle(exProject)
exProject.currentTranslationX = (new WebKitCSSMatrix(style.webkitTransform)).m41
projects.forEach(project => {
project.style.transform = 'translateX(' + (exProject.currentTranslationX) + 'px)'
shiftPosition(project, 0)
})
}
function move() {
if (speed === 0) {
clearInterval(intervalFunction)
} else if (Math.abs(speed) <= frictionPerMilliseconds) {
style = window.getComputedStyle(exProject)
exProject.currentTranslationX = (new WebKitCSSMatrix(style.webkitTransform)).m41
projects.forEach(project => {
project.style.transform = 'translateX(' + ((exProject.currentTranslationX) + (speed)) + 'px)'
shiftPosition(project, 0)
})
speed = 0
} else {
style = window.getComputedStyle(exProject)
exProject.currentTranslationX = (new WebKitCSSMatrix(style.webkitTransform)).m41
projects.forEach(project => {
project.style.transform = 'translateX(' + ((exProject.currentTranslationX) + (speed)) + 'px)'
shiftPosition(project, 0)
})
speed < 0 ? speed += frictionPerMilliseconds : speed -= frictionPerMilliseconds;
}
}
function pushToMousePositions(positionToPush) {
if (lastMousePositions.length < 50) {
lastMousePositions.push([positionToPush, (new Date()).getTime()])
} else {
lastMousePositions.shift();
lastMousePositions.push([positionToPush, (new Date()).getTime()])
}
}
function shiftPosition(project, mouseMovement) {
//projectVisualPosition is relative to the left border of container div
projectVisualPosition = project.offsetLeft + (exProject.currentTranslationX + mouseMovement)
tempStyle = window.getComputedStyle(project)
if (projectVisualPosition < LeftSideBoundary) {
project.style.left = ((parseInt(tempStyle.left) + RightSidePosition + 350) + 'px')
}
if (projectVisualPosition > RightSidePosition) {
project.style.left = ((parseInt(tempStyle.left)) - (RightSidePosition + elementAWidth)) + 'px'
}
}
*,
*::before,
*::after {
margin: 0px;
padding: 0px;
box-sizing: border-box;
font-size: 0px;
user-select: none;
font-size: 0;
}
body {
position: relative;
}
.project-container {
font-size: 0px;
position: relative;
width: 1500px;
height: 400px;
background-color: rgb(15, 207, 224);
margin: auto;
margin-top: 60px;
white-space: nowrap;
overflow: hidden;
padding-left: 40px;
padding-right: 40px;
}
.project {
font-size: 100px;
margin: 40px;
display: inline-block;
height: 300px;
width: 350px;
background-color: red;
border: black 3px solid;
user-select: none;
position: relative;
}
<div class="project-container">
<div class="project">1</div>
<div class="project">2</div>
<div class="project">3</div>
<div class="project">4</div>
<div class="project">5</div>
<div class="project">6</div>
<div class="project">7</div>
<div class="project">8</div>
</div>
The problem is this:
projectContainer.addEventListener("mouseleave", (e) => {
dragEnd(e);
});
You're calling dragEnd(e) when the cursor leaves projectContainer. That can happen while the lastMousePositions array is still empty.
Option 1: Don't call dragEnd(e) on the mouseleave event
Option 2: Inside the dragEnd(e) function, check that the array is not empty before you try to access its elements:
if (lastMousePositions.length !== 0) {
if (
endTime - lastMousePositions[lastMousePositions.length - 1][1] >=
pauseTime
) {
speed = 0;
}
}

Need help to limit how many tiles and target spawn in this game

I got some simple bomberman game from code pen.For my study,i need to limit how many tiles and target.For tiles max 32 and target 7 (tiles grey & target red).
Here the source : codepen.io/Digiben/pen/oGYGrx
I dont understand how the script create the target and tiles with random algoritm.
Thanks for anyone who look this thread.
window.onload = function(){
//Map Kelas
class Map {
constructor (nbX, nbY, tileSize){
this.nbX = nbX;
this.nbY = nbY;
this.mapArray = new Array(this.nbX);
this.tileSize = tileSize;
this.map = document.getElementById('map');
}
init() {
console.log('Map size: ' + this.nbX * this.nbY);
let i = 0;
let j = 0;
let bool = null;
this.map.style.width = (this.tileSize * this.nbX) + 'px';
this.map.style.height = this.tileSize * this.nbY + 'px';
for (i = 0; i < this.nbX; i++) {
this.mapArray[i] = new Array(this.nbY);
for (j = 0; j < this.nbY; j++) {
bool = Math.random() >= 0.7 ? true : false;
if (bool) {
for (var z = Things.length - 1; i >= 0; i-) {
Things[i]
}
} else if (!bool) {
this.mapArray[i][j] = 1;
}
}
}
}
appendTile(i, j) {
let tile = document.createElement('div');
this.map.appendChild(tile);
tile.style.width = this.tileSize + 'px';
tile.style.height = this.tileSize + 'px';
tile.classList.add('tile');
tile.style.left = (i * this.tileSize) + 'px';
tile.style.top = (j * this.tileSize) + 'px';
}
getMapArray () {
return this.mapArray;
}
getMapSize () {
return {sizeX: this.nbX, sizeY:this.nbY}
}
}
//Create Target
class Target {
constructor (map, tileSize) {
this.mapArray = map.getMapArray();
this.playerSpace = map.getMapSize();
this.targetsArray = new Array();
this.possiblePositionToStartX = new Array();
this.possiblePositionToStartY = new Array();
this.tileSize = tileSize;
this.map = document.getElementById('map');
this.totalTargets = 0;
}
getTotalTargets(){
return this.totalTargets;
}
//Show Total Target
showTotalTargets () {
let totalDiv = document.querySelector('#score strong');
totalDiv.innerHTML = ' / ' + this.totalTargets;
}
showTargets(i, j) {
let tile = document.createElement('div');
this.map.appendChild(tile);
tile.classList.add('target');
tile.style.width = this.tileSize + 'px';
tile.style.height = this.tileSize + 'px';
// set attribute to identify the target when we need to remove it
tile.setAttribute('data-pos', i + ':' + j );
// positionning and styling
tile.style.left = (i * this.tileSize) + 'px';
tile.style.top = (j * this.tileSize) + 'px';
tile.style.backgroundColor = 'red';
tile.style.opacity = 0.5;
}
createTargets() {
//Target looping
for (var i = 1; i < this.playerSpace.sizeX-1; i++) {
//Maks Target 2D 10x10
this.targetsArray[i] = new Array();
if (i == 1) this.targetsArray[i-1] = new Array();
if (i == 8) this.targetsArray[i+1] = new Array();
for (var j = 1; j < this.playerSpace.sizeY-1; j++) {
this.targetsArray[i][j] = 1;
//Target aLgorithm
//Player dont Looping On red Zone
this.possiblePositionToStartX.push(i+1);
this.possiblePositionToStartY.push(j+1);
//Target Array if 0 to display Win on the End
this.targetsArray[i][j] = 0;
//Total Targets
this.totalTargets++;
//Show Target On map
this.showTargets(i, j);
}
}
}
//Show Total Targets
this.showTotalTargets();
}
// Start Player
getPossiblePosToStart() {
//Random Start PLayer
let xPos = this.possiblePositionToStartX[Math.floor(Math.random() * (this.possiblePositionToStartX.length))];
let yPos = this.possiblePositionToStartY[Math.floor(Math.random() * (this.possiblePositionToStartY.length))];
return {x: xPos, y: yPos}
}
//Player Array
getTargetsArray(){
return this.targetsArray;
}
}
//PLayer CLass
class Player {
constructor (mapArray, map, targets, tileSize) {
this.positionArray = mapArray;
this.position = {x: 0, y: 0}
this.playerDiv = document.getElementById('player');
this.playerDiv.style.left = 0;
this.playerDiv.style.top = 0;
this.playerDiv.style.right = 0;
this.playerDiv.style.bottom = 0;
this.playerDiv.style.width = tileSize + 'px';
this.playerDiv.style.height = tileSize + 'px';
this.playerSpace = map.getMapSize();
this.playerMap = map.getMapArray();
this.score = 0;
this.targetsArray = targets.getTargetsArray();
this.totalTargets = targets.getTotalTargets();
this.tileSize = tileSize;
}
//Record Posisition Player
recordPosition(mapArray){
this.positionArray = mapArray;
}
//Reset Score when Restart The game
static resetScore() {
let scoreSpan = document.querySelector('#score span'); scoreSpan.innerHTML = '0';
}
//Set Palyer
setPosition (position){
this.playerDiv.style.left = (position.x * this.tileSize) + 'px';
this.playerDiv.style.top = (position.y * this.tileSize) + 'px';
this.position.x = position.x;
this.position.y = position.y;
}
getPosition() {
return this.position;
}
//Limt Map
moveRight() {
if(this.position.x > this.playerSpace.sizeX-2) return false;
if(this.positionArray[this.position.x+1][this.position.y] != 0){
this.position.x++;
let nb = this.playerDiv.style.left.split('px');
this.playerDiv.style.left = (parseInt(nb[0]) + this.tileSize) + 'px';
console.log('Droite | X : ' + this.playerDiv.style.left);
console.log(this.position.x + ' : ' + this.position.y);
} else {
console.log('Not OK');
}
}
moveDown() {
if(this.position.y > this.playerSpace.sizeY-2) return false;
if(this.positionArray[this.position.x][this.position.y+1] != 0){
this.position.y++;
let nb = this.playerDiv.style.top.split('px');
this.playerDiv.style.top = (parseInt(nb[0]) + this.tileSize) + 'px';
console.log('Bas | Y : ' + this.playerDiv.style.top);
console.log(this.position.x + ' : ' + this.position.y);
} else {
console.log('Not OK');
}
}
moveLeft() {
if(this.position.x == 0) return false;
if(this.positionArray[this.position.x-1][this.position.y] != 0){
this.position.x--;
let nb = this.playerDiv.style.left.split('px');
this.playerDiv.style.left = (parseInt(nb[0]) - this.tileSize) + 'px';
console.log('Gauche | X : ' + this.playerDiv.style.left);
console.log(this.position.x + ' : ' + this.position.y);
} else {
console.log('Not OK');
}
}
moveUp() {
if(this.position.y <= 0) return false;
if(this.positionArray[this.position.x][this.position.y-1] != 0){
this.position.y--;
let nb = this.playerDiv.style.top.split('px');
this.playerDiv.style.top = (parseInt(nb[0]) - this.tileSize) + 'px';
console.log('Haut | Y : ' + this.playerDiv.style.top);
console.log(this.position.x + ' : ' + this.position.y);
} else {
console.log('Not OK');
}
}
//Update Score
updateScore () {
let scoreDiv = document.querySelector('#score span');
scoreDiv.innerHTML = this.score;
//Winner Message
if(this.score == this.totalTargets) document.querySelector ('#win').classList.add('show');
console.log('Score : ' + this.score);
}
//Update Target Array
updateTargetsArray (posx, posy){
this.targetsArray[posx][posy] = 1;
console.log('Array state : ');
console.log(this.targetsArray);
}
//Remove Target
removeTarget(posx, posy) {
let targetToRemove = document.querySelectorAll('.target');
let coords = posx + ':' + posy;
let attr = '';
//Loop To find Right Target accroding Coordinates Player
for (var i = 0; i< targetToRemove.length; i++) {
attr = targetToRemove[i].getAttribute('data-pos');
if(attr == coords) {
targetToRemove[i].remove();
//Update Score
this.score++;
this.updateScore();
}
}
//Remove Html node (Remove Array Target)
if(this.targetsArray[posx][posy] == 0){
this.targetsArray[posx][posy] == 1;
}
}
//Plant Bomb
plantBomb(){
//Make Child Bomb
let map = document.getElementById('map');
let bomb = document.createElement('div');
map.appendChild(bomb);
bomb.style.width = this.tileSize + 'px';
bomb.style.height = this.tileSize + 'px';
//Posision Bomb
bomb.classList.add('bomb');
bomb.style.left = (this.position.x * this.tileSize) + 'px';
bomb.style.top = (this.position.y * this.tileSize) + 'px';
//Variables
var posx = this.position.x;
var posy = this.position.y;
var that = this;
var timer = setInterval(bombTimer, 500, posx, posy, that);
var iter = 0;
//BombTimer
function bombTimer() {
switch (iter) {
case 1:
bomb.classList.add('waiting');
break;
case 2:
bomb.classList.add('before');
bomb.classList.remove('waiting');
break;
case 3:
bomb.classList.add('explode');
bomb.classList.remove('before');
break;
case 4:
clearInterval(timer);
bomb.remove();
that.updateTargetsArray(posx, posy);
that.removeTarget(posx, posy);
default:
break;
}
iter++;
}
}
}
//Game Class
class Game {
constructor (tileSize, mapX, mapY) {
//Create Map
var map = new Map(mapX,mapY, tileSize);
map.init();
//Create Target
var targets = new Target(map, tileSize);
targets.createTargets();
//Create PLayer
var player = new Player(map.getMapArray(), map, targets, tileSize);
//Place The player
player.setPosition(targets.getPossiblePosToStart());
//Keyboard Events
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '38') {
player.moveUp();
}
else if (e.keyCode == '40') {
player.moveDown();
}
else if (e.keyCode == '37') {
player.moveLeft();
}
else if (e.keyCode == '39') {
player.moveRight();
}
else if (e.keyCode == '32') {
player.plantBomb();
}
}
}
//Destroy Game
static destroy () {
let targets = document.querySelectorAll('.target');
let tiles = document.querySelectorAll('.tile');
Player.resetScore();
if(tiles){
targets.forEach(function(element) {
element.remove();
});
tiles.forEach(function(element) {
element.remove();
});
}
}
}
class Session {
constructor () {
this.totalTargets = 0;
this.players = {};
this.restartBtn = document.querySelector('#restart');
this.restartBtn.addEventListener('click', function() {
Session.restart();
});
}
static restart () {
Game.destroy();
var game = new Game(25, 10, 10);
}
}
var session = new Session();
};
#map {
width: 500px;
height: 500px;
background: lightgrey;
position: relative;
margin: auto;
}
#game {
width: 500px;
height: 500px;
position: relative;
margin: auto;
}
#map .tile {
width: 50px;
height: 50px;
background: grey;
position: absolute;
outline: 1px solid #eee;
}
#map .target {
width: 50px;
height: 50px;
background: red;
position: absolute;
outline: 1px solid #eee;
}
#map #player {
border-radius: 25%;
width: 50px;
height: 50px;
position: absolute;
background: #222222;
z-index: 1;
transition: 0.1s;
}
.bomb {
border-radius: 100%;
width: 50px;
height: 50px;
position: absolute;
background: #333;
z-index: 1;
transition: 0.3s ease;
}
.bomb.waiting {
animation: waiting 2s infinite;
}
.bomb.before {
animation: before 1s infinite;
}
.bomb.explode {
animation: explode 1s infinite;
}
#score p, #score span {
font-family: sans-serif;
color: #333;
font-size: 16px;
display: inline;
}
#keyframes waiting {
0% {
transform: scale(0.9);
}
100% {
transform: scale(1.1);
}
}
#keyframes before {
0% {
transform: scale(1.0);
background: orange;
}
100% {
transform: scale(1.2);
background: red;
}
}
#keyframes explode {
0% {
transform: scale(1.0);
background: red;
opacity: 1;
}
100% {
transform: scale(2);
background: yellow;
opacity: 0;
}
}
#keyframes win {
0% {
opacity: 0;
}
10% {
opacity: 1;
}
66% {
opacity: 1;
}
100% {
opacity: 0;
}
}
h4 {
font-family: sans-serif;
color: #333;
text-align: center;
}
p, strong {
font-family: sans-serif;
color: #333;
text-align: left;
font-size: 12px;
}
#win {
position: fixed;
left: 0;
right: 0;
top:0;
bottom: 0;
z-index: 9999999;
background: rgba(181, 181, 195, 0.1);
pointer-events: none;
opacity: 0;
}
#win p {
color: red;
font-size: 130px;
text-align: center;
font-family: sans-serif;
text-transform: uppercase;
height: 100%;
margin: 0;
top: 50%;
position: absolute;
left: 50%;
transform: translate(-50%, -25%);
right: 0;
bottom: 0;
font-weight: bold;
text-shadow: 5px 5px #333;
}
#win.show {
animation: win 4s ease;
}
#restart {
text-align: center;
padding: 10px 20px;
font-family: sans-serif;
color: #333;
outline: #ccc 1px solid;
display: table;
margin: auto;
margin-top: 20px;
cursor: pointer;
transition: 0.1s ease;
}
#restart:hover {
background: #eee;
}
<!DOCTYPE html>
<html>
<head>
<title>Bomberman</title>
<link href="bomber.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="1.js"></script>
</head>
<body>
<h4>Space bar to plant a bomb / Arrows to move </h4>
<div id="win"><p>WIN !</p></div>
<div id="restart"> RESTART </div>
<div id="score"><p>Score: </p><span>0</span><strong> / 0</strong></div>
<section id="game">
<div id="map">
<div id="player"></div>
</div>
</section>
</body>
</html>
I'm not certain I understand your question, but I think you're trying to debug the createTargets method in the Targets class. The problem there is an extra closing bracket (}) right before the line with //Show Total Targets.

How to prevent element from exceeding his container borders

I have a square, when clicked it appears in a random location and it also change size (so for example if I have a 30px box but it is 10px from the left border I still get 10px outside the gamespace).
sometimes the square exceed his container border
How can I make sure that the square will never exceed his container?
function position() {
var positionTop = Math.random() * 100;
var positionLeft = Math.random() * 100;
var position = "position:relative;top:" + positionTop + "%;left:" + positionLeft + "%;"
return position;
}
document.getElementById("shape").onclick = function() {
document.getElementById("shape").style.cssText = position();
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin: 0;
padding-top: 30px;
}
#playSpace {
width: 90%;
height: 90%;
margin: 0 auto;
margin-top: 10px;
border: 1px black solid;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
You need to set position: relative; to the parent element and position: absolute; to the shape element. Then use max min value for random where max is the parent width/height and subtract the shape width/height ...
This is snippet before update
function position() {
var playSpace = document.querySelector('#playSpace');
var shape = document.getElementById("shape");
var maxHeight = playSpace.offsetHeight - shape.offsetHeight;
var maxWidth = playSpace.offsetWidth - shape.offsetWidth;
var positionTop = Math.random() * (maxHeight - 0) + 0;
var positionLeft = Math.random() * (maxWidth - 0) + 0;
// think of this like so:
// var positionTop = Math.random() * (max - min) + min;
// more information about it https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
var position = "position:absolute;top:" + positionTop + "px;left:" + positionLeft + "px;"
return position;
}
document.getElementById("shape").onclick = function() {
document.getElementById("shape").style.cssText = position();
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin:0;
padding-top: 30px;
}
#playSpace {
position: relative; /* add this line */
width: 90%;
height: 90%;
margin: 0 auto;
border: 1px black solid;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
Updated after comment
Not sure how you added the size() function but probably the problem was with using ...cssText that you overwrote the changes. So now I changed the code with passing the element to the functions and then only change the single CSS statements which need to be changed.
function position(element) {
var playSpace = document.querySelector('#playSpace');
var shape = document.getElementById("shape");
var maxHeight = playSpace.offsetHeight - shape.offsetHeight;
var maxWidth = playSpace.offsetWidth - shape.offsetWidth;
var positionTop = Math.random() * (maxHeight - 0) + 0;
var positionLeft = Math.random() * (maxWidth - 0) + 0;
// think of this like so:
// var positionTop = Math.random() * (max - min) + min;
// more information about it https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
element.style.position = 'absolute';
element.style.top = positionTop + "px";
element.style.left = positionLeft + "px";
}
function size(element) {
var sizeMath = (Math.random() * 200) + 50;
element.style.width = sizeMath + "px";
element.style.height = sizeMath + "px";
}
document.getElementById("shape").onclick = function() {
size(document.getElementById("shape"));
position(document.getElementById("shape"));
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin:0;
padding-top: 30px;
}
#playSpace {
position: relative; /* add this line */
width: 90%;
height: 90%;
margin: 0 auto;
border: 1px black solid;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
You can use a specify the range (min/max) in Math.random function and then use this function Math.floor(Math.random() * (max - min + 1)) + min; to limit the returned value of the random function between min and max.
maxTop : height of the container - height of shape
maxLeft : width of the container - width of shape
minTop : 0
minLeft : 0
You need to use position:absolute and px value on shape for this to work
See code snippet:
function position() {
var minTop = 0;
var maxTop = document.getElementById("playSpace").clientHeight - document.getElementById("shape").clientHeight;
var minLeft = 0;
var maxLeft = document.getElementById("playSpace").clientWidth - document.getElementById("shape").clientWidth ;
var positionTop = Math.floor(Math.random() * (maxTop - minTop + 1) + minTop);
var positionLeft = Math.floor(Math.random() * (maxLeft - minLeft + 1) + minLeft);
var position = "position:absolute;top:" + positionTop + "px;left:" + positionLeft + "px;"
return position;
}
document.getElementById("shape").onclick = function() {
document.getElementById("shape").style.cssText = position();
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin: 0;
padding-top: 30px;
text-align:center;
}
#playSpace {
width: 90%;
height: 90%;
border: 1px black solid;
position:relative;
display:inline-block;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
With CSS calc, limit the position inside playSpace area (you can use different units, here % and px).
Then with offsetTop/offsetLeft, get the real position of the square and avoid negative positions (when positionTop < 100px or positionLeft < 100px).
function position() {
var positionTop = Math.random() * 100;
var positionLeft = Math.random() * 100;
var position = "position:relative;top: calc(" + positionTop + "% - 100px);left: calc(" + positionLeft + "% - 100px);";
return position;
}
document.getElementById("shape").onclick = function() {
var shapeDiv = document.getElementById("shape");
shapeDiv.style.cssText = position();
var top = shapeDiv.offsetTop;// Result of calc(" + positionTop + "% - 100px) in px
if(top < 0) {
shapeDiv.style.top = '0px';
}
var left = shapeDiv.offsetLeft;// Result of calc(" + positionLeft + "% - 100px) in px
if(left < 0) {
shapeDiv.style.left = '0px';
}
}
Don't forget to add position: relative to #playSpace, to get offsetTop/left correct
#playSpace {
position:relative;/* mandatory */
}
You can get the parent element size, so that in your scirpt, use a condition to prevent the square to exceed.
function position() {
var maxWidth = document.getElementById("playSpace").offsetWidth;
var maxTop = document.getElementById("playSpace").offsetHeight;
var positionTop = Math.random() * 100;
var positionLeft = Math.random() * 100;
if (positionTop > maxTop) { positionTop = maxTop;)
if (positionLeft > maxWidth) { positionLeft = maxWidth;)
var position = "position:relative;top:" + positionTop + "%;left:" + positionLeft + "%;"
return position;
}
I'm not sure if .offsetWidth and .offsetHeight works well, but you got the idea :)
By tweaking just a little your positionTop and positionLeft variable, I managed to keep the square inside. You just need to change the maximum % that it needs to have to not exceed the container. I found that 75% for the top and 80% for the left seems to be the max!
var positionTop = Math.floor(Math.random() * 75) ;
var positionLeft = Math.random() * 80;
Here's a fiddle
If you set the containing element to position: relative; and the inner element with position: absolute; the inner elements top left right and bottom properties will calculate from the borders of the containing element.
Here is a good source of css positioning.
In your case additional validation should be set to positionTop and positionLeft.
positionTop should be in the interval [( shapeHeight/2 ) - (100 - shapeHeight/2 ) ]
positionLeft should be in the interval [( shapeWidth/2 ) - (100 - shapeWeight/2 ) ]

Categories