jQuery get the first next element in DOM - javascript

I have an HTML form with two DOM elements that work together - input and error message. When the form is submitted and the input is empty, I want to apply some code to the error message. My problem is that my HTML for the position of the error message is constructed differently based on the platform - desktop or mobile - and I cannot do anything about it.
Example desktop:
<form name="form">
<div>
<input type="text" name="input-one">
<div class="error-message"></div>
</div>
<div>
<input type="text" name="input-two">
<div class="error-message"></div>
</div>
...
</form>
Example mobile:
<form name="form">
<div>
<input type="text" name="input-one">
</div>
<div class="error-message"></div>
<div>
<input type="text" name="input-two">
</div>
<div class="error-message"></div>
...
</form>
You can see, that based on the platform, the error message can be part of the same or a different parent. For that reason I cannot use jQuery's .next() selector. I tried using also .closest() selector, but that transfers the DOM upwards and also doesn't work.
So what I am trying to achieve is - with a relative reference of a DOM element (in this case input), find the first following DOM element containing a specific class (in this case "error-message").
Example Javascript stub:
$('[name=form]').find(':text:visible').each(function (i, el) {
// select the next error message
});
Is there any combination of selectors that can help me achieve this?

It's unfortunate that this couldn't have been handled with CSS, but if you're really stuck with that structure, then assuming $input is a jQuery object for the input element, then:
const $error = $input.nextAll(".error-message").add($input.parent().next(".error-message"));
nextAll will select all following siblings that match the selector. parent will go up to the parent, and next will match the following sibling, but only if it matches the selector. Since one or the other of those will be empty, you'll end up with a set of one element — the error message element.
Desktop:
$("input").on("input", function() {
const $input = $(this);
const $error = $input.nextAll(".error-message").add($input.parent().next(".error-message"));
$error.text("Count: " + $input.val().length);
});
<form>
<div>
<input type="text" name="input-one">
<div class="error-message"></div>
</div>
<div>
<input type="text" name="input-two">
<div class="error-message"></div>
</div>
Type in either input to see a count in its error box.
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Mobile:
$("input").on("input", function() {
const $input = $(this);
const $error = $input.nextAll(".error-message").add($input.parent().next(".error-message"));
$error.text("Count: " + $input.val().length);
});
<form>
<div>
<input type="text" name="input-one">
</div>
<div class="error-message"></div>
<div>
<input type="text" name="input-two">
</div>
<div class="error-message"></div>
Type in either input to see a count in its error box.
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related

How to trigger JS event only for the non-hidden media query class?

I have few input html tags with same class name for mobile and desktop (media query)
Sometimes $(".className").val() is empty since it is taking value from the hidden html tag.
$(".className").val() should only fetch value from the non hidden html tag.
Html -
<div class="mobileDiv">
<input type="text" class="searchItem">
<input type="text" class="searchCategory">
</div>
<div class="desktopDiv">
<input type="text" class="searchItem">
<input type="text" class="searchCategory">
</div>
Javascript -
// Same code is shared for both mobile and desktop
$(document).on('keyup', '.searchItem', function() {
val = $(".searchItem").val()
categoryVal = $(".searchCategory")
// cannot use "this" because other class values are also needed on this event
});
How do i achieve this?
Using $(".searchItem").val() will always return the value of the first one found in the page.
Within the event handler function this is the element the event actually occurred on
$(document).on('keyup', '.searchItem', function() {
let val = $(this).val()
console.log(val)
});
input.mobileDiv{display:none}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="searchItem mobileDiv">
<input type="text" class="searchItem desktopDiv">

How to access form data nested inside divs (TypeScript)

