Javascript size of a form object - javascript

I have a very critical issue.
Below is my jsp code:
<html:select property="city" name="city" onchange="javascript:checkCity(this);">
<html:option value="N">NewYork</html:option>
<html:option value="F">France</html:option>
<html:option value="I">Italy</html:option>
<html:option value="P">Paris</html:option>
</html:select>
There can be single or multiple html select since my <html:select> is placed in for loop.
Below is my Javascript code:
var citySelected = new Array();
function checkCity(selObject)
{
var form = document.forms[0];
var cityObj = form["city"];
var len = cityObj.length;
if(selObject==cityObj) // if there is single <html:select> selObject is same as city Object.so this logic works fine
{
if(cityObj.value==cityObj.options[3].value)
{
alert("You have selected Paris City");
citySelected[0] = true;
}
if(!cityObj.options[3].selected && cityObj[0])
{
var result = confirm("You have selected cities other than paris");
if(result)
{
citySelected[0] = false;
}
else
{
cityObj.options[cityObj.options.selectedIndex].selected=false;
cityObj.options[3].selected=true;
}
}
}
else{
for(var i=0; i<len; i++) { //if there are multiple <html:select> then take length of form object n iterate
if (selObject == cityObj[i] )
{
if(cityObj[i].value==cityObj[i].options[3].value) // if 3rd option is selected
{
alert("You have selected Paris City");
citySelected[i] = true;
}
if(!sctypeObj[i].options[3].selected && citySelected[i]) //if 3rd option is deselected
{
var result = confirm("You have selected cities other than paris");
if(result)
{
cityObj[i] = false;
}
else
{
cityObj[i].options[cityObj[i].options.selectedIndex].selected=false;
cityObj[i].options[3].selected=true;
}
}
}
}
}
}
Below is Javascript which works on jsp onload():
function onload()
{
var form = document.forms[0];
var formObj = form["city"];
var size=formObj.size;
var len = formObj.length;
for(var i=0; i<len; i++) {
citySelected[i] = false;
}
if(size==0){ //if there is seingle <html:select> element
var cityvalue=formObj.value;
if(cityvalue=="P")
{
citySelected[0] = true;
}
}
else
{
for(var i=0; i<len; i++) { //if there are multiple <html:select> elements
var cityvalue=formObj[i].value;
if(cityvalue=="P")
{
citySelected[i] = true;
}
}
}
}
Here is where am finding problem. Onload if there is single or multiple <html:select> elements the logic works fine.But when there are no <html:select> elements at all in my jsp per say if I have option to delete all dropdowns then my jsp throws Javascript error:
"size is null or not an object".
How do I resolve this? In onload() function I am differentiating between <html:select> element using size.
if(size==0)
{
//logic for single <html:select>
}
else
{
//logic for multiple html select
}
But when there are no <html:select> elements at all in my jsp per say if I have option to delete all dropdowns then my jsp throws Javascript error:
"size is null or not an object".
How do I resolve this? Any help would be great..

An alternate way to determine the number of <select> elements within a form would be to use jQuery's selectors like so:
$('#myForm select').length // returns number of <select> elements in the form

You can use the fact that null/undefined evaluates to false in Javascript, like so:
if(!size)
{
//logic for single <html:select>
}
else
{
//logic for multiple html select
}

The line var size=formObj.size; could be the cause of the problem. Try using an "or" statement to prevent the error when the size attribute is null or undefined:
var size = formObj.size || 0;

If for single select element length is returning 4, then it seems that other select elements present inside jsp with the same name and those are hidden.
However, getElementByName('propertyName') is not a correct function to iterate collection type, rather we need getElementsByName('propertyName').

Use:
var formObj = document.getElelementsByName('city');
var length = formObj.length;
if(length == 0) {
// No select element
}
if(length == 1) {
// One select element
} else {
// More than one select elements
}
I am not sure how size will help here, this is not required. Size always will be returning undefined in this case.

Related

