There is a website that I want to simulate user clicks on. In this website, there is the following div, let's call it div1, where there is a dropdown menu. There are actually other two similar divs (lets call them div2 and div3) following but I didn't place here for the simplicity. When you select one of the item in the dropdown menu in div1, the div2 is enabled (disabled by default in the beginning) and its menu content is fetched from database based on the item selected from the div1.
I can select the menu item using following script.
Code:
function setSelectedValue(selectObj, valueToSet) {
for (var i = 0; i < selectObj.options.length; i++) {
if (selectObj.options[i].value== valueToSet) {
selectObj.options[i].selected = true;
return;
}
}
}
var number = document.getElementById('level1-option');
setSelectedValue(number, "p3");
However, when I do this, the div2 is never enabled. I tried jQuery code to emit change signal on the dropdown menu but it doesn't work. When I was debugging the below html code, I saw the button tag there and I immediately thought that it submits when there is click. However, I don't see any form. If I debug the website using chrome, I see that the code jumps different js files when I select an item in the menu. Could anyone guide me how I can find out which signal is triggered when an item is selected? Apparently they do some tricks in the website to prevent normal ways of clicking
Code:
<div data-custom-select="" class="custom-select focus">
<label for="level1-option" class="has-hidden-label label-text">Sections</label>
<span class="btn-select icon-down_thin">Choose a section</span>
<select class="categories-options" data-level="1" name="level1-option" id="level1-option" required="">
<option value="">Choose a section</option>
<option value="p1" data-href="/callback/discovery/p1/">P1</option>
<option value="p2" data-href="/callback/discovery/p2/">P2</option>
<option value="p3" data-href="/callback/discovery/p3/">P3</option>
<option value="p4" data-href="/callback/discovery/p4/">P4</option>
</select>
<span class="icon-down_thin"></span>
<button type="submit" class="category-submit ui-button-secondary ">Choose</button>
Usually you could use:
$("#level1-option").val(valueToSet).trigger("click")
or
$("#level1-option").val(valueToSet).trigger("change")
but it might depend on the rest of the code on the webpage.
Try ...
$(element).trigger('click');
... from jQuery.
Try dispatching onchange event once you have changed its value:
var number = document.getElementById('level1-option');
setSelectedValue(number, "p3");
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
number.dispatchEvent(evt);
Sorry, that I couldn't help with the overlay issue. Your markup is pretty complex.
Anyway, I coded a bit for the updating/fetching data from database. Please find below a demo of it.
The demo is also here at jsFiddle
The JSON data looks like this {"data": ["1st_1", "1st_2", "1st_3"]}
During my work I had one issue that wasn't that easy to solve, but another SO question helped here. If you'd only use the change event you can't trigger the first element to fetch your next data.
The counter trick works pretty well.
var dynamicOptions = (function () {
var url; // here you can add your url to the backend script
// urlList only required for demo because no backend available
var urlList = ['http://www.mocky.io/v2/54839e2a2f4b84a0041bba49',
'http://www.mocky.io/v2/54839e4c2f4b84a5041bba4a',
'http://www.mocky.io/v2/54839e6a2f4b84a9041bba4b'];
var cc = 0; // click counter
// e.g. $optionEl = $('#firstSelection');
// $nextOptionEl = $('#secondSelection');
function Selector($optionEl, $nextOptionEl) {
this.$optionEl = $optionEl;
this.$nextOptionEl = $nextOptionEl;
this.ajaxRequest = function (optionValue) {
return $.ajax({
type: 'GET', // later 'POST'
//data: {'data': optionValue}, // for posting
url: url,
contentType: "application/json",
dataType: 'jsonp',
context: this,
});
};
this.getData = function(value) {
url = urlList[value]; // simulating backend returns based on this value
var ajaxReq = this.ajaxRequest(value); // this.value not used in this demo
ajaxReq.success(this.jsonCallback)
.fail(function (xhr) {
alert("error" + xhr.responseText);
});
};
// handle click and change event. Source from here: https://stackoverflow.com/questions/11002421/jquery-event-to-fire-when-a-drop-down-is-selected-but-the-value-is-not-change
this.clickHandler = function ($element) {
//console.log($element);
var that = this;
return $element.click(function () {
//console.log('clicked');
cc++;
if (cc == 2) {
$(this).change();
cc = 0;
}
}).change(function (e) {
cc = -1; // change triggered
//console.log(this.value);
that.getData(this.value);
});
}
this.clickHandler($optionEl);
this.jsonCallback = function (json) {
var $nextEl = this.$nextOptionEl;
$nextEl.empty(); // clear selection
$nextEl.prop('disabled', false); // enable 2nd select
this.triggerChangeEvent(); // maybe a check if they really changed would be good
$.each(json.data, function (index, value) {
$('<option/>')
.val(index)
.text(value)
.appendTo($nextEl);
});
};
this.triggerChangeEvent = function () {
var event = jQuery.Event("optionsChanged");
event.context = this;
event.message = "Options changed, update other depending options";
event.time = new Date();
$.event.trigger(event);
};
}
return {
Selector: Selector
}; // make Selector public
})();
$(function () {
var $first = $('#firstSelection');
var $second = $('#secondSelection');
var $third = $('#thirdSelection');
// use our dynamic options selector class
var options12 = new dynamicOptions.Selector($first, $second);
var options23 = new dynamicOptions.Selector($second, $third);
$(document).on('optionsChanged', function (e) {
console.log("options changed", e);
var obj_id = e.context.id;
//console.log(obj_id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<div>
<form role="form">
<div class="form-group">
<label>Please select first value:</label>
<select id="firstSelection" class="form-control">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
<div class="form-group">
<label>Please select second value:</label>
<select id="secondSelection" class="form-control" disabled="true">
<!-- fetched from server -->
</select>
</div>
<div class="form-group">
<label>Please select third value:</label>
<select id="thirdSelection" class="form-control" disabled="true">
<!-- fetched from server -->
</select>
</div>
</form>
</div>
Related
I'm trying to save the "selected" option from the <select> HTML tag to the localStorage, so when I refresh the page the last selected option is selected. I can see that it's saved in the console.log, but it's not working on the page load. How can I make it work?
<select class="multiply_ing">
<option value="0.5">0.5x</option>
<option value="1" selected>1x</option>
<option value="1.5">1.5x</option>
<option value="2">2x</option>
<option value="2.5">2.5x</option>
<option value="3">3x</option>
<option value="4">4x</option>
<option value="5">5x</option>
<option value="6">6x</option>
<option value="8">8x</option>
<option value="10">10x</option>
</select>
<p class="portion" data-val="<?php echo $portion; ?>"></p> <!-- PHP Generated value, let's just say it's "1" -->
<div class="ingredient">
<p data-val="1"></p>
<p data-val="5"></p>
<p data-val="6"></p>
</div>
<script>
$(function() {
$(".multiply_ing").on("change", function() {
let multiply_val =+ this.value;
$('.ingredient p:nth-child(1)').each(function() {
let ing =+ this.dataset.val;
this.innerHTML = ing * multiply_val;
});
$('.multiply_ing option').each(function() {
let multi_opt = $(this).val();
let portion = parseFloat(document.querySelector(".portion").dataset.val);
let portions = multi_opt * portion;
});
let portion =+ document.querySelector(".portion").dataset.val;
document.querySelector(".portion").innerHTML = portion * multiply_val;
}).change();
jQuery($ => {
let $select = $('.multiply_ing');
// get on load
$select.val(localStorage.getItem('value') || 1); // 1 = default value
$select.on('change', e => {
localStorage.setItem('value', e.target.value);
});
});
});
</script>
Note: there is more code than in this example, but it's irrelevant to the problem.
To do what you require you can just use val() to both get and set the value of the select when required:
jQuery($ => {
let $select = $('.multiply_ing');
// get on load
$select.val(localStorage.getItem('value') || 1); // 1 = default value
$select.on('change', e => {
localStorage.setItem('value', e.target.value);
});
});
Also note that the each() in your example is doing nothing and can be removed. In addition, multiply_val is not defined anywhere.
As a general rule, if you're going to incur the performance penalty of loading jQuery in to the DOM, then you're better off making use of it everywhere. Mixing JS and jQuery just leads to confusion.
To store value in localStorage you have to use key value pair like this localStorage.setItem('selectedValue',yourValue) and to get value use key to access the saved value localStorage.getItem('selectedValue')
$(function() {
$('.multiply_ing').change(function() {
localStorage.setItem('selectedValue', this.value);
});
if(localStorage.getItem('todoData')){
$('.multiply_ing').val(localStorage.getItem('selectedValue'));
}
});
for working code you can see this demo
I have a Javascript that stores a variable for a default phone number, but I would like users to be able to override this based on the options in a select menu. If they make a selection from the menu I would like the Javascript variable to be updated with the new value from the selected option.
Here's the script:
$("#callContact1").click(function() {
$.ajax({
url: "https://www.server.com/callback.php?recipientNumber=0412345678&type=makecall",
data: {},
type: "GET"
})
.then(function(data) {
$('#ajaxResponse').html(data).show();
})
.fail(function(xhr) {
var httpStatus = (xhr.status);
var ajaxError = 'There was an requesting the call back. HTTP Status: ' + httpStatus;
console.log('ajaxError: ' + ajaxError);
//make alert visible
$('#ajaxResponse').html(ajaxError).show();
})
})
I would like to edit the value of the 'recipientNumber=0412345678' in the url of the AJAX request function whenever this select menu is changed:
<select class="form-control" name="callBackNumber" id="callBackNumber">
<option value=""></option>
<option value="0418468103" selected>Mobile (0412345678)</option>
<option value="0294846565">Work (0299887766)</option>
<option value="0233445566">Home (0233445566)</option>
</select>
I'm not sure if this is possible or if there is a better way to construct this to achieve the same result?
Create a global variable with your defaultPhoneNumber.
var defaultPhoneNumber = $("#callBackNumber").val();
Update that variable on change of dropdownlist.
$("#callBackNumber").change(function(){
defaultPhoneNumber = $(this).val();
});
And use updated value in URL
$.ajax({
url: "https://www.server.com/callback.php?recipientNumber="+ defaultPhoneNumber +"&type=makecall",
data: {},
type: "GET"
});
Use $("#callBackNumber").on("change", function() { and pass the this.value number
$("#callBackNumber").on("change", function() {
var number = this.value;
if(!number) {
return console.log("Please select a number!"); //
}
// Now let's use that number
$.ajax({
url: "https://www.server.com/callback.php?recipientNumber="+ number +"&type=makecall",
data: {},
type: "GET"
})
.then(function(data) {
$('#ajaxResponse').html(data).show();
})
.fail(function(xhr) {
var httpStatus = (xhr.status);
var ajaxError = 'There was an requesting the call back. HTTP Status: ' + httpStatus;
console.log('ajaxError: ' + ajaxError);
//make alert visible
$('#ajaxResponse').html(ajaxError).show();
})
})
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="form-control" name="callBackNumber" id="callBackNumber">
<option value=""></option>
<option value="0418468103" selected>Mobile (0412345678)</option>
<option value="0294846565">Work (0299887766)</option>
<option value="0233445566">Home (0233445566)</option>
</select>
Sure it is possible, and You have done something similar ;)
select element support's change event, which fires after selecting option from dropdown.
$('#callBackNumber').on('change', (event) => {
const value = event.target.value
fireCallback(value)
})
ofc You have to write fireCallback function, which will do the thing
This is how I would do it:
var phoneNum = "0412345678";
$("#callBackNumber").change(function() {
phoneNum = $(this).val();
});
Here is the JSFiddle demo
Create a global variable, always concatenate it in the ajax URL. Update the value of the variable whenever the dropdown is changed. You will always have latest value in your variable and hence in your ajax URL.
I have a form which has multiple parts of it which change based on user input. Some fields are required in certain cases but not in others and there is JS which hides and shows the appropriate fields.
I am aware of the checkValidity() function which can be called on a form object to check if the HTML5 validation passes (attributes like required, pattern, etc.).
But my form is too complex for that and checkValidity() for the form may indicate that my form is invalid but I have intentionally hidden that field from the user based on, e.g. an option chosen in a select box.
Is there something similar to checkValidity() for an individual field? Or is there another elegant solution to this problem?
EDIT: Here's a working example that demonstrates the issue https://jsfiddle.net/w5ycvtsm/
HTML:
<form id="mainform">
<select id="opts" name="opts">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="_other">Other</option>
</select>
<br/>
<input type="text" id="opt_other" name="opt_other" required>
<br/>
<input type="submit"/>
</form>
JS:
function fixOptsState() {
var v = document.getElementById('opts').value;
var otherEl = document.getElementById('opt_other');
if (v == "_other") {
otherEl.style.display = 'block';
} else {
otherEl.style.display = 'none';
}
}
document.getElementById('opts').addEventListener('change', fixOptsState);
fixOptsState();
document.getElementById('mainform').addEventListener('submit', function(e) {
e.preventDefault();
var mainform = document.getElementById('mainform');
console.log(mainform.checkValidity());
});
checkValidity() actually gives an error in Chrome, saying
An invalid form control with name='opt_other' is not focusable.
You can use checkValidity function to validate the html5 field as soon as it loose focus. so that it will not validate hidden input field.
$('input').blur(function(event) {
event.target.checkValidity();
}).bind('invalid', function(event) {
setTimeout(function() { $(event.target).focus();}, 50);
});
How about creating and destroying the input dynamically?
function fixOptsState() {
var v = document.getElementById('opts').value;
var otherEl = document.createElement('input');
otherEl.id="opt_other";
otherEl.setAttribute("required","");
if (v == "_other") {
document.getElementById('mainform').insertBefore(otherEl,document.querySelector('input[type=submit]'));
} else {
document.getElementById('opt_other')!=undefined?document.getElementById('mainform').removeChild(document.getElementById('opt_other')):void(0);
}
}
document.getElementById('opts').addEventListener('change', fixOptsState);
fixOptsState();
document.getElementById('mainform').addEventListener('submit', function(e) {
e.preventDefault();
var mainform = document.getElementById('mainform');
console.log(mainform.checkValidity());
});
<form id="mainform">
<select id="opts" name="opts">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="_other">Other</option>
</select>
<br/>
<input type="text" id="opt_other" name="opt_other" required>
<br/>
<input type="submit"/>
</form>
Javascript does enable you to read the input in a single textbox in the form. Just grab it by giving it a unique ID in HTML5 and validate on key update. Then make whatever many functions needed to test all textboxes individually with its own parameters and complexity.
This works great for me, it is an improvement on Sagar V's. In my case, you don't need to append the form to the body, much cleaner.
function checkInput(el) {
// Clone Input
const clone = el.cloneNode(true);
// Create Temp From
const tempForm = document.createElement('form');
tempForm.appendChild(clone);
// Check Form
console.log('Validity = ' + tempForm.checkValidity());
}
const requiredInputs = querySelectorAll('input[required]');
// or whatever selector applies to your case
requiredInputs.forEach(el => {
el.addEventListener('change', () => { checkInput(el) });
});
I think you can validate using the following method.
Refer to a link to find more Validity Properties
if (!$("#your_id")[0].validity.valid)
// display your message label
$('#InvalidPhoneNumber').text('Invalid phone number');
You can use the following function to validate single and form both.
Notes: you need to update according to your requirement.
function formValidation(
event,
form_id,
list_of_elements = []
) {
var form = $(`#${form_id}`);
if (event != undefined) {
event.preventDefault();
event.stopPropagation();
}
if (list_of_elements.length > 0) {
list_of_elements.forEach(id => {
var ele = $("#"+id)[0];
if (!ele.validity.valid) {
//display error messages
ele.next().text('error message');
}
});
return false;
}
if (form[0].checkValidity() == false) {
form.addClass('was-validated');
return false;
}
return true;
}
Using print_media_templates i add some settings into wordpress gallery creator that allow me to chose gallery shortcode output (default gallery, masonry, slider) based on additional shortcode parameters.
My code so far :
<?php
add_action('print_media_templates', function(){ ?>
<script type="text/html" id="tmpl-custom-gallery-setting">
<label class="setting">
<span>Gallery Type</span>
<select name="type" data-setting="type" onchange="getval(this);">
<option value="default">Default</option>
<option value="masonry">Masonry</option>
<option value="slider">Slider</option>
</select>
</label>
<div id="slider-settings">
<label class="setting">
<span>Animation</span>
<select id="gallery-type" name="animation" data-settings="animation">
<option value=""></option>
<option value="fade">Fade</option>
<option value="slide">Slide</option>
</select>
</label>
</div>
</script>
<script>
jQuery(document).ready(function() {
wp.media.view.Settings.Gallery = wp.media.view.Settings.Gallery.extend({
template: function(view){
return wp.media.template('gallery-settings')(view)
+ wp.media.template('custom-gallery-setting')(view);
}
});
});
</script>
<?php
});
?>
It's only small part as example since there's much more options to each gallery type. Since there's lot of options i want to display only one corresponding to selected gallery type. In this example i want to display #slider-settings only when #gallery-type select value == "slider".
As for checking select value i found this code:
<script>
function getval(sel) {
if (sel.value == "slider") {
alert(sel.value);
}
}
</script>
with return selected type value (along with onchange="" on #gallery-type select) and display it if it's set to "slider".
But when i want to hide #slider-settings like :
function getval(sel) {
if (sel.value != "slider") {
$('#slider-settings').hide();
}
}
it's not hiding at all.
You have to handle native update function. Update function is fired for each label when a single change is made. (media-views.js line 7232)
var oldUpdate = wp.media.view.Settings.Gallery.prototype.update;
wp.media.view.Settings.Gallery.prototype.update = function(key) {
if( key === "type" ) {
var value = this.model.get( key );
if ( value === "slider" ) {
setTimeout(function(){
jQuery("#slider-settings").css({"display":"block"});
});
} else {
setTimeout(function(){
jQuery("#slider-settings").css({"display":"none"});
});
}
}
// Initialize native code.
oldUpdate.apply(this, arguments);
};
Somehow i managed to get it work by hiding #slider-settings using not jQuery but javascript :
<script>
function getval(sel) {
if (sel.value != "slider") {
document.getElementById('slider-settings').style.display = 'none';
} else {
document.getElementById('slider-settings').style.display = 'block';
}
}
</script>
But to get value it's has to change (since it's onselect=) so first time i display settings it's not hiding. And as i searched there's seems to be not anything like onload= i can use with .
Or is there a way to just reselect it on load ?
I'd like to know if it's possible for a select box to have two functions.
1.Redirects automatically when selecting an option using value.
2.Load content via ajax into the closest div using data-file.
<select class="loadurl">
<option value="#">Select</option>
<option value="contact.php">Contact</option>
<option value="about.php">About</option>
<option data-file="fans.php">Fans</option>
</select>
<div class="area"></div>
But when I tried the following script, the ajax option (Fans) didn't work but attempted to redirect instead. May I know how to have two functions in just one select box? Here's a demo.
$(".loadurl").bind('change', function () {
var selected = $(this).find('option:selected');
var loadfile =selected.data('file');
var area = $(".area");
$(this).next(".area").load(loadfile);
area.empty();
});
$('.loadurl').bind('change', function () {
window.location.href = $(this).val();
});
You need to use a conditional choice here - if the selected option has data-file then load the target in the area else reload the page.
var area = $(".area");
$(".loadurl").on('change', function () {
var selected = $(this).find('option:selected');
var loadfile = selected.data('file');
if (loadfile) {
area.empty();
$(this).next('.area').load(loadfile);
} else {
window.location.href = $(this).val();
}
});