Jquery will not remove div - javascript

I have form in which I am adding some dynamic actions. I have a table in which I have rows of positions
applicants applied for. There is an offer postion button and when they click on the offer button I want to insert the offer fields to be submitted and updated. I can get the feilds to insert but when I click on the cancel transaction button, I can't get it to empty the div addapptrans where the form is built. Below is the code. I know it must be something simple I am missing.
<head>
<script type="text/javascript">
$(function(){
$(".offerposition").click(function(){
var row = $(this).closest('tr').find('td:nth-child(1)').text();
alert('You clicked on ' +row);
$("#addapptrans").empty();
$("#addapptrans").append(
$("<input>").attr('type','hidden').attr( 'value',row).attr('Name','Mchposid'))
.append(
$("<input>").attr('type','submit').attr( 'value','Complete Offer').attr('id','completeoffertrx').attr('name','completeoffertrx').addClass("buttonlarge buttonmargin")
).append(
$("<input>").attr('type','button').attr( 'value','Cancel Transaction').attr('id','canceloffertrx').attr('name','canceloffertrx').addClass("buttonlarge buttonmargin")
);
}
)
}
);
$(function(){
$("#canceloffertrx").click(function(){
$("#addapptrans").empty();
})
})
</script>
</head>
<body>
<form >
<div id="addapptrans"></div>
<p class="posttitle">Positions applied For</p>
<table class="tabpositions">
<tbody>
<tr>
<th class="position">Position</th>
<th class="department">Department</th>
<th class="dateapp">Date Applied</th>
<th class="appdate">Offer?</th>
</tr>
<tr>
<td style="display: none;">2281</td>
<td>Building Service Worker - Part time</td>
<td>Environmental Services</td>
<td>08/13/2001</td>
<td><input type="button" class="offerposition" value="Offer Position"></td>
</tr>
</tbody>
</table>
</form>