How can I remove the last checkbox from an array using vanilla javascript

This is an email preferences form with a bunch of checkboxes (16) to allow users to subscribe/unsubscribe.
I have a collection of checkboxes like this;
var checkboxes = document.querySelectorAll('input[type="checkbox"]');
I have a button which when clicked will select all checkboxes on the page and then deselect the unsubscribeAll checkbox;
getAllButton.addEventListener("click", function () {
selectAll();
});
function selectAll() {
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == "checkbox") checkboxes[i].checked = true;
}
// un-check the unsubscribeAll checkbox
unsubscribeAll.checked = false;
}
I have a checkbox which when clicked(checked) will deselect all of the other checkboxes on the page;
var unsubscribeAll = document.getElementById("unsubscribeAll");
unsubscribeAll.addEventListener("click", function () {
// un-check this box if already checked
if (this.checked !== true) {
this.checked = false;
} else {
deselectAll();
}
});
function deselectAll() {
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == "checkbox") checkboxes[i].checked = false;
}
unsubscribeAll.checked = true;
}
This is all working perfectly. However, my problem is that if the the unsubscribeAll checkbox is checked and the user then selects a checkbox to subscribe to an email I want to deselect the unsubscribeAll checkbox but I'm struggling to make that happen.
I thought I would be able to run another function that would deselect that checkbox like this;
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener("click", deselectUnsubscribeAll);
}
function deselectUnsubscribeAll() {
if (unsubscribeAll.checked === true) {
unsubscribeAll.checked = false;
}
}
Of course, this doesn't work because unsubscribeAll is included in the checkboxes[] array.
Next, I thought I would be able to create a new array of checkboxes that excluded unsubscribeAll so I tried this because it's the last element in that array;
var unsubscribeAll = document.getElementById("unsubscribeAll");
var getAllButton = document.getElementById("select-all");
var checkboxes = document.querySelectorAll('input[type="checkbox"]');
console.log(checkboxes.length); // 16
var popped = checkboxes.pop(); // Uncaught TypeError: checkboxes.pop is not a function
As you can see, that generates an error but I don't understand why. This seems like clunky code but it almost works.
This is one of the pages that I referenced to solve my problem;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop#examples
I need some direction please.
You say it's the last element in that array, so why do you loop through the end of array and not using for (var i = 0; i < checkboxes.length - 1; i++)?
And then you can add an event listener separately to that.
You can also use Element.matches() API to check if the clicked checkbox is unsubscribeAll and run appropriate functions accordingly. But the first method is more efficient cause you don't need to check for the element on each click event.

How to make other JQuery run when a separate function runs?

