I have a piece of HTML that gets repeated over and over using jQuery (when a user clicks 'add' it creates another block:
<p>
<label for="question[1][text]">Question: <span class="req">*</span></label>
<input name="question[1][text]" id="A_Question_1" value="" type="text" class="f_input" />
</p>
<p>
<label for="question[1][type]">Type: <span class="req">*</span></label>
<input name="question[1][type]" id="A_Type_1" type="text" class="f_input" />
</p>
I need to increment each number by 1 for each iteration of that block, so that the next block automatically creates:
<p>
<label for="question[2][text]">Question: <span class="req">*</span></label>
<input name="question[2][text]" id="A_Question_1" value="" type="text" class="f_input" />
</p>
<p>
<label for="question[2][type]">Type: <span class="req">*</span></label>
<input name="question[2][type]" id="A_Type_1" type="text" class="f_input" />
</p>
I'm sure it's simple enough but I'm not experienced enough with Regexs etc. to work out how to go about it. Thanks :)
JQote offers an HTML templating library for JQuery. It is invoked with an object containing its parameters.
<script type="text/html" id="template">
<![CDATA[
<p>
<label for="question[<%= this.iteration %>][text]">Question: <span class="req">*</span></label>
<input name="question[<%= this.iteration %>][text]" id="A_Question_<%= this.iteration %>" value="" type="text" class="f_input" />
</p>
<p>
<label for="question[<%= this.iteration %>][type]">Type: <span class="req">*</span></label>
<input name="question[<%= this.iteration %>][type]" id="A_Type_<%= this.iteration %>" type="text" class="f_input" />
</p>
]]>
</script>
Then as part of your add() function:
<script type="text/javascript">
var globalIteration = 0
function add() {
<...your code...>
globalIteration++;
var obj= {
iteration: globalIteration,
<...any other variables to insert into template...>
};
$('#template').jqote(obj).appendTo($('body'));
}
</script>
You can store template in some hidden div with placeholders for ids (something like #id#).
Then, you can replace placeholders with actual id in javascript. Something like
var html = $('#template').html().replace('#id#', id);
list.append(html);
The next id can be calculated from the current amount of children.
var id = list.children().length + 1;
Something like this should work:
$(document).ready(function() {
$container = $('#container');
$button = $('#button')
.data('clicked', 0)
.click(function() {
var clicked = $button.data('clicked');
$container.append('<p><label for="question[' + clicked + '][text]">Question: <span class="req">*</span></label><input name="question[' + clicked + '][text]" id="A_Question_' + clicked + '" value="" type="text" class="f_input" /></p>');
$button.data('clicked', clicked + 1);
});
});
It depends on how you are binding your function. If you are binding it in javascript I would probably use the number as a fake property of the add link.
Something like
'Add
Replace [1] with $(this).attr('question_number') in your javascript and at the end add $(this).attr('question_number', nextId)
A better solution might be to tack it on to the id of the link and change the id when the javascript finishes, not a good solution if you are binding by id though.
If you are binding the onclick directly in the html using something like
<a href="javascript:;" onclick="my_func();">Add</a/>
modify your function to take a parameter and change the paramter at the end of the javascript similar to above. I also like Andy's solution.
Here is how I have done it http://pintum.com.au/goCruising/details.html#tabs-2
Click the add button.
It uses jQuery, jtemplates plugin and JSON. Just look at the source for how it works.
Related
I need to select the first child of clicked element and my click listener must be tied to the class "test". How can I do this?
<span class="test">click<input type="text" value="1"></span>
<span class="test">click<input type="text" value="2"></span>
<span class="test">click<input type="text" value="3"></span>
<span class="test">click<input type="text" value="4"></span>
I'm trying this but it's always returning 1.
$(".test").click(function(){
$test = $(".test").children("input[type='text']:first").val();
alert($test);
});
Here is jsfiddle that demonstrates the problem
https://jsfiddle.net/6zudq9wy/
You are referencing all test class elements within the click function, so jQuery will pick the first and output its' first children. Instead, reference this:
$(".test").click(function(){
$test = $(this).children("input[type='text']:first").val();
alert($test);
});
You mean something like this:
$(".test").click(function(){
alert ($(this).children().eq(0).val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="test">click<input type="text" value="1"></span>
<span class="test">click<input type="text" value="2"></span>
<span class="test">click<input type="text" value="3"></span>
<span class="test">click<input type="text" value="4"></span>
$(document).ready(function () {
toggleFields();
});
function toggleFields() {
if ($("#people").val() == 1)
$("#personen1").show();
else
$("#personen1").hide();
$("#personen2").hide();
$("#personen3").hide();
$("#personen4").hide();
$("#personen5").hide();
$("#personen6").hide();
$("#personen7").hide();
$("#personen8").hide();
}
<p>Personen:
<input type="number" id="people" name="ppl" min="1" class="uniform-input number" value="1" required="">
</p>
<div id="personen1">
<p>1. Person:
<input id="personen1_person1" type="text" name="person_name" />
</p>
</div>
<div id="personen2">
<p>1. Person:
<input id="personen2_person1" type="text" name="person_name" />
</p>
<p>2. Person:
<input id="personen2_person2" type="text" name="person2_name" />
</p>
</div>
<div id="personen3">
<p>1. Person:
<input id="personen3_person1" type="text" name="person_name" />
</p>
<p>2. Person:
<input id="personen3_person2" type="text" name="person2_name" />
</p>
<p>3. Person:
<input id="personen3_person3" type="text" name="person3_name" />
</p>
</div>
I have a people number input on my landingpage. I want to use the input value to add fields to my checkout. Like if the input is 5 I want 5 fields in my checkout page so the customer can fill in the names. The code above is not working correctly. What am I missing?
The first and foremost mistake you are making is duplicating ids, which are supposed to be unique, else unintended effects may appear.
The next thing is, the snippet will not work because you haven't included jQuery library, which is more important than anything to execute the $ function.
Thirdly, find these mistakes you have made:
You didn't bind the event with the input.
You need to check the input for the existence of id.
You aren't closing the if correctly.
You can compress the code a lot of effective ways, by using class or by using ids in a single $ selector.
$(document).ready(function () {
toggleFields();
$("#people").on("keyup change", function () {
toggleFields();
});
});
function toggleFields() {
$("#personen1, #personen2, #personen3, #personen4, #personen5, #personen6, #personen7, #personen8").hide();
if ($("#people").val() < 9)
$("#personen" + $("#people").val()).show();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>Personen:
<input type="number" id="people" name="ppl" min="1" class="uniform-input number" value="1" required="">
</p>
<div id="personen1">
<p>1. Person:
<input id="person1-1" type="text" name="person_name" />
</p>
</div>
<div id="personen2">
<p>1. Person:
<input id="person2-1" type="text" name="person_name" />
</p>
<p>2. Person:
<input id="person2-2" type="text" name="person2_name" />
</p>
</div>
<div id="personen3">
<p>1. Person:
<input id="person3-1" type="text" name="person_name" />
</p>
<p>2. Person:
<input id="person3-2" type="text" name="person2_name" />
</p>
<p>3. Person:
<input id="person3-3" type="text" name="person3_name" />
</p>
</div>
You should not have multiple ids with same value.
That is not a right way of doing this, you should generate the HTML using JavaScript only:
// Sample code, you can create a function for this as well.
$(function(){
var count = 5; // Change this count with the input field value.
var _html = "";
for(var i=0; i<count; i++){
_html += '<p>'+(i+1)+'. Person:'
+'<input id="person'+(i+1)+'" type="text" name="person'+(i+1)+'_name" />'
+'</p>';
}
$(".container").html(_html);
});
Here is a fiddle
Every id attribute you use on a webpage has to be unique in the entire document, also -- you're using some kind of template to load when a user types a number but what if a user wants to add 10 people instead of 3 or 5? Individually adding cases will cause you much pain in the future.
I also understand that you want users to input a number and then get a certain amount of fields back from that, with that assumption made the code
$(document).ready(function() {
toggleFields();
});
will not work since it only gets executed once, onload of the page and doesn't get executed anymore after that since no events are bound.
var insertPeople = function(n) {
var amt = !isNaN(n) ? n : 1;
var fieldStr = '';
//using a for loop to 'build' the fields dynamically
for (var i = 0; i < amt; i++) {
var num = i + 1;
fieldStr += '<p>'+ num +'. person<input type="text" id="person'+ num +'" name="person'+ num +'_name"></p>'
}
//append HTML to container
$('#people-container').html(fieldStr);
}
//Use this to insert fields on page load instantly.
$(insertPeople);
//Use this if you would like a user to control the amount of fields through an input field.
$(function() { //shorthand for $(document).ready
$('#people').on('keyup', function() {
insertPeople($(this).val());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="number" id="people" value="1" />
<div id="people-container"></div>
This code will loop for n times where n is the user input (validate the type of that yourself) and creates fields with ID's starting from 0 through the end point at the end of the loop. At the last step it appends the fields to a container, if this were a form then that form would simply be submit with those values.
I got this snippet of code and I would like to replace the "ARRIVAL" text which is between the top and lower level <div> element but I can't figure out a way.
I don't want to use replaceWith , html or similar methods on <div class="left booktext"> because that would replace the rest of html elements. There is an event handler attached to input class="bookfields" and I don't want to lose that. Unfortunately, there is no event delegation.
<div class="left booktext">
ARRIVAL
<div class="bookborder">
<input type="hidden" name="checkin" value="2014-03-05">
<input type="text" class="bookfields hasDatepicker" style="width:65px;" id="checkin-select" placeholder="dd/mm/yyyy">
</div>
</div>
You can use contents() along with replaceWith():
$('.left').contents().first().replaceWith("New Text");
Fiddle Demo
In pure Javascript:
var books = document.querySelectorAll('.booktext');
for (var i = 0, length = books.length; i < length; i++) {
books[i].firstChild.data = "your text";
}
Easier with jQuery though:
$('.booktext').contents().first().replaceWith("your text");
Advice
Is better put text in a span element, with all the benefits of the case.
In this way you can put your text in any order inside div, like:
<div class="left booktext">
<div class="bookborder">
<input type="hidden" name="checkin" value="2014-03-05">
<span>ARRIVAL</span>
<input type="text">
</div>
</div>
And than replace with:
$('.bookborder span').text('my new text');
In pure javascript you can access a text node like this
var bookText = document.querySelector(".booktext");
bookText.firstChild.nodeValue = "Some other text";
see it working here
http://codepen.io/sajjad26/pen/JkAms
I have the following javascript code:
game.bind('gameover', function(seconds) {
setTimeout(function() {
var rank = game.getRank(seconds);
scorecard.find('.time').text(seconds + ' sec');
scorecard.find('.rank').text(rank[0]);
scorecard.find('.byline').text(rank[1]);
...more code
In the following div this data is displayed (so the js script is working):
<div class="inner">
<h3>Nice job! Your time:</h3>
<h1 class="wobble time"><!-- 15 seconds --></h1>
<h2 class="rank"><!-- Friendly Mallard --></h2>
<h3 class="byline"><!-- (That's pretty good) --></h3>
</div>
Now I want to put the results also in a form so I can post it to the a database (mysql). So I've added a form and put it in the same div:
<form id="form" action="updatescore.php" method="post">
<input type="text" id="time" name="time" value="" />
<input type="text" id="rank" name="rank" value="" />
<input type="text" id="byline" name="byline" value="" />
</form>
Now in the JS I've copied the lines (e.g. scorecard.find('.time').text(seconds + ' sec');) and changed it to look for the id, so . becomes # and passed it in the js like:
scorecard.find('.time').text(seconds + ' sec');
scorecard.find('#time').text(seconds + ' sec');
etc
So this should work I think, but the form inputs stay empty. What am I doing wrong?
Kind regards,
Maurice
If you are just looking to move js variables into your database via updatescore.php you don't need to use a form at all! You can do it with AJAX.
var scoreData = {
time : time,
rank : rank[0],
byline : rank[1]
};
$.post('updatescore.php', scoreData); //done!
Use val() instead of text() for setting the values
I have an INPUT text field, a DIV and an IMG.
The IMG has an onClick event:
reads the INPUT field's current value,
increase it with 1,
does a calculation with the increased value,
writes the result into the DIV.
The value of the INPUT is always increased the right way and the DIV's innerHTML always gets the right result but nothing changes in display. The displayed numbers always stay the same even if everything is done correctly in the "background".
The funny thing in it that I used the same operation at another place on the same site and there everything works and displays perfectly.
Here is the function:
function priceCalculator(max_amound,price,id)
{
var amound = parseInt(document.getElementById('sell_amound_' + id).value);
max_amound = parseInt(max_amound);
if (amound < max_amound)
{
amound = amound + 1;
document.getElementById('sell_amound_' + id).value = amound;
var item_value = amound * price;
document.getElementById('price_' + id).innerHTML = item_value;
alert(document.getElementById('sell_amound_' + id).value + ',' + document.getElementById('price_' + id).innerHTML);
}
}
And here are the elements within a PHP code:
<img src="images/plus.png" onclick="priceCalculator(\''.$bag_items[$i]['amound'].'\',\''.$bag_items[$i]['infos']['price'].'\',\''.$i.'\')" />
<form>
<input id="sell_amound_'.$i.'" type="text" readonly value="1" />
</form>
<div id="price_'.$i.'">'.$bag_items[$i]['infos']['price'].'</div>
The alert at the end of the function shows the right values but the displayed values stay the same.
It's a really simple action... What could be the problem?
EDIT:
After loading the source code of an "item" looks like this (these parts are created with loops from database, and, of course, I removed the irrelevant styling from the code and those many divs are there because of them):
<td>
<img id="item_pic_3" src="images/potions/3.png" onClick="shopSellInfo('3')" />
<div>26</div>
<form>
<input type="hidden" id="selected_item" value="" />
</form>
<div id="item_3" style="display: none;">
<span>blah...</span><br />
<span>
<br />blah...<br /><br />
<div>
<div>
<img src="images/increase.png" onclick="priceCalculator('26','10','3')" /><br />
</div>
<div>
<form>
<input id="sell_amound_3" type="text" readonly value="1" />
</form>
/26
</div>
</div>
<br />
<div id="price_3">10</div>
</span>
</div>
</td>
shopSellInfo('3') is the function that makes item_3 displayed at the right place.
Can you please view source and show what is output by:
<div id="price_'.$i.'">'.$bag_items[$i]['infos']['price'].'</div>
Check that the div id is corresponding to the JavaScript's.
EDIT: item_3 has CSS style display: none, that is why changes are not showing up.
I solved the problem!
The problem was that the IDs appeared at another place, too, so the function didn't know where to change the values because of the duplicated IDs.
Anyway, thanks your answers and will for help!