JS: get value of element in ajax updated div - javascript

I have a page with a div updated with Ajax request as needed; this div contains an input with dynamic name that I need to get data from. The button and the script that need this data are placed on the main page. When I try to get data with scripts placed in the updated div html itself, it works fine; but same code placed on the main page does not work. How do I find an element by id in Ajax updated div?
Main page:
/* ajax updated div */
<span id="i_descr_{{i.id}}" class="tooltiptext"></span>
/* button */
<div class="trade_move arrow_r" item_id="{{i.id}}" partner_id="{{data.partner_id}}"></div>
<script>
$(".trade_move").click(function() {
var item_id = $(this).attr("item_id");
var partner_id = $(this).attr("partner_id");
var quantity = 1;
var sliderElem = document.getElementById("slider_".concat($(this).attr("item_id")));
if (sliderElem) {
quantity = sliderElem.value;
}
}
</script>
Ajax template, input part:
<input class="slider" type="range" item_id="{{description.id}}" id="slider_{{description.id}}" min="0" max="{{description.slider}}" value="{{description.slider}}" step="1">
If I put the button and the script into the ajax template, they work just fine; is it possible to address the input by its id from main page, loaded before the ajax part?
edit:
I tried adding the button press script to ajax unction that updates the div as by suggestion from Arathi Sreekumar, but it behaves same as before. It also does not work unless you actually load the div with the slider now, meaning it comes from ajax function and not somewhere else. Could I get the syntax wrong or something?
$(".item_description").hover(function(){
var param = $(this).attr("d_id");
$.get('/sud/item_na/', {id: param}, function (data) {
$('#i_descr_'.concat(param)).html(data);
$(".trade_move").click(function() {
var item_id = $(this).attr("item_id");
var quantity = 1;
var sliderElem = document.getElementById("slider_".concat($(this).attr("item_id")));
if (sliderElem) {
quantity = sliderElem.value;
}
$.ajax({
...
});
});
});
edit2: I got it working, not exactly how I wanted it initially, but still.
I did not go into details about the general layout but to make things clear:
1) Layer 1: main page with empty div and a button
2) Layer 2: empty div on main page is populated with ajax html generated by button press. This html is a list of items, each coming with an empty tooltip div, that on hover triggers another ajax query and populates it with item info.
3) Layer 3: Item info window which has the slider control and the button to do something with the item, considering the slider value (and item id naturally).
I put the button and the script attached to it into the last layer 3 template. Here goes the code:
<div align="left">
<input class="slider_value" id="slider_value_{{description.id}}" type="number" value="{{description.slider}}" disabled>
<input class="slider" type="range" item_id="{{description.id}}" id="slider_{{description.id}}" min="0" max="{{description.slider}}" value="{{description.slider}}" step="1">
<div class="trade_move_slider arrow_r" id="trade_move_slider_button_{{description.id}}" item_id="{{description.id}}" partner_id="{{description.partner_id}}" quantity="{{description.slider}}" style="width: 30px;height: 20px;display: inline-block;">
</div>
<script>
$(document).ready(function() {
$(".slider").change(function() {
$("#slider_value_".concat($(this).attr("item_id"))).val($(this).val());
$("#trade_move_slider_button_".concat($(this).attr("item_id"))).attr("quantity", $(this).val());
});
$(".trade_move_slider").click(function() {
$('#output').html('<span class="dot"></span><span class="dot"></span><span class="dot"></span>');
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
var item_id = $(this).attr("item_id");
var partner_id = $(this).attr("partner_id");
var quantity = $(this).attr("quantity");
$.ajax({
type:"POST",
url:"/sud/trade_action/",
data: {
'partner': "container",
'id': partner_id,
'goods_id': item_id,
'csrftoken': csrftoken,
'quantity': quantity
},
success: function(data){
$('#output').html(data);
}
});
});
});
</script>
Note how button attribute "quantity" is updated on slider change. For some reason I could not address the slider directly with $('#slider_'.concat(item_id)).val(); might me the problem that brought me here initially. For general purposes I would still like to know how to address elements of one ajax generated DOM (if I'm putting this correctly) with a script in another ajax generated DOM.
This is the code that updates item info on hover:
$(".item_description").hover(function(){
if ($(this).attr("data") == "empty")
{
$(this).attr("data", "loaded");
var param;
var partner_id = $(this).attr("partner_id");
param = $(this).attr("d_id");
$.get('/sud/item_na/', {id: param, list_type: 'char', 'partner_id': partner_id}, function (data) {
$('#i_descr_'.concat(param)).html(data);
});
}
});

You could add a pseudo-class, js-slider in your input element:
<input class="slider js-slider" type="range"
item_id="{{description.id}}"
id="slider_{{description.id}}"
min="0" max="{{description.slider}}"
value="{{description.slider}}" step="1">
and then you this class in order to grab your element.
$(".trade_move").click(function() {
var item_id = $(this).attr("item_id");
var partner_id = $(this).attr("partner_id");
var quantity = 1;
var sliderElem = $(".js-slider");
if (sliderElem) {
quantity = sliderElem.val();
}
}
In the above code, I think that it is evident that item_id and partner_id are not used. So you can eliminate them. Furthermore, I don't see where you use the quantity.

Related

Dynamically check javascript value after database update

I am developing a dynamically generated and self updating form in ASP.NET MVC using javavascript, Jquery, JSON/Ajax calls.
Here is how I set up my view code from the controller. I loop through all available controls from the controller:
<ul>
#using (Html.BeginForm("Index", "WebMan", FormMethod.Post)) {
foreach (var row in Model.controls)
{
<li>
<label>#row.Name</label>
#if (row.ControlType == "STRING" || row.ControlType == COMMENT")
{
<input type="text" name="#row.Name" id="#row.NameID" value="#row.Value" data-original-value="#row.Value" class="form-control data-field" style="width: 300px"/>
}
else if (row.ControlType == "DDL")
{
<select name="#row.Name" id="#row.NameID" class="form-control data-field" value="#row.Value" data-original-value="#row.Value" style="width: 300px">
#foreach (var o in row.Options)
{
<option value="#o.Value">#o.Text</option>
}
</select>
}
</li>
}
<button type="submit">Update</button>
}
</ul>
(notice that I set the value to the value from the database and I also set the “data-original-value” to the value from the database as well)
I am using the “data-original-value” to check to see if the value has changed later.
I also set up a javascript timer that executes every 5 seconds. This timer is meant to “update” the page. (code for timer below)
var interval = setInterval(function () { Update(); }, 10000);
When the timer executes, we loop through each control in the “data-field” class. This allows me to check each dynamically generated control.
Basically, If a user has edited a control, I DO NOT want to update that control, I want to ignore it. I only want to update that specific control if a user has not changed the value. When a user changes the value, the current value != orig value (Data-original-value), so we set the field to yellow and ignore the database update code.
function Update() {
UpdateControls();
}
function UpdateControls() {
$(".data-field").each(function () {
var nameAttr = $(this).attr('name');
var id = $(this).attr('id');
var val = document.getElementById(id).value;
var origVal = $(this).data("original-value");
if (origVal == val) {
//user did not change control, update from database
var url = "/WebMan/UpdateControlsFromDB/";
$.ajax({
url: url,
data: { name: nameAttr },
cache: false,
type: "POST",
success: function (data) {
if (data != null) {
document.getElementById(id).setAttribute("data-original-value", data);
document.getElementById(id).value = data;
}
else {
alert(data);
}
},
error: function (response) {
alert("Issue updating the page controls from database");
}
});
}
else {
document.getElementById(id).style.backgroundColor = "yellow";
//user changed control, do not update control and change color
}
});
}
If no change, this ajax method in my controller is called:
[HttpPost]
public ActionResult UpdateControlsFromDB(string name)
{
var curValue= db.Setup.Where(x => x.Name == name).Select(x =>Value).FirstOrDefault();
return Json(curValue);
}
The code works correctly if a user modifies the field. It senses that the user modifies the code, and changes the field yellow.
The part that does not work correctly, is if the database updates the field. When the database first updates the field, it looks great. We set the “data-original-field” value to the value as well, to tell our code that is should not turn yellow and the user has not modified it.
But after another update, “value” and “original-value” do not match. The code document.getElementById(id).value somehow gets the OLD version of the control. It does not get the current value. So then on next loop, the values don’t match and we stop updating from DB and the control turns yellow.
My issue is that my code senses that the control value changed (database update) and turns it yellow, when I only want to turn the control yellow when a USER has changed the value in the control.
I only want to change the control and prevent updating from DB when the control has been modified by the user.
Thank you for any help.

Add to cart adding first item

I have a simple cart where I can add items on the fly and it update via AJAX. Issue being I am pulling my items from the database but when I click 'add to cart' it populates the cart but with the first item only so no matter which one I click it adds item 1.
I am looping through a result and getting the row:
while ($row = mysqli_fetch_array($r)) {
echo '
<div class="items" id="item">
'.$row["prod_name"]. '';
echo "
<div class='product_display'>
<p><img src='../admin/uploads/".$row['file_upload']."'></p>";
echo"
<input type='button' value='Add To CART' onclick='cart(\"item\");' ";
echo'
<p>Price - '.$row["prod_price"]. '</p>
<input type="hidden" id="item_name" value="'.$row["prod_name"]. '">
<input type="hidden" id="item_price" value="'.$row["prod_price"]. '">';?>
<?php echo'
</div>
</div>
';
}
The echo's really need cleaning up but they confuse me so much!
I am using a little bit of JS to do the AJAX:
$(document).ready(function(){
$.ajax({
type:'post',
url:'store_items.php',
data:{
total_cart_items:"totalitems"
},
success:function(response) {
document.getElementById("total_items").value=response;
}
});
});
And my JS does the rest:
function cart(id)
{
var ele=document.getElementById(id);
var img_src=ele.getElementsByTagName("img")[0].src;
var name=document.getElementById(id+"_name").value;
var price=document.getElementById(id+"_price").value;
$.ajax({
type:'post',
url:'store_items.php',
data:{
item_src:img_src,
item_name:name,
item_price:price
},
success:function(response) {
document.getElementById("total_items").value=response;
}
});
}
function show_cart()
{
$.ajax({
type:'post',
url:'store_items.php',
data:{
showcart:"cart"
},
success:function(response) {
document.getElementById("mycart").innerHTML=response;
$("#mycart").slideToggle();
}
});
}
I thought I would share it all so you can see - but the main issue is the fact it just adds item 1 form the list no matter which one you click on - I am getting no errors and the console is giving me nothing?
It is because you are using the same id for all your items. IDs should only be used once per page, and in cases where you are using it multiple times, document.getElementById(id) will only get the first one that it finds which is why you keep on getting the first item in the list only.
You can give each item different ids and pass that id to the cart function. Or to make things simplier, use event delegation (since you're already using jQuery) to listen for clicks on the Add To Cart button so that you don't have to use the onclick attribute anymore. You can do it like this:
$(document).on('click', 'ADDTOCARTBUTTONSELECTOR', function() {
var element = $(this).closest('.items');
var image = element.find('img')[0].src;
var name = element.find('NAMESELECTOR').val();
var price=document.find('PRICESELECTOR').val();
// the ajax part follows here
});
The ADDTOCARTBUTTONSELECTOR, NAMESELECTOR, and PRICESELECTOR are just placeholders to the actual selectors to those elements, and just replace them appropriately to select the proper elements.

Saving <div> styles with its content inside a contenteditable div

The title of this question might be unclear, but thats why I'm trying to explain it right here. I've got a contenteditable div which acts like a textarea for the articles of my blog (adminpanel). Getting the db data to display properly in the contenteditable div is no problem. But when I save the updated article version to my database, it aint saving the div styles ( as example) which are in the contenteditable div.
Example:
<div id="article_content" class="edit_article_content_container_inner" contenteditable="true"><?php echo $db_content ?></div>
outputs:
<div id="article_content" class="edit_article_content_container_inner" contenteditable="true">
<div>Dear visitor,</div>
<div><br /></div>
<div>Thank you for visiting</div>
</div>
When I make changes and decide to save the new version, the db_content column gets updated and looks like:
Dear visitor,Thank you for visiting this page
So the contenteditable div destroys my div styles when saving the new updated article. Is there a way to still store these div styles?
Thank you.
This is the part where I make the ajax call
$("#btn-save-new-article").on('click', function (event) {
var article_id = $('.edit_article_title_container').attr('data-article-id');
var article_title = $("#article_title").text();
var article_content = $("#article_content").text();
event.preventDefault();
$.ajax({
type: "POST",
url: "/includes/db-requests/admin/db-save-edited-article.php",
data: {article_id: article_id, article_title: article_title, article_content: article_content},
success: function(data,textStatus,jqXHR){ finish_editing_article(data,textStatus,jqXHR); }
});
});
function finish_editing_article(data,textStatus,jqXHR) {
//alert (data);
if (data == "article_edited_success") {
//location.reload();
alert(data);
} else {
alert(data);
}
}
As you can see, I'm storing the article_id, article_title and article_content.
Receiving the data to actual store it:
//DIV SUBMITTED DATA
$article_id = safe($mysqli,$_POST['article_id']);
$article_title = safe($mysqli,$_POST['article_title']);
$article_content = $_POST['article_content'];
.text() returns just the text content of an element. .html() returns the content with the HTML intact.
var article_content = $("#article_content").html();

Javascript populates input, but not span?

I am using Select2 dropdown menu to get data from database threw ajax and json/php.
The option i make will then populate some input fileds for editing the database.
I use (This field get´s populated ok):
<input type="text" class="form-control" name="valt_element_id" id="valt_element_id" placeholder="Objekt ID" />
But on some field i just want to show the data, not to be edited.
I figured to use:
<span id="valt_element_id"></span>
But this span code won´t work!
Why?
JS:
$(document).ready(function(){
var valtObjektElement = $('#valj_objekt_element');
$('#valj_objekt_element').select2({
ajax: {
url: "valj_objekt_element.php",
dataType: 'json',
data: function (term, page) {
return {
q: term
};
},
results: function (data, page) {
return { results: data };
}
} // Ajax Call
}); // Select2
// Start Change
$(valtObjektElement).change(function() {
var ElementId = $(valtObjektElement).select2('data').id;
var ObjektNummer = $(valtObjektElement).select2('data').text;
$('#valt_element_id').val(ElementId);
$('#valt_objekt_nummer').val(ObjektNummer);
}); //Change
}); //Domument Ready
There is no value attribute for span. You should either use text or html.
Replace
$('#valt_element_id').val(ElementId);
with
$('#valt_element_id').text(ElementId);
Using javascript:
document.getElementById("valt_element_id").innerHTML = ElementId;
Or jQuery:
$('#valt_element_id').html(ElementId);
You mentioned:
But on some field i just want to show the data, not to be edited . Why not use readonly attribute in input rather than replacing it with a span ?

Best way to pass JS/ css info to a form

I am sure this is so easy and I'm just a huge huge noob. I have a form on a PHP page, and it has a few normal form elements (1 textarea, 1 text field).
I am also dynamically adding 100 small images to the page, which are random, and I am using JQuery to let someone select or deselect these images:
Here is the html that loops 100 times to display the images:
<div class='avatar'><img class='avatar_image' src='$this_profile_image' name='$thisfriend'></div>
and here is the Jquery:
<script type="text/javascript">
$(document).ready(function() {
$(".avatar_image").click(function() {
$(this).toggleClass("red");
});
});
</script>
What I want to do is, when the form is submitted, have the script that processes it be able to tell which of those 100 images is selected (so it's class will be "red" instead of "avatar_image"). I am blanking on this.
You'll need to add hidden inputs with some kind of identifiers for those images, and toggle the state of those inputs based on the image selected-ness. Something like this:
Change your image markup:
<div class='avatar'>
<img class='avatar_image' src='$this_profile_image' name='$thisfriend'>
<input type="hidden" name="avatar_image[]" value="$this_profile_image" disabled="disabled" />
</div>
Change jQuery binding (and use event delegation, maybe pick a better container than document.body):
<script type="text/javascript">
$(function() {
var selClass = 'red';
$(document.body).on('click', ".avatar_image", function() {
var $this = $(this);
var $inp = $this.siblings('input[type="hidden"]');
var isSelected = $this.hasClass(selClass), willBeSelected = !isSelected;
$this.toggleClass(selClass);
if(willBeSelected) {
$inp.removeAttr('disabled');
} else {
$inp.attr('disabled', 'disabled');
}
});
});
</script>
Read the submitted data in PHP (assuming you're submitting via a POST form):
$selectedImages = $_POST['avatar_image'];
Add a ID to each image, when its clicked grab the id and then inject it into a hidden textfield
<input type="hidden" name="avatar" id="avatar" value="" />
$(".avatar_image").click(function() {
$(this).toggleClass("red");
//assign its id to the hidden field value
$("input[name='avatar']").attr('value', $(this).attr('id'));
// pass that to your DB
});
I presume your using ajax to grab this data back
success : function(callback){
$("image[id*='"+callback.avatar+"']").addClass('red');
}
Try this
PHP: Add the id for the friend to the html you had
<div class='avatar'>
<img class='avatar_image' src='$this_profile_image' name='$thisfriend' data-id='$thisFriendsId>
</div>
JS: Create an empty array. Use each function to go through push the selected id into your array. Then use post to submit to your php.
selected = [];
$(function(){
$(".avatar_image").click(function() {
$(this).toggleClass("red");
});
$('.submit').click(function(){
$('.red').each(function(){
var selectedId = $(this).data('id');
selected.push(selectedId);
});
$.post ('http://mysite.com/process.php', selected, function() { alert('succes!'); });
});
​});​

Categories

Resources