In a following code I want to access user data written in a form each time user presses an enter key after typing some text data inside an input field in chat-form. Do you have any idea how can I access the following text-data using TypeScript? I have already tried with jQuery but none of the tested code seems to work. I am new to web-dev but very eager to learn new things.
<div id="chat-container">
<div id="search-container">
<input type="text" placeholder="search" />
</div>
<div id="conversation-list">
</div>
<div id="new-message-container">
+
</div>
<div id="chat-title">
</div>
<div id="chat-message-title">
</div>
<div id="chat-form">
<input id="chat-form" type="text" placeholder="Type a message!" />
</div>
</div>
first, you should use a semantic HTML by using form tag instead of div so u can use enter key to handle the submit action. second, it is not an appropriate way to duplicate an id for two different elements because id is a unique identifier for the element. finally here is a simple form and it might be helpful.
HTML:
<form id="my-form">
<input type="text" id="my-input" />
<button type="submit" id="submit-btn">send</button>
</form>
JS:
const formEl = document.getElementById("my-form") as HTMLFormElement;
const inputEl = formEl.querySelector("my-input") as HTMLInputElement;
const submitBtnEl = formEl.querySelector("submit-btn") as HTMLButtonElement;
formEl.addEventListener("submit", e => {
e.preventDefault();
// do what you want
});
inputEl.addEventListener("change", (e:Event|any) => {
console.log(e.target.value)
// do what you want
})
Before the answer: you have duplicated id="chat-form"
<div id="chat-form">
<input id="chat-form"type="text" placeholder="Type a message!"/>
</div>
Example
// select element
const elInput: HTMLInputElement = document.querySelector(`#chat-form-input`)
// add onkeypress listener
document.onkeypress = function (e: any) {
// use e.keyCode
if (e.key === 'Enter') {
// code for enter
console.log(elInput)
console.log(elInput.value)
}
}
<body>
<div id="chat-container">
<div id="search-container">
<input type="text" placeholder="search"/>
</div>
<div id="conversation-list">
</div>
<div id="new-message-container">
+
</div>
<div id="chat-title">
</div>
<div id="chat-message-title">
</div>
<div id="chat-form-container">
<input id="chat-form-input" type="text" placeholder="Type a message!"/>
</div>
</div>
</body>
You should try using a combination of JQuery.
Using this, you should put an id on the input element like so:
<input type="text" id="inputField" placeholder="search"/>
Then query the input field with JQuery. Best practice would suggest to store it in a local variable as well.
let inputFieldText = $("#inputField");
Then test for the value in the text field object as returned from JQuery.
if(inputFieldText.val()){
console.log(inputFieldText.val())
}
For reference, there is also a way to do so with document.getElementById("inputField"). Just link this function to a button that runs on pressing it (such as a "submit" button). Hope this helps!

Why form.id returns child input instead of id?

