I am trying to make an independently working div which has a form inside of it.
I use jquery to calculate the price of a product depending of the user's selections in the form. However the user is able to add multiple items in his 'cart' so the form is duplicated to another div. The problem is that the calculation pattern can't separate these two divs and the calculation will be incorrect. The form is also interactive so it will be generated by the user's input. This is really complex set and renaming every variable by the 'product number' doesn't sound really efficient to me.
I'm kind of stuck here and i don't really know how to solve this problem. I had an idea that what if I put an iframe inside of the div and load my form and its calculation script inside of it, and then use post command to transfer the price of the product to the 'main page' to calculate the total price of all of the products the user wanted.
However it seems that jQuery scripts doesn't work independently inside of these iframes, they still have connection so they broke each other.
i will appreciate any kind of suggestions and help to solve this matter, thank you!
here's the code so far
Heres the body
var productNumber = 1;
<div id="div_structure">
</div>
<button id="newProduct" >Add new product</button><br \>
add new item
<!-- language: lang-javascript -->
$('#newProduct').click(function ()
{
$('<div id="productNo'+productNumber+'">')
.appendTo('#div_structure')
.html('<label onclick="$(\'#div_productNo'+productNumber+'\').slideToggle()">Product '+productNumber +' </label>'+
'<button onclick="$(\'#product'+productNumber+'\').remove()">Remove</button>');
$('<div id="div_product'+productNumber+'" style="display: none;">').appendTo('#product'+productNumber+'');
$('<iframe src="productform.html" seamless frameborder="0" crolling="no" height="600" width="1000">').appendTo('#div_product'+productNumber+'');
productNumber++;
});
it also has a function that allows the user to remove the inserted div.
Here's just few lines from the productform
$(document).ready(function()
{
$('#productCalculation').change(function ()
{
shape = $('input[name=productShape]:checked', '#productCalculation').val();
alert(shape);
});
});
<form id="productCalculation">
<div id="div_productShape" class="product1">
<h1>Select the shape of the product</h1>
<input type="radio" name="productShape" value="r1">R1</input><br \>
<input type="radio" name="productShape" value="r2">R2</input><br \>
<input type="radio" name="productShape" value="r3">R3</input><br \>
</div>
.
.
.
</form>
I translated all of the variables so they may not function correctly since i didn't test the translated version. So the problem is, if i try to make selections in the second generated div it wont even alert() the selected variable
There are two problems with this code: You say somewhere "I translated all of the variables so they may not function correctly since i didn't test the translated version. So the problem is, if i try to make selections in the second generated div it wont even alert() the selected variable". This is because event handlers are attached to elements that are in the DOM at that specific moment. To get it to work for all elements, use event delegation:
$(document).ready(function()
{
$(document).on( 'change', '#productCalculation', function ()
{
shape = $('input[name=productShape]:checked', '#productCalculation').val();
alert(shape);
});
});
Your other question is "My question in a nutshell: Is there a way to restrict jquery to function only in certain div even though i use the same variable names in the second div ". You can use the this variable to access the element the click was invoked on. From this element you can traverse the DOM if needed, for example with .parent().
$('div').on( 'change', function( e ) {
console.log( $(this).val() );
} );
Related
I tried following the information here, editing it to match my needs, but so far it's not working.
I'm trying to hide a parent div with two child elements. The parent div is part of a list, all with the same classes, and each div has two child elements: an input, and an image. Each input has a unique "data-wapf-label" that I'm trying to select so that I can hide the parent div. The HTML is as follows:
<div class="has-pricing wapf-swatch wapf-swatch--image">
<input type="radio" id="wapf-field-61b148f2fc8fe_lzhx7" name="wapf[field_61b148f2fc8fe]" class="wapf-input" data-field-id="61b148f2fc8fe" value="lzhx7" data-wapf-label="Peppermint Mocha" data-is-required data-wapf-pricetype-"fx">
<img src="...">
</div>
There are several pages where this product shows up, and rather than going in and deleting the product field (because I'll just have to add it again next season), I'm trying to create a piece of code that will hide all the divs for all the products that have the above code (since each has a unique "id", I'd have to do it several times for each id using "selectElementById", and I'd like to avoid doing that, obviously).
I installed Code Snippets, but I'm having a bit of trouble with the Javascript. I should add that Code Snippets inserts code to the website via php (so php tags are required with every snippet). I've tried several things, but this is my latest version. It throws a syntax error "unexpected 'hideFlavors' (T_STRING), expecting '('".
Here's my php/Javascript code:
<?php
add_action( 'wp_head', function hideFlavors() { ?>
<script>
if var peppermintMocha = document.querySelectorAll("[data-wapf-label='Peppermint Mocha']") {
peppermintMocha.parentNode.style.display = "none";
}
</script>
<?php } );
I've also tried it with "document.querySelector" (without the "All"), but with the same or similar problem. When I do get the code to actually go through without any errors, it still doesn't fix the problem.
At this point, I feel a little like the guy looking through the tank's periscope on "Independence Day". No matter what I do, "target remains".
<?php
add_action( 'wp_head', function() {
?>
<script>
window.onload = function() {
document.querySelectorAll("[data-wapf-label='Peppermint Mocha']").forEach(function(el) {
el.parentNode.style.display = "none";
});
};
</script>
<?php
});
?>
querySelectorAll returns an array of elements, so you need to loop through each element and hide their parent respectively.
Instead querySelectorAll use querySelector. Then it would be work. But make sure that exists only one input field with the selector [data-wapf-label='Peppermint Mocha'].
I am a beginner in HTML and I want to create a region on a HTML page where the values keep on changing. (For example, if the region showed "56" (integer) before, after pressing of some specific button on the page by the user, the value may change, say "60" (integer) ).
Please note that this integer is to be supplied by external JavaScript.
Efforts I have put:
I have discovered one way of doing this by using the <canvas> tag, defining a region, and then writing on the region. I learnt how to write text on canvas from http://diveintohtml5.info/canvas.html#text
To write again, clear the canvas, by using canvas.width=canvas.width and then write the text again.
My question is, Is there any other (easier) method of doing this apart from the one being mentioned here?
Thank You.
You can normally do it with a div. Here I use the button click function. You can do it with your action. I have use jquery for doing this.
$('.click').click(function() {
var tempText = your_random_value;
// replace the contents of the div with the above text
$('#content-container').html(tempText);
});
You can edit the DOM (Document Object Model) directly with JavaScript (without jQuery).
JavaScript:
var number = 1;
function IncrementNumber() {
document.getElementById('num').innerText = number;
number++;
}
HTML:
<span id="num">0</span>
<input type='button' onclick='IncrementNumber()' value='+'/>
Here is a jsfiddle with an example http://jsfiddle.net/G638z/
I have a list of Questions, and each of those Questions has a list of Answers (which can be any integer from 1-5). I would like to dynamically create a chart for each Question, using the count of all answers that match a specific "rank"; i.e. all the answers that were a '1', '2', '3', etc.
So what I've done is set a for loop that creates an element for each question; this element is used as a placeholder for the chart. (As an aside, I am using flot charts).
The problem I'm having is trying to name the placeholders dynamically; what I really want is to create something that ends up looking like this:
<div id='chart1'/>
<div id='chart2'/>
etc
The closest I've managed is this:
<div id="'chart'#currentQuestion"/>
which of course gives an id like this: 'chart'1
Later, when I try to append the chart to the div I've created, the following doesn't work:
$("#'chart'"+i).append(div); //where i is the current loop counter
If I use
$("#chart"+i).append(div);
it correctly finds the element 'chart1', 'chart2' etc; but I'm struggling to name the div to match.
Can anyone help? It seems trivial unless you know how to solve it :-)
Edit: As requested, here is the relevant HMTL:
<div id="'chart#currentQuestion'">CHART</div>
SOLVED:
Like this: id="chart#(currentQuestion)" (via a colleague) Thanks for your efforts.
You haveen't close your div correctly. try this code
<div id='chart1' style="border:dashed">
</div>
<br />
<div id='chart2' style="border:dotted">
</div>
<script type="text/javascript" src="jquery_library.js">
</script>
<script type="text/javascript">
function fnc(value){
$("#chart"+value).append('1');
}
</script>
<input type="button" onclick="fnc(1)" value="for div1"/>
<input type="button" onclick="fnc(2)"value="for div2" />
You are using razor syntax, so here how it should be.
// Define your counter
#{long i = 0;}
// On document ready dynamically add your items
$("document").ready(function(){
// Create red divs starting by zero
// after 5 divs stop creating red divs
#for (i = 0;i<5;i++){
#:$("#form").append('<div id="chart' + #(i) + '">Red</div>');
}
});
// I made a button for action, you can choose other ways to invoke this function
$("#form>input").click(function(){
// Your counter is at 4 now
// lets change it to 2
#(i = 2;) // Now your counter is at 2
// Put a blue div into 2nd div starting by 0
$("#chart"+#(i)).append('<div class="blue">blue</div>');
});
this is how you use razor syntax with scripts
To summarise briefly what I'm trying to do: I'm providing the facility for a user to view a gallery of thumbnail images, each with a corresponding download link. When the download link is clicked, I present the user with a confirmation div, and assuming the user clicks 'agree', they'll be able to proceed with the download of the full size version of the thumbnail.
To do this, I'm using a repeater to generate the thumbnails. I'm creating a unique id for each link within the 'ItemCreated' event, along with a unique hidden field that stores the relative path for the destination file for that thumbnail.
When the user clicks on the 'Download' link for the appropriate thumbnail, my code should select the 'agree' link, and update it's target path with the hidden field value of the item that was clicked (I hope that made sense?). This basically means whenever a 'Download' button is clicked, the 'agree' link is updated to direct you to the correct file.
The problem that I'm having however is that my 'agree' link never gets updated - it seems to point to the same file for every thumbnail.
Here's a snippet of the rendered thumbnail list:
<div class="download-listing">
<div class="download">
<img src="/img/thumb0.jpg" alt="" />
<div id="downloadLink0" class="dl">Download</div>
<input type="hidden" id="hf0" value="/GetImage.ashx?path=/img/0.jpg" class="hf" />
</div>
<div class="download">
<img src="/img/thumb1.jpg" alt="" />
<div id="downloadLink1" class="dl">Download</div>
<input type="hidden" id="hf1" value="/GetImage.ashx?path=/img/1.jpg" class="hf" />
</div>
<div class="download">
<img src="/img/thumb2.jpg" alt="" />
<div id="downloadLink2" class="dl">Download</div>
<input type="hidden" id="hf2" value="/GetImage.ashx?path=/img/2.jpg" class="hf" />
</div>
</div>
<input id="count" type="hidden" value="3" />
<!-- Hidden popup -->
<div id="popup">
<p><a id="close" class="bClose action">I disagree</a><a id="file-link" class="action" href="#">I agree</a></p>
</div>
Hopefully you can see from the above code that I'm trying to extract the hidden field path from the download that's clicked, and then update the #file-link 'href' with this value.
The Javascript/Jquery I'm using (and this is where the problem seems to be) is the following:
<script type="text/javascript">
$(document).ready(function () {
for (var i = 0; i < $("#count").val(); i++) {
var index = i;
$("#downloadLink" + index).click(function () {
$('#file-link').attr('href', $('#hf' + index).val());
$('#popup').bPopup();
});
}
});
</script>
However, none of this is working! What seems to be happening is that every download link points to the same path - the last one in the list. I can't figure out where I'm going wrong. Is there something obvious I'm missing?
I appreciate any help given!
Thanks
Isn't it easier to do this:
$(function(){
$(".download .dl").click(function(){
$('#file-link').attr('href', $(this).next("input").val());
$('#popup').bPopup();
});
});
Try Something like this...
$("div[id*='downloadLink']").click(function () {
$('#file-link').attr('href',$(this).siblings('img').attr('src'));
$('#popup').bPopup();
});
After a click on any download link, this code will pass the associated image href path to the file-link element.
here is the working fiddle
I'd recommend against using all those input fields. It just creates a bunch of unnecessary markup. Why not store the #count value simply in a JavaScript variable? And the inputs that contain the image paths could be removed as well. You could store that info in an attribute on each download link, named something like "data-path". For example:
<div id="downloadLink0" class="dl" data-path="/GetImage.ashx?path=/img/0.jpg">Download</div>
Now, going back to your original problem, the above markup would solve the issue quite easily:
$('.dl').click(function(){
$('#file-link').attr('href', $(this).attr('data-path')); //could also do $(this).data('path') if using jQuery 1.6 or later
$('#popup').bPopup();
});
Other people have already suggested different ways to achieve what you want, but nobody explained why your current code doesn't work.
The reason it currently doesn't work is because of how scope works in Javascript. There is no block scope* and so your index variable is defined once, and updated every time the loop runs, until in the end it has the maximum (last) value. Then whenever your event handler is run, index still has this value, and the last item will be used.
So, in JS, the easiest way to get a new scope is to use a closure. Here's an example adapted from your code:
$(document).ready(function () {
for (var i = 0; i < $("#count").val(); i++) {
var fn = (function(index) {
return function () {
$('#file-link').attr('href', $('#hf' + index).val());
$('#popup').bPopup();
};
})(i);
$("#downloadLink" + i).click(fn);
}
});
This is not as good a way to solve your actual problem as some of the other answers. However, it demonstrates the concept of creating a scope: you're calling a function that takes one parameter, index, for which you pass the loop iterator variable i. This means that the function inside it (which it returns) can now always access the value of this parameter. The inner function gets stored in fn, which then gets passed as the click handler.
If this looks really tricky, here's a more in-depth look at function and scope in Javascript.
*Note that proposed new versions of Javascript/Ecmascript may add block scoped variables. It is not currently implemented in a cross-browser fashion, however.
You should probably calculate it from the event source (#downloadLinkn), by getting n from the end of the string.
I have a script which dynamically adds rows to a form with default values:
$(document).ready(function() {
var defaults = {
'name[]': 'Name',
'email[]': 'Email',
'organisation[]': 'Organisation',
'position[]': 'Position'
};
var setDefaults = function(inputElements, removeDefault)
{
$(inputElements).each(function() {
if (removeDefault)
{
if ($(this).data('isDefault'))
{
$(this).val('')
.removeData('isDefault')
.removeClass('default_value');
}
}
else
{
var d = defaults[this.name];
if (d && d.length)
{
this.value = d;
$(this).data('isDefault', true)
.addClass('default_value');
}
}
});
};
setDefaults(jQuery('form[name=booking] input'));
$(".add").click(function() {
var x = $("form > p:first-child").clone(true).insertBefore("form > p:last-child");
setDefaults(x.find('input'));
return false;
});
$(".remove").click(function() {
$(this).parent().remove();
});
// Toggles
$('form[name=booking]').delegate('input', {
'focus': function() {
setDefaults(this, true);
},
'blur': function() {
if (!this.value.length) setDefaults(this);
}
});
});
For the following form:
<form method="post" name="booking" action="bookingengine.php">
<p><input type="text" name="name[]">
<input type="text" name="email[]">
<input type="text" name="organisation[]">
<input type="text" name="position[]">
<span class="remove">Remove</span></p>
<p><span class="add">Add person</span><br /><br /><input type="submit" name="submit" id="submit" value="Submit" class="submit-button" /></p>
</form>
I would now like to split the form into 2 sections, each of which can have rows added dynamically to it. The second section would only have spaces for name and email, so the form as a whole, before any additional rows are added, would look something like this:
But I'm not sure how to achieve this. Either I would create a separate form with a seperate script, and then would need to know how to submit the information from both forms together, or I would just have one form but would then need to work out how to add rows dynamically to each section.
Could someone help with this?
Thanks,
Nick
I've implemented this in a fully functional example here.
I cleaned up your code a little bit, but it's basically the same. The main addition is that I wrapped the inputs in a fieldset element (you could use a div just as well, but fieldset is the semantically correct element for grouping related input fields). Your 4-input section lives in one fieldset, and your 2-input section lives in another; the "Add Person" handler looks for the parent fieldset, clones the first child, and adds it into that fieldset. Conveniently, in your use case the defaults for the first fieldset are the same as those for the second fieldset, but it would be easy enough to set up multiple sets of defaults and pass them into the setDefaults function.
A few other changes to the code:
I split your setDefaults function into two different functions, setDefaults and removeDefaults - you weren't gaining anything by making them a single function, and splitting them makes the code more legible.
I used .delegate to assign the "Remove" handler - otherwise the "Remove" button wouldn't work for new input sets. I also created the "Remove" button with jQuery, rather than cloning it, because I assumed that it wouldn't make sense to include it for the first input set.
I used jQuery in a couple of places where you were using raw Javascript (e.g. getting and setting input values). I generally assume that jQuery is more reliable for cross-browser DOM access and manipulation, so if you're loading the library already there's rarely any point not using it for all but the simplest DOM functions.
I removed your .data calls, since you can get the same information by inspecting the class, and it's generally better to reduce complexity. It's possible that .hasClass('test') is slightly slower than .data('test'), but I don't think it should make any difference here.
Create one form. Put two divs inside of it. Have your script add/remove form elements to the appropriate div.
When you submit the form it should automatically submit all of the form elements in both divs since the divs are contained in the form.