Are dynamically created table rows not targetable by jQuery? - jquery-ui

I'm trying to make table rows draggable and then connectToSortable -able.
For some reason, when I put the ID of the tbody ("#sem1") in the selector, it works but obviously drags the whole table-body with all of its rows.
However, when I put "#sem1 tr" in the selector the webpage seems to just ignore that code, meaning the table still shows up correctly, but nothing becomes draggable.
HTML:
<table class = "sem">
<thead>
<th class = "header1">header</th>
<th class = "header2">header</th>
<tr>
<td class = "static1">static1</td>
<td class = "static2">static2</td>
</tr>
</thead>
<tbody id = "sem1">
</tbody>
</table>
Through some JavaScript table rows get added to sem1 like so.
JavaScript:
First pos0[0] (an array) gets populated:
for(var i in setPos[0]){
setPos[0][i]=("<tr><td class = " + String(setClass[i])+ ">" + setPos[0][i].slice(2) + "</td><td class = 'someClass'>"+setThis[i]+"</td></tr>");
}
Then pos0[0][a] gets added to sem1 like this:
for(var a in pos0[0]){
document.getElementById("sem1").innerHTML += pos0[0][a];
}
and when I try to make the rows draggable, it just doesn't work.
jQuery:
$("#sem1 tr").draggable()
Putting just tr in the selector doesn't work either (I don't mind if all the table rows in the whole document are draggable)
**I know that the code says setPos[0] - it's part of a function that does the same thing to pos1, pos2...
Thanks in advance for any help!

My guess is that you are calling the $("#sem1 tr").draggable() line before the code that has inserted the new <tr>'s has been run, so it doesn't see the rows you've added.
Also, have you tried manually inserting some markup to check that the draggable code actually works on a per row basis?
It would help if you could post an example in jsfiddle or something so we can work on this with you.
Finally it could be overkill for this situation but have you looked into using a JavaScript templating engine if you are going to be building chunks of html in your app?

Related

How would I use xpath to get the alternate ids

