I have two pages with HTML forms. The first page has a submission form, and the second page has an acknowledgement form. The first form offers a choice of many controls, while the second page displays the data from the submission form again with a confirmation message. On this second form all fields must be static.
From what I can see, some form controls can be readonly and all can be disabled, the difference being that you can still tab to a readonly field.
Rather than doing this field by field is there any way to mark the whole form as readonly/disabled/static such that the user can't alter any of the controls?
Wrap the input fields and other stuff into a <fieldset> and give it the disabled="disabled" attribute.
Example (http://jsfiddle.net/7qGHN/):
<form>
<fieldset disabled="disabled">
<input type="text" name="something" placeholder="enter some text" />
<select>
<option value="0" disabled="disabled" selected="selected">select somethihng</option>
<option value="1">woot</option>
<option value="2">is</option>
<option value="3">this</option>
</select>
</fieldset>
</form>
Not all form elements can be set to readonly, for example:
checkboxes
radio boxes
file upload
...more..
Then the reasonable solution would be to set all form elements' disabled attributes to true, since the OP did not state that the specific "locked" form should be sent to the server (which the disabled attribute does not allow).
Another solution, which is presented in the demo below, is to place a layer on top of the form element which will prevent any interaction with all the elements inside the form element, since that layer is set with a greater z-index value:
DEMO:
var form = document.forms[0], // form element to be "readonly"
btn1 = document.querySelectorAll('button')[0],
btn2 = document.querySelectorAll('button')[1]
btn1.addEventListener('click', lockForm)
btn2.addEventListener('click', lockFormByCSS)
function lockForm(){
btn1.classList.toggle('on');
[].slice.call( form.elements ).forEach(function(item){
item.disabled = !item.disabled;
});
}
function lockFormByCSS(){
btn2.classList.toggle('on');
form.classList.toggle('lock');
}
form{ position:relative; }
form.lock::before{
content:'';
position:absolute;
z-index:999;
top:0;
right:0;
bottom:0;
left:0;
}
button.on{ color:red; }
<button type='button'>Lock / Unlock Form</button>
<button type='button'>Lock / Unlock Form (with CSS)</button>
<br><br>
<form>
<fieldset>
<legend>Some Form</legend>
<input placeholder='text input'>
<br><br>
<input type='file'>
<br><br>
<textarea placeholder='textarea'></textarea>
<br><br>
<label><input type='checkbox'>Checkbox</label>
<br><br>
<label><input type='radio' name='r'>option 1</label>
<label><input type='radio' name='r' checked>option 2</label>
<label><input type='radio' name='r'>option 3</label>
<br><br>
<select>
<option>options 1</option>
<option>options 2</option>
<option selected>options 3</option>
</select>
</fieldset>
</form>
You can use this function to disable the form:
function disableForm(formID){
$('#' + formID).children(':input').attr('disabled', 'disabled');
}
See the working demo here
Note that it uses jQuery.
On the confirmation page, don't put the content in editable controls, just write them to the page.
This is an ideal solution for disabling all inputs, textareas, selects and buttons in a specified element.
For jQuery 1.6 and above:
// To fully disable elements
$('#myForm :input').prop('disabled', true);
Or
// To make elements readonly
$('#myForm :input').prop('readonly', true);
jQuery 1.5 and below:
$('#myForm :input').prop('disabled', 'disabled');
And
$('#myForm :input').prop('readonly', 'readonly');
There is no built-in way that I know of to do this so you will need to come up with a custom solution depending on how complicated your form is. You should read this post:
Convert HTML forms to read-only (Update: broken post link, archived link)
EDIT: Based on your update, why are you so worried about having it read-only? You can do it via client-side but if not you will have to add the required tag to each control or convert the data and display it as raw text with no controls. If you are trying to make it read-only so that the next post will be unmodified then you have a problem because anyone can mess with the post to produce whatever they want so when you do in fact finally receive the data you better be checking it again to make sure it is valid.
There's no fully compliant, official HTML way to do it, but a little javascript can go a long way.
Another problem you'll run into is that disabled fields don't show up in the POST data
<form inert>
This won't change the styling of the form but will stop all the inputs from being focusable and stop any buttons from being clickable.
Have all the form id's numbered and run a for loop in JS.
for(id = 0; id<NUM_ELEMENTS; id++)
document.getElementById(id).disabled = false;
A simple need : display non-editable form (that can become editable later on) with minimum code and headache.
If you can't use the 'disabled' attribut (as it erases the value's input at POST), and noticed that html attribut 'readonly' works only on textarea and some input(text, password, search, as far I've seen), and finally, if you don't want to bother with duplicating all your select, checkbox and radio with hidden input logics,
you might find the following function or any of his inner logics to your liking :
addReadOnlyToFormElements = function (idElement) {
// textarea an input of type (text password search) work with the html readonly
$('#' + idElement + ' textarea, #' + idElement + ' input').prop('readonly',true);
// but you still have to destroy their associated objects, as I.E, datepicker (in our old project, datepicker is appended to input where 'Date' is in name attribut, don't ask why)
$('#' + idElement + ' input[name*="Date"]').datepicker('destroy');
// html readonly don't work on input of type checkbox and radio, neither on select. So, a safe trick is to disable the non-selected items
$('#' + idElement + ' input[type="checkbox"]:not(:checked), #' + idElement + ' input[type="radio"]:not(:checked)').prop('disabled',true);
$('#' + idElement + ' select>option:not([selected])').prop('disabled',true);
// and, on the selected ones, to disable mouse/keyoard events and mimic readOnly appearance
$('#' + idElement + ' input[type="checkbox"]:checked').prop('tabindex','-1').css('pointer-events','none').css('opacity','0.5');
$('#' + idElement + ' input[type="radio"]:checked').css('opacity','0.5');
$('#' + idElement + ' select').css('background-color','#eee');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
And there's nothing easier than to remove these readonly
removeReadOnlyFromFormElements = function (idElement) {
// just remove the html readonly on textarea and input
$('#' + idElement + ' textarea, #' + idElement + ' input').prop('readonly',false);
// and restore their Objects, as I.E, datepicker
$('#' + idElement + ' input[name*="Date"]').datepicker();
// Remove the disabled attribut on non-selected
$('#' + idElement + ' input[type="checkbox"]:not(:checked), #' + idElement + ' input[type="radio"]:not(:checked)').prop('disabled',false);
$('#' + idElement + ' select>option:not([selected])').prop('disabled',false);
// Restore mouse/keyboard events and remove readOnly appearance on selected ones
$('#' + idElement + ' input[type="checkbox"]:checked').prop('tabindex','').css('pointer-events','').css('opacity','');
$('#' + idElement + ' input[type="radio"]:checked').css('opacity','');
$('#' + idElement + ' select').css('background-color','');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I'd rather use jQuery:
$('#'+formID).find(':input').attr('disabled', 'disabled');
find() would go much deeper till nth nested child than children(), which looks for immediate children only.
Another simple way that's supported by all browsers would be:
HTML:
<form class="disabled">
<input type="text" name="name" />
<input type="radio" name="gender" value="male">
<input type="radio" name="gender" value="female">
<input type="checkbox" name="vegetarian">
</form>
CSS:
.disabled {
pointer-events: none;
opacity: .4;
}
But be aware, that the tabbing still works with this approach and the elements with focus can still be manipulated by the user.
Easiest way
$('#yourform .YOUR_CLASS_FOR_INPUTS').prop('readonly', true);
You can use an opaque layer over the form:
Put position: relative on the form
Add the transparent blocking div as a child of this form with position: absolute and top, bottom, left, right equal to 0
You add html invisible layer over the form. For instance
<div class="coverContainer">
<form></form>
</div>
and style:
.coverContainer{
width: 100%;
height: 100%;
z-index: 100;
background: rgba(0,0,0,0);
position: absolute;
}
Ofcourse user can hide this layer in web browser.
To make a whole fieldset disabled conditionally in angular you can do like this:
<fieldset [attr.disabled]="isEditable ? null : 'disabled'">
Related
I am trying to create an HTML form is separate parts for layout reasons. As far as I understand, you can use a fieldset with a form attribute to associate the fieldset with the form, even if it’s not inside the form (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset).
However, if I have a separate fieldset with a submit button or another input in it, it doesn’t seem to work.
<form id="test">
<input name="inside-stuff" value="Inside">
<button type="submit">Doit Inside</button>
</form>
<fieldset form="test">
<input name="outside-stuff" value="Outside">
<button type="submit">Doit Outside</button>
</fieldset>
In the above snippet I have two submit buttons and two inputs. The one in the actual form works, while the one in the attached fieldset doesn’t. When I use the inside submit button, it only submits what’s in side the main form, not what is in the associated fieldset.
This may not be obvious when running the snippet, but is certainly the case when tried in real life.
What is missing to make this work?
Update 1
The problem appears to be more generic than that. I find that input elements inside an associated fieldset don’t get submitted either.
Update 2
This is not a duplicate of Submit form using a button outside the <form> tag. This question specifically refers to a fieldset element. The other doesn’t even mention it.
I wrote the following javascript
function control() {
function view(i) {
var frm = items[i].getAttribute("form");
var fBase = document.querySelector("form[id=" + frm + "]");
fBase.addEventListener("submit", function(){
var fld = document.querySelector("fieldset[form='" + this.id + "']");
var cln = fld.cloneNode(true);
cln.style.display = "none";
document.getElementById(frm).appendChild(cln);
},true);
}
var items = document.querySelectorAll("FIELDSET[form]");
var getter = function () {
return this.getAttribute("form");
};
for(var i = 0; i < items.length; i++) {
view(i);
Object.defineProperty(items[i], 'form', {
get: getter
});
}
}
window.addEventListener("load",control,true);
It's happening because the Form you have placed inside the fieldset is wrong. The form should be the parent of the fieldset in order to get it to work!
The form tag should always be the parent of the fieldset.
If you place <form> and <fieldset> then it will work. The code below should do.
<form id="test">
<input name="stuff">
<button type="submit">Doit</button>
</form>
<form>
<fieldset>
<input type="text" name="stuff2">
<button type="submit">Doit</button>
</fieldset>
</form>
I hope this will help!
I have a simple input field:
<input id="myInput" class="someClass"></input>
and some JQuery code:
$(e.currentTarget).prop('readonly', true);
where e.currentTargetis that [object HTMLInputElement] as IE11 names it.
I'm only trying to set this input field to be readonly. In chrome that code works but in IE not.
I tried already:
.prop('readonly','readonly');
.prop('readonly', '');
.attr('readonly', true);
but none of them works in IE11 ( in chrome everyone of them works)
Okay, this is bizarre: If you make the field read-only while it has focus, IE11 seems to go a bit bonkers, and one of the ways it goes bonkers is to let you keep modifying the field while the cursor is there — with some keystrokes, but not others. Here's an example: Fiddle
$("#myInput").one("click", function(e) {
$(e.currentTarget).prop('readonly', true);
display("e.currentTarget.readOnly: " + e.currentTarget.readOnly);
});
$("#myInput").on("keydown", function(e) {
display("e.currentTarget.readOnly: " + e.currentTarget.readOnly);
});
function display(msg) {
$("<p>").html(String(msg)).appendTo(document.body);
}
Adding this line before setting readOnly fixes it (fiddle):
$(e.currentTarget).blur();
Side note: You don't need jQuery to set the readOnly property, just:
e.currentTarget.readOnly = true; // Note the capital O
'Read-only' input element doesn't work consistently in IE 8,9, 10 or 11.
In this case, we can use onkeydown="javascript: return false;" in the input element.
I have used Focusin() function in jquery side with Id. When I click on textbox then we remove readony attribute as below:
HTML:
<input type="text" id="txtCustomerSearch" readonly class="customer-search"
placeholder="Search customer:" maxlength="100" autocomplete="off">
Jquery:
$("#txtCustomerSearch").focusin(function () {
$(this).removeAttr('readonly');
});
Note: it will working in IE11 and other browser.
Currently on button click, I'm able to display the user input from inside the textbox, but it's displayed inside the same Div every time.
Textbox and the button (HTML file)-
<input type="text" name="inputText"><br>
<tr>
<input type="button" value="ADD" ng-click="$ctrl.addtext()">
</tr>
<div id="outputDiv"></div>
JS function-
ctrl.addtext = function () {
var div = document.getElementById('outputDiv');
div.innerHTML += newtext+"\n";
}
How can I get the user input in a different Div and a newline every time?
EDIT: A similar question has been asked for JQuery and it's JS is-
$('#submit').click(function() {
var text = $('#input').val();
$('#newDivs').append('<div>' + text + '</div>');
});
How can I do that append in Angular?
Got it to work using this in the JS function-
div.innerHTML += "<div>"+newtext+"</div>\n";
Instead of-
div.innerHTML += newtext+"\n";
Reference (solved for Jquery)-
Create/Display a new Div each time text is submitted by a user
Is there anyway that I can add functionality to this arrow?
▼
I want it to be clickable and if clicked for it to increase a value of an input by one. So say there is the value of 5 in an input box, if the arrow was clicked, the value would show 6.
Is this possible to do or is there a better approach?
It sounds like you could be looking for the number input type. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input for a list of input types. The code to make a number input is:
<input type="number">
In HTML
<input type="text" readonly id="textbox" />
<a id="increment" style="cursor:pointer;">▼</a>
In Jquery, add this
$("#increment").click(function(e) {
var old_val = +$("#textbox").val();
var increment = +'1'
var new_val = old_val + increment;
$("#textbox").val(new_val);
});
This will increment the text field value on the arrow click.
I know that the html date input field defaults to "mm/dd/yyyy", but was wondering if there was a way to overwrite that with text to say something like "pick a date".
I have tried changing the value and placeholder attributes like so:
<input type="date" placeholder="Pick a Date">
<input type="date" value="Pick a Date">
but it ultimately doesn't seem to work as I assume it's expecting some sort of ISO date. Any ideas?
Example in a fiddle: http://jsfiddle.net/AY2mp/
An alternative is to use the jQuery date selector that uses an input field instead of date field so that the value and placeholder attributes can be used:
http://jqueryui.com/datepicker/
html
<input type="text" id="datepicker" value="The Date">
js
$(function() {
$( "#datepicker" ).datepicker();
});
I believe you could do it like this. I am no javascript guru so there may be a more efficient way to do it, but it gets the job done.
Of course you will need to change the selectors.
Fiddle: http://jsfiddle.net/ce2P7/
HTML
<div class="date1">
<input type="text" placeholder="Please choose a date" value="">
</div>
<div class="date2">
<input class="date" type="date" value="">
</div>
CSS
.date1 {
width: 150px; /* For consistency */
}
.date2 {
width: 150px; /* For consistency */
display: none;
}
JAVASCRIPT
<script>
$(function(){
$("input").one("click", function () {
$(".date1").hide();
$(".date2").show();
});
});
</script>
EDIT:
I had to change things a bit, realized it wasn't working properly
The date type doesn't support placeholder attribute. Also, the
WebKit implementation says it's fixed.
related answer: https://stackoverflow.com/a/12869288/3625883
you should use a label instead. (simple jsfiddle example: http://jsfiddle.net/7L4tb/ )
<label for="test">Test Date :</label>
<input id="test" type="date" value="2014-07-14" />
Placeholder isn't supported.
Value should be in RFC3339 format yyyy-mm-dd.
For full details, see http://www.w3.org/TR/html-markup/input.date.html
Edit now that I read the question correctly...
No, the field must contain a well formatted date. It cannot contain text. Either use a text field and add something like jQuery UI's DatePicker, or use some awful jQuery hackery with absolutely positioned div's covering the datefields - if yuo absolutely must use a date field.
$(document).ready(function () {
var i = 0;
$('input[type="date"]').each(function () {
var dfEl = $(this);
var str = '<div class="datePlaceholder" id="divph' + i + '">Choose a date</div>';
dfEl.after(str);
var phEl = $('#divph' + i);
var dateFieldPos = dfEl.offset();
phEl.css({
top: dateFieldPos.top + 1,
left: dateFieldPos.left + 1,
width: $(this).width() + 1,
height: $(this).height() + 1
});
phEl.click(function () {
$(this).hide();
dfEl.focus();
});
dfEl.blur(function () {
if (!dfEl.val()) {
phEl.show();
}
});
i++;
});
});
http://jsfiddle.net/daveSalomon/AY2mp/1/