Embedding database ID of element in HTML for Ajax request - javascript

There is given code:
<div id="256">
<p>SOMELEMENT</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<div id="257">
<p>SOMELEMENT2</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<script>
$(".edit").click(function() { var id = $(this).parent().attr("id"); /* do some Ajax here, edit element in database with given id*/});
$(".delete").click(function() { var id = $(this).parent().attr("id"); /* do some Ajax here, delete element in database with given id*/});
</script>
There is a database with some elements, these elements have ID and I would like to do some actions on these elements via Ajax. I need database ID of element so that I can do some Ajax requests on this element. Solution above works, however there are some flaws - it is dependent from HTML structure (for example when I wrap button with some other element then parent() will not work because HTML structure changed).
How to store the better way database IDs of elements in HTML so JavaScript can get it for example for Ajax requests?

Why not do something like this using the data() method:
<div>
<p>SOMELEMENT</p>
<button class="edit" data-id="256">EDIT</button>
<button class="delete" data-id="256">DELETE</button>
</div>
<div>
<p>SOMELEMENT2</p>
<button class="edit" data-id="257">EDIT</button>
<button class="delete" data-id="257">DELETE</button>
</div>
Now that you have the data-id associated with your buttons, you can do:
$(".edit").click(function() {
var id = $(this).data("id");
/* do some Ajax here, edit element in database with given id*/
});
EXAMPLE