This code here:
$(function(){
$("#canceloffertrx").click(function(){
$("#addapptrans").empty();
})
})
Runs before #canceloffertrx exists on the page. So $("#canceloffertrx").click(fn) Matches zero elements on the page, and binds a click handler to all zero of them.
You can fix this by binding the click handler to the document, or closest parent that is present, instead.
$('#addapptrans').on('click', '#canceloffertrx', function(){
This says that when the element #addapptrans receives a click event, and element that matches the selector #canceloffertrx was the one that was actually clicked, fire the event handler function.
Or by binding the click handler when you create the button.
$("<input>")
.attr('type','submit')
.attr( 'value','Complete Offer')
.attr('id','completeoffertrx')
.attr('name','completeoffertrx')
.addClass("buttonlarge buttonmargin")
.click(function() { ... });
Lastly, some style advice :) Especially when chaining jQuery methods, you can put each call on it's own line which makes it much more readable.
And you should also know that attr() can accept an object as an argument, allowing to call it just once to set many attributes.
$("<input>")
.attr({
type: 'submit',
value: 'Complete Offer',
id: 'completeoffertrx',
name: 'completeoffertrx'
})
.addClass("buttonlarge buttonmargin")
.click(function() { ... });

Related

Dynamically added element is forcing a reload

I have a table that has a range of elements inside of it.
I have registered some event handlers and add these elements dynamically through injecting new html.
Everything works for the original elements, but when I add a new ( dynamically created element ) and trigger one of the newly created event handlers the page seems to force reload and I lose all of my data/content.
Here is a simplified version:
<table id="asset-table" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr class="asset-row">
<td align="center" style="padding-bottom: 32px;">
<form id="asset-title" class="asset-title">
<input type="text" placeholder="Add Asset Title Here ..." id="title-input1" />
<input id="title-submit" class="submit" type="submit">
</form>
<p id="asset-title-replacement" style="text-align: center; display: none;"><strong></strong></p>
</td>
</tr>
</table>
<button id="add-asset-button">Add Asset</button>
EventHandler
// asset title load
$('#asset-table').on("submit", '.asset-title', function (event) {
event.preventDefault();
console.log("asset-title");
let text = $(this).find('#title-input1').val();
let td = $(this).children().first()
td.find('.asset-title').hide();
td.find('.asset-title').next('p').text(function () {
return text
}).css("font-weight", "Bold");
td.find('.asset-title').next('p').show()
});
To add the new element:
$('#add-asset-button').click(function () {
console.log("adding asset");
$('#asset-table').append("<tr class='asset-row'><td align='center' style='padding-bottom: 32px;'><form id='asset-title' class='asset-title'><input type='text' placeholder='Add Asset Title Here ...' id='title-input1' /><input id='title-submit' class='submit' type='submit'></form><p id='asset-title-replacement' style='text-align: center; display: none;'><strong></strong></p>/td></tr>")
})
So when dynamically adding the element, everything goes as planned, it is once I interact with adding the new "title" and click submit that the page seems to reload and I lose any "state" and content previously handled.
The problem that I am having is that the eventHandler is bound to #asset-table, so when a dynamic element is created the "this" keyword is bound to the #asset-table element, so how can I specify which that I am working with for that event??
You will have multiple forms with the same id as you have it now, though that's not the main problem. You're also listening to .assetTitle rather than .asset-title and your listener is wrong, which are the main problem. When you do:
$('.asset-row').on("submit", '.assetTitle', function (event) {
...
})
jQuery will only listen for form submits within .asset-row that currently exist when the listener is attached. All of your subsequent .asset-rows with .asset-titles (not .assetTitle) that are created programmatically do not have listeners attached. Instead, you need to apply it to an element that is present when the listener is attached, and then listen to any programmatically-created elements within it, like this. Note that I've changed .assetTitle to .asset-title.
$('#asset-table').on("submit", '.asset-title', function (event) {
...
})
Fiddle

Jquery trigger click then fill in input

I have a table row that when clicked should trigger a click event on page that opens a div. once this div is open, i need #poId to be populated with given id.
$('tr').click(function(){
var id = $(this).attr('id');
$('#purchase\\.exist').trigger('click');
//What goes here?
});
the page that results from the click is:
<input type='text' id='poId' name='poId'>
basically i need to know what i can use to fill poId with click automatically. in layman's terms
$('tr').click(function(){
var id = $(this).attr('id');
//Open page as a result of trigger
//paste the variable id in the poId input
});
Added fiddle:
This fiddle is completely stripped down but the idea is a user clicks on the word question. a table appears with two rows. when a user click on the table row, the purchase div is opened and the input needs to be populated with the id of the tr clicked.
Fiddle
I know there are other ways to do this without trigger, but opening the div actually entails a bunch of other things (ajax functions and such) before the div is opened, so just simply opening the purchase div wont work
To populate poId with the value of the ID of the tr that was clicked on (which I think is what you're asking):
$('tr').click(function(){
$("#poId").val(this.id);
$('#purchase').trigger('click');
});
(I am assuming that "#purchase\.exist" was a typo of some sort?)
$(function() {
$('.hide').hide();
$('tr').click(function() {
var id = $(this).attr('id');
$('#poId').val(id);
// the second argument is an array of parameters that will be passed to the function
$('#purchase').trigger('click', [id]);
});
// the first argument of function `click` receives is the event, the next are the arguments passed from the trigger
$('li').click(function(e, id) {
var liID = $(this).attr('id');
var div = $('#div_' + liID)
div.show();
div.find('input').val(id)
});
});
li:hover {
cursor: pointer;
}
tr:hover {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id='purchase'>Purchase</li>
<li id='question'>Question</li>
</ul>
<div id='div_purchase' class='hide'>
<input type='text' id='poID' name='poID'>
</div>
<div id='div_question' class='hide'>
<table id='myTable'>
<tr id='12345'>
<th>12345</th>
</tr>
<tr id='45678'>
<th>45678</th>
</tr>
</table>
</div>

Using each() for checking which class is clicked

So here's my problem, I'm new to jQuery. What I am trying to do here is check for user to click on a certain table cell/row and it would then display a div named popup of an index the same as the table cell votes. Without having to make separate functions of all the rows in my table.
Using some numerical value will display all the dialogs from a click of the cell of the same value the first time and from the second time only the correct one.
I bet there's some other way to do it and maybe there's just a stupid error.
Using the index value in the click and dialog function won't work.
I am open to suggestions on improvement also.
The scripts:
<script type='text/javascript'>
$(document).ready( function() {
$('.votes').each(function(index) {
$('.votes:eq(index)').click(function() {
$('.popup:eq(index)').dialog();
});
});
});
</script>
HTML for the table part, only a snippet
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
HTML for the div part, only a snippet of the div:
<div class='popup'>
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class='popup'>
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
jsFiddle Demo
You don't have to iterate using each for .click, that will happen internally. You can use .index() to get the index of the element clicked with reference to its parent.
$('.votes').click(function() {
$('.popup').eq($(this).index()).dialog();
});
Initially, the main problem is that you are not using string concatenation to apply the index to the selector (demo):
$('.votes:eq(index)')
// the Sizzle selector engine doesn't know what the string "index" is.
instead of
$('.votes:eq(' + index + ')')
// using concatenation calls the .toString() method of index to apply "0" (or "1", "2", etc.)
// so that the parsed string becomes '.votes:eq(0)' which the Sizzle selector engine understands
Once the Sizzle selector engine understands which elements to target (demo), the second problem is how jQueryUI changes the DOM with the .dialog method.
Inital markup:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
Once the first click event is handled, one of the div.popup elements is transformed into a jQueryUI Dialog and is appended to the body, removing it from its initial position, like so:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
<div class="ui-dialog ui-widget ..."> ... </div>
So your initial indexes no longer apply. Fortunately, there are several solutions to both problems (a few of which I've listed below).
Solutions to Problem 1:
Use string concatenation as described above.
Use the .eq method instead, which will accept the index variable as-is
Use a delegate handler instead and grab the index from within the handler:
Example of 2:
$('.votes').eq(index);
Example of 3:
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.parent().index(vote);
});
Solutions to Problem 2:
Create all of the dialogs initially and open them as needed.
Create the dialogs using a deep clone of the div element. (Not recommended)
Remove the td element to match the removed and re-appended div element. (Not recommended)
Example of 1:
var popups = [];
$('.popup').each(function (i, elem) {
var popup = $(elem).data('index', i).dialog({
"autoOpen": false
});
popups.push(popup)
});
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.index();
popups[index].dialog('open');
});
I'm sure there are other solutions as well, but these are the ones I thought of of the top of my head.
Functional demo: http://jsfiddle.net/2ChvX/2/
UPDATE:
With your chosen table structure, you're actually looking for the index of the parent tr element as that is what corresponds with the div.popup element. To get the index of the parent tr element, change the line that gets the index from:
index = vote.index();
to:
index = vote.parent().index();
Updated fiddle: http://jsfiddle.net/AZpUQ/1/
Updated
FWIW, here's an example using the jQueryUI dialog (which I presume you are using?) and javascript sectionRowIndex and cellIndex.
Reusable code allowing you to identify the cell the user clicked in and perform appropriate action.
http://jsfiddle.net/KbgcL/1/
HTML:
<table id="myTable">
<tr>
<th>Label:</th>
<th>Washington</th>
<th>Idaho</th>
<th>California</th>
</tr>
<tr>
<td class='label'>Votes</td>
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
</tr>
<tr>
<td class='label'>Voters</td>
<td class='voters'>5,000</td>
<td class='voters'>15,000</td>
<td class='voters'>25,000</td>
</tr>
</table>
<div id="msg"></div>
jQuery/javascript:
var myTr;
$('#msg').dialog({
autoOpen:false,
title: 'Report:'
});
$('#myTable tr td').click(function() {
myTr = $(this).closest('td').parent()[0].sectionRowIndex;
myCell = this.cellIndex;
myState = $('#myTable').find('tr:eq(0)').find('th:eq(' +myCell+ ')').html();
myVoters = $('#myTable').find('tr:eq(' +myTr+ ')').find('td:eq(' +myCell+ ')').html();
if (myTr==2 && myCell==3){
//California
$('#msg').html('There are ' +myVoters+ ' voters in ' +myState);
$('#msg').dialog('open');
}else if(myTr==1 && myCell==1){
$('#msg').html('There were ' +myVoters+ ' votes made in ' +myState);
$('#msg').dialog('open');
}
});

