Foreach loop table, max 2 cells then a new row? - asp.net-mvc

I have a question for my foreach loop on a table design in my mvc view.
I want my loop to output max 2 cells for each table row and if and it has data to loop out more than 2 cells it adds a new row and continues to loop out the data on the cells on that row etc..
Anyone have a solution for this?

Iterate over the collection in increments of two. Check to make sure that the i+1th item is available before outputting it, outputting an empty cell instead if it isn't.
<table>
<thead>
<tr><th>Column 1</th><th>Column 2</th></tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count(); i = i + 2)
{
<tr>
<td>#Model[i]</td> // or #Model.ElementAt(i)
<td>#(i+1 < Model.Count() ? Model[i+1] : "")</td> // similar
</tr>
}
</tbody>
</table>

You shouldn't use tables for this.
Instead, put your content in <div>s with float: left or display: inline-block, and make the parent element just wide enough to hold two children.

You want to look at using the modulus operator (%).
Something like
if i%2 = 0 { new line }

Related

Print custom barcode label using TCPDF

I have a project to print barcode in roll label like
this.
It is possible to do these things with tcpdf? At first the barcode should be placed at bottom and rotated 180° but i think its impossible to rotate the barcode using start transform and rotate since its only for graphic. So i tried to rotate the text, its works but only in another page to test that with dummy data. How to implement it in this code since im using serializeTCPDFtagParameters?
foreach($product as $row){
$description = $row['description'];
$barcode = $row['barcode_code'];
$barcode = $pdf->serializeTCPDFtagParameters(array($barcode, 'C128','','',25,10,0.5, array('position'=>'S','border'=>false,'padding'=>0, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica','fontsize'=>7, 'stretchtext'=>6), 'N'));
$html .= '
<table width="60mm" height="15mm" cellpadding="3" border="1">
<tr>
<td><tcpdf method="write1DBarcode" params="'.$barcode.'" /></td>
</tr>';
'<tr>
<td> '.$description.'</td>
</tr>';
$html = '</table>';
$item = $item+1;}
$pdf->setFont('helvetica', '','4');
$pdf->writeHTML($html, true,0,true,0);
$pdf->lastPage();
$pdf->output('test.pdf','I');
And should i using cell to make the label side by side per table row? Im gonna use it for labeling jewelry and accessories. Is there any other alternative?
ps. Sorry for my poor english.

ui-grid - How to pin a ROW to the top

I'm using the angularjs ui-grid and I have a "total" row that I want to pin to the top of the grid no matter what is the current sorting.
How can I accomplish that?
I think this is what you are looking for : Row Pinning
Essentially add another hidden column, something like this:
{
field: 'pinned',
visible: false,
sort: {direction: uiGridConstants.ASC, priority: 0}, //use uiGridConstants.DESC for pinning to the bottom
suppressRemoveSort: true,
sortDirectionCycle: [uiGridConstants.ASC] //use uiGridConstants.DESC for pinning to the bottom
}
Row entities which have pinned = true rise to the top, even when other sorting are applied.
DISCLAIMER: I know it's not exactly answers the question, but this is how I solved it for now until I'll have a better solution:
Create an other grid above the main grid :
<div style="height:30px" ui-grid="totalGridOptions"></div>
<div ui-grid="gridOptions" class="grid"></div>
with definitions:
$scope.totalGridOptions = {showHeader:false,enableHorizontalScrollbar:false};
and then bind the columns of the main grid to the total grid (for width and other adjustments):
$scope.$watch('gridOptions', function (newVal) {
$scope.totalGridOptions.columnDefs = newVal.columnDefs;
}, true);
I think you should use something like this
$scope.gridOptions.data.unshift({label:value});
unshift adds it to the top
Edit 2 / Actual Solution: The way I finally settled this issue was by using custom header cell templates. I essentially create a second header row by adding a div at the bottom of what was previously my header. Here's a simple version:
<div class="super-special-header>
<div class="header-display-name">{{col.displayName}}</div>
<div class="totals-row">{{grid.appScope.totals[col.field]}}</div>
</div>
I store my totals on the controller's $scope and can access them in that div with grid.appScope.totals[whateverThisColumnIs]. This way I can still update them dynamically, but they don't get mixed into a sort function like my previous 'solution' was aiming for.
Edit 1 / Dead-end 'solution': Just ran into a problem with my solution, if your table is long (you have to scroll to get to bottom rows), the totals row will scroll out of view. Going to leave this 'solution' here so no one else makes the same mistake!
I had this same issue but with a twist. Since I was going to need to change the default sorting algorithms for many of the columns anyway, I set my algorithm up to skip the first element in the sort. You can use the sortingAlgorithm property on any columndef that would be part of a sortable column. This is really only a solution if you have only a few sortable columns though. It becomes unmaintainable for huge tables.
I couldn't find any built-in feature for ui-grid to keep a specific row at the top of the grid when sorting is applied. But this could be done using sortingAlgorithm parameter in the columnDefs( please refer to http://ui-grid.info/docs/#!/tutorial/Tutorial:%20102%20Sorting).
I have written an algorithm which keeps the row('total' is the particular cell value in the row) at the top of the grid without applying a sorting.
var sortingAlgorithm = function (a, b, rowA, rowB, direction) {
if (direction == 'total') {
if (a == 'total') {
return 0;
}
return (a < b) ? -1 : 1;
} else {
if (a == 'total') {
return 0;
}
if (b == 'total') {
return 1;
}
}
}

MVC how to add two fields

How to multiply two fields that are in my view.
View
#Html.DisplayFor(modelItem => item.Ship_Quantity)
#Html.DisplayFor(modelItem => item.Deal_Amt_1)
<p>Output Total Here</p>
I want to multiply these two fields to get a total amount
and show it, in the view. How to do it? Can I do it directly in the view or
do I have to modify the model? I am using .edmx models created, so I do not
want to modify them directly.
Try this, It will Work
#Html.Raw(Model.Ship_Quantity * Model.Deal_Amt_1)
var shipquantity = item.Ship_Quantity;
var dealamt1 = item.Deal_Amt_1;
var TotalAmountLine2 = shipquantity * dealamt1;
output: #TotalAmountLine2

To access a specific cell and retrieve its content

How can I retrieve the content of a specific cell in a TableSorter object ? Let say I want to retrieve the content of cell[3,4] meaning the content of the third row and fourth column. I'm sure there is an easy way to do that...
Thanks !
FG
According to the documentation TableSorter works on a standard table
Assuming this is your table
<table id='myTable'>
<tr>
<td>Row 0 / Cell 0</td>
<td>Row 0 / Cell 1</td>
</tr>
<tr>
<td>Row 1 / Cell 0</td>
<td>Row 1 / Cell 1</td>
</tr>
</table>
So you should be able to get a specific cell by getting a reference to your table
var myTable = document.getElementById('myTable');
Then access the specific cell by calling
var cell = myTable.rows[1].cells[0]
The contents of the cell should be accessible using
cell.firstChild.nodeValue; // returns "Row 1 / Cell 0"

jQuery UI sortable drag initiation is slow when container has hidden items

I have an unordered 'source' list that can contain up to around 1,000 list items. I want to be able to drag the items from the source list into a connected 'destination' list. I have everything working great until my source list gets filtered. I'm using the jquery quicksearch plugin to filter (search) my source list. The filter is accomplished by setting 'display:none;' on items that don't match the search.
When 1..n items in my source list are hidden, the drag operation is not fluid when initiated. Meaning, I click on the item I want to drag, move my mouse around the screen, but the item I'm dragging does not appear under my cursor until about a full second after I've initiated the drag.
For diagnosis, I've slimmed down my use case to just one list that I want to sort. I've completely eliminated the use of quicksearch by just hard coding half of my list items as hidden. I'm still able to reproduce the 'non-fluid' behavior. My example is here:
http://pastebin.com/g0mVE6sc
If I remove the overflow style from the list in my example, the performance is a little better, but still slower than I'd hope to see.
Does anyone have any suggestions for me before I start considering other options?
Thanks in advance.
As you can see on this jsferf example, calculating outerWidth()/outerHeight() (this is what the plugin does - see below) for hidden elements (with display none) is terribly slower than for visible elements, wether it is achieved by a style attribute or a class.
The only way I have found to bypass this and still achieve the same result is to set the height for the elements to hide to zero, instead of working with the display property, whether using the style atttibute or a class:
<li style="height: 0;">b</li>
<li class="hidden">b</li>
.hidden { height: 0 }
DEMO (with class) - DEMO (with style attr)
What's happenning with sortable when dragging an element ?
When starting dragging, the plugin refreshes the list of all items and recalculates positions of all elements. The plugin actually gets outerWidth and outerHeight:
_mouseStart: function(event, overrideHandle, noActivation) {
...
//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
this.refreshPositions();
...
}
refreshPositions: function(fast) {
...
for (var i = this.items.length - 1; i >= 0; i--) {
var item = this.items[i];
...
if (!fast) {
item.width = t.outerWidth();
item.height = t.outerHeight();
}
var p = t.offset();
item.left = p.left;
item.top = p.top;
};
...
return this;
},​
If you still want to use display:none, this is a simple fix to the jQuery UI source specified in Didier's answer:
if (!fast) {
if(item.item.css('display') === 'none') {
item.width = 0;
item.height = 0;
}
else {
item.width = t.outerWidth();
item.height = t.outerHeight();
}
}
This is my very first post on stackoverflow, so do let me know if I messed something up.
I was also having a similar problem, but with hidden drop containers instead of sortable items. Here is my solution applying Jordan's answer to both sortable items and their containers and simply replacing the relvent method.
$.ui.sortable.prototype.refreshPositions = function(fast) {
//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
if(this.offsetParent && this.helper) {
this.offset.parent = this._getParentOffset();
}
for (var i = this.items.length - 1; i >= 0; i--){
var item = this.items[i];
//We ignore calculating positions of all connected containers when we're not over them
if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
continue;
var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
if (!fast) {
/********** MODIFICATION ***********/
if(item.item.css('display') === 'none') {
item.width = 0;
item.height = 0;
} else {
item.width = t.outerWidth();
item.height = t.outerHeight();
}
/********** END MODIFICATION ***********/
}
var p = t.offset();
item.left = p.left;
item.top = p.top;
};
if(this.options.custom && this.options.custom.refreshContainers) {
this.options.custom.refreshContainers.call(this);
} else {
for (var i = this.containers.length - 1; i >= 0; i--){
/********** MODIFICATION ***********/
if (this.containers[i].element.css('display') == 'none') {
this.containers[i].containerCache.left = 0;
this.containers[i].containerCache.top = 0;
this.containers[i].containerCache.width = 0;
this.containers[i].containerCache.height = 0;
} else {
var p = this.containers[i].element.offset();
this.containers[i].containerCache.left = p.left;
this.containers[i].containerCache.top = p.top;
this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
}
/********** END MODIFICATION ***********/
};
}
return this;
};
I came across with the same problem...
I've searched for a solution, but it seems there is no solution to the jquery problem, only some workaround...
I didn't found either a solution, just another workaround.
In my case I just created a general method to to a search in a sortable list, where on keyup, the code goes and do a find on every element in the list and was hiding it by fadeout if didn't match the value.
This was working very well, but when you have hundreds of items in a list, the of hidden gets big enough to trigger the slow effect on the drag&drop.
My solution was to reorder the list, bringing to the top the matched items..
Just remove and appendTo again...
This way I don't have problems with the hidden elements :)
Sorry this was no solution, but just another workaround..
Regards
More recently I came accross with this issue again... and found that my workaround was not the best solution anymore. Since the issue is the height... I've just create a CSS class with
.hidden {display: block; line-height:0; height: 0; overflow: hidden; padding: 0; margin: 0; }
and instead of setting the element hidden with just add this class and remove it to show/hide the element..
Regards,
AP
I got the same issue today with sortable + draggable table rows.
The solution was simple : use visibility:collapse instead of display:none and removing the jQuery hide/show function for the hidden lines did the trick. It's a lot faster now.
Hope I will help.

Resources