I have an address finder system whereby a user enters a postcode, if postcode is validated then an address list is returned and displayed, they then select an address line, the list dissappears and then the address line is split further into some form inputs.
The issue i am facing is when they have been through the above process then cleared the postcode form field, hit the find address button and the address list re-appears.
Event though the list and parent tr have been removed from the DOM it is still reporting it is present as length 1?
My code is as follows:
jQuery
// when postcode validated display box
var $addressList = $("div#selectAddress > ul").length;
// if address list present show the address list
if ($addressList != 0) {
$("div#selectAddress").closest("tr").removeClass("hide");
}
// address list hidden by default
// if coming back to modify details then display address inputs
var $customerAddress = $("form#detailsForm input[name*='customerAddress']");
var $addressInputs = $.cookies.get('cpqbAddressInputs');
if ($addressInputs) {
if ($addressInputs == 'visible') {
$($customerAddress).closest("tr").removeClass("hide");
}
} else {
$($customerAddress).closest("tr").addClass("hide");
}
// Need to change form action URL to call post code web service
$("input.findAddress").live('click', function(){
var $postCode = encodeURI($("input#customerPostcode").val());
if ($postCode != "") {
var $formAction = "customerAction.do?searchAddress=searchAddress&custpc=" + $postCode;
$("form#detailsForm").attr("action", $formAction);
} else {
alert($addressList);}
});
// darker highlight when li is clicked
// split address string into corresponding inputs
$("div#selectAddress ul li").live('click', function(){
$(this).removeClass("addressHover");
//$("li.addressClick").removeClass("addressClick");
$(this).addClass("addressClick");
var $splitAddress = $(this).text().split(",");
$($customerAddress).each(function(){
var $inputCount = $(this).index("form#detailsForm input[name*='customerAddress']");
$(this).val($splitAddress[$inputCount]);
});
$($customerAddress).closest("tr").removeClass("hide");
$.cookies.set('cpqbAddressInputs', 'visible');
$(this).closest("tr").fadeOut(250, function() { $(this).remove(); });
});
I think you're running into the same issue I recently ran into. If you have a variable pointing to 5 DIV's (example: var divs = $('.mydivs');) and then you call jQuery's remove() on one of the DIV's, like so: divs.eq(0).remove() you'll see that divs.size() still returns 5 items. This is because remove() operates on the DOM. However... if after calling remove() you then re-set your variable: divs = $('.mydivs'); and get the size you'll now get the correct size of the array. I've added sample code displaying this below:
// get all 5 divs
var d = $('.dv');
// remove the first div
d.eq(0).remove();
// you would expect 4 but no, it's 5
alert(d.size());
// re-set the variable
d = $('.dv');
// now we get 4
alert(d.size());
Related
Can't get the title right. I am using jquery to create a textarea.
function build_form() {
// Clear all previous form elements
$('#form_content').html('');
// Grabs all elements that will be dynamically created
var elements = templates.types[$('#selectType')[0].selectedIndex].content.elements;
for (ele in elements){
var $div = $(document.createElement('div'));
$div.attr('class', 'div_form');
// Create description for input box
var $x = $(document.createElement('text'));
$x.html(elements[ele].description);
$div.append($x);
// Create input box itself
var $i = $(document.createElement(elements[ele].type));
$i.attr('placeholder', elements[ele].placeholder);
$i.attr('class', 'form_input');
if (elements[ele].value) {
// For textareas
$i.text(elements[ele].value);
// For input
$i.val(elements[ele].value);
}
console.log($x);
console.log($x[0]);
console.log($x[0].scrollHeight);
$div.append($i);
$('#form_content').append($div);
var $linebreak = $(document.createElement('br'));
$('#form_content').append($linebreak);
}
}
Resulting in:
This is as much an understanding problem as a problem blocking me. $x shows that there is a textarea at $x[0] and, expanding it, I see a giant list of properties. One of which is scrollHeight which I am trying to access.
However once accessing $x[0], it then gives me the HTML and $x[0].scrollHeight results in 0. The text is present.
What am I missing?
Edit: The height of the textarea is non-zero.
I've three icons on my page. Each icon clicked, ajax called and contented fetched and appended to another div respectively. The problem I face now, if an icon fired multiple time continuously, it fires ajax for the no of time it's clicked.
Noticing this problem, I check, if the request pass in property called sweep. If it does I would empty the div and append the content; this is to avoid duplicate data being appended. But now when the icons pressed multiple times, it appends more than once the same data.I can't find what causing this to happen. For some reason, I had to use append and not html to put in the content.
I thought can overcome this by event.stopPropagation and event.stopImmediatePropagation but they're of no use. Please check my code below and help me to fix it...thanks..
screen cast of the problem:
demo
code:
//links in the footer clicked
$('body').off('click.footer').on('click.footer', '[data-footer] ul li a', function(event){
event.stopImmediatePropagation();
event.preventDefault();
event.stopPropagation();
var layout = $(this).data('ck-tab');
$(this).trigger('ck.chat.layout', [{'layout':layout}]);
if(layout == 'list'){
ckit.render({"layout":'getConversations', "sweep": 1, "limit":localStorage.getItem("cListlimit"), "userId": localStorage.getItem("ckuser")});
}else if(layout == 'contact'){
ckit.render({"layout":'getContacts', "sweep": 1, "limit":localStorage.getItem("cntlimit"), "userId": localStorage.getItem("ckuser")});
}else if(layout == 'setting'){
//ckit.render({"layout":'getSettings', "sweep": 1});
ckit.setting();
}
});
I check if data already appended to the div this way. But even this shows the data multiple times..
if($.inArray(data[i].id, temp)<0) {
//add to array
temp.push(data[i].id);
}
function to display content:
function display(value, arg){
var wrapper = $('[data-body-content]');
if(arg[0]['sweep'] == 1){
temp = [];
wrapper.empty();
}
setTimeout(function(){
for(var i=0; i < counter;i++){
if($.inArray(data[i].id, temp)<0) {
//add to array
temp.push(data[i].id);
}
}//end for
console.debug(temp);
wrapper.append(temp);
}, 300);
}
I want to execute a function repeatedly on groups of predictably named html divs.
I am using a drag and drop relationship shown below in which dragging text into a certain div space "target" causes that text to appear in another div called "saves".
<script type="text/javascript">
function OnDragStart (event) {
if (event.dataTransfer) {
var format = "Text";
var textData = event.dataTransfer.getData (format);
}
}
function OnDropTarget (event) {
if (event.dataTransfer) {
var format = "Text";
var textData = event.dataTransfer.getData (format);
if (!textData) {
textData = "<span style='color:red'>The data transfer contains no text data.</span>";
}
var savesDiv = document.getElementById ("saves");
savesDiv.innerHTML = savesDiv.innerHTML + "<br />" + textData;
}
else {
alert ("Your browser does not support the dataTransfer object.");
}
if (event.stopPropagation) {
event.stopPropagation ();
}
else {
event.cancelBubble = true;
}
return false;
}
</script>
The script in combination with the corresponding html works perfectly for the target and saved divs... but what i would really like is to apply the same script to a set of divs pairs named
(target1, saves1 )
(target2, saves2)
(target3,saves3)
(target4 saves4) etc etc
with numbers in div ids going up every time by 1 up to (target20, saves 20) ... Without obviously repeating the same script 20 times with different id names when referring to all the target and saved divs.
I realize this is a total newbie question but I'm really interested to learn the different ways this can be approached.
Give a common class name to these divs so when the dragdrop event occurs, it can be handled using the class name instead of the id; that is, like $('.someClass').someEvent instead of $('#target1'). You can get its id property inside this function using $(this).attr("id").
So if you have "target1" as the id, get the last character ("1") using the JavaScript substring function; you can write generic code such as this:
$('.someClass').someEvent(function(){
var id=$(this).attr(id);
var lastno=id.substring(id.lastIndexOf("t"),id.length);
//now rest of code
$("#saves"+lastno).val($("#target"+lastno).val());
});
I have a function that loops through all of the inputs of my form and checks if they are filled or not. If the field is blank, it makes that specific input pink and returns false.
I'm trying to add a "Field Required" message underneath the inputs that are not filled. So i coded an extra table row after each one, with a div that holds the error message. The css for the div is set to "display:none" on page load.
Right now my function is showing "required" for every input and not just the ones that are blank, but the pink coloring is still working correctly.
How do I get the "required" div to show and hide correctly like the pink coloring does?
checkinputs = function (blockOne,blockTwo) {
inputGood = true;
blOne = $(blockOne);
blTwo = $(blockTwo);
blInput = [blOne,blTwo];
for (x = 0; x < 2; x++) {
var validators = blInput[x].find(" [id$='RequiredIndicator']").parent().parent('tr').find(':input:not(:hidden)');
var notAllFilled = validators.filter(function(){
var myInput = $(this); //.parent().parent('tr').find(':input');
var filledVal = myInput.val();
var isFilled = $.trim(filledVal).length;
if (isFilled) {
$(this).css('background-color', 'white');
$(this).closest('div').find('.required').hide();
$(this).parent('td').prev('td').find('span').text('*');
}
else {
$(this).css('background-color', 'pink');
$(this).closest('div').find('.required').show();
$(this).parent('td').prev('td').find('span').text('*');
inputGood = false;
}
return isFilled;
}).length;
var inputCount = validators.length;
};
if( !inputGood ){
$('#errorAlert').append('<span style="font-weight:bold;">"Some required information is missing. Please complete the missing fields below."</span>' + '<br><br>');
$('#errorAlertTwo').append('<span style="font-weight:bold;">"Some required credit card information is missing. Please complete the missing fields below."</span>' + '<br><br>');
}
return inputGood;
};
HERE IS A FIDDLE OF THE ISSUE:
http://jsfiddle.net/RNMM7/
Your issue is almost definitely your line to show the div:
$(this).closest('div').find('.required').show();
What this line does is:
Starting at your $(this), it finds the nearest ancestor [including $(this)] that is a div, going up the DOM tree
Finds all elements with class 'required' under that div, and shows them.
Without seeing how your HTML is structured, my guess is that the nearest div element up the DOM tree encompasses all your .required elements. You'd need to replace the 'div' in that statement with an element lower in the DOM tree that would only encompass your $(this) and the one .required element you want to show.
Lets clarify my question,
I want to make an element which the element contains 5 fields so I dont want the user should be able to put in a new element if the old one is null, so I made the alert when looping through the old element and see if there is some strings, if not then dont put a new element and make an alert please fill out all fields
Here again my code
function addEvent() {
var ni = document.getElementById('discount'); // Takes the a div named discount
var discountForm = document.getElementById('discountForm'); // Takes the a form named discountForm
var numi = document.getElementById('theValue'); // Takes the a hidden input field named theValue
var num = (document.getElementById("theValue").value -1)+ 2; // Start counting to set the new divs form numbers
numi.value = num;
var divIdName = "my"+num+"Div"; // the new divs will be named
var allDivTags = discountForm.getElementsByTagName('div'); // take all div tags
var numOfDivs = (allDivTags.length -1); // take the number of the old div
var oldDivIdName = document.getElementById(allDivTags[numOfDivs].id); // old div id
var newdiv = document.createElement('div'); //the new div
newdiv.setAttribute("id",divIdName);
newdiv.innerHTML = "Company <select name=\"company[]\"><option value=\"\"></option><option value=\"ZI\">Avis</option><option value=\"ET\">Enterprise</option><option value=\"ZE\">Hertz</option><option value=\"ZD\">Budget</option><option value=\"ZR\">National</option><option value=\"AL\">Alamo</option></select> Discount Type <select name=\"type[]\"><option value=\"CD\">Discount Number</option><option value=\"PC\">Coupon Number</option></select> Code <input name=\"code[]\" type=\"text\"> Title <input name=\"title[]\" type=\"text\"> Remove"; // creating the fileds in the new div
ni.appendChild(newdiv);
for(i=0; i<discountForm.elements.length;i++){ // loop through the divs
if(numOfDivs != i-1){ // if tho old div exist and if the old div fields are empty
if(oldDivIdName.children[i].value.length == 0){
removeElement(divIdName); // then dont put the new one
alert('Please enter all fields');
}
}
}
}
But my problem is that in IE comes out an error children[...].value.length is null or not an object so I trying to figure how to fix it,
I hope its more clearly for you now.
It's very hard to tell from the information you've given us. But my first guess is the following:
for(i=0; i<discountForm.elements.length;i++){
if(numOfDivs != i-1){
if(oldDivIdName.children[i].value.length == 0){
removeElement(divIdName);
alert('Please enter all fields');
}
}
}
Above you're doing:
oldDivIdName.children[i]
But i is defined as the number of elements in the form from what I can see... not the number of children of the oldDivIdName. If there are more elements in the form than there are in oldDivIdName then the value of oldDivIdName.children[i] will be null. And "value" is not defined on null.
It's very hard to tell from the information you've given us. But my first guess is the following:
When you first call this method, allDivTags.length whether is null or negative, and results
not got element:
var oldDivIdName = document.getElementById(allDivTags[numOfDivs].id);