onclick defined text-var returns emptystring on log

var listname=$(this).parents(".x-grid3-row-table").children(".x-grid3-cell-inner.x-grid3-col-1").text();
console.log(listname);
the console.log returns following:
(an empty string)
can you help me on why listname is empty? and could you also tell me how to pass listname as parameter to a server-side method in an Ext.Ajax.request?
this is the html-code coming from my generated page:
<table class="x-grid3-row-table>
<tr>
<td class="x-grid3-col x-grid3-cell x-grid3-td-1 " tabindex="0" style="text-align: left;width: 265px;">
<div class="x-grid3-cell-inner x-grid3-col-1" unselectable="on">foo_bar#domain.de</div>
</td>
<td class="x-grid3-col x-grid3-cell x-grid3-td-2 x-grid3-cell-last " tabindex="0" style="width: 59px;">
<div class="x-grid3-cell-inner x-grid3-col-2" unselectable="on">
<span class="free">free</span>
</div>
</td>
</tr>
<tr class="x-grid3-row-body">
<!-- 7 Elements Markup down, who all act wrapping for the following -->
<div class="details">
<!-- some other markup elements, who also contain data, but are not further interesting-->
<td class="data"> foo bar detail data </td><!-- not of interest-->
<td class="edit"><input value="edit" onclick="see function on top" type="button" /> </td>
</div>
</tr>
</table>
target is to extract: foo_bar#domain.de and pass it to a server-method as parameter. the method is supposed to make a Window, but that's a different story.
the onclick call is from a expanded grid panel body, which is wrapped in a table('.x-grid3-row-table') with the given html-code.
You have a space between class names in your children selector, however your markup suggests that both the class names are of same elements.
To select an element with more than one class names the selector should not have space between class names as .classname1.className2.
var listname=$(this).parents(".x-grid3-row-table").children(".x-grid3-cell-inner.x-grid3-col-1").text();
console.log(listname);
should work.
Further clarification:
If you have space between class names as in question it would mean that you are trying to select an element having .x-grid3-col-1 class within .x-grid3-cell-inner class. Which is parent child relationship.
Edit:
If your button is in the next row you can use .prev() selector of JQuery with combination of using tr as parent selector rather than table.
listname=$(this).parents("tr").prev().children(".x-grid3-cell-inner.x-grid3-col-1").text();
Or if it is in same row then simply
listname=$(this).parents("tr").children(".x-grid3-cell-inner.x-grid3-col-1").text();
There might be a cleaner way of doing this but I came up with this as your button click handler, it assumes that the text() your looking for is one table row up from the button.
var $rows,button=this,i;
$rows=$(".x-grid3-row-table tr");
for(i=0;i<$rows.length;i++){
// get the button of that row
// not sure how to as your button is not
// in a table row with the code you posted
if($rows[i].getElementsByTagName("input")[0]===
button){
break;
}
}
// I assume the button is in a row before the button
console.log($($rows[i-1])
.find(".x-grid3-cell-inner.x-grid3-col-1")
.text()

How can I decouple this JavaScript code further?

I have a JavaScript object. And you can see the line:
window.gv.borderiseTDCell(this);
Is tigthly coupled to the window (if gv is not initialised it crashes). However what I really want is to be able to do is:
//bind the click event
jQuery('.highlightableTDCell').click(function () {
borderiseTDCell(this);
});
But that doesn't work. Any ideas what I can do? This is the full lisinng (with tight coupling):
gridview = function () {
//bind the click event
jQuery('.highlightableTDCell').click(function () {
window.gv.borderiseTDCell(this);
});
};
//selecting cell
gridview.prototype.selectCell = function (obj) {
//dostuff to cell
};
And a page...
<table class="EditTable" cellpadding="0" cellspacing="0">
<tr>
<td>
<div style="">0</div>
</td>
<td>
<div style="">0 akudsfsa fdhsad fiasgdf swae</div>
</td>
<td class="highlightableTDCell">
<div>
<input value="0.00"/>
</div>
</td>
</tr>
</table>
It's probably because you're using this when you should be using $(this)
borderiseTDCell($(this));
Also, gridview doesn't seem to be defined:
var gridview = function (){}
Not sure why you'd need a library to outline a table cell. How about creating a class called outlinedCell
.outlinedCell{border:1px solid #f00;}
Then you can add, remove, or toggle this class
//bind the click event
$('.highlightableTDCell').click(function () {
$(this).addClass('outlinedCell');
// or // $(this).removeClass('outlinedCell');
// or // $(this).toggleClass('outlinedCell');
});
LIVE SAMPLE: http://jsfiddle.net/WJp2Z/

Categories

Resources