JavaScript/Jquery - Copy table row inside a handler - javascript

I got a function like this:
function isRowEmpty(){
var emptyRow = true;
var tableRow;
$('#ProblemsGrid').delegate('td a', 'click', function() {
tableRow = $(this).closest ('tr');
});
tableRow.find('textarea').each(function(index, element){
var value = $(element).val();
if(value != "") {emptyRow = false;}
});
return emptyRow;
}
What I'm trying to do is to get the table row that has the that was clicked and check the of that row to see if it's empty, then return true/false. I think the problem I got here has something to do with javascript closure. The var tableRow is not being changed in the outer function. I've been trying to figure out a workaround but no luck. I'm relatively new to JavaScript and Jquery.
Update: Here's how isRowEmpty() is used.
function deleteRow(){
if (isRowEmpty()===true){
$('#ProblemsGrid').delegate('td a', 'click', function() {
$(this).closest ('tr').remove();
});
}
}
Here's part of my HTML:
<tr>
<td><textarea name='text' style='width: 98%; height:40px'>....</textarea></td>
<td><a href='#anchor' name='DeleteButton' onclick='deleteRow();'>
<img src='../images/delete.gif'></img> </a>
</td>
</tr>

You should utilize the power of jQuery when you are using it. I tried to simplify your code:
$('.deleteRow').on('click', function() {
var tr = $(this).closest('tr');
var remove = true;
tr.find('textarea').each(function() {
if ($(this).val() != '') {
remove = false;
}
});
if (remove) {
tr.remove();
}
});
Just add a class deleteRow to your remove button/image and lose your inline event handler (onclick='functionCall())
Example jsFiddle
It seems you're appending your rows dynamically, then your selector should look like this:
$(document).on('click', '.deleteRow', function() {
// ...
});
By the way. From the .delegate docs:
As of jQuery 1.7, .delegate() has been superseded by the .on() method. For earlier versions, however, it remains the most effective means to use event delegation. More information on event binding and delegation is in the .on() method. In general, these are the equivalent templates for the two methods:

Try this:
function deleteRow(){
if (emptyRow){// isRowEmpty returning emptyRow
$('#ProblemsGrid').delegate('td a', 'click', function() {
$(this).closest ('tr').remove();
});
}
}

Try this.
function isRowEmpty(el){
var emptyRow = true;
if(el.val() != "" && el.val() != "....")
emptyRow = false;
return emptyRow;
}
$(document).delegate('#ProblemsGrid td a', 'click', function() {
if (isRowEmpty($(this).closest('tr').find('textarea'))){
$(this).closest('tr').remove();
}
});
Fiddle

Related

Add function inside Quicksand jquery

I'm using quicksand but I'd like to add a hover effect inside the element that is filtered by Quicksand jquery.
(function ($) {
var $itemsHolder = $('ul.proyectosthumb');
var $itemsClone = $itemsHolder.clone();
var $filterClass = "";
$('ul.filter li').click(function(e) {
e.preventDefault();
$filterClass = $(this).attr('data-value');
if ($filterClass == 'all') {
var $filters = $itemsClone.find('li');
}
else {
var $filters = $itemsClone.find('li[data-type='+ $filterClass +']');
}
$itemsHolder.quicksand($filters);
});
}(jQuery));
Function for hover effect:
$('.thumbnail').hover(
function(){
$(this).find('.caption-hover').fadeIn(250); //.fadeIn(250)
},
function(){
$(this).find('.caption-hover').fadeOut(250); //.fadeOut(205)
}
);
Any Idea to add this function inside Quicksand?
I also had the same issue with quick sand elemnts question here. this worked for me.use this function .this may help .
jQuery(document).on('hover',".thumbnail",function(){
//code here .
});
reason behind this is
The .on() method attaches event handlers to the currently selected set of elements in the jQuery object. check full desc

create stackoverflow tagging system?

I am trying to create a tagging system just like SO has.
I have added the tags,now I want to remove them.
MyQuestion:
How do I remove the tags appended?
how do I make the cross button(a span) look identical to that in SO tagging system?
SO TAGGING
var tags = [];
$("#textBox").keypress(function (e) {
if (e.which === 13) {
$(".target").append("X</span>'+ "");
function remove_tag(){
//what to do here?
}
tags.push(this.value);
this.value = "";
}
});
Here's my JSFiddle: http://jsfiddle.net/Wky2Z/11/
Basically, listen on the .cross to be clicked, and then remove from array and delete element
//enter something in textbox and press enter....
var tags = [];
$("#textBox").keypress(function (e) {
if (e.which === 13) {
$(".target").append("X</span>'+ "");
tags.push(this.value);
this.value = "";
}
});
$('body').on('click','.cross',function(){
tags.splice($(this).parent('a').html(), 1);
$(this).parent('a').remove();
});
As for the look of the cross, SO use a CSS Sprite, so you can do the same by making a png or gif or jpeg of the two states, off(grey) and hover(red) and switch the background-position to red with css eg: .cross:hover { background-position:0px -20px }
You can delete elements making use of remove().
Also, i would recommend you to make use of jQuery events instead of using inline events. (if you take a look at the source code of stackoverflow you will notice there are no inline javascript calls)
In this case you would need to add an event handler to the document object as you want to assign the events to elements which are not loaded in the DOM from the start.
$(document).on('click', '.tag span', function(){
$(this).parent().remove();
});
Living example: http://jsfiddle.net/Wky2Z/7/
Update
I updated the example removing the element from the list of tags too:
http://jsfiddle.net/Wky2Z/8/
Added a data-value for the tag links:
$(".target").append("X</span>'+ "");
And modified the click event:
$(document).on('click', '.tag span', function(){
$(this).parent().remove();
var removeItem = $(this).parent().data('value');
tags = $.grep(tags, function(value) {
return value != removeItem;
});
});
For a full jQuery solution you can remove the inline remove_tag function and use jQuery on function. it works for dynamically created elements too.
Attach an event handler function for one or more events to the
selected elements.
Here you can get the parent element of the deleted element and remove it from the DOM using remove.
To "sync" the array with the current situation you can use grep to delete the item from the array; note the removedItem variable used to get the text only of the parent excluding the children from the text.
Code:
//enter something in textbox and press enter....
var tags = [];
$(document).ready(function () {
$('body').on('click', 'span.cross', function () {
var removedItem = $(this).parent().contents(':not(span)').text();
$(this).parent().remove();
tags = $.grep(tags, function (value) {
return value != removedItem;
});
});
$("#textBox").keypress(function (e) {
if (e.which === 13) {
$(".target").append("X</span>' + "");
tags.push(this.value);
this.value = "";
}
});
});
Demo: http://jsfiddle.net/IrvinDominin/pDFnG/
Here's the updated link: http://jsfiddle.net/Wky2Z/6/
Move remove_tag outside of keypress event handle and pass a this pointer to it for quick solution:
//enter something in textbox and press enter....
var tags = [];
function remove_tag(x) {
$(x).parent('a').remove();
}
$(function () {
$("#textBox").keypress(function (e) {
if (e.which === 13) {
$(".target").append("X</span>' + "");
tags.push(this.value);
this.value = "";
}
});
});

jQuery how to get the class or id of last clicked element?

I am trying to get the class or an id of the last clicked element. This is what I have based off of what I found here...
HTML
Button
JQUERY
$('.button').click(function () {
myFuntion();
});
function myFunction (e) {
e = e || event;
$.lastClicked = e.target || e.srcElement;
var lastClickedElement = $.lastClicked;
console.log(lastClickedElement);
}
This sort of does what I want, but I am not sure how to go about modifying it so I can get just the class.
I have also tried using this solution but couldn't get it to work with my code.
$('.button').click(function () {
myFuntion();
});
function myFunction(){
var lastID;
lastID = $(this).attr("id");
console.log(lastID);
}
When I do this my console log comes back as undefined. I am probably missing something obvious. Any help is much appreciated. Thanks.
You can pass clicked element as parameter to your function:
$('.button').click(function () {
myFunction(this);
});
function myFunction(element) {
console.log(element);
console.log(element.id);
console.log($(element).attr("class"));
}
UPDATE added jsfiddle
A couple of ways come to mind:
$(".button").click(myFunction);
Should work with the above myFunction.
$(".button").click(function () { myFunction($(this)); });
function myFunction($elem) {
var lastID;
lastID = $elem.attr('id');
$.data('lastID', lastID);
}
In order to get the class-name of the element, assuming you have an accurate reference to the element from which you want to retrieve the data:
var lastClickedElement = $.lastClicked,
lastClickedElementClassNames = lastClickedElement.className;
This does return the full list of all the classes of the element though.
$('.button').click(function () {
myFuntion(this);
});
function myFunction(ele){
var lastID;
lastID = $(ele).attr("id");
console.log(lastID);
}
First Select all possible DOM Elements
var lastSelectedElement = null
$(document).ready(function(){
$("*").live("click",function(){
lastSelectedElement = $(this);
myFunction($(this));
});
});
function myFunction(element) {
console.log(element);
console.log(element.id);
console.log($(element).attr("class"));
}
than you could play with lastSelectedElement by grabbing it's ID or Class with jQuery .attr("ID OR CLASS");

Can't select added tr by jQuery

I add table and it's raws by jQuery when find result in database,and remove table when don't find anything.It works correctly.
$("#AdminSearch").bind("change keyup", function() {
var url = "http://localhost/PmMusic/index.php/admin/ajax/admin_search/"+$("#AdminSearch").val();
$.getJSON(url,function(data){
if (data.length == 0)
{
$("#AutoSearch").hide(1000);
$("#AutoSearchTable").remove();
}
else
{
$("#AutoSearchTable").remove();
$("#AutoSearch").append('<table id="AutoSearchTable">');
for(var i = 0;i < data.length && i < 5;i++)
{
$("#AutoSearchTable").append('<tr><td id="TableSearchTR'+i+'" value="'+data[i]+'">'+data[i]+'</td></tr>');
}
$("#AutoSearch").append('</table>');
$("#AutoSearch").show(1000);
}
});
});
but when I wanna select tr by following code
$('tr').click(function(){
alert("Hi");
});
When I click on other table tr in page it works,but it can't select tr which added by upper code).
where is the problem?
You need to use .live() or .delegate() to attach click events to dynamically-created elements.
$("#AdminSearch").delegate("tr","click",function() {
alert("Hi");
});
That's because you're binding with .click, which only applies to elements already in the page.
Change your code to
$('tr').live('click', function(){
alert("Hi");
});
If the TR is not there when your .click() function is added, then it won't have a click event attached. You should look at using the .delegate() function instead.
click() will only work for elements already in the DOM. If you're loading in some content w/ ajax then I would suggest live().
$('tr').live('click', function() {
alert("Hi");
});

Trigger a click event on an inner element

A row in a table where each first cell contains a link needs to be clicked and open a url.
<table>
<tr>
<td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td>
<td>more data</td>
</tr>
<tr>
<td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td>
<td>more data</td>
</tr>
...
</table>
The complete row should be clickable instead of only the link top open the detail page in a fancybox, ie in the page itself.
So I tried to do something like this:
$("table tr").bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');
});
But it seems that the event is bubbling recursivly resulting in a:
Uncaught RangeError: Maximum call stack size exceeded
How can I trigger the click on the full row instead of only the link in a proper way avoiding the stackoverflow?
UPDATE: I really appreciate the answers below, but my question is about triggering the event, NOT executing the behaviour inside that event. Workarounds could be nice, but not in this case.
This worked well:
$("table tr").click(function(e) {
var $link = $(this).find("a");
if (e.target === $link[0]) return false;
$link.trigger('click');
return false;
});
EDIT:
Why most solutions don't work — they fail, because when the link was clicked, the immediate handler attached runs. The event then bubbles to see if a handler was attached to a table cell, row, etc.
When you suggest triggering a click you cause the recursion: the link was clicked → fancybox → bubbles → aha! table row → trigger the link click → the link was clicked…
When you suggest to stop propagation, please note that event stops bubbling to parent elements, so a click handler attached to body will not be executed.
Why the code above works — we check if the event bubbled from a link. If true, we simply return and stop further propagation.
See the updated fiddle: http://jsfiddle.net/F5aMb/28/
try
$('table tr').click(function() {
var href = $(this).find("a").attr("href");
if(href) {
window.location = href;
}
});
Try this:
$("table tr a").bind('click', function(e) {
e.preventDefault();
window.open($(this).attr('href'));
return false;
});
$("table tr").bind('click', function(e) {
$(this).find("a").trigger('click');
});
I found what went wrong.
In your code,
$("table tr").bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');//This line again triggers a click event binded on the tr ELEMENT which contains the 'a' ELEMENT. So it goes into a infinite loop.
});
Update:
This will do.
$("table tr").bind('click', function(e) {
window.location.href = $(this).find("a.fancybox").attr('href');
});
$(this).find("a").trigger('click'); is actually not triggering the default
anchor tag behavior. It just tries to trigger a click event if a click event
is already bound to that element explicitly.
It may be that I misunderstood your question, but doesn't this do what you need:
$("table tr").click(function(e) {
e.stopImmediatePropagation();
if (! $(e.target).is('a')) {
$(this).find("a").trigger('click');
}
});
For the funny purpose of this exercise, here is a pure js solution, i.e., w/o using jQ lib).
Available here for testing: http://jsfiddle.net/Sr5Vy/3/
<table>
<tr id="node_1">
<td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td>
<td>more data</td>
</tr>
<tr id="node_2">
<td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td>
<td>more data</td>
</tr>
</table>
function AddEvent(id, evt_type, ma_fonction, phase) {
var oElt = document.getElementById(id);
if( oElt.addEventListener ) {
oElt.addEventListener(evt_type, ma_fonction, phase);
} else if( oElt.attachEvent ) {
oElt.attachEvent('on'+evt_type, ma_fonction);
}
// Debug
// alert('a \'' + evt_type + '\' event has been attached on ' + id );
return false;
}
function getElementsByRegExpOnId(search_reg, search_element, search_tagName) {
search_element = (search_element === undefined) ? document : search_element;
search_tagName= (search_tagName === undefined) ? '*' : search_tagName;
var id_return = new Array;
for(var i = 0, i_length = search_element.getElementsByTagName(search_tagName).length; i < i_length; i++) {
if (search_element.getElementsByTagName(search_tagName).item(i).id &&
search_element.getElementsByTagName(search_tagName).item(i).id.match(search_reg)) {
id_return.push(search_element.getElementsByTagName(search_tagName).item(i).id) ;
}
}
return id_return; // array
}
function FollowSpecialLinks(event) {
// Debug
// alert('event was successfully attached');
// Prevent propagation
event.preventDefault();
// Identify targetted node (eg one of the children of <tr>)
var targetted_elt = ShowEventSource(event);
//alert('Event\'s target : ' + targetted_elt);
// Extract the targetted url
if (targetted_elt == "A") {
var current_link = GetEventSource(event).href;
} else {
var current_tr = GetEventSource(event).parentNode;
var child_links = current_tr.getElementsByTagName('a');
var current_link = child_links[0].href;
}
// Now open the link
if(current_link) {
// Debug
alert('will now open href : ' + current_link);
window.location = current_link;
}
}
function GetEventSource(event) {
var e = event || window.event;
var myelt = e.target || e.srcElement;
return myelt;
}
function ShowEventSource(event) {
var elmt;
var event = event || window.event; // W3C ou MS
var la_cible = event.target || event.srcElement;
if (la_cible.nodeType == 3) // Vs bug Safari
elmt = la_cible.parentNode;
else
elmt = la_cible.tagName;
return elmt;
}
// Get all document <tr> id's and attach the "click" events to them
my_rows = new Array();
my_rows = getElementsByRegExpOnId(/^node_.+/, document , 'tr') ;
if (my_rows) {
for (i=0; i< my_rows.length; i++ ) {
var every_row = document.getElementById( my_rows[i] ) ;
AddEvent(every_row.id, 'click', FollowSpecialLinks, false);
}
}
Try
$(".fancybox").parent('td').parent('tr').bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');
});
Have you tried stopping immediate propagation when you click the link?This way you should stop the recursion
$('a').click(function(e){
e.stopImmediatePropagation();
alert('hi');
});
fiddle here: http://jsfiddle.net/3VMGn/2/
In order to compensate for the bubbling, you need to detect the target of the event and not click on the link more than once.
Also, jQuery's "trigger" function won't work for plain links, so you need a specialized click function.
you can try it out at: http://jsfiddle.net/F5aMb/27/
$("table tr").each(function(i, tr){
$(tr).bind('click',function(e) {
var target = $(e.target);
if( !target.is("a") ) {
clickLink($(this).find("a")[0]);
}
})
});
function clickLink(element) {
if (document.createEvent) {
// dispatch for firefox + others
var evt = document.createEvent("MouseEvents");
evt.initEvent("click", true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
} else {
//IE
element.click()
}
}
I was able to do it by giving each link a unique ID and then using jQuery to set the click event of that unique ID to redirect the window to the appropriate page.
Here is my working example: http://jsfiddle.net/MarkKramer/F5aMb/2/
And here is the code:
$('#link1').click(function(){
// do whatever I want here, then redirect
window.location.href = "detail.aspx?CID=67525";
});
$('#link2').click(function(){
// do whatever I want here, then redirect
window.location.href = "detail.aspx?CID=17522";
});
$("table tr").click(function(e) {
e.stopImmediatePropagation();
$(this).find("a").trigger('click');
});
You can do what you want with following code. I tested it on you jsfilddle seems working.
$("table tr").click(function(e) {
// check if click event is on link or not.
// if it's link, don't stop further propagation
// so, link href will be followed.
if($(e.target).attr('class')=='fancybox'){
alert('you clicked link, so what next ?.');
// else if click is happened somewhere else than link,
// stop the propagation, so that it won't go in recursion.
}else{
alert('no link clicked, :( ');
alert('now clicking link prgrammatically');
$(this).find('a').click();
e.preventDefault();
}
});
Let me know, if you want to achieve something else than this.
I think .click() or .trigger("click") only fires the event handlers for onclick.
See a sample here http://jsfiddle.net/sethi/bEDPp/4/
. Manually clicking on the link shows 2 alerts while firing the event through jQuery shows only 1 alert.
You can also refer to this link : re-firing a click event on a link with jQuery
Solution
If you are just looking to open a fancybox try this:
$("table tr").bind('click',function(e) {
var elem = $(e.target);
if(elem.is('a')){
return;
}
e.stopImmediatePropagation();
var parent= elem.is('tr') ? elem:elem.parents("tr").eq(0);
parent.find("a").trigger('click.fb');
});
where click.fb is the event that fancybox binds with the anchor element.
$('a.fancybox').click(function(evt){evt.stopPropagation())});
$('table tr:has[.fancybox]').click(function(evt){
$(this).find('.fancybox').trigger('click')
})
I think I have what you're looking for. What you need to do is to call click() on the anchor tag in the handler, and make sure you ignore events from the anchor itself. Also, WebKit doesn't support click(), so you have to implement it yourself.
Notice from the fiddle below that it properly follows the link target, that is, opens a new window, or loads into the same window. http://jsfiddle.net/mendesjuan/5pv5A/3/
// Some browsers (WebKit) don't support the click method on links
if (!HTMLAnchorElement.prototype.click) {
HTMLAnchorElement.prototype.click = function() {
var target = this.getAttribute('target');
var href = this.getAttribute('href');
if (!target) {
window.location = href;
} else {
window.open(href, target);
}
}
}
$("table tr").bind('click',function(e) {
// This prevents the stack overflow
if (e.target.tagName == 'A') {
return;
}
// This triggers the default behavior of the anchor
// unlike calling jQuery trigger('click')
$(this).find("a").get(0).click();
});
My usecase was to trigger a click when a -element was clicked. Checking the type of the target element solves the recursive call problem.
$('#table tbody td').click(function(e){
if ($(e.target).is('td')) {
$(this).find('input').trigger('click');
}
});

Categories

Resources