How is this not a function?

I havea function

function rotate() {
  var x = document.getElementById("rotate");
  if (x.value === "No") {
    x.value = "Yes";
	document.getElementById('new_row').setAttribute("height", "94");
	document.getElementById('new_row').setAttribute("width", "28");
  } else {
    x.value = "No";
	document.getElementById('new_row').setAttribute("width", "94");
	document.getElementById('new_row').setAttribute("height", "28");
  }
} 

thats supposed to run when a button is clicked

<button type="button" class="btn btn-outline-dark" onclick="rotate()"><span class="icon-repeat"></span>&nbsp;&nbsp;Rotate</button>

but I get

Heres the svg element im trying to rotate…


<rect x="25" y="25" width="94" height="28" class="draggable" id="new_row"/>

And heres how I toggle the rotation

<input type="hidden" name="rotate" id="rotate" value="No">

Where is the function defined? Is it loaded when it is called? For example, if it is in an external JS file, is that file referenced to from the HTML?

Why is a javascript error coming from a php file? Looks like you are mixing up all languages in one file. That mostly lead to unexpected errors.

sure, I have

 <button type="button" class="btn btn-outline-dark" onclick="rotate()"><span class="icon-repeat"></span>&nbsp;&nbsp;Rotate</button>
...
//then I define the function just above </body>
<script>
function rotate() {
  var x = document.getElementById("rotate");
  if (x.value === "No") {
    x.value = "Yes";
	document.getElementById('new_row').setAttribute("height", "94");
	document.getElementById('new_row').setAttribute("width", "28");
  } else {
    x.value = "No";
	document.getElementById('new_row').setAttribute("width", "94");
	document.getElementById('new_row').setAttribute("height", "28");
  }
} 

</script>
</body>
</html>

I thought I had to put all the functions just above
</body>

There’s nothing wrong from what we’re seeing there. More info is needed.

Can you please view the source of the page, and copy/paste the whole thing to somewhere like controlc.com ?

1 Like

is this it?

Thank you, I can now experience the same problem that you have there.

This is when I remove all that I can, to simplify as much as possible while still keeping the problem.

I can remove all except for the form and the script, and the problem still remains.

<form action="add_row_engine.php" method="POST" class="form-inline float-right">
<div class="btn-group mr-3" role="group" aria-label="Basic example">
<button type="button" class="btn btn-outline-dark" onclick="rotate()"><span class="icon-repeat"></span>&nbsp;&nbsp;Rotate</button>
<button type="button" class="btn btn-outline-dark" onclick="nudgeLeft()"><span class="icon-chevron-left"></span></button><button type="button" class="btn btn-outline-dark" onclick="nudgeUp()"><span class="icon-chevron-up"></span></button><button type="button" class="btn btn-outline-dark" onclick="nudgeDown()"><span class="icon-chevron-down"></span></button><button type="button" class="btn btn-outline-dark" onclick="nudgeRight()"><span class="icon-chevron-right"></span></button>
</div>
<input type="text" class="form-control" maxlength="25" id="label" name="label" placeholder="Label" required><button class="btn btn-outline-dark" type="submit"><span class="icon-ok"></span>&nbsp;&nbsp;Submit</button>
<input type="hidden" name="width" value="90"><input type="hidden" name="height" value="28"><input type="hidden" name="rotate" id="rotate" value="No">
<input type="hidden" name="x_coord" id="x_coord"><input type="hidden" name="y_coord" id="y_coord"><input type="hidden" name="bays" value="5"><input type="hidden" name="room_id" value="3">
</form>	  		  
<script>
function rotate() {
  var x = document.getElementById("rotate");
  if (x.value === "No") {
    x.value = "Yes";
	document.getElementById('new_row').setAttribute("height", "94");
	document.getElementById('new_row').setAttribute("width", "28");
  } else {
    x.value = "No";
	document.getElementById('new_row').setAttribute("width", "94");
	document.getElementById('new_row').setAttribute("height", "28");
  }
} 

</script>

Remove the form wrapper, and the problem no longer occurs:

<!--<form action="add_row_engine.php" method="POST" class="form-inline float-right">-->
...
<!--</form>-->

The problem occurs from a conflict between the rotate function, and the named form element of the same name.

The inline event attribute has been a problem for many years now, which is why we have other better techniques to use there instead.

You could just use different form name attributes from function names, but that’s just avoiding the problem, leaving it there as a trip-mine for later on. Better is to use solid and reliable techniques to actually solve the problem.

How I would solve this problem is to remove the inline event attribute from the button, and use a class name instead so that JavaScript can attach the event handler.

In this case I would use “js-” as the prefix, to help indicate that the classname is not for CSS, but for JS reasons only.

<!--<button type="button" class="btn btn-outline-dark" onclick="rotate()">-->
<button type="button" class="btn btn-outline-dark js-rotate">
const rotateButton = document.querySelector("button.js-rotate");
rotateButton.addEventListener("click", rotate);

When you have several event handlers to assign, it’s best to group them together at the end of the JS code.

const rotateButton = document.querySelector("button.js-rotate");
rotateButton.addEventListener("click", rotate);
const nudgeLeftButton = document.querySelector("button.js-nudgeLeft");
nudgeLeftButton.addEventListener("click", function nudgeLeft);
const nudgeDownButton = document.querySelector("button.js-nudgeDown");
nudgeDownButton.addEventListener("click", function nudgeDown);
const nudgeUpButton = document.querySelector("button.js-nudgeUp");
nudgeUpButton.addEventListener("click", function nudgeUp);
const nudgeRightButton = document.querySelector("button.js-nudgeRight");
nudgeRightButton.addEventListener("click", function nudgeRight);

That way duplication is easily spotted. We can take care of the duplication by moving information out to an array of objects.

const clickButtons = [
  {classname: "button.js-rotate", handler: rotate},
  {classname: "button.js-nudgeLeft", handler: nudgeLeft},
  {classname: "button.js-nudgeUp", handler: nudgeUp},
  {classname: "button.js-nudgeDown", handler: nudgeDown}
];
clickButtons.forEach(function addButtonHandler(button) {
  const button = document.querySelector(button.classname);
  button.addEventListener("click", button.handler);
});
2 Likes

thanks, so Its not an issue if I were to assign all event handlers at the end of my jscode (afterI create the functions)

<script>
function rotate() {
...
}
...
...
const rotateButton = document.querySelector("button.js-rotate");
rotateButton.addEventListener("click", rotate);
const nudgeLeftButton = document.querySelector("button.js-nudgeLeft");
nudgeLeftButton.addEventListener("click", function nudgeLeft);
const nudgeDownButton = document.querySelector("button.js-nudgeDown");
nudgeDownButton.addEventListener("click", function nudgeDown);
const nudgeUpButton = document.querySelector("button.js-nudgeUp");
nudgeUpButton.addEventListener("click", function nudgeUp);
const nudgeRightButton = document.querySelector("button.js-nudgeRight");
nudgeRightButton.addEventListener("click", function nudgeRight);
</script>
</body>
</html>
1 Like

No it isn’t but normally you write the functions inline. That makes it easier to read


const rotateButton = document.querySelector("button.js-rotate");
rotateButton.addEventListener("click", () =>
{
      Rotate code here….
});

1 Like

Oh, 1 more thing,
Why do some people use querySelector and other say getElementById?

It used to be getElementByid and getElementByName and getElementByTagName and all sorts of other ones.

With the comparatively more recent querySelector and querySelectorAll you get to remain consistent with how CSS refers to things too, which can help to make things easier to do.

Also, when you refactor code to replace an id with a classname for example, there’s less to update when using querySelector.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.