I have a large set of data that needs virtual scrolling and I use PrimeNg v13.4.0 with angular/cdk v13.3.7. I have exactly the same issue with PrimeNg demo. When scrolling down, the sticky header works well, but when scrolling up, it start jumping, the faster scroll, the bigger jump. Does anyone has any solution for this?
This issue and its pull request is added to version 13 future milestone which has no due date.
https://github.com/primefaces/primeng/milestone/175
For now you can do this solution:
If you slow down the wheel speed of the cdk-virtual-scroll-viewport, even slightly,
The thead works as it should without any jumping.
changeWheelSpeed(container, speedY) {
var scrollY = 0;
var handleScrollReset = function() {
scrollY = container.scrollTop;
};
var handleMouseWheel = function(e) {
e.preventDefault();
scrollY += speedY * e.deltaY
if (scrollY < 0) {
scrollY = 0;
} else {
var limitY = container.scrollHeight - container.clientHeight;
if (scrollY > limitY) {
scrollY = limitY;
}
}
container.scrollTop = scrollY;
};
var removed = false;
container.addEventListener('mouseup', handleScrollReset, false);
container.addEventListener('mousedown', handleScrollReset, false);
container.addEventListener('mousewheel', handleMouseWheel, false);
return function() {
if (removed) {
return;
}
container.removeEventListener('mouseup', handleScrollReset, false);
container.removeEventListener('mousedown', handleScrollReset, false);
container.removeEventListener('mousewheel', handleMouseWheel, false);
removed = true;
};
}
implement it in the ngAfterViewInit function:
ngAfterViewInit(): void {
const el = document.querySelector<HTMLElement>('.cdk-virtual-scroll-viewport');
this.changeWheelSpeed(el, 0.99);
}
Related
So I am using Line from react-chartjs-2 and I've added an onClick event to the labels which blur all the lines except the current one.
Here is my onClick function code:
legend:{
'onClick': function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = this.chart;
console.log(ci.data.datasets);
//var alreadyHidden = (ci.data.datasets[index].borderColor === ci.data.datasets[index].accentFadedColor) ? false : true;
for(var i=0; i< ci.data.datasets.length;i++){
if (i !== index) {
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentFadedColor;
} else if (i == index){
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentColor;
}
}
that.updateValue(index);
ci.update();
}
The problem is, the function updates the chart on first click but not after that. Though I can see the updates values with console.log()
Any idea what I am doing wrong?
Update:
So apparently my chart is working fine. Inside the onClick() I'm making call to another function ( which sets state ) which is causing this behavior.
Here's a link to stackblitz
Any advice?
So apparently, just making the function call inside onClick() but before updating the datasets solved the problem.
I think rendering after setState and canvas update were somehow mixing up.
Here's the updated code:
legend:{
'onClick': function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = this.chart;
that.updateValue(index);
for(var i=0; i< ci.data.datasets.length;i++){
if (i !== index) {
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentFadedColor;
ci.data.datasets[i].lineWidth = ci.data.datasets[i].highlightedWidth;
} else if (i == index){
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentColor;
ci.data.datasets[i].lineWidth = ci.data.datasets[i].fadedWidth;
}
}
ci.update(); }
We're using Redactor(https://imperavi.com/redactor/) version 10.1.1 and not migrated to Redactor II due to lot of dependencies on project.
Recently We're facing a very weird issue with Chrome version 58. Issues are:
-- Not able to format bold, italic, underline, sup, sub etc. for selected text
Kindly let us know is there any fix for this. Any kind of help would be greatly appreciated.
Update as per accepted work around solution:
// Provided solution is tested for Redactor version 10.1.1
createMarkers: function()
{
this.selection.get();
var node1 = this.selection.getMarker(1);
this.selection.setMarker(this.range, node1, true);
if (this.range.collapsed === false) {
var node2 = this.selection.getMarker(2);
this.selection.setMarker(this.range, node2, false);
// Fix for Chrome58 Issues
if (this.utils.browser('chrome')) {
this.caret.set(node1, 0, node2, 0);
}
// End Chrome58 Issues
}
this.savedSel = this.$editor.html();
},
I think I may have found the solution: It seems that Chrome 58 (sometimes) resets the selection when we call Range.insertNode.
The solution I suggest is to restore the selection when the Redactor adds the selection markers: In the createMarkers function, right after setting the node2 marker, you can add this function call:
this.caret.set(node1, 0, node2, 0);
Here's the solution that should fix Redactor for concrete5 (but it should also work for other projects too).
instead of this in 10.2.5 version
Overall you can do like that:
rewrite setMarker function:
setMarker: function (range, node, type) {
var nclone = window.getSelection().getRangeAt(0).cloneRange();
range = range.cloneRange();
try {
var selection = window.getSelection();
range.collapse(type);
range.insertNode(node);
selection.removeAllRanges();
selection.addRange(nclone);
}
catch (e)
{
this.focus.setStart();
}
},
or add fix in createMarkers function:
// Provided solution is tested for Redactor version 10.1.1
createMarkers: function()
{
this.selection.get();
var node1 = this.selection.getMarker(1);
this.selection.setMarker(this.range, node1, true);
if (this.range.collapsed === false)
{
var node2 = this.selection.getMarker(2);
this.selection.setMarker(this.range, node2, false);
// Fix for Chrome58 Issues
if (this.utils.browser('chrome')) {
this.caret.set(node1, 0, node2, 0);
}
// End Chrome58 Issues
}
this.savedSel = this.$editor.html();
},
this is working and tested on chrome 60.
original code is like this in both 10.2.2 and 10.2.5
getNodes: function()
{
this.selection.get();
var startNode = this.selection.getNodesMarker(1);
var endNode = this.selection.getNodesMarker(2);
if (this.range.collapsed === false)
{
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount > 0) {
var range = sel.getRangeAt(0);
var startPointNode = range.startContainer, startOffset = range.startOffset;
var boundaryRange = range.cloneRange();
boundaryRange.collapse(false);
boundaryRange.insertNode(endNode);
boundaryRange.setStart(startPointNode, startOffset);
boundaryRange.collapse(true);
boundaryRange.insertNode(startNode);
// Reselect the original text
range.setStartAfter(startNode);
range.setEndBefore(endNode);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
else
{
this.selection.setNodesMarker(this.range, startNode, true);
endNode = startNode;
}
how to change it?
How do I restrict the drag operation not exceeding certain boundary. Is there any config in extjs (version 3), I saw that, Ext.dd.DragZone class is used. But Im not sure what is the usability. I saw a method dropNotAllowed. Is that the method, that has to be used? if so, how should I use that? Please provide some examples.
Im looking for something similar to (jquery UI's draggable containment property)
http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.dd.DragZone-cfg-dropNotAllowed
I tried using the set X and Y constraints, but it did not work-out:
abc.prototype.initDrag = function(v) {
v.dragZoneobj = new Ext.dd.DragZone(v.getEl(), {
getDragData : function(e) {
var sourceEl = e.getTarget(v.itemSelector, 10);
// sourceEl.setXConstraint( 0, 10 );
var t = e.getTarget();
var rowIndex = abc.grid.getView().findRowIndex(t);
var columnIndex = abc.grid.getView().findCellIndex(t);
if ((rowIndex !== false) && (columnIndex !== false)) {
if (sourceEl) {
abc.isDragged = true;
abc.scriptGrid.isDraggableForObject = false;
abc.scriptGrid.dragRowIndex = false;
d = sourceEl.cloneNode(true);
d.id = Ext.id();
d.textContent = sourceEl.innerHTML;
// d.setXConstraint( 0, 10 );
// d.setYConstraint( 0, 10 );
return {
ddel : d,
sourceEl : d,
sourceStore : v.store
}
}
}
},
getRepairXY : function() {
return this.dragData.repairXY;
},
});
}
Both are commented in the above code. The above code is initiated when the panel is rendered.
edit:
How these setX and setYcontraints have to be used?
By default, the element can be dragged any place on the screen. In the doc there are two methods setXConstraint( iLeft, iRight, iTickSize) and setYConstraint( iUp, iDown, iTickSize )
These two methods is used to set to limit the vertical travel and horizental travel of the element.
I'm using ngAudio to control audio tracks (spotify 30 seconds previews) on an ionic app. It all works swell in the browser. However, in both ionic view and the actual demo app, the tracks will only stream when I have the phone vibrate toggle turned to not silent/ring mode. If it's in vibrate mode, the user hears nothing. I've dug all over and can't seem to solve this riddle.
Here's my service:
.factory('PlayerService', function(ngAudio) {
var _play = function(show) {
if (typeof audioObject === "undefined") {
audioObject = ngAudio.load(show.track1_preview);
console.log(audioObject);
audioObject.play();
audioObject.playing = show.id;
return audioObject;
} else if (audioObject.paused) {
audioObject = ngAudio.load(show.track1_preview);
audioObject.play();
audioObject.playing = show.id;
return audioObject;
} else {
audioObject.stop();
audioObject = ngAudio.load(show.track1_preview);
audioObject.play();
audioObject.playing = show.id;
return audioObject;
}
}
var _pause = function(show) {
audioObject.stop();
audioObject.playing = '';
}
return {
play: _play,
pause: _pause
};
Here's the controller:
$scope.playStream = function(show) {
PlayerService.play(show);
$scope.audioObject = audioObject; // this allow for styling the play/pause icons
}
$scope.pauseStream = function(show) {
PlayerService.pause(show);
$scope.audioObject = audioObject; // this allow for styling the play/pause icons
//console.log($scope.audioObject);
}
$scope.togglePlayPause = function(show) {
if (!$scope.audioObject || $scope.audioObject.paused) {
$scope.playStream(show);
} else if (show.track1_preview !== $scope.audioObject.id) {
$scope.playStream(show);
} else {
$scope.pauseStream(show);
}
}
Obviously, it's a bit of a crap user experience if someone has to put the phone off vibrate to hear the tracks.
I'm wondering if this is related to asyncronous stuff and mobile. I just don't know. Giving up after 4 hours of messing with it.
I'm looking for resources that create scrolling functions like the ones found on these sites:
Outpost Journal
Unfold
Once the scroll bar hits the bottom of the page, I want it to loop back to the top.
I'm familiar with with the infinite scroll, and this is not what I want. I've also found scripts that will write/add the same content to the bottom of the page, but none that loop back to the top of the page.
Try this:
$('document').ready(function() {
$(document).scroll(function(){
if(document.documentElement.clientHeight +
$(document).scrollTop() >= document.body.offsetHeight )$(document).scrollTop(0);
});
});
if you want infinite scroll in both directions use
if (document.documentElement.clientHeight + $(window).scrollTop() >= $(document).height()) {
$(document).scrollTop(0)
} else if ($(window).scrollTop() < 0) {
$(document).scrollTop($(document).height())
}
(I know it's a late reply but it still helps users like me who just google stuff like this)
Here a solution that makes a duplicate of the body so the bottom and the top can be seen at the same time at a certain point so the transition is smoother.
$('document').ready(function() {
// We need to duplicate the whole body of the website so if you scroll down you can see both the bottom and the top at the same time. Before we do this we need to know the original height of the website.
var origDocHeight = document.body.offsetHeight;
// now we know the height we can duplicate the body
$("body").contents().clone().appendTo("body");
$(document).scroll(function(){ // detect scrolling
var scrollWindowPos = $(document).scrollTop(); // store how far we have scrolled
if(scrollWindowPos >= origDocHeight ) { // if we scrolled further then the original doc height
$(document).scrollTop(0); // then scroll to the top
}
});
});
mrida's answer was causing my browser to not be able to scroll, here is a modified version that worked for me:
$('document').ready(function() {
$(document).scroll(function(){
if (document.documentElement.clientHeight + $(window).scrollTop() >= $(document).height()) {
$(document).scrollTop(0);
}
});
});
Forked from #clankill3r's answer, create two copy of body, prepend and append to the original body, then you can scroll the page in two direction endless.
$('document').ready(function() {
var origDocHeight = document.body.offsetHeight;
var clone=$("body").contents().clone();
clone.appendTo("body");
clone.prependTo("body");
$(document).scroll(function(){
var scrollWindowPos = $(document).scrollTop();
if(scrollWindowPos >= origDocHeight ) {
$(document).scrollTop(0);
}
if(scrollWindowPos <= 0 ) {
$(document).scrollTop(origDocHeight);
}
});
});
Adding loop scroll backwards, upgrading #clankill3r answer. It should be something like this.
$('document').ready(function() {
// We need to duplicate the whole body of the website so if you scroll down you can see both the bottom and the top at the same time. Before we do this we need to know the original height of the website.
var origDocHeight = document.body.offsetHeight;
// now we know the height we can duplicate the body
$("body").contents().clone().appendTo("body");
$(document).scroll(function(){ // detect scrolling
var scrollWindowPos = $(document).scrollTop(); // store how far we have scrolled
if(scrollWindowPos >= origDocHeight ) { // if we scrolled further then the original doc height
$(document).scrollTop(scrollWindowPos + origDocHeight); // then scroll to the top
} else if (scrollWindowPos == 0) { // if we scrolled backwards
$(document).scrollTop(origDocHeight);
}
});
});
I'm using it horizontally and it's working just fine. Hope someone finds it useful.
Posted a similar question: https://stackoverflow.com/a/65953934/7474712 and found the answer via this pen: https://codepen.io/vincentorback/pen/zxRyzj
Here's the code:
<style>
html,
body {
height: 100%;
overflow: hidden;
}
.infinite {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.clone {
height: 50vw;
}
</style>
<script>
var doc = window.document,
context = doc.querySelector('.infinite'),
clones = context.querySelectorAll('.clone'),
disableScroll = false,
scrollHeight = 0,
scrollPos = 0,
clonesHeight = 0,
i = 0;
function getScrollPos () {
return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
}
function setScrollPos (pos) {
context.scrollTop = pos;
}
function getClonesHeight () {
clonesHeight = 0;
for (i = 0; i < clones.length; i += 1) {
clonesHeight = clonesHeight + clones[i].offsetHeight;
}
return clonesHeight;
}
function reCalc () {
scrollPos = getScrollPos();
scrollHeight = context.scrollHeight;
clonesHeight = getClonesHeight();
if (scrollPos <= 0) {
setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
}
}
function scrollUpdate () {
if (!disableScroll) {
scrollPos = getScrollPos();
if (clonesHeight + scrollPos >= scrollHeight) {
// Scroll to the top when you’ve reached the bottom
setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
disableScroll = true;
} else if (scrollPos <= 0) {
// Scroll to the bottom when you reach the top
setScrollPos(scrollHeight - clonesHeight);
disableScroll = true;
}
}
if (disableScroll) {
// Disable scroll-jumping for a short time to avoid flickering
window.setTimeout(function () {
disableScroll = false;
}, 40);
}
}
function init () {
reCalc();
context.addEventListener('scroll', function () {
window.requestAnimationFrame(scrollUpdate);
}, false);
window.addEventListener('resize', function () {
window.requestAnimationFrame(reCalc);
}, false);
}
if (document.readyState !== 'loading') {
init()
} else {
doc.addEventListener('DOMContentLoaded', init, false)
}
</script>