I have a solution that contains an ng-repeat within another ng-repeat. I use this to create two tables with both static content and dynamic content. At first load the scroll doesnt work. Once you resize the page with the content, the scroll works fine. On iPad and Android tablets I have encountered that the scroll works at first load but the width doesnt contains the last two static TD's in the table.
I am pretty sure that the solution is to setup a correct .refresh method for iScroll but I cannot figure out the correct setup.
I have tried using the ng-iScroll plugin but without any luck. I have also tried to put in a timeout for the .refresh method but still with no result.
I was able to reconstruct the problem with this fiddle: jsfiddle.net/8BUjf/115/
When you run the fiddle the scroll doesnt work. Once you resize the content page just a little bit the scroll works fine with a correct width that contains all static and dynamic td's.
The following code is also found in the fiddle above.
EDIT
After the answer from steppefox I tried to setup the solution with the directive. I am now getting 0 errors in the consol and the angular shows the list correctly but the scroll still doesnt work - even if I try to resize the content.
Here is the new fiddle http://jsfiddle.net/8BUjf/149/ and the code below is also updated.
My HTML
<div ng-app="app">
<div ng-controller="TodoCtrl">
<div class="tfl-overflow" id="iscrollwrapper" iscrollDirective>
<div id="iscroller">
<table class="table" style="border-bottom: 1px solid #E77E23; ">
<tr>
<td>
<h3 class="text-width">
Static TD 1
</h3>
</td>
<td ng-repeat="parentCategory in totalParentCategoriesCount" class="text-info">
<h3 class="text-width">
Dynamic TD {{parentCategory.count}}
</h3>
</td>
<td>
<div>
<h3 class="text-width">
Static TD 2
</h3>
</div>
</td>
<td>
<div>
<h3 class="text-width">
Static TD 3
</h3>
</div>
</td>
</tr>
</table>
<table class="table table-striped">
<tr ng-repeat="fighter in totalFighterList">
<td>
<p class="text-width">Static TD</p>
</td>
<td ng-repeat="parentCategory in totalParentCategoriesCount">
<p class="text-width">Dynamic TD {{parentCategory.count}}</p>
</td>
<td>
<p class="text-width">Static TD 2</p>
</td>
<td>
<p class="text-width">Static TD 3</p></td>
</tr>
</table>
</div>
</div>
</div>
</div>
Angular
var mainApp = angular.module("app", []);
mainApp.directive('iscrollDirective', iscrollDirective);
iscrollDirective.$inject = ['$timeout'];
function iscrollDirective($timeout) {
return {
restrict:'A',
link: function ($scope, element, attrs) {
$timeout(function(){
var iscrollwrapper = new IScroll(element.attr('#iscrollwrapper'), {
scrollX: true,
scrollY: false,
mouseWheel: false,
scrollbars: false,
useTransform: true,
useTransition: false,
eventPassthrough: true,
});
iscrollwrapper.refresh();
})
}
}
};
mainApp.controller('TodoCtrl', function($scope) {
$scope.totalParentCategoriesCount = [
{count:1},
{count:2},
{count:3},
{count:4},
{count:5},
{count:6}];
$scope.totalFighterList = [
{count:1},
{count:2},
{count:3},
{count:4},
{count:5},
{count:6}];
});
CSS
#iscroller{
display:inline-block;
width:auto;
}
.text-width{
width:150px;
}
.tfl-overflow {
overflow-x: auto !important;
-webkit-overflow-scrolling: touch;
}
#iscrollwrapper{
width:100%;
}
The problem is, because iScroll was runned earlier than ng-repeat had run by angular.
Create an angular directive
angular.module('app').directive('iscrollDirective', iscrollDirective);
iscrollDirective.$inject = ['$timeout'];
function iscrollDirective($timeout) {
return {
restrict:'A',
link: function ($scope, element, attrs) {
$timeout(function(){
iscrollwrapper = new IScroll(element.attr('id'), {
scrollX: true,
scrollY: false,
mouseWheel: false,
scrollbars: false,
useTransform: true,
useTransition: false,
eventPassthrough: true,
});
iscrollwrapper.refresh();
})
}
}
});
Remove your JS code of calling iscroll in function loaded, cuz it's useless now (we have directive for that).
Add to your wrapper <div class="tfl-overflow" id="iscrollwrapper"> attribute iscroll-directive, like that <div class="tfl-overflow" id="iscrollwrapper" iscroll-directive>
UPDATE 2015-08-03
http://jsfiddle.net/8BUjf/160 - fixed fiddle
Related
I have a table or articles and a toggle on each row that displays the child row content. In the child row I also display Disqus comments. This all works fine but I do not want multiple rows opened up all at once and multiple Disqus comments loading, slowing down my page.
I want to disable all toggle buttons when one toggle is activated. Each toggle link (class option_toggle) and the row it's on has a unique ID. See below. How can I accomplish this via JQuery?
//Hide main article table's options row
$(document).ready(function() {
$(".option_toggle").click(function(e) {
e.preventDefault();
aid = $(this).attr('id');
//Determine if we are showing the comments or hiding the comments
is_hidden = $(this).parent().parent().next(".options_row").is( ":hidden" );
if(is_hidden)
{
disqus_container = '#disqus_container_' + aid;
jQuery('<div id="disqus_thread"></div>').insertBefore(disqus_container);
$.ajax({
type: 'POST',
url: 'http://www.example.com/disqus',
data: {'msmm_tn' : '12d406df3c8b2e178893e2c146d318e5', 'aid' : aid},
dataType: 'json',
success : function(data) {
if (data)
{
$('#disqus_container_' + aid).html(data.script);
DISQUS.reset({
reload: true,
config: function () {
this.page.url = 'http://www.example.com/#!'+ aid;
this.page.remote_auth_s3 = data.payload;
this.page.identifier = aid;
this.page.api_key = "cULB96iURBu1pZOtLOOSVlVgBj10SY9ctXWiv0eiQdzhdxqBq9UgmVr5SeSiaFiP";
}
});
}
}
});
}
else
{
//Remove the comments
$('#disqus_container_' + aid).prev('#disqus_thread').remove();
$('#disqus_container_' + aid).html('');
}
$(this).parent().parent().next(".options_row").toggle("fast");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<tbody>
<tr class="main_row" data-id="ROWID428272">
<td class="bkgcol-sunflower wht-border">
<td>
<a id="428272" class="option_toggle" href="#" title="Ratings/Comments">
</td>
<td class="key-title dark unpadded">
<td class="artcl_info text-center">Scitech</td>
<td class="text-center" style="width:10px">
<td class="text-center">
</tr>
<tr class="options_row" style="display: table-row;">
<td colspan="6">
<div class="row article_options">
<div class="row comments_row">
<div id="comments" class="col-md-12">
<div class="text-center article_title top_pad" style="width: 100%;">Comment on This Article</div>
<div id="disqus_thread">
<div id="disqus_container_428272">
</div>
</div>
</td>
</tr>
<tr class="main_row" data-id="ROWID427694">
I want to disable all toggle buttons when one toggle is activated.
$(".option_toggle").click(function(e) {
e.preventDefault();
// Remove click event handler defined above, and add a new one which prevents
// the click from doing anything
$(".option_toggle").off('click').on('click', function(e) {
e.preventDefault();
});
aid = $(this).attr('id');
// Continue with rest of your code ...
});
But is this really what you want? It means once you click a toggle, you cannot click any others. It also means all other toggles still look like links, maybe you should update styling to indicate they are disabled or something like that, eg add a disabled class and style that:
Javascript:
$(".option_toggle").addClass('disabled-link');
CSS:
a.disabled-link {
cursor: default;
color: #666;
text-decoration: none;
}
I have an Angular page with the below HTML:
<div style="overflow-y:scroll; height:700px;" data-ng-if="ctrl.items.length">
<table class="table table-striped">
<tbody>
<tr bindonce data-ng-repeat="i in ctrl.items">
<td class="note-row">
<div my-tooltip-template="nav-fo-to-bo-compare/comments-hover-template.html" my-tooltip-scope="i.navSummary">
<div break-notes nav-summary="i.navSummary" item="i" note-disable="!ctrl.allowChanges"></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
The page displays a custom tooltip for each record in the table. Below is the custom tooltip directive.
angular.module('app').directive("myTooltipTemplate", function ($compile) {
var contentContainer;
return {
restrict: "A",
scope: {
myTooltipScope: "="
},
link: function (scope, element, attrs) {
var templateUrl = attrs.myTooltipTemplate;
scope.hidden = true;
var tooltipElement = angular.element("<div class='customTooltip' ng-hide='hidden'>");
tooltipElement.append("<div ng-include='\"" + templateUrl + "\"'></div>");
element.parent().append(tooltipElement);
element
.on('mouseenter', function () { scope.hidden = false; scope.$digest(); })
.on('mouseleave', function () { scope.hidden = true; scope.$digest(); });
var toolTipScope = scope.$new(true);
angular.extend(toolTipScope, scope.myTooltipScope);
$compile(tooltipElement.contents())(toolTipScope);
$compile(tooltipElement)(scope);
}
};
});
Custom tooltip CSS class:
.customTooltip{
position:absolute;
background-color:#00adee;
z-index:2;
display:block;
right: 25px;
}
The tooltip appear properly positioned for the records that show up on the screen. It shows up on mousehover. However, when I scroll the page to view the records towards end of the table, the custom tooltip appears to be still showing up at a position where the that table record was originally present. How can I ensure that even when the user scrolls the table, the tooltips from the bottom rows will appear just as the tooltips at the top of the grid ?
Add
position:relative
to the parent container of the absolutley positioned div. That is, add position:relative to the div with class note-row.
More details can be found in this tutorial
I am new to programming and am mostly just playing around with HTML and JavaScript right now. I recently learned about jQuery and was trying to use it in a periodic table quiz page I made. I wanted to be able to mouse over certain elements and see a relevant picture and then mouse off and restore it to the element symbol and name that was there before. Here is my code:
The element is in a table coded by HTML, like so:
<table id="ptable" style="text-align:center;">
<tr>
<td>
<div id="einsteinium"><span style="font-size:32px;">Es</span>
<p style="font-size:12px;">Einsteinium</p>
</div>
</td>
<td>hydrogen</td>
<td>helium</td>
</tr>
</table>
And here is the jQuery:
$(document).ready(function () {
var oldhtml = "";
oldhtml = $("#einsteinium").html();
$("#einsteinium").hover(function () {
$("#einsteinium").html("<img src=\"http://images.mentalfloss.com/sites/default/files/styles/insert_main_wide_image/public/einstein1_7.jpg\" height=\"70px\" width=\"70px\">");
},
function () {
$("#einsteinium").html(oldhtml);
});
});
Fiddle
The problem is that the picture of Einstein will get stuck and won't return to the element symbol/name. On the fiddle, if you keep mousing over it, it will start working again, but it doesn't do that on my code. For me, when it gets stuck it doesn't get unstuck (but the fiddle does get stuck too, and I don't want that to happen at all). I have tried changing the z-index of the div and table, but no luck there. I'd really appreciate any help!
The problem is because, you are changing the contents of the hovering div, which is messing up the mouse enter/leave events
You can do it without any javascript, but with css and the :hover selector like
#einsteinium > img {
display: none;
}
#einsteinium:hover > img {
display: inline-block;
}
#einsteinium:hover > div {
display: none;
}
<table id="ptable" style="text-align:center;">
<tr>
<td>
<div id="einsteinium">
<img src="http://images.mentalfloss.com/sites/default/files/styles/insert_main_wide_image/public/einstein1_7.jpg" height="70px" width="70px">
<div>
<span style="font-size:32px;">Es</span>
<p style="font-size:12px;">Einsteinium</p>
</div>
</div>
</td>
<td>hydrogen</td>
<td>helium</td>
</tr>
</table>
I might redefine what the buttons do when they are clicked but that is irrelevant. I do not need help setting up ng-click events come on people. That part is easy. I am struggling big time getting the animation effects that I want. The application is in ionic so naturally I am working toward an AngularJS solution all of the examples out there are just a bit off.
I manged to piece together information and construct this:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swipe left to delete implementation using AngularJs</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-touch.js"></script>
<script type="text/javascript">
var app = angular.module('ngSwipeLeftExample', ['ngTouch']);
app.controller('SampleSwipe', ['$scope', '$window', function($scope, $window) {
// $scope.swipeLeft=false;
// $scope.swipeRight=false;
$scope.delete = function() {
alert('bbb');
// $scope.swipeLeft=true;
// $scope.swipeRight=true;
}
$scope.edit = function() {
alert('aaa');
// $scope.swipeLeft=true;
// $scope.swipeRight=true;
}
$scope.clickedTable = function() {
// alert('clicked table');
// $scope.swipeLeft=false;
// $scope.swipeRight=false;
}
}]);
</script>
</head>
<body ng-app="ngSwipeLeftExample" ng-controller="SampleSwipe">
<table ng-init="swipeLeft = false; swipeRight = false;" data-ng-swipe-right="swipeRight = true" data-ng-swipe-left="swipeLeft = true" data-ng-click="" border=1 width="100%">
<tr>
<td width="100px">
<div ng-show="swipeRight" >
<button ng-click="edit()" style="height: 44px;width: 109px;border: 0;background-color: green; color: white;font-size: 18px;font-weight: bold;cursor:pointer;">Edit</button>
</div>
</td>
<td>
<div ng-click="clickedTable()">
<table>
<tr>
<td>aaaa</td><td>bbbb</td><td>cccc</td>
</tr>
<tr>
<td>aaaa</td><td>bbbb</td><td>cccc</td>
</tr>
</table>
</div>
</td>
<td width="100px">
<div ng-show="swipeLeft" >
<button ng-click="delete()" style="height: 44px;width: 109px;border: 0;background-color: red; color: white;font-size: 18px;font-weight: bold;cursor:pointer;" align="right">Delete</button>
</div>
</td>
</tr>
</table>
</body>
</html>
But I don't really want to ng-hide the buttons I just want to size the record so that the html block in the middle column (I will put whatever in there it doesn't really matter what I put in there) should be sized to fit the page (width=100% I guess) Then the edit and delete buttons being off canvas can be swiped left or right so the user can see them and click them. I think this can be done with transitions somehow. But nothing seems to work. I am really not a CSS guy at all mostly I just piece my css together to get something almost what I want and then hand it over to my UI guy to fix it. But he doensn't know how to do this either.
It seems like most ios and android apps work this way when there is a list and you swipe left to delete but it seems nobody wants to share the wisdom of how to do this correctly.
Let me guess soeone will reply that you are confused about my question and do not know what I am asking even though it is totally clear? Correct?
I am using datatables's Scroller extension.
When the table have more than 1 row, the rows are displayed fine. But if the table only contains of 1 row, the "lower part" of the row isn't displayed. The table cut the row of almost in the middle.
Im trying to make a second line inside the row, using the div as you can see in my example. It's like the table can figure out to include it in it's height calculation if there is more than 1 row, but not if there is only 1 row. Does anyone know what I can do about it?
Focus should be here I think: <div>second line</div>
html:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<script src="http://datatables.net/release-datatables/media/js/jquery.js"></script>
<script src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js"></script>
<script src="http://datatables.net/release-datatables/extensions/Scroller/js/dataTables.scroller.js"></script>
<meta charset=utf-8 />
<title>DataTables - JS Bin</title>
</head>
<body>
<div class="container">
<table id="example" class="display nowrap" width="100%">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
</div>
</body>
Javascript:
$(document).ready( function () {
var table = $('#example').DataTable({
deferRender: false, // TODO learn from doc
dom: 'f<"table-toolbar">tS',
language: {
"search": '<i class="fa fa-search"></i>'
},
stateSave: false,
//scrollY: $(document).height() - 266,
scrollY: true,
scrollCollapse: true,
columns: [
{
"className": '',
"orderable": false,
"sortable": false,
"data": null,
"defaultContent": "first line<div>second line</div>"
}
]
});
} );
Update 1 : Fiddle where it breaks
Fiddle where the rows dowsn't work
Update 2 : Fiddle where it works. (2 rows instead of 1 - notthing else!)
Fiddle where the rows works
The display problem is caused by the surrounding div (.dataTables_scrollBody) that causes the data to be cut off. It comes out as 37px for a one row table and 112px for a two row one. 37px is obviously not enough, so as a workaround you can put .dataTables_scrollBody {min-height:55px} in the CSS. That will solve the display problem. See http://live.datatables.net/ceqijesi/12/edit
To solve the actual issue however, you should dive into the JavaScript that creates the table. Or, more precisely, the div that comes after the table. It has no class, only a style attribute that defines its height. (The table itself is positioned absolutely, so it's this next div that determines the height of .dataTables_scrollBody.)
To confuse matters, this div has different heights in different browsers here.
It can also be done with:
text-overflow: ellipsis;
white-space: nowrap;
See Datatables doc