I have the JS code below which filters based on checkboxes being checked or not (I don't think you need to see all the HTML because my question is rather simple/general, I think). All this code works fine, but I added a new function at the bottom (I noted it in the code) that simply has an uncheck all button for one of the sets of checkboxes (because there are like 30 checkboxes and I don't want the user to have to uncheck them all manually).
Anyway, the new script works properly too, except that the overall unrelated script that compares all checkboxes needs to run each time the new Uncheck All/Check All button is clicked.
Is there a simple way to make sure all the other JS runs when this new script is run?
I could be wrong, but I think I just need to somehow trigger this function inside the NEW FUNCTION:
$checkboxes.on('change', function() {
but am not sure how to do that.
ALL JS:
<script>
$(window).load(function(){
Array.prototype.indexOfAny = function(array) {
return this.findIndex(function(v) {
return array.indexOf(v) != -1;
});
}
Array.prototype.containsAny = function(array) {
return this.indexOfAny(array) != -1;
}
function getAllChecked() {
// build a multidimensional array of checked values, organized by type
var values = [];
var $checked = $checkboxes.filter(':checked');
$checked.each(function() {
var $check = $(this);
var type = $check.data('type');
var value = $check.data('value');
if (typeof values[type] !== "object") {
values[type] = [];
}
values[type].push(value);
});
return values;
}
function evaluateReseller($reseller, checkedValues) {
// Evaluate a selected reseller against checked values.
// Determine whether at least one of the reseller's attributes for
// each type is found in the checked values.
var data = $reseller.data();
var found = false;
$.each(data, function(prop, values) {
values = values.split(',').map(function(value) {
return value.trim();
});
found = prop in checkedValues && values.containsAny(checkedValues[prop]);
if (!found) {
return false;
}
});
return found;
}
var $checkboxes = $('[type="checkbox"]');
var $resellers = $('.Row');
$checkboxes.on('change', function() {
// get all checked values.
var checkedValues = getAllChecked();
// compare each resellers attributes to the checked values.
$resellers.each(function(k, reseller) {
var $reseller = $(reseller);
var found = evaluateReseller($reseller, checkedValues);
// if at least one value of each type is checked, show this reseller.
// otherwise, hide it.
if (found) {
$reseller.show();
} else {
$reseller.hide();
}
});
});
//NEW FUNCTION for "UNCHECK ALL" Button
$(function() {
$(document).on('click', '#checkAll', function() {
if ($(this).val() == 'Check All') {
$('input.country').prop('checked', true);
$(this).val('Uncheck All');
} else {
$('input.country').prop('checked', false);
$(this).val('Check All');
}
});
});
});
New button HTML for the new UNCHECK portion:
<input id="checkAll" type="button" value="Uncheck All">
I kept researching and discovered the trigger() function to handle this.
http://api.jquery.com/trigger/

else condition is always executed even if the if statement is true

I am trying forever to fix this code: i have a list and i am searching through the list to find students. Once i don't find a student, an error message should appear. At the moment i have a function who searches the student based on text match. I have an if statement inside the function. When the match is found show student and when not, hide all the students. I created a variable 'found' set to 'true' when the student is found. if this is false the message should be appended.
The problem is that both conditions are being executed it seems so if i put found as being false inside the second condition the error message will display every time.
At the moment i have another if which checks if found was false. the problem is it doesn't recognise that it is false...so confusing. Please see screenshot with the console where you can see that although the student is found, the second condition is executed each time... screenshot with the console - second condition is always executed
First condition doesn't execute unless it's true.
Please help as I am trying to investigate this forever and I asked lots of questions here around this issue but with no big results.
Thanks so much,
Alina
var ul = document.getElementsByClassName("student-list");
var li = document.getElementsByTagName("li");
//add search bar
$( ".page-header" ).append('<div class="student-search"></div>');
$( ".student-search" ).append('<input id="input-search" placeholder="Search for students..."/><button id="search">Search</button>');
// append to the .page the container div for the error message
$('.page').append('<div class="error"></div>');
// append to the error div a p with the error message if student is not found
var found = true;
//myFunction
function myFunction() {
var input = document.getElementById("input-search");
var filter = input.value.toUpperCase();
for (var i = 0; i < li.length; i+=1) {
var h = li[i].getElementsByTagName("h3")[0];
if (h.innerHTML.toUpperCase().indexOf(filter) != -1) {
li[i].style.display = "";
console.log('yey found it');
found = true;
} else {
li[i].style.display = "none";
console.log('condtion 2');
}
}
if (found===false) {
$('.error').append('<p>"student not found!"</p>');
}
$('.pagination').hide();
}
//myFunction end
$('#search').on('click', function(){
myFunction();
});
// when the input is empty return to page 1, empty the error div, show pagination,
$('#input-search').on('keyup', function() {
if($(this).val() === '') {
go_to_page(0);
$('.pagination').show();
}
});
I think the function is called more than once judging that 'condition 2' got logged 50 times , and the condition isn't satisfied every time,
To make sure that it doesn't reach the else statement even if the code entered the if statement edit the function to be like this:
function myFunction() {
var input = document.getElementById("input-search");
var filter = input.value.toUpperCase();
found = false
for (var i = 0; i < li.length; i+=1) {
var h = li[i].getElementsByTagName("h3")[0];
if (h.innerHTML.toUpperCase().indexOf(filter) != -1) {
li[i].style.display = "";
console.log('yey found it');
found = true;
} else {
li[i].style.display = "none";
console.log('condtion 2');
}
}
if (found===false) {
$('.error').append('<p>"student not found!"</p>');
}
$('.pagination').hide();
console.log('--------------------------------------');
}
That way you see how many times the function was being called

Javascript toggle checkbox

I need to toggle all buttons with a single function. Function needs to toggle all checkboxes in the document as my checkboxes are freestanding and not part of a form.
I currently have this, but it is not working properly. I get syntax error: syntax error in my firefox console.
checked=false;
function checkedAll() {
var c = new Array();
c = doc.getElementsByTagName('input');
if (checked == false){
checked = true;
}else{
checked = false;
}
for (var i = 0; i < c.length; i++){
if (c[i].type == 'checkbox'){
c[i].checked = checked;
}
}
}
How can I fix my code?
Thanks
Two main items to refactor. First, instead of doc it must be document. Second instead of relying on a global just pass in a boolean to determine whether or not to check the checkboxes.
function checkedAll(isChecked) {
var c = document.querySelectorAll('input[type="checkbox"]');
for (var i = 0; i < c.length; i++){
c[i].checked = isChecked;
}
}
JS Fiddle: http://jsfiddle.net/Jvnfm/107/
You can alternatively perform the following for each checkbox element:
c[i].click();
This version will trigger any associated event handlers associated with that element.

Apex getter returning wrong value

I have javascript function in my salesforce page to validate if one of the contacts have open cases. This function calls an apex getter to get the value. The problem I`m facing is that the apex getter is always returning the wrong boolean. I tried debugging it, everything seems to work but for some reason the returned bool is wrong.
apex function:
public Boolean openCase{
get{
if (Contacts.size() > 0){
for(cContact wContact: dicContacts.values()){
if(wContact.selected){
if(wContact.con.account.Number_of_open_Financial_Review_Cases__c > 1){
return true;
}
}
}
return false;
}
set{}
}
js function:
function validateOpenCases(sendEmail){
doIt = true;
oc = {!openCase}; // <<== problem here
alert(oc);
if (oc)
{
doIt=confirm('blabla?');
}
if(doIt){
// do stuff
}
else{
// do nothing
}
}
You should not bind Apex objects/variables directly in JavaScript (like you have {!openCase};). I've had many issues with this before. Instead use JavaScript Remoting or the Ajax Toolkit.
Update
Another option is to use a hidden Visualforce input to store your bound Visualforce value. Then you can get that value in your JavaScript.
Here's an example:
<apex:page controller="myController">
<script>
function getInputEndingWith(endsWith)
{
// put together a new Regular Expression to match the
// end of the ID because Salesforce prepends parent IDs to
// all elements with IDs
var r = new RegExp("(.*)"+endsWith+"$");
// get all of the input elements
var inputs = document.getElementsByTagName('input');
// initialize a target
var target;
// for all of the inputs
for (var i = 0; i < inputs.length; ++i)
{
// if the ID of the input matches the
// Regular Expression (ends with)
if (r.test(inputs[i].id))
{
// set the target
target = inputs[i];
// break out of the loop because target
// was found
break;
}
}
// return the target element
return target;
}
function validateOpenCases(sendEmail)
{
doIt = true;
oc = getInputEndingWith("OpenCase").value;
alert(oc);
if (oc === "true") {
doIt = confirm('Are you sure?');
}
if (doIt) {
// do stuff
}
else {
// do nothing
}
}
</script>
<apex:form>
<apex:outputpanel>
<apex:inputhidden id="OpenCase" value="{!openCase}" />
</apex:outputpanel>
<input type="button" class="btn" onclick="validateOpenCases('Send');" value="Validate" />
</apex:form>
</apex:page>

Categories