In a site I’m working on this is the code for my delete button.
<form action="<?= PAMWF_WEBROOT ?>/episodeofcare" method="POST" class="delete">
<span class="confirmMessage">You are about to delete an episode of care. This will delete all claims, bills and procedures in the claim. This action CANNOT be undone. Are you sure you wish to do this?</span>
<input type="hidden" name="action" value="delete">
<input type="hidden" name="table" value="episode">
<input type="hidden" name="recordid" value="<?= $episode['recordid'] ?>">
<input type="submit" name="delete" value="Delete">
</form>
If javascript is present it stops normal form submission to do the submission in an AJAX manner. If PHP receives the request in AJAX style it responds with a javascript command to delete the row the delete button appears on. If javascript fails and the post went through normally PHP sends the updated page back.
My question is with the use of the span in this manner. It carries the warning message javascript shows in a confirm() box. Depending on what is getting deleted that message needs to change. From a separation of information standpoint is this a bad way to go about transmitting the sentence? The span is styled to be hidden - a screen reader is only going to read it if the user starts reading the delete form back (in which case I want the warning to be read out).
Footnote: The use of a form rather than a simple link is due to the “restful” nature of the framework. Get operations like links are only for read operations. A delete is a write operation and perforce needs to be a post operation. Mentioning this since not all the readers here might not be familiar with that principle though most are and I learned it here.
EDIT: Instead of a span I could use the title attribute of the submit button of the form, or its alt attribute. Would that be better?
We’ll have to agree to disagree then. I hope I never have to clean up after you, cause I know what kind of tangled mess spaghetti crapstorms that kind of coding leads to.
It’s not that simple. <a href> works in the absence of scripts. Accessibility requires that page be able to work without scripts. Functionality may be reduced, often noticably, but it should still work.
It is certainly defining a behaviour. It is saying “when this is clicked, call this controller/function”. The same can be said for <form action=“”> which even lets you specify parameters that are sent back to the controller (in this case web server).
But there are multiple events possible. Click is only one. What about double click? Or, more frequently, blur and focus. Occassionally mouseover and mouseout. You are making the argument that all of these need to be attached by HTML DOM and I’m calling it for what it is, ludicrious.
so when you create an element dynamically, do you place it on the page and re-run the code which assigns events? or do you attach the event to it while you’re defining its other properties?
Typically I re-run the function that attaches events, but instead of parsing the entire document, limit it to the scope of the recently attached events. I have the option not to though. If you embed the event code into the HTML DOM you don’t have that option.
I don’t see how this is relevant… I’m just saying that creating a link is the web equivalent of assigning a callback to a controller action and is essentially a special type of event, yet you don’t assign this using an onload event.
But there are multiple events possible. Click is only one. What about double click? Or, more frequently, blur and focus. Occassionally mouseover and mouseout. You are making the argument that all of these need to be attached by HTML DOM and I’m calling it for what it is, ludicrious.
From a code clarity point of view it is certainly better to see
Yet when viewing the page, focus will do something. For anyone unfamiliar with the code they need to read through lines of code to even begin to attempt debugging.
Using class names to denote specific events is potentially worse because it can have unexpected visual knock on effects and you are still essentially defining the behaviour in the DOM, only you’ve moved it to the class attribute instead, which may in some cases be useful (as you say where you want to assign a pair or related events) although it limits flexibility because you can’t use one without the other.
I actually have no strong feelings either way on this. There are benefits to and disadvantages of each and mostly these are situational, I just err on the side of code clarity. Attaching the events in an onload function (or elsewhere) is magic and seems like deliberate obfuscation.
I’m not going to say it’s always bad to assign events separately, but nor can I agree with the statement “Never use HTML on event handlers. Ever”.
I’ve seen this defense before - for procedural coding, or in favor of not using MVC.
It works until you need to scale it. Then it fails utterly.
You’ll see my point of view when you have to write a javascript program that has more than a handful of events or has to actively maintain the DOM rather than add a few gimmick effects. Once the application is large enough the reverse becomes true - instead of having events in a central library you find yourself hunting through dozens, perhaps hundreds of template files for all the instances of an event if it ever needs to be modified.
And the href example is a red-herring argument. That’s a parameter, not a behavior in and of itself.
If all you’re doing is defining a callback function name why would it change? Either you’ll want to globally modify the behaviour and change the function definition or you want to change it in a specific place in which case you change the template that needs to be updated.
as for href, it’s identical to <a onclick=“window.location=‘…’;”> it is defining what should happen on an event (a mouse click). It is certainly defining a behaviour. It is saying “when this is clicked, call this controller/function”. The same can be said for <form action=“”> which even lets you specify parameters that are sent back to the controller (in this case web server).
so when you create an element dynamically, do you place it on the page and re-run the code which assigns events? or do you attach the event to it while you’re defining its other properties?
The HTML is messier, but the events are easy to find. I can easily see which javascript event is being triggered by looking at the code where the element triggering the event is defined.
This applies to javascript too.
Would you do:
var button = document.createElement('button');
button.id = 'test';
document.body.appendChild(button);
then in an entirely different function (or better analogy, file!) call
var button = document.getElementById('test');
button.addEventListener('click', buttonClickEventHandler);
It’s the same as defining the behaviour/properties of the same object in multiple places moving the event assignments to javascript for the sole purpose of keeping the html “tidy” makes following the code far more difficult for anyone looking at it.
Separation of business logic and display logic is important in MVC, but even there the callbacks to controller actions are defined in the view. Keep in mind that <a href=“”> essentially creates a callback from the view to the controller too.
Getting back to the original setup, here it is with a title attribute.
<form action="<?= PAMWF_WEBROOT ?>/episodeofcare" method="POST" class="delete">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="table" value="episode">
<input type="hidden" name="recordid" value="<?= $episode['recordid'] ?>">
<input type="submit" name="delete" value="Delete" title="Delete this episode of care and all its claims, bills and procedures.">
</form>
I like the look of it. Tried putting the <li> elements in the form but there’s a problem with that. The <li> are set to “display: inline-block;” If there is an interceding element, or even a carriage return, the Firefox renders about .5 em’s worth of space between the li and it’s neighbor. I believe the spec calls for that since it is “inline” and needs to respect at least some neighboring space.
Puhlease. Even someone with no programming experience at all can get the answer right on this one.
MVC can’t be a foreign concept to you. I’ve seen your debates with Tony Marston but if you don’t grasp the concept of separation of business logic (javascript) from data logic (HTML DOM) you’ve utterly undermined your credibility here. MVC applies to the clientside scripting just as much as the serverside, perhaps even more. The event attributes of DOM elements should NEVER EVER be used and will never be used by any credible javascript programmer. When I do interviews for javascript programmers the use of those handlers in sample code is good enough reason to look to the next applicant - its that serious a problem.
Your approach is also seriously flawed when we enter the theater of dynamically created elements and attaching events to them, or making decisions on whether we even want an event attached.
And honestly, if you think an HTML DOM snarled to the gills with event handlers is clean code I don’t even want to see examples.
Indeed, but it’s better to show some sort of confirmation dialog than let someone accidentally delete data.
If the request has the XMLHTTP requested by header we know it came from javascript - so we delete. If not we know it came from the browser without javascript - so the user has not seen any confirmation form and we need to send one out as a response.
If the framework is correctly written the PHP side can provide the proper action without javascript’s help, but if javascript is present it can take a shortcut.
If javascript fired the request then PHP knows that all it has to do after doing the delete action is send back a javascript snippet:
$('Row_<?= $id ?>').remove();
The javascript framework (prototype in my case) will then eval the response as long as it has headers of application/javascript.
What? It makes debugging easier. You have a list of event handlers for an element in one place… where the element is defined. Otherwise to find the relevant code you need to read through a (potentially long) onload function and find out which function is being assigned to the element you’re after. This is anything but ‘unobtrusive’ in terms of code clarity: it’s messy and creates far less maintainable, hard to locate code than using the on* attributes.
edit: the attributes should only be referencing functions though, not actually containing any logic.
In visual programming IDEs, for example, you create a button, you define all the visual attributes and events associated with it in 1 place. The button itself. You don’t need to open up a separate dialog which defines all the events for the window.
Having an entire page reload causes a much more severe break in workflow.
Indeed, but it’s better to show some sort of confirmation dialog than let someone accidentally delete data. JavaScript is preferable of course but sometimes that’s not available.
Never use HTML on event handlers. Ever. They need to be taken out of the spec because debugging scripts that make heavy use of them is a pain. Unobtrusive Javascript is the way to go - use the window on load event to then search for elements in the document that have behaviors and attach them. That’s a lot easier than tracking down and debugging code scattered all over the place.
To handle non-js browsers I’d rather add a hidden input to the form and then set the value using JS on confirm then in the processing script if the value’s not set take them to a HTML confirmation page, otherwise delete it.
Having an entire page reload causes a much more severe break in workflow.
Well the javascript itself is a universal delete function. It attaches itself to any form that has the CSS class of “Delete”. The idea is that I label the form with the appropriate class and I can forget about the details. The javascript does have a generic “Deletion cannot be undone. Are you sure?” message that it falls back to as a default, but implementing the alternative is what I’m pondering.
I’m beginning to lean towards the idea of putting the sentence in the title attribute and changing the sentence to read, “This will delete the claim and all of it’s bills and procedures.” Javascript can then add the generic end to the phrase “This action cannot be undone. Are you sure?”
That way if they hover the mouse over the button to get the title to appear it makes sense in that context as well.
I agree. I don’t believe it is required, so if you don’t want to, you don’t have to.
Back to your original question: Why do you use your span to hold a message? There should definitely be a better spot to put the message – like in the javascript somewhere.
It would be horrible in this case. This is an input button among a list of links. The only reason for the form is that you can’t post from an anchor tag - any link is implicitly a get.
My framework doesn’t allow write operations to be performed from a get. They must be a post. Hence a form with a single button.
I also don’t agree with the ideal of sticking a block level element in when the CSS is just going to need to change it to an inline block anyway. Seems pointless.
no, I think felgall is saying it should be <li><form><fieldset><input></fieldset></form></li> Though I’ve never seen this requirement, it is a good structure to use.
Ignoring HTML validation, why is having the error text as a span better than just onsubmit=“return confirm(‘…’);” you mention screen readers… but these will almost certainly ignore text in an element with display: none;
To handle non-js browsers I’d rather add a hidden input to the form and then set the value using JS on confirm then in the processing script if the value’s not set take them to a HTML confirmation page, otherwise delete it.
I handle this by adding triggers to delete/update on the table and simply keeping a backup of the deleted record in another table. This way all changes are backed up and any queries to the table don’t need extra criteria to filter out the old records Though it’s not much to do with the original question. I disagree with allspiritseve, I think you really should have a confirmation box. Sometimes people press things by mistake. It happens. People also expect confirmation boxes these days.
That was my original goal, but when you write it that way you still need to write a “Yes, really delete this” function and a restore from delete function. Time constraints on the project prevented that.
The next iteration of my framework will support journaling - every commit to the database will be a new row. There will be a two keys for the row - the true primary key and the record key which all iterations of the same record will show. This will allow users to see the history of the changes to a record.
However, to support this I still will need the ability to archive old versions of the record and then purge them out of the system.
Hmm you have a point but I still don’t think it’s the best option in a lot of cases. E.g. anywhere you’re giving users a list of options “Rename, Move, Delete, Properties” etc, performing the delete without confirmation in these cases would be annoying. Gmail, for instance, has the delete button next to other buttons which will also remove the email (archive and report spam). If, for instance, delete was next to “Reply” then I don’t think it would work because it would be easier to press it by mistake.