I'm using CSS grid for a timeline. The grid is yielding about 1300 divs, which is really bad for performance.
I need to have each of these cells to be clickable and show a different color on hover. I cannot find any way to style "empty" nodes or interact with them without rendering all of those 1300 divs.
What can I do?
as Mike 'Pomax' Kamermans
suggested, the best way would be detect mouse click and add item dynamically. You can customize the width and height of items by assigning values to item_width and item_height.
var item_width=40;
var item_height=40;
var added_items=[];
$(function(){
$('.grid').on('click', function(e){
var x = e.pageX - $(this).offset().left;
var y = e.pageY - $(this).offset().top;
var item=$('<div class="item"></div>');
var left=Math.floor(x/item_width)*item_width;
var top=Math.floor(y/item_height)*item_height;
var position={ 'left':left, 'top':top };
var index=added_items.findIndex(p => p.left == position.left && p.top == position.top);
if(index<0){
added_items.push(position);
item.css('left', left);
item.css('top', top);
item.css('background', "#"+((1<<24)*Math.random()|0).toString(16))
item.appendTo($('.grid'));
}
});
});
.grid {
width:400px;
height:400px;
border:1px solid red;
position:relative;
margin:10px;
}
.item {
width:40px;
height:40px;
position:absolute;
background:red;
}
.item:hover {
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid"> </div>
You can add your columns classes a eventHandler and same classes act same hover or click..
Also 1300 divs are really decreace your page's performance. For that you can research for infinite scroll or like that methods.
https://demos.telerik.com/kendo-ui/grid/endless-scrolling-local
Related
Experiencing some strangeness with jQuery mouse events.
Check the jsFiddle at: https://jsfiddle.net/Lb8r3907/1/
What I am trying to achieve is an inner element that when the mouse is over it, the pointer element will follow your cursor and when you mouse out of the inner element the pointer is then hidden.
I have an outer element that fills the screen and the mouse enter / leave of this element shows and hides the pointer element that will follow your cursor.
$(function() {
$('.outer').on('mouseenter', function(){
console.log('MOUSE OVER OUTER!!');
if($('.pointer').is(':visible')){
$('.pointer').fadeOut(50);
}
});
//
$('.outer').on('mouseleave', function(){
console.log('MOUSE OUT OF OUTER!!!');
if(!$('.pointer').is(':visible')){
$('.pointer').fadeIn(50);
}
});
//
$('.inner').on('mousemove', function(e){
var mX = e.pageX-$('.inner').offset().left,
mY = e.pageY-$('.inner').offset().top;
$('.pointer').css({"top": mY+"px", "left": mX+"px"});
});
});
.outer { position:absolute; display:block; z-index:0; top:0px; left:0px; width:100%; height:100%; background-color:rgba(255,0,0,0.5); }
.inner { position:absolute; display:block; z-index:1; top:50%; left:50%; width:50%; height:25%; margin-top:-12.5%; margin-left:-25%; background-color:#fff; }
.inner .pointer { display:block; position:absolute; top:50%; left:50%; width:50px; height:50px; background-color:blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<body>
<div class="outer"></div>
<div class="inner">
<div class="pointer" style="display:none;"></div>
</div>
</body>
What's really odd is that when the mousemove event is activated it seems to delay the firing of the mouseleave event.
I also notice that the delay really only seems to occurr when you mouse out on the right or bottom edge of the inner element.
Can anyone offer any insights as to why this is occurring??
I would really like to know how to address this issue or if it is a bug in the browser / jQuery.
Your "Pointer" is consuming some of the events intended for the "outer" element.
Try some spacing between the cursor and the pointer. The space should help keep the pointer away when you mouse out to the outer, so that the outer gets its events as intended
$('.pointer').css({"top": mY+2+"px", "left": mX+2+"px"});
This change Should work better.
I would have tackled this problem differently. Instead, I would use the boundary box of the .inner and add the .pointer if the cursor was inside. This way you only need one mouse listener and the code is easier to understand (in my opinon):
html:
<div class="container">
<div class="outer"></div>
<div class="inner">
<div class="pointer" style="display:none;"></div>
</div>
</div>
CSS (no change)
JS:
$(function() {
var rect = $('.inner')[0].getBoundingClientRect();
$('.container').on('mousemove', function(e) {
var mX = e.pageX;
var mY = e.pageY;
// Is the cursor inside the boundaries?
if(mX > rect.x && mX < rect.x + rect.width && mY > rect.y && mY < rect.y + rect.height ) {
if(!$('.pointer').is(':visible')) { // This can be optimized as well
$('.pointer').show();
}
$('.pointer').css({"top": mY - rect.y, "left": mX - rect.x});
} else {
$('.pointer').hide(); // This can be optimized as well
}
});
});
You can add CSS pointer-events:none; to .pointer. pointer-events is supported in all major browsers
This CSS property, when set to "none" allows elements to not receive hover/click events, instead the event will occur on anything behind it.
https://caniuse.com/pointer-events
I'm guessing this is really easy but I'm new to jQuery so I'm a little lost.
What’s the best way to animate a number going up relative to a users vertical scroll position? I’m making a div a million pixels long and want a fixed number that counts from 0 to a million. Am I right in saying I'd have to use the .scrollTop() function?
Cheers for any help in advanced!
B
The following code should help you to get started. If you increase the height of the html tag to 1 million pixel, you'll have a counter with the desired range.
The source code is from this page. I have just created the jsFiddle from it.
$(function() {
// move the counter with page scroll
// source from this page http://www.pixelbind.com/make-a-div-stick-when-you-scroll/
var s = $("#counter");
var pos = s.position();
$(window).scroll(function() {
var windowpos = $(window).scrollTop();
s.html("Distance from top:" + pos.top + "<br />Scroll position: " + windowpos);
if (windowpos >= pos.top) {
s.addClass("stick");
} else {
s.removeClass("stick");
}
});
});
html {
/*force to show vert. scrollbar*/
overflow-y: scroll;
height: 1000200px;
background: url("http://placehold.it/1000x500");
}
div#counter {
padding:20px;
margin:20px 0;
background:#AAA;
width:190px;
}
.stick {
position:fixed;
top:0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Dummy text. just to show distance from top calculation.<br/><br/><br/><br/></p>
<div id="counter"></div>
clicking the link the anchor is reached, but even if the parent element has overflow:hidden
it scrolls unnecessarily hiding the contents
<style>
div#x
{overflow:hidden;border-bottom:1px red solid;}
div#x > div
{border:1px red solid;padding:10px;float:left;width:33%;box-sizing:border-box;padding-bottom:10000px;margin-bottom:-10000px;}
</style>
<div id="x">
<div>go to<br><br>a</div>
<div>a<br><br><br><br>a</div>
<div>a<br><br><br><br><br><br><span id="test">go here</span></div>
</div>
demo: http://jsfiddle.net/aj8cX/5/
is there a way to fix this behavior?
This is as close as I could get, using table > table-cell:
http://jsfiddle.net/mikedidthis/AmNxf/
Would work well for static content, but for dynamic content it may cause some issues.
You could use some javascript trickery.
I am using jQuery, but you can use anything you want.
$('a[href="#test"]').on('click', function(){
var test_element = $('#test');
var scroll_top = test_element.scrollTop();
var max_height = test_element.parent().height();
if (scroll_top < max_height) { return false; }
else { return true; } //only scroll if the item is in view
});
You can use javascript to get elements of equal height:
var height = 0;
$.each($('#x div'),function(k,v){
if($(this).height() > height){
height = $(this).height();
}
});
$.each($('#x div'),function(){
$(this).height(height);
});
Fix your css like so:
div#x
{
overflow:visible;
height:10000px;
}
div#x div
{
border:1px red solid;
float:left;
width:33%;
box-sizing:border-box;
margin-right:-1px;
}
Working example: http://jsfiddle.net/aj8cX/6/
I'm trying to develop a slide gallery with image tooltips according to this design:
What I need to develop is a slider controlled by two buttons, each time a button is pressed the slider's content must move a width of the slider or the width of the content left on that side, whichever is smaller. Upon mouse entering an image inside the slider the full-size version must be displayed as a tooltip.
Here's a fiddle of my solution so far, the problem I'm having is that images that don't fully fit into view plus the hidden area to the left get moved to a new line. You can see the problem by clicking the
"Show content size" button, the width of the content element will be equal to the width of the container element + content element's margin-left.
Bonus points if you can suggest an algorithm for moving the content to the right, I've got left figured out to a T (or so I think, anyway), but right is going to take a little more work (it doesn't check whether the end of the content has been reached). Update: It seems I can't implement proper movement to the right until the other issue is resolved, here's the algorithm I came up with, I can't measure "left to display" if I can't measure the actual width of the content element.
I created something you might like:
gallery demo
The gallery does not scroll the full gallery width by default (you can change that) cause some initially cut-off images at the right side, after a 'full' slide would result cut-off again, just on the other side of our gallery. You have for that cause the beKind variable. Adjust it as you like.
It hides the buttons if there's not enough content to make the gallery usable.
The gallery calculates the remaining space to scroll.
Once the slider end reached - the left/right buttons make the gallery jump to the beginning/end, so that are always usable. (Seems kinda weird to have a button... but that does nothing right? ;) )
The Tooltip has a hover-intent built in, to not piss off our users if they unintentionally hovered our gallery: (the tooltip fades in if the hover is registered for more that 120ms. Fair timing. I like it.)
As pointed out in your comment now the tooltip will not go off the screen.
jQ:
// Slide Kind Gallery - by roXon // non plugin v. // CC 2012.
$(window).load(function(){
var galW = $('#gallery').outerWidth(true),
beKind = 120, // px substracted to the full animation to allow some images to be fully visible - if initially partly visible.
sumW = 0;
$('#slider img').each(function(){
sumW += $(this).outerWidth(true);
});
$('#slider').width(sumW);
if(sumW <= galW){ $('.gal_btn').remove(); }
function anim(dir){
var sliderPos = Math.abs($('#slider').position().left),
rem = dir ==='-=' ? rem = sumW-(sliderPos+galW) : rem = sliderPos,
movePx = rem<=galW ? movePx = rem : movePx = galW-beKind;
if( movePx <= 10){
movePx = dir==='-=' ? movePx=rem : movePx = galW-sumW;
dir = '';
}
$('#slider').stop(1).animate({left: dir+''+movePx },1000);
}
$('.gal_btn').on('click', function(){
var doit = $(this).hasClass('gal_left') ? anim('+=') : anim('-=');
});
});
And the tooltip script:
// Addon // Tooltip script
var $tt = $('#tooltip');
var ttW2 = $tt.outerWidth(true)/2;
var winW = 0;
function getWW(){ winW = $(window).width(); }
getWW();
$(window).on('resize', getWW);
$('#slider img').on('mousemove',function(e){
var m = {x: e.pageX, y: e.pageY};
if( m.x <= ttW2 ){
m.x = ttW2;
}else if( m.x >= (winW-ttW2) ){
m.x = winW-ttW2;
}
$tt.css({left: m.x-ttW2, top: m.y+10});
}).hover(function(){
$clon = $(this).clone();
var t = setTimeout(function() {
$tt.empty().append( $clon ).stop().fadeTo(300,1);
},120);
$(this).data('timeout', t);
},function(){
$tt.stop().fadeTo(300,0,function(){
$(this).hide();
});
clearTimeout($(this).data('timeout'));
});
HTML
(Place the #tooltip div after the body tag)
<div id="tooltip"></div>
<div id="gallery_container">
<div id="gallery">
<div id="slider">
<img src="" alt="" />
<img src="" alt="" />
</div>
</div>
<div class="gal_left gal_btn">◀</div>
<div class="gal_right gal_btn">▶</div>
</div>
CSS:
/*GALLERY*/
#gallery_container{
position:relative;
margin:0 auto;
width:600px;
padding:0 30px; /*for the buttons */
background:#eee;
border-radius:5px;
box-shadow: 0 2px 3px #888;
}
#gallery{
position:relative;
height:100px;
width:600px;
overflow:hidden;
}
#slider{
position:absolute;
left:0px;
height:100px;
}
#slider img{
height:100.999%; /* fixes some MOZ image resize inconsistencies */
float:left;
cursor:pointer;
border-right:3px solid transparent; /* instead of margin that could leat to some wrong widths calculations. */
}
.gal_btn{
position:absolute;
top:0px;
width:30px; /*the container padding */
height:40px;
padding:30px 0;
text-align:center;
font-size:30px;
cursor:pointer;
}
.gal_left{left:0px;}
.gal_right{right:0px;}
/* end GALLERY */
/* TOOLTIP ADDON */
#tooltip{
position:absolute;
z-index:100;
width:300px;
padding:10px;
background:#fff;
background: rgba(255,255,255,0.3);
box-shadow:0px 3px 6px -2px #111;
display:none;
}
#tooltip *{
width:100%;
vertical-align:middle;
}
/* end TOOLTIP ADDON */
Hope you'll like it, and you learned some useful UI design tricks.
By the way, if you want to populate your ALT attributes (Search engines like it!) you can also grab that text and make it appear inside the tooltip like here!:
demo with text inside the tooltip
Happy coding.
I don't know if I understand correctly your problem. If you set a width wide enough to .scroll-content div, images wouldn't go to the "next line". So a solution would be to set a width with css. If not, you could use jquery to determine the total width of all the images and give it to the .scroll-content div. Calculate total width of Children with jQuery
This is a little hard to explain, but I'm going to do my best:
My webpage is divided using two divs: one floating at left, and other floating at right (50% each one more or less).
I want to add a new feature: dynamically resize. That is: when I click on right border of DIV#1 or click on left border of DIV#2, each one should resize from left to right or right to left.
Maybe you don't understand me, but this effect is what I need (from this plugin):
This plugin only works for images, not divs. I need the same effect on my divs. Actually, I'm trying to use JQueryUI Resizable class but I don't know how to synchronize both resizes.
Can you help me? Any suggestion or track about this would be really appreciated. Thanks!
I created this functionality using 15 lines of JS/jQ: http://jsfiddle.net/xSJcz/
Hope it helps! You could easily modify it to respons to click, or similar.
EDIT: For future records, here is the answer's CSS:
#left,#right{
border:1px solid #aaa;
float:left;
height:100px;
width:48%;
}
#handle{
background:#000;
float:left;
height:100px;
margin:1px;
width:1%;
}
HTML:
<div id="left">
Left
</div>
<div id="handle"></div>
<div id="right">
Right
</div>
JS:
var h = $('#handle'),
l = $('#left'),
r = $('#right'),
w = $('body').width() - 18;
var isDragging = false;
h.mousedown(function(e){
isDragging = true;
e.preventDefault();
});
$(document).mouseup(function(){
isDragging = false;
}).mousemove(function(e){
if(isDragging){
l.css('width', e.pageX);
r.css('width', w - e.pageX);
}
});