I have tried to get the each alternate ID from that box but with no avail I'm using Ruby on rails with Nokogiri
Here's the link to the page with alternate ID's (Look below the picture Alternate ID's) http://lol.gamepedia.com/Cain
<tr>
<th> Alternate IDs:
</th>
<td> wvwvvwvwwvwvvvwv (NA), 나진 카인, Nurinim, 나진 카인
</td></tr>
You can try the following XPath to get the alternate Ids value :
//tr/th[normalize-space()='Alternate IDs:']/following-sibling::td[1]
Brief explanation :
//tr : find all <tr> elements anywhere in the HTML document
/th[normalize-space()='Alternate IDs:'] : from the found tr elements, find child element th having inner text (after removing excess whitespaces) equals "Alternate IDs:"
following-sibling::td[1] : from such th, return the first td element that follow the th element within the same parent tr

How to keep a table row selected across multiple Views AngularJS

On the left side of my Layout page there is a table with a list of Job Names. To the right is where the views populate. My views each have identical tables. ChangeOrders.cshtml, PurchaseOrders.cshtml, etc... Right now when you are on the ChangeOrders view nothing appears until you select a job from the Job Names table. The ChangeOrders with that JobId appear. However when I switch to another view the job Selection clears itself. I need that Job to stay selected until I select another Job or a clear filter button is pressed.
Jobs Table on the Layout Page
<table class=" table table-bordred table-striped table-hover" ng-table=" tableparams" show-filter="true" ng-scroll-viewport style="height:200px;">
<tr ng-repeat="job in jobArray" class="pointer" ng-click="selectJob(job)">
<td data-title="'Job Name'" sortable="'JobName'" filter="{ 'JobName': 'text' }">{{job.JobName}}</td>
</tr>
</table>
ChangeOrder.cshtml (All other views will identical except the data)
<table class=" table table-bordred table-striped table-hover" ng-table="tableParams" show-filter="true" >
<tr ng-repeat="job in selectedJob().ChangeOrders" class=" pointer">
<td ng-click="editChangeOrderModal(job)" data-title="'CO Number'" sortable="'ChangeOrderNumber'" filter="{ 'ChangeOrderNumber': 'text' }">{{job.ChangeOrderNumber}}</td>
<td data-title="'CO Date'" sortable="'ChangeOrderDate'" filter="{ 'ChangeOrderDate': 'text' }">{{job.ChangeOrderDate | date : date : shortDate}}</td>
<td data-title="'CO Name'" sortable="'ChangeOrderName'" filter="{ 'ChangeOrderName': 'text' }">{{job.ChangeOrderName}}</td>
<td data-title="'CO Amount'" sortable="'ChangeOrderAmount'" filter="{ 'ChangeOrderAmount': 'text' }">${{job.ChangeOrderAmount | number : fractionSize}}</td>
<td data-title="'CO ApprovedDate'" sortable="'ChangeOrderApprovedDate'" filter="{ 'ChangeOrderApprovedDate': 'text' }">{{job.ChangeOrderApprovedDate | date : date : shortDate}}</td>
<td data-title="'CO ApprovedAmount'" sortable="'ChangeOrderApprovedAmount'" filter="{ 'ChangeOrderApprovedAmount': 'text' }">${{job.ChangeOrderApprovedAmount | number : fractionSize}}</td>
<td data-title="'CO ApprovedNumber'" sortable="'ChangeOrderApprovedNumber'" filter="{ 'ChangeOrderApprovedNumber': 'text' }">{{job.ChangeOrderApprovedNumber}}</td>
<td data-title="'CO Attn'" sortable="'ChangeOrderAttn'" filter="{ 'ChangeOrderAttn': 'text' }">{{job.ChangeOrderAttn}}</td>
</tr>
</table>
Controller
//Sync Table Selections
$scope.selectJob = function (job) {
$rootScope.selectedJob = job;
};
Updated
I am using ngStorage for my sessionStorage
ngStorage
I tried to implement it but I am not sure how to use it with the $rootScope. I also need to add the jquery function as well.
$scope.selectJob = function (job) {
$rootScope.selectedJob = $sessionStorage.$default(job);
console.log($rootScope.selectedJob);
};
$scope.selectedJob = $scope.selectedJob = function () {
return $rootScope.selectedJob;
};
$('#myTable').on('click', ' tbody tr', function (event) {
$(this).addClass('highlight').siblings().removeClass('highlight');
});
Summary of the Problem
As discussed $rootScope is being cleared because your current
application setup is not an AngularJS Single Page App. It is
understandable that you can not switch it out at this time and that is
ok, your application will still be a nice switch to some angular.
In order to have data be persistent across views you will need to save the data in some form of client storage then check for the values when a controller loads and populate your values.
Several Storage Options
1) HTML5 Storage
Here is a an article about HTML5 storage. There are two types of html5 web storage.
localStorage
This can be very flexible it persists across sessions and tabs. But if you want it to clear it has to be manually clearedk, so it can be considered insecure depending on what you are storing.
sessionStorage
sessionStorage is almost identical to local storage except it does not save after the session ends. So it is not available on a new window.
If you are interrested in this option these objects are not hard to work with on your own. But if you found it easier you could use this project, which wraps the objects in an angular factory.
2) Cookies
While a valid storage option. Cookies are really meant if you want to share the data serverside and want the data sent in the headers.
Angular has modules for handling cookies. You have to download angular-cookies from the AngularJS site and include it to use ngCookies. Angular API Reference
Angular cookies can be implemented in two ways
$cookie (API reference) which is a basic wrapper for the document.cookie object. And sets named values.
$cookieStore (API reference) has the same base functionality but uses a (key,value) format.

jquery attr title removing is not working in Mozilla FF

Cold you plz look the following code,
<table title="Demo1">
<tr>
<td> Test1 </td>
<td> Test2 </td>
</tr>
</table>
Here the both Test1 and Test2 links displays default title "Demo1"
But i do not want the title for both links, for this functionality i am doing as follows
$("#anch1").removeAttr("title");
$("#anch2").removeAttr("title");
or
$("#anch1").attr("title", "");
$("#anch2").attr("title", "");
this code works in IE, but M FF is not working, the title is still displaying, and the table title should be there, we should not remove the table tile,
Could you plz answer..
You need to temporary clear the parent table title when hovering over the links, then restore the title when mouse leave the links. Most simple way is adding id to the table itself then:
var $table = $("#table1");
var originalTitle = $table.attr("title");
$("#anch1, #anch2").hover(function() {
$table.attr("title", "");
}, function() {
$table.attr("title", originalTitle);
});
This way you're not dependent on browser behavior.
If you want this applied to all the links in the table, change the selector from "#anch1, #anch2" to $table.find("a").
Live test case.
Try:
$('table').removeAttr('title');
The title is applied to the table, not the anchors. Also, your table markup is malformed (you need to wrap TDs in TR), and that might confuse the selector engines.

