It's possible to disable spellcheck or autocomplete on individual input elements by adding the tags spellcheck="false" or autocomplete="off" to that element.
But for those who would like to disable it globally across the entire DOM, is there a way to do this using vanilla javascript or HMTL (accounting for the fact that new input elements may be created over the lifetime of the page)?
In vanilla javascript, one option would be to iterate all the inputs on the page and apply the necessary attribute, something like this:
var inputs = document.getElementsByTagName("input");
for(var i = 0; i < inputs.length; i++){
inputs[i].setAttribute("spellcheck", "false");
}
For a more dynamic situation where you're unable to control the creation of new inputs, a mutation observer could be used to apply the desired attributes to dynamically created:
window.addInput = function(){
var container = document.getElementById("container");
var input = document.createElement("input");
input.setAttribute("type", "text");
container.appendChild(input);
container.appendChild(document.createElement("br"));
}
//MutationObserver docs: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
var observer = new MutationObserver(function (e){
for(var i = 0; i < e.length; i++){
for(var j = 0; j < e[i].addedNodes.length; j++){
if(["INPUT", "TEXTAREA"].indexOf(e[i].addedNodes[j].tagName) > -1){
e[i].addedNodes[j].setAttribute("spellcheck", "false");
console.log("attribute set")
}
}
}
}).observe(document.getElementById("container"), {childList:true});
<button onclick="addInput();">
Add Input
</button>
<div id="container">
</div>
To handle dynamic elements, try this
document.addEventListener('focus',function(e){
var elem = e.target;
if (elem && elem.tagName.toLowerCase()=="input" {
elem.spellcheck=false;
}
})
Else loop:
var inp = document.querySelectorAll("input[type=text], textarea");
for (var i=0; i<inp.length; i++){
inp[i].spellcheck=false;
inp[i].autocomplete="off";
}
To be able to handle dynamically created elements, you should use DOM Mutation Observers, which can monitor a DOM node for changes and fire a callback at that point:
// Create the mutation observer
var observer = new MutationObserver(function(mutations) {
// Loop through the mutations
mutations.forEach(function(mutation) {
// Loop through the mutation record for that mutation
for (var i = 0; i < mutation.addedNodes.length; i++){
// Cache current node being added
var n = mutation.addedNodes[i];
// Check node for an input
if(n.nodeName === "INPUT"){
// Set properties as desired
n.setAttribute("spellcheck", "false");
n.setAttribute("autocomplete", "off");
// Confirm changes to new element
console.log(n);
}
}
});
});
// Start observing the <body>
observer.observe(document.body, { childList: true });
// Dynamically add a new input
document.body.appendChild(document.createElement("input"));
Related
I'm new to JS and jQuery but I've been trying to use the addClass() and removeClass with some Javascript variables and don't know what I'm doing wrong.
I have this 1–5 star rating system.
I want it to change classes when hovering and save rating when I click.
The HTML looks like this:
<span class="icon-rating-empty" id="blob1"></span>
and so on for blobs 2–5.
The JS I currently have is
var blob1 = document.getElementById('blob1');
var blob2 = document.getElementById('blob2');
var blob3 = document.getElementById('blob3');
var blob4 = document.getElementById('blob4');
var blob5 = document.getElementById('blob5');
var rating = 0;
blob1.addEventListener('hover', function() {
$(blob1).addClass("icon-rating-full").addClass("green-blob").removeClass("icon-rating-empty")
},
function() {
$(blob1).addClass("icon-rating-empty").removeClass("green-blob").removeClass("icon-rating-full")
});
blob1.addEventListener('click', function() {
rating = 1;
});
This doesn't work—I'm sure I don't know how to handle variables with the jQuery, but can't find any article on what I'm supposed to do.
I've tested it and if I use $("#blob1") instead of $(blob1) it works, but I'd like to use the variables because I have more in plan.
You're not far off. You will need to set up two sets of event listeners: one for when the user clicks on a star, and one for when the user hovers over a star.
I suggest saving the "rating" as a variable. When the user clicks a star, you adjust the rating. I used a data attribute to keep track of the value of each star. After adjusting the rating, you loop through the elements and add or remove classes accordingly.
Hovering adds a layer of complexity. Every time there is mouseover, you will need to loop over the star elements and update the classes as though that was the new rating. When you mouseout, you will update the classes again according to the rating that you saved.
var rating = 0;
var stars = $('li');
// Set up listeners
$('li').on('click', function(){
rating = parseInt($(this).data('val'));
drawStars(rating);
});
$('li').hover(
function(){
tempRating = parseInt($(this).data('val'));
drawStars(tempRating);
},
function(){
drawStars(rating);
}
);
// This function loops through the "star" elements and adds and removes a 'selected' class
function drawStars(numStars){
// Reset the colour by removing the selected class from all elements
for(var i = 0; i < stars.length; i++){
$(stars[i]).removeClass('selected');
}
// Add a selected class to some of the elements
for(var i = 0; i < numStars; i++){
$(stars[i]).addClass('selected');
}
}
See this jsfiddle: https://jsfiddle.net/ffz5y9fm/5/
Untested:
<span class="rating">
<span data-star="0">STAR</span>
<span data-star="1">STAR</span>
<span data-star="2">STAR</span>
<span data-star="3">STAR</span>
<span data-star="4">STAR</span>
<span data-star="5">STAR</span>
</span>
<script>
try{
var elements = document.querySelectorAll('.rating'),
listener = function(e){
var a = this, parent = a.parentNode, value = parseInt( a.getAttribute('data-star') );
// reset
parent.classList = 'rating';
// add class
parent.classList.add( 'star-'+value );
};
// get all elements and attach listener
for( var i = 0; i < elements.length; ++i ){
var current = elements[i], childs = current.children;
for( var ii = 0; ii < childs.length; ++ii ){
childs[ii].addEventlistener('mouseenter',listener,false);
}
}
} catch(e){ console.log('error',e); }
</script>
If something doesn't work just report here.
I am using ckeditor inline on a webpage that i have built.I can save the data to a database but the major problem is that ckeditor applies its own classes and other attributes to all the elements on which contenteditable is set to true.Also it removes some classes on elements. This is affecting the styling of my webpage. I wish to remove the classes and other attributes set by ckeditor before printing it on the browser.For this I need to loop through all the elements having content editable set to true. How can we do this using js?
Plain JS:
var el = document.getElementsByTagName("*");
for(var i = 0, l = el.length; i < l; i++)
{
if (el[i].contentEditable)
{
// Do here what you want
}
}
jQuery:
as dandavis said:
$("*[contentEditable]").each(function()
{
//
});
Edit:
As far as the .contentEditable does not return boolean,
you must check whether the element has the contentEditable attribute like this:
var el = document.getElementsByTagName("*");
for(var i = 0, l = el.length; i < l; i++)
{
if (el[i].contentEditable === "true" || el[i].contentEditable === "")
{
// Do here what you want
}
}
In order to remove the contentEditable attribute:
In jQuery you can do it like this:
$("*[contentEditable]").each(function()
{
this.prop("contentEditable", false);
});
Plain js:
el[i].contentEditable = "false";
I am trying to dynamically create a set of check-boxes that each call a function differently when clicked
function initAllButtons(variable, length)
{
for(c = 0; c < length; c++)
{
clicks.push(true);
}
for(i = 0; i < length; ++i)
{
var label = document.createElement("label");
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = true;
checkbox.value = btns[i];
checkbox.class = "colorCoder";
label.appendChild(checkbox);
document.getElementById('Buttons').appendChild(checkbox);
$('#Buttons').on('click', function(){updateData(i,clicks);});
}
}
Btns is just an array of strings. I really want to call the UpdateData function (which I have tested and works like it should) with the value or index of the button pressed, but nothing seems to be working.
This version just calls updateData ten times with index = 10. It obviously is not looking at the buttons as individual things. What am I doing wrong?
When dynamically adding elements to the dom, attaching event listeners gets tricky. This is a perfect use case for delegate on a parent container:
var clickcontainer = document.getElementById('clickcontainer');
clickcontainer.addEventListener('click', function(e) {
var target = e.target || e.srcElement;
e.stopPropagation();
}, false);
Use closures to get this behavior, the closure function will create a new isolated scope and store the state of the variables.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
function clickClosure(i, clicks){
return function(){
updateData(i,clicks);
}
}
function initAllButtons(variable, length)
{
for(c = 0; c < length; c++)
{
clicks.push(true);
}
for(i = 0; i < length; ++i)
{
var label = document.createElement("label");
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = true;
checkbox.value = btns[i];
checkbox.class = "colorCoder";
label.appendChild(checkbox);
document.getElementById('Buttons').appendChild(checkbox);
var clickFnct = clickClosure(i, clicks);
$('#Buttons').on('click', clickFnct);
}
}
The problem is that you are doing nothing in your click handler to reference the clicked element. To do that you need to specify selector as parameter to on(). That might look like this:
$('#Buttons').on('click', ':checkbox', function() {
// determine index of clicked item
var index = $('#Buttons :checkbox').index(this);
// call your function
updateData(index,clicks);
}
You should also place this code after your loop as you only need to execute this line of code once.
Guessing by the code you are actually attaching a click event on a button rather than on the checkbox itself. Once you've created the element with document.createElement you can create your jQuery object and use the event handlers jQuery got.
var checkbox = document.createElement("input");
$(checkbox).on('click' function(){
//Code here
}
If you want to keep the value of i you must use a closure. Look at my fiddle:
http://jsfiddle.net/u13Le70g/
I have a form that pop up inside a layer, and I need to make everything inside that form read only regarding what type of input it is. Anyway to do so?
This is quite simple in plain JavaScript and will work efficiently in all browsers that support read-only form inputs (which is pretty much all browsers released in the last decade):
var form = document.getElementById("your_form_id");
var elements = form.elements;
for (var i = 0, len = elements.length; i < len; ++i) {
elements[i].readOnly = true;
}
With HTML5 it's possible to disable all inputs contained using the <fieldset disabled /> attribute.
disabled:
If this Boolean attribute is set, the form controls that are its
descendants, except descendants of its first optional
element, are disabled, i.e., not editable. They won't received any
browsing events, like mouse clicks or focus-related ones. Often
browsers display such controls as gray.
Reference: MDC: fieldset
You can use the :input selector, and do this:
$("#myForm :input").prop('readonly', true);
:input selects all <input>, <select>, <textarea> and <button> elements. Also the attribute is readonly, if you use disabled to the elements they won't be posted to the server, so choose which property you want based on that.
Its Pure Javascript :
var fields = document.getElementById("YOURDIVID").getElementsByTagName('*');
for(var i = 0; i < fields.length; i++)
{
fields[i].disabled = true;
}
Old question, but nobody mentioned using css:
pointer-events: none;
Whole form becomes immune from click but also hovers.
You can do this the easiest way by using jQuery. It will do this for all input, select and textarea elements (even if there are more than one in numbers of these types).
$("input, select, option, textarea", "#formid").prop('disabled',true);
or you can do this as well but this will disable all elements (only those elements on which it can be applied).
$("*", "#formid").prop('disabled',true);
disabled property can applies to following elements:
button
fieldset
input
optgroup
option
select
textarea
But its upto you that what do you prefer to use.
Old question, but right now you can do it easily in pure javascript with an array method:
form = document.querySelector('form-selector');
Array.from(form.elements).forEach(formElement => formElement.disabled = true);
1) form.elements returns a collection with all the form controls (inputs, buttons, fieldsets, etc.) as an HTMLFormControlsCollection.
2) Array.from() turns the collection into an array object.
3) This allows us to use the array.forEach() method to iterate through all the items in the array...
4) ...and disable them with formElement.disabled = true.
$("#formid input, #formid select").attr('disabled',true);
or to make it read-only:
$("#formid input, #formid select").attr('readonly',true);
Here is another pure JavaScript example that I used. Works fine without Array.from() as a NodeList has it's own forEach method.
document.querySelectorAll('#formID input, #formID select, #formID button, #formID textarea').forEach(elem => elem.disabled = true);
// get the reference to your form
// you may need to modify the following block of code, if you are not using ASP.NET forms
var theForm = document.forms['aspnetForm'];
if (!theForm) {
theForm = document.aspnetForm;
}
// this code disables all form elements
var elements = theForm.elements;
for (var i = 0, len = elements.length; i < len; ++i) {
elements[i].disabled = true;
}
This one has never failed me and I did not see this approach on the other answers.
//disable inputs
$.each($("#yourForm").find("input, button, textarea, select"), function(index, value) {
$(value).prop("disabled",true);
});
disable the form by setting an attribute on it that disables interaction generally
<style>form[busy]{pointer-events:none;}</style>
<form>....</form>
<script>
function submitting(event){
event.preventDefault();
const form = this; // or event.target;
// just in case...
if(form.hasAttribute('busy')) return;
// possibly do validation, etc... then disable if all good
form.setAttribute('busy','');
return fetch('/api/TODO', {/*TODO*/})
.then(result=>{ 'TODO show success' return result; })
.catch(error=>{ 'TODO show error info' return Promise.reject(error); })
.finally(()=>{
form.removeAttribute('busy');
})
;
}
Array.from(document.querySelectorAll('form')).forEach(form=>form.addEventListener('submit',submitting);
</script>
Javascript : Disable all form fields :
function disabledForm(){
var inputs = document.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
inputs[i].disabled = true;
}
var selects = document.getElementsByTagName("select");
for (var i = 0; i < selects.length; i++) {
selects[i].disabled = true;
}
var textareas = document.getElementsByTagName("textarea");
for (var i = 0; i < textareas.length; i++) {
textareas[i].disabled = true;
}
var buttons = document.getElementsByTagName("button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].disabled = true;
}
}
To Enabled all fields of form see below code
function enableForm(){
var inputs = document.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
inputs[i].disabled = false;
}
var selects = document.getElementsByTagName("select");
for (var i = 0; i < selects.length; i++) {
selects[i].disabled = false;
}
var textareas = document.getElementsByTagName("textarea");
for (var i = 0; i < textareas.length; i++) {
textareas[i].disabled = false;
}
var buttons = document.getElementsByTagName("button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].disabled = false;
}
}
As the answer by Tim Down I suggest:
const FORM_ELEMENTS = document.getElementById('idelementhere').elements;
for (i = 0; i < FORM_ELEMENTS.length; i++) {
FORM_ELEMENTS[i].disabled = true;
}
This will disable all elements inside a form.
for what it is worth, knowing that this post is VERY old... This is NOT a read-only approach, but works for me. I use form.hidden = true.
Thanks Tim,
That was really helpful.
I have done a little tweaking when we have controls and we handle a event on them.
var form = document.getElementById("form");
var elements = form.elements;
for (var i = 0, len = elements.length; i < len; ++i) {
elements[i].setAttribute("onmousedown", "");
}
I have a div element in an HTML document.
I would like to extract all elements inside this div with id attributes starting with a known string (e.g. "q17_").
How can I achieve this using JavaScript ?
If needed, for simplicity, I can assume that all elements inside the div are of type input or select.
var matches = [];
var searchEles = document.getElementById("myDiv").children;
for(var i = 0; i < searchEles.length; i++) {
if(searchEles[i].tagName == 'SELECT' || searchEles.tagName == 'INPUT') {
if(searchEles[i].id.indexOf('q1_') == 0) {
matches.push(searchEles[i]);
}
}
}
Once again, I strongly suggest jQuery for such tasks:
$("#myDiv :input").hide(); // :input matches all input elements, including selects
Option 1: Likely fastest (but not supported by some browsers if used on Document or SVGElement) :
var elements = document.getElementById('parentContainer').children;
Option 2: Likely slowest :
var elements = document.getElementById('parentContainer').getElementsByTagName('*');
Option 3: Requires change to code (wrap a form instead of a div around it) :
// Since what you're doing looks like it should be in a form...
var elements = document.forms['parentContainer'].elements;
var matches = [];
for (var i = 0; i < elements.length; i++)
if (elements[i].value.indexOf('q17_') == 0)
matches.push(elements[i]);
With modern browsers, this is easy without jQuery:
document.getElementById('yourParentDiv').querySelectorAll('[id^="q17_"]');
The querySelectorAll takes a selector (as per CSS selectors) and uses it to search children of the 'yourParentDiv' element recursively. The selector uses ^= which means "starts with".
Note that all browsers released since June 2009 support this.
Presuming every new branch in your tree is a div, I have implemented this solution with 2 functions:
function fillArray(vector1,vector2){
for (var i = 0; i < vector1.length; i++){
if (vector1[i].id.indexOf('q17_') == 0)
vector2.push(vector1[i]);
if(vector1[i].tagName == 'DIV')
fillArray (document.getElementById(vector1[i].id).children,vector2);
}
}
function selectAllElementsInsideDiv(divId){
var matches = new Array();
var searchEles = document.getElementById(divId).children;
fillArray(searchEles,matches);
return matches;
}
Now presuming your div's id is 'myDiv', all you have to do is create an array element and set its value to the function's return:
var ElementsInsideMyDiv = new Array();
ElementsInsideMyDiv = selectAllElementsInsideDiv('myDiv')
I have tested it and it worked for me. I hope it helps you.
var $list = $('#divname input[id^="q17_"]'); // get all input controls with id q17_
// once you have $list you can do whatever you want
var ControlCnt = $list.length;
// Now loop through list of controls
$list.each( function() {
var id = $(this).prop("id"); // get id
var cbx = '';
if ($(this).is(':checkbox') || $(this).is(':radio')) {
// Need to see if this control is checked
}
else {
// Nope, not a checked control - so do something else
}
});
i have tested a sample and i would like to share this sample and i am sure it's quite help full.
I have done all thing in body, first creating an structure there on click of button you will call a
function selectallelement(); on mouse click which will pass the id of that div about which you want to know the childrens.
I have given alerts here on different level so u can test where r u now in the coding .
<body>
<h1>javascript to count the number of children of given child</h1>
<div id="count">
<span>a</span>
<span>s</span>
<span>d</span>
<span>ff</span>
<div>fsds</div>
<p>fffff</p>
</div>
<button type="button" onclick="selectallelement('count')">click</button>
<p>total element no.</p>
<p id="sho">here</p>
<script>
function selectallelement(divid)
{
alert(divid);
var ele = document.getElementById(divid).children;
var match = new Array();
var i = fillArray(ele,match);
alert(i);
document.getElementById('sho').innerHTML = i;
}
function fillArray(e1,a1)
{
alert("we are here");
for(var i =0;i<e1.length;i++)
{
if(e1[i].id.indexOf('count') == 0)
a1.push(e1[i]);
}
return i;
}
</script>
</body>
USE THIS I AM SURE U WILL GET YOUR ANSWER ...THANKS