Although you already have a (completely valid) accepted answer, I wanted to offer another way of solving your problem that removes the burden of having to attach data to every button, instead relying on a class that can be used to get a handle to the actual item/record/entry to which the data is attached, as my HTML tends to have such a class anyway I found this pretty convenient (I'll use a list of comments as an example):
<div class="comment" data-id="256">
<p>SOMELEMENT</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<div class="comment" data-id="257">
<p>SOMELEMENT2</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<script>
$(".comment .edit" ).click(function() { var id = $(this).closest('.comment').data('id'); });
$(".comment .delete").click(function() { var id = $(this).closest('.comment').data('id'); });
</script>
Key is the .closest() jQuery function that travels up the DOM tree to find the '.comment' div that represents the comment entry. This means that as long as you keep your .edit and .delete elements inside the .comment DIV, you're free to modify your HTML structure without having to worry about your JavaScript, and without having to add the data-* attributes in multiple places.

You could use data attributes. Instead of having the id of an data entity be represented by an html id attribute. These are attributes of the form data-*.
Your code could then look like this:
<div data-elementid="256">
<p>SOMELEMENT</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
</div>
<div data-elementid="257">
<p>SOMELEMENT2</p>
<button class="edit">EDIT</button>
<button class="delete">DELETE</button>
<script>
$(".edit").click(function() { var id = $(this).parent().data('elementid'); });
$(".delete").click(function() { var id = $(this).parent().data('elementid'); });
</script>
John Resig writes about it here:
http://ejohn.org/blog/html-5-data-attributes/
Additionally you could set the data attribute on the button elements, then you wouldn't have to traverse up to the parent() to get the id.
If you want to go deeper, check out a js framework like Angular.js, Ember.js or Backbone.js. The idea is that the DOM shouldn't be used for storing data, only presenting it. Javascript models can then be used to store your application data.

Related

Dynamic Div Tags in a While Loop

I have a while loop that populates 4 div tabs (in one parent div) with PHP.
I also have a copy-to-clipboard script to copy text from a P tag. Unfortunately, this function works only if the tag and button have a unique Id.
So my question is this:
How do I assign a sequential Id to my looped P tags? In the sense that I want the first set of tabs in the first populated div to have Ids 1,2,3,4, and the next one to have 5,6,7,8...and so on.
Here is the HTML in the PHP loop:
<div id='content' class='tab-content'>
<div id='navpills-1' class='tab-pane active'>
<p id='text'>Text to be copied to clipboard.</p>
<button id='jsbtn' class='btn jsbtn' onclick='copyToClipboard('p#text')'>Copy</button>
</div>
</div>
Here is the script I'm using to copy text from the P tag to the clipboard:
<script>
function copyToClipboard(element) {
var $temp = $("<textarea>");
var brRegex = /<br\s*[\/]?>/gi;
$("body").append($temp);
$temp.val($(element).html().replace(brRegex, "\r\n")).select();
document.execCommand("copy");
$temp.remove();
}
</script>
If you are not committed to using jQuery then you can easily accomplish your goal with some fairly basic, vanilla Javascript. The Clipboard API provides the modern solution for copying text (& other things) to & from the system clipboard.
In general working with IDs can become troublesome as they need to be unique within the DOM so where the same functionality needs to be applied to multiple it items you must try to do what you were initially hoping to do - assign sequential IDs or some other such solution and reference that ID in the function call. This does not scale well and better options exist.
The following uses no ID attributes anywhere - instead the event handler assigned to each button uses the event to identify which element was clicked ( invoked the handler ) and from that node it is possible, given that you know the DOM structure, to find other nodes of interest. In the code below the event.target refers to the button - from there we find it's parent and from that parent we find the specific P element whose content is to be copied. The method suggested by #CBroe does this using jQuery methods - something I'm not familiar with.
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Basic Clipboard Copy Example</title>
</head>
<body>
<div class='tab-content'>
<div class='tab-pane active'>
<p class='copy'>Text to be copied to clipboard.</p>
<button class='btn jsbtn'>Copy</button>
</div>
<div class='tab-pane active'>
<p class='copy'>Some other text to be copied to clipboard.</p>
<button class='btn jsbtn'>Copy</button>
</div>
<div class='tab-pane active'>
<p class='copy'>Guess what...more text and not an ID in sight</p>
<button class='btn jsbtn'>Copy</button>
</div>
<div class='tab-pane active'>
<p class='copy'>And the final Paragraph and final chapter and final word.</p>
<button class='btn jsbtn'>Copy</button>
</div>
</div>
<textarea cols=100 rows=10></textarea>
<script>
document.querySelectorAll('button.jsbtn').forEach( bttn=>bttn.addEventListener('click',e=>{
const pttn=/<br\s*[\/]?>/gi;
const paragraph=e.target.parentNode.querySelector('p.copy');
const textarea=document.querySelector('textarea');
// writeText copies text to the clipboard
navigator.clipboard.writeText( paragraph.innerHTML.replace( pttn, String.fromCharCode( 10 ) ) )
.then(
()=>{
/*
All good... and to illustrate reading this copied text...
readText - reads from the clipboard
*/
navigator.clipboard.readText()
.then( text=>{
textarea.value=text;
})
},
(e)=>{console.log( 'error: %s',e.message )}
)
}));
</script>
</body>
</html>

How to print the content of a div that changes based on a foreach statement?

I have an ArrayList named conversations_client, I want to be able to get the value of conversation[6] for each div.
Each one the the media div represent a conversation.
Here is a part of my code :
<c:forEach var="conversation" items="${conversations_client}" >
<div class="media">
<div class="media-left">
<input class="checkbox" type="checkbox" name="selected-conv">
</div>
<div class="media-body">
<h4 class="media-heading">${conversation[0]}</h4>
<span class="hidden">${conversation[6]}</span>
......
I had first tried to use this code :
<script type="text/javascript">
$('.media').click(function(){
var text = $(this).text();
alert(text);
});
</script>
But it would print not only conversation[6] but others as well since they're all inside the div with class media.
Then I tried this :
<script type="text/javascript">
$('.media').click(function(){
var text = $('.hidden').text();
alert(text);
});
</script>
But it would print the same id for all divs, which is the id of the first one.
How can I do that? and would it be better to wrap those media divs with tags to be able to use a specific action for each one of them? because I am displaying all conversations, then once the user will click on one them I'll have to recover its id to be able to display the messages of that specific conversation and it isn't advisable to write Java code inside of jsp.
Thank you :)
Use find from current element.
$('.media').click(function()
{
var text = $(this).find('#hidden').text();
alert(text);
});
UPDATE:
You are using loop to repeat the markup. It's not good to use ID hidden multiple times as per W3C standards. ID should be unique and should be used once in the page.
Use class instead of id for multiple usages. In this case class="hidden"
Better change <span id="hidden">${conversation[6]}</span> to <span class="hidden">${conversation[6]}</span>
Also change JS to find .hidden
$('.media').click(function()
{
var text = $(this).find('.hidden').text();
alert(text);
});

Add element in Handlebar