In w3school specification it says it should return a string representing the id of element. Replicated this issue on Microsoft Edge 42.17134.1.0 and Firefox 62.0.2.
element = document.getElementById('form');
document.getElementById('result').innerHTML = element.id
document.getElementById('getAttributeResult').innerHTML = element.getAttribute('id')
<form id="form">
<input type="hidden" name="id" />
</form>
Result of using .id:
<div id="result">
</div>
<br>
Result of using getAttribute:
<div id="getAttributeResult">
</div>
There is a special behavior on form elements that extends properties for the names of the inputs. From MDN
Named inputs are added to their owner form instance as properties, and can overwrite native properties if they share the same name (eg a form with an input named action will have its action property return that input instead of the form's action HTML attribute).
if you change the input it will work as expected. EG:
element = document.getElementById('form');
document.getElementById('result').innerHTML = element.id
document.getElementById('getAttributeResult').innerHTML = element.getAttribute('id')
<form id="form">
<input type="hidden" name="_id" />
</form>
Result of using .id:
<div id="result">
</div>
<br>
Result of using getAttribute:
<div id="getAttributeResult">
</div>

How get specific elememt that have data-bind attribute and call now (using now-active now)?

<div class="container">
<div class="well" data-id="myApp">
// Data-Bind is Here
<input type="text" value="" class="form-control input-sm"
data-bind="value:name,valueUpdate:'afterkeyup'" />
// Data-Bind is Here
<p class="info" data-bind="text:name"></p>
<button class="btn btn-success" data-bind="click:showName">Show</button>
</div>
</div>
I want to get html element that have "data-bind" attribute for example I want to Get something like this :
<input type="text" value="" class="form-control input-sm"
data-bind="value:name,valueUpdate:'afterkeyup'" />
if I change above code like this :
<div class="container">
// Data-Bind is HERE Now
<div class="well" data-id="myApp" data-bind="value:name,valueUpdate:'afterkeyup'">
// Data-Bind is HERE Now
<input type="text" value="" class="form-control input-sm" />
<p class="info" data-bind="text:name"></p>
<button class="btn btn-success" data-bind="click:showName">Show</button>
</div>
</div>
now I want to get element like this :
<div class="well" data-id="myApp" data-bind="value:name,valueUpdate:'afterkeyup'">
How can I have function for get active element that set data-bind for it , when data-bind read I can get correspondingly element of it
I need general way not for specific event or ...
If you are using JQuery then you can use "has attribute" selector. For example:
$("[data-bind]")
You can get all elements with a data-bind attribute with the jquery attribute selector.
$("*[data-bind]")
Next you can refine the selector in various ways, e.g. to consider only certain tags or choosing only a slice of the result,or by employing jquery filters:
$("div[data-bind], input[data-bind], p.data-carrier[data-bind]"); // consider only div, input, or p elements, the latter only when having class data-carrier
$("*[data-bind]:first"); // use the first match only
$("*[data-bind]")[1]; // use the second match only
$("*[data-bind]").filter(":even"); // use only matches with an even index in the list of matches
$("*[data-bind]").each ( function ( idx, element ) { /* your code */ } ); // the most general approach: iterate through the results and decide upon each element what to do next
Are you looking for this in jquery:
var elem = $('.container').find('[data-bind]');
Use $("*[data-bind]")[0].outerHTML
It will you the outerHTML of the element.
Working Fiddle

Populate Text Input With Form Buttons

I have a simple html form where I input a title and description and hit submit. At the top of the page are some paragraphs of text that I often copy and paste into these fields. It's a repetitive task, and the paragraphs are generated dynamically with php.
Can I put a button or link at the end of each paragraph or div that would fill in my form input fields with a script? Then all I would have to do is hit submit. I'm already using jquery on the page too.
EDIT:
<p>Sentence one. Longer than this</p><!--would like a button here to populate field in form below-->
<p>Sentence two. Longer than this</p>
<p>Sentence three. Longer than this</p>
<form id="sampleform" action="actionpage.php" method="post">
Title<input type="text" name="title>
Desc<input type="text" name="title>
<input type="submit" value="Submit"></form>
If you have some selector that can select all of the <p> tags that contain those paragraphs, you can do something like the following:
$(function() {
var $descInput = $('input[name=desc]');
// wrap the text of each paragraph in a span so we can target it easily.
// Then add a button inside each <p> at the end that will prepopulate that text.
$('p.prefill').wrapInner('<span class="text"></span>').append('<button class="prefill-sentence">Prefill</button>');
// Add a click handler for all the newly added buttons
$('button.prefill-sentence').click(function() {
// get the contents of the span we used to wrap the sentence with
var sentence = $(this).prev('.text').text();
// add that sentence to the current value of the description input
$descInput.val($descInput.val() + sentence);
});
});
.prefill-sentence {
margin-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="prefill">Sentence one. Longer than this</p>
<p class="prefill">Sentence two. Longer than this</p>
<p class="prefill">Sentence three. Longer than this</p>
<form id="sampleform" action="actionpage.php" method="post">
Title
<input type="text" name="title" />Desc
<input type="text" name="desc" />
<input type="submit" value="Submit" />
</form>
(Note I assumed you had a name of "desc" for your description input. Ideally, you can use a class or id to target it easier in the real code).
Is this what you are looking for?
http://plnkr.co/edit/S3OegSh80UH6oQJPDatr?p=preview
$(function(){
$('p').each(function(){
$(this).after('<button>Click<\/button>');
});
$('button').on('click', function(){
var txt = $(this).prev().text();
$('input').eq(0).val(txt);
})
});
You'll probably want to add something more specific to those php-generated paragraphs/divs, so they can safely be selected and manipulated by JS.
CodePen: http://codepen.io/anon/pen/PwJwmO
HTML
<div class="text-section">
Sentence one. Longer than this
</div>
<div class="text-section">
Sentence two. Longer than this
</div>
<div class="text-section">
Sentence three. Longer than this
</div>
<form id="sampleform" action="actionpage.php" method="post">
Title<input type="text" name="title">
Desc<input type="text" name="desc">
<input type="submit" value="Submit">
</form>
JS
var $text_section = $('.text-section');
var $description_field = $('input[name="desc"]');
$text_section.each(function(){
var section_text = $(this).text();
var $autofill_button = $('<button>Autofill</button>');
$autofill_button.click(function(){
$description_field.val(section_text);
});
$(this).append($autofill_button);
});

Categories

Resources