Refresh KnockoutJS Data In DataTables

I have the following table
<table class="datatable zebra-striped">
<thead>
<tr>
<th>Name</th>
<th>Issue</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: Publications">
<tr>
<td><span data-bind="text: Name" /></td>
<td><span data-bind="text: IssueNumber" /></td>
<td><button type="button" class="btn" data-bind="click: $parent.DeletePublication">Delete</button></td>
</tr>
</tbody>
</table>
Here is a snippet of the viewmodel:
function EditReaderViewModel() {
var self = this;
self.Publications = ko.observableArray([]);
self.OnAddPublicationSaveButtonClicked = function () {
//.. code omitted.
self.Publications.push(new Publication(publication.value, publication.label, publication.issueNumber));
};
};
}
and the Publication object binded to the table:
function Publication(id, name, issueNumber) {
var self = this;
self.Id = id;
self.Name = name;
self.IssueNumber = issueNumber;
self.LoadedFromDatabase = false;
}
When the data is first loaded into the table, and the datatable initialisation e.g.
$(".datatable").dataTable({ // blahh });
Everything works fine - the data is loaded in the table, sorting and filtering is working, etc.
Now when I add a new item to the Publications array in the viewmodel things just fall apart. For example, say I originally have 1 item in the Publications array, when I add another item, it will appear in the table until I click on a column heading to sort.
It seems that the datatable has it's own internal data list somewhere which does not include the new Publication I created.
Can someone guide me on how to rebuild the datatable, taking into account that the data is from a KnockoutJS viewmodel?
Please note that I have looked at this binding plugin:
http://www.joshbuckley.co.uk/2011/07/knockout-js-datatable-bindings/
The problem is that when I use this, I get error messages such as:
Requested unknown parameter '0' from the data source for row 0.
EDIT:
I'm looking through the code and I think I see the problem. In jQuery.DataTables.js there is this function function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
In that function there is this line:
if ( (sData=oCol.fnGetData( oData )) === undefined )
which in turn calls:
function _fnGetObjectDataFn( mSource )
Now, in function _fnGetObjectDataFn( mSource ) there is this code which is called:
else
{
/* Array or flat object mapping */
return function (data) {
return data[mSource];
};
}
data is not an array, it's a JSON object which means that the above code will fail (return data[mSource];).
I'm really not sure what to do here.
EDIT - IMPORTANT:
As one of the commentators has noticed, and I've just confirmed, accessing
http://www.joshbuckley.co.uk/2011/07/knockout-js-datatable-bindings
will result in a Trojan warning. So please be aware that this url is now an big NO-NO.
I know that´s an older thread but since I found it when I had the same problem I feel the need to post the solution so others might find it quicker.
When refreshing the Table you can simple .clear() and then .destroy() the table.
After that just reinitialize the table using the already known .DataTable()
Although that's a little messy because you really tear down the structure and rebuild it it work very smoothly.
You just have to add a boolean identifier you set to true the first time you initialize the table. And of course you have to bind the Table to a variable to be able to work the DataTable API magic on the DOM Element.
if (managementLoadedDone){
userTable.clear();
userTable.destroy();
}
Fill data in your Table
userTable = $("#userTable").DataTable({responsive: true});
usersLoaded = true;
You mention that you used datatable plugin and get "Requested unknown parameter '0' from the data source for row 0" error.
In my previous experineces using datatable without knockout plugin i got this error only using more columns than the header definitions or vice versa. You have to check your tbody and thead section and make it sure that both of them is the same size.
Or may be you are using "aoColumnDefs" option when you initialize the table.Again checked the option definiton and make sure that you havent try to reach unknown column :
For example if you have a definition like this
"aoColumnDefs": [{
"bSearchable": false,
"bVisible": false,
"aTargets": [0]
}, {
"bSortable": false,
"bSearchable": false,
"sWidth": "45px",
"aTargets": [2]
}]
and if you have only 2 thead section this will give you that error. Because you are reaching third column with aTargets : [2]
I was experiencing a similar problem as you've described here (and didn't have any intention of exploring the "bindings" link after the Kaspersky warning, even if it is really safe.)
Going a bit on the approach suggested here KnockoutJs - how to use datatables with existing bound table, I ended up taking a route where when using knockout on the table, I added a knockout if statement to test if the observableArray had at least one row of data.
<!-- if Publications.length() > 0 -->
<table class="datatable zebra-striped">
<thead>
<tr>
<th>Name</th>
<th>Issue</th>
</tr>
</thead>
<tbody>
<!-- ko foreach: Publications -->
<tr>
<td><span data-bind="text: Name" /></td>
<td><span data-bind="text: IssueNumber" /></td>
</tr> <!-- /ko -->
</tbody>
</table>
<!-- /ko -->
When loading the View Model, I then called the dataTables function
inside my .ajax success function.
Then the other part to making it work was to make use of dataTables "bStateSave": true,
so that any sorting I had done prior to a refresh would not be lost.

Changing the background colour of a given row in a table

I need to change the background color of a given row in a table based on a value of a model (boolean) property which is used in the #Html.CheckBox. The model is updated with the new checkbox value in the PostExampleCompleted action method.
<table>
<thead>
<tr>
<th>Item name</th>
<th>Comments</th>
<th>User</th>
<th>Complete</th>
</tr>
</thead>
<tbody>
<tr id="FooRow">
<td>Foo</td>
<td>#Model.FooComments</td>
<td>#Model.FooUserName</td>
<td>
#using (Ajax.BeginForm("PostFooCompleted", "Home", new AjaxOptions { OnBegin = "ShowProcessingMsg", OnComplete = "HideProcessingMsg" }))
{
#Html.CheckBox("FooItemComplete", Model.FooComplete, new { onClick = "$(this).parent('form:first').submit();" })
}
</td>
</tr>
<tr id="WidgetRow">
<td>Widget</td>
<td>#Model.WidgetComments</td>
<td>#Model.WidgetUserName</td>
#using (Ajax.BeginForm("PostWidgetCompleted", "Home", new AjaxOptions { OnBegin = "ShowProcessingMsg", OnComplete = "HideProcessingMsg" }))
{
#Html.CheckBox("WidgetItemComplete", Model.WidgetComplete, new { onClick = "$(this).parent('form:first').submit();" })
}
</td>
</tr>
</tbody>
</table>
What would be the best way to achieve this? Code examples would be appreciated :).
Thanks.
Something like this should do the trick, given that I've understood what you're trying to do correctly.
First here's a css class which I've used to colour a row if a checkbox is checked.
.redBackground
{
background-color: Red;
}
Next, here is some JQuery code to colour the row where the check-box resides if it is checked. I've also added a 'change' handler to each check-box so if any of them are updated, the row colour is updated appropriately (I've just used red for a row where a check-box is checked and no colour where a check-box is not checked).
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(function () {
$('input[type=checkbox]').each(function () {
var checkbox = $(this);
// if the checkbox is already checked, colour its row
CheckStatus(checkbox);
//Every time a check-box status changes we
//want to re-evaluate the row colour
checkbox.change(function () {
CheckStatus(checkbox);
});
});
//Method which checks if the check-box is checked. If it's checked
//the row is given the 'redBackground' class, otherwise it is taken away
function CheckStatus(checkbox) {
if (checkbox.attr('checked') == 'checked') {
checkbox.parent().parent().addClass('redBackground');
}
else {
checkbox.parent().parent().removeClass('redBackground');
}
}
});
</script>
Hopefully this makes sense... :)
The code is a little to small to exactly get what your settings are.
From the fact that you have a Element I deduce that you have multiple rows in a table.
Personally I'd object to having a AjaxForm in each of the rows. That seems like a lot of overhead.
You could very easy have a single construct of jQuery code to handle all rows and perform the neccessary tasks by itself.
If you use the live function of jQuery you are even independent of rows being added.
The checkbox or the row need to have an identifier with which you can send the ajax call back to your controller. On success you can evaluate the state of the checkbox and color the row appropriately.
I would have to see more of the code, to really help you with that.
Maybe I'm missing something. This seems like a job for html or css. As far as I can make out, there are several ways to approach this depending on your requirements.
On a row by row basis (i.e., you will never know what the colours are until they are defined somewhere by the app or in a database where storing their value statically is not an option), assign the html style property <tr style='background-color: #Model.Colour'> on the row to set the background-color to the colour you want.
On a type/state basis (i.e., you know what the colours are going to be ahead of time, but not what rows they are going to be assigned to), I'd define a class for each row: <tr class='#Model.Type'> and then assign the background-color in your CSS class with the same name as the value in Model.Type.
To get that colour/type itself, you are going to want to pass it in using your model. You might already have that property on your model, I don't know.
For simple alternating pattens, simply use this technique or the :nth-child(odd) and :nth-child(even) css selectors.
Sometimes the simplest solutions are the best solutions.

Resources