I have handlebar.js integration and I am populating a number of dropdowns using the template. Now I need to have a button which needs to add the same elements below. The code is like this
<div class='row'>
//my HTML goes here
<button>Add One more</button>
</div>
When I click on the Add One more button it needs to clone the div with class name row and needs to add it to the next line. How can I do this using Handlebars? Or I need to use jQuery here?
Don't know handlebars.js, but with jQuery it'll be preety simple:
$(document).on('click', '.row button', function() {
var cloned = $(this).closest('.row').clone();
$(this).closest('.row').parent().append(cloned);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="row">
other stuff
<button>add one</button>
</div>
</div>

How to pass viewBag data into Javascript and display in div

I am always leery of asking dumb questions here but I need to move on and create a few more active pages but this is a lingering issue in my way ...The chtml in razor contains a switch ,,, in one of the cases there's three if statements.. THIS IS JUST ONE OF THEM depending on the if statements a different string in viewdata is to be fed into a div and the div class "hidden" is removed and the supplied text displayed....
I have over the past few hours regained my briefly lost ability to remove that hidden class (I hate css) but I have never been able to update the content of the div.
PLEASE Advise Thank you !!
<div id="divUnUsableEvent" class="hidden">
<div class="row clearfix">
<div class="col-md-1"></div>
<div id="systemExceptionLbl" style="font-size: 2em; color: red;"
class="text-danger:focus">
Please contact IS support
</div>
</div>
</div>
//alphascores Not present AND BetaSCores Not Present Ready for xxxxx //alphascores Not present AND BetaSCores Not Present Ready for xxxxx Scoring
if (!Convert.ToBoolean(#ViewData["alphaPresent"])
&& !Convert.ToBoolean(#ViewData["betaPresent"]))
{
<script type="text/javascript">
$(function() {
$('#UnUseableEvent').addClass("hidden");
var txtMsg = #Html.Raw(Json.Encode(ViewData["beforeAlpha"]));
$('#divUnUsableEvent').removeClass("hidden");
$('#systemExceptionLbl').removeClass("hidden");
$('#systemExceptionLbl').innerText = txtMsg;
});
</script>
<a id="XXXReScoreEvent"
href="#Url.Action("Readyforxxxxxx", "Exception", new { Id = (int)#ViewData["Id"] })"
class="btn btn-primary btn-default btn-too-large pull-left margin"
aria-label="XXXReScoreEvent">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Ready for xxxxxx Scoring
</a>
}
break;
I know its hitting the javascript, as that html element (a button) named '#UnUseableEvent' is correctly being hidden in this case. I of course would want the javascript out of this html page and just have function calls in the razor but baby steps
Specifically regarding the ('#systemExceptionLbl').innerText = txtMsg; I have tried
.text
.value
.innerHTML
all to no avail. I can see the correctly formatted Json.Encoded text reach the variable txtMsg, but again I cant get it into the div ..
I am having success now with displaying the div (remove class hidden) I was attempting to affect the wrong div name and the line removing the hidden class from the element $('#systemExceptionLbl') is not needed.
I even tried to skip the JQuery reference and go old school document.getElementById('systemExceptionLbl').innerHTML = txtMsg;
Ever tried :
$('#systemExceptionLbl').text( txtMsg );
or
$('#systemExceptionLbl').html( txtMsg );
as innerText is not a jquery function. Instead use .html() or .text() to insert data into it

easy way to assign function onclick - javascript

I am searching for much time now, for a very simple and effective way to aasign function on the click of a button in javascript (not jQuery).
The problems that I have are : 1.sometimes the dom is not yet created and the javascript function has undefined vars in it. 2.I can't pass in the right way attributes to this function.
So baically i have these:
<div class="container">
<button type=button class="click">Click</button>
<div class="smallContainer">
<img src="source.com" class="myimage">
<div class="data"> some data</div>
</div>
</div>
<div class="container">
<button type=button class="click">Click</button>
<div class="smallContainer">
<img src="source.com" class="myimage">
<div class="data"> other data</div>
</div>
</div>
<div class="container">
<button type=button class="click">Click</button>
<div class="smallContainer">
<img src="source.com" class="myimage">
<div class="data"> usefull data</div>
</div>
</div>
for (){ assign in each button the onclick function}
function onclick(){
here i want to change the opacity of the image by the class "myimage",
take the innerHTML of the div by the class "data" and do something to it(maybe i ll send an ajax request in this function also)
}
So I need a for loop or something (inside the javascript file maybe), that will asign to all buttons this function. I need every time I click the button, the function to know which button is and what the div by the class "data" has inside.
I tried many ways, each one had problems. Can anyone help with a simple working solution?
Thank you
Since you mention you do not have the skills to do this simple in plain JavaScript, then it is time to get jQuery added to your toolbox.
Here is about all the code you would need
$function() { // when the page is ready
$(".click").on("click", function(e) { // assign a function to ALL class="click"
var id = this.id; // or $(this).attr("id"); - if you need the button's ID
var divContent = $(this).parents().find(".data").html()
$.get("someserver.php",{"id":id,"parm":divContent},function(data) {
alert(data);// from server
});
});
});
try using jquery library :) with that yoy can do codes like
<script>
$(".data").click(function(){
var class_value = $(this).html();
})
</script>
as you can see, the function will be applied to all element having tha class "data"

Categories

Resources