Flow and Scroll Text around non rectangular shapes - javascript

I have created a little code which lets text flow around some shapes. Using a simple Javsscript:
See http://jsfiddle.net/lobin/YPBmJ/2/
What I try to achieve is that the shape is fixed and when scrolling, the text will scroll around the shape. I let the shape stay fixed via a JS bound to the scroll event, but it seams the rendering does not adopt itself to the new situation (See jsfiddle).
Any Ideas how that could work?
HTML:
<div class="box"><div class="shapewrapper"></div>Some long Text</div>
CSS:
.box {
width:600px;
height:400px;
position: absolute;
overflow-y: scroll;
}
.box .shapewrapper {
position: relative;
}
.box .shapewrapper .left {
background-color: #f00;
height:1px;
float:left;
clear:left;
}
JS:
var hbratio=10;
var h=$(".box").height();
for (i=h;i>0;i--) {
b=Math.round(i/10);
$(".shapewrapper").prepend('<div class="left" style="width:'+b+'px;" />');
}
$(".box").scroll(function() {
var y=$(".box").scrollTop();
$(".shapewrapper").css("top",eval(y)+'px');
});
(Idea from http://www.csstextwrap.com)

I don't know if there is a way to achieve this with css (alone), but I came up with a solution that involves jQuery.
Whenever the user scrolls the ".box" element, the top margin of the first ".left" element should be adjusted.
$(".box").scroll(function() {
$(".box .left").first().css("margin-top", $(this).scrollTop()+"px");
});
In order to make this work, the user must actually scroll the box element, so I changed the CSS of the box to overflow:auto. It would also work of the user scrolls the parent-element, but then the selector for the scroll event would need to be changed to the parent element.
I created a new jsFiddle to demonstrate it: http://jsfiddle.net/EwQ5J/1/

Related

Prevent div from extending scrollbar

Take the following example:
https://jsfiddle.net/atg5m6ym/5079/
Here, you have to scroll down a bit to see the message "Hello!". I also animated a div to move down beyond the screen:
$("div").animate({top: '3000px'}, 6000);
You can see how the scrollbar changes and we now have a much larger page to scroll through.
Now, I want users to be able to scroll down to the "Hello!" text, if the text is beyond the user's screen. However, I don't want the div to extend the vertical scrollbar once it reaches the bottom of the screen. Rather, I want the div to continue moving down beyond the screen, with the scroll bar remaining unchanged. This way, the scrollbar could not follow it.
Doing "overflow-y: hidden" would prevent users from scrolling downwards on their own choice and reading the "Hello!" Is there anything I can do to accomplish both of these using JS (preferably jQuery) or CSS?
EDIT: I still want the div to exist, so I don't want to fade it out. If I had a div that returns afterward or travels in an elliptical orbit, I would like it to still reappear when it reenters the screen, but not to affect the scrollbar.
This will make div travel to whatever the Y position of the paragraph is, and after that gets faded out:
$(document).ready(function() {
var p_pos = $("p").offset().top;
$("div").animate({top: p_pos}, 6000).fadeOut();
});
Alright, try the following:
<div id="everything">
<div id="orb"></div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br>
<p>
Hello!
</p>
</div>
And in your css:
#everything {
display: inline-block;
position: relative;
width: 100%;
height: 800px;
max-height: 800px;
overflow-y: hidden;
background-color: #ccc;
}
Make sure to animate $("#orb") instead of just $("div") (and rename it in your css.
There you go. Just add to the body and set the div position to
body {
overflow: hidden
}
div {
bottom: 0;
}
https://jsfiddle.net/atg5m6ym/5082/

Div1 covers Div2: how to check if the mouse is over the covered Div2?

I'm a bit lost. I try to check if my mouse is over a Div which is covered by another Div. I search a vanilla js solution if possible.
I tried to use the elementFromPoint method, but it only seems to give me the top Div.
I also tried to mess around with the "onmouseover" Event, but I didn't found a solution either. Maybe I just overlooked something.
Any ideas how to solve this? I want a method to check if my mouse is over the smaller Div2 or not. I made a jsFiddle to show the situation. I made the covering Div
translucent for easier understanding from the setup.
http://jsfiddle.net/y2L5C/
<div id="div1"></div>
<div id="div2"></div>
#div1 {
width:300px;
height:300px;
background:red;
position:absolute;
top:0px;
z-index:1;
opacity: 0.5;
}
#div2 {
width:200px;
height:200px;
background:blue;
position:absolute;
top:0px;
}
if you want to check if your mouse is over a <div> that is covered by another <div>, you can achieve this by declaring this code: pointer-events: none; to the css of the covering <div>.
For example:
<div id="under"></div>
<div id="over"></div>
Add this to your css file:
#over{ pointer-events: none; }
In that case, all pointer events for the div having the id=over will be ignored. You can now then add this code to test if its working.
Add this JavaSCript code:
$('#under').mouseover(function() {
alert("Mouse is over the div having the id='under'");
});
Give it a try! Good luck!
Here's a quick and dirty solution. I'll leave it up to you to optimize it. Here's the fiddle: http://jsfiddle.net/y2L5C/1/
var div2 = $("#div2"),
width = div2.outerWidth(true),
height = div2.outerHeight(true),
offset = div2.offset(),
top = offset.top,
left = offset.left;
$(document).mousemove(function(evt) {
if(evt.pageX <= (left + width) && evt.pageX >= left &&
evt.pageY <= (top + height) && evt.pageY >= top) {
$("#indicator").text("Over the div #2");
} else {
$("#indicator").text("NOT over the div #2");
}
});
Interesting concept. I do want to bring up that for plain CSS events there are plain CSS solutions such as here. However, if what you are looking to do is initiate Javascript events then the trouble is that onMouseOver is not going to trigger for #div1 if #div2 is on top of it.
One potential, very simple solution, is to create a script to copy the position of your #div2 element and change the style to be a higher z-index. While JQuery might be "easier" to create this, you could certainly create a vanilla JS solution. This script may give you a little guidance as to how you can find positioning. You can use element.style values in order to assign CSS values. If your element positions are declared by CSS then you can do something like this:
var div1 = getElementById('div1');
var div2 = getElementById('div2');
var newElem = document.createElement('div');
newElem.id = 'div2makefacade';
Now you can either utilize newElem.style.top etc. and assign div2.style.top's value, or you can even assign a custom class which has the correct position values. When you initiate onMouseOver, you can do so on #div2makefacade rather than #div2, and perform actions on #div2
well i made a function that perhaps it help you in some way, first in your view you have to load jquery librarie like this
<script type="text/javascript" src="Scripts/jquery-1.6.2.js"></script>
and your css you have this
.visiblepanel{
display: none;
}
.visiblepanela{
display: none;
}
your script this, you have to add the hover function
$('#quickstart').hover(function() {
$('#visiblepanel').toggle();
});
$('#quickstarta').hover(function() {
$('#visiblepanela').toggle();
});
and your html body
<div id="quickstart">Div 1</div>
<div id="quickstarta">Div 2</div>
<div id="visiblepanel" class="visiblepanel">mouse encima div 1</div>
<div id="visiblepanela" class="visiblepanel">mouse encima div 2</div>
so it consist that when the mouse is over the DIV 1 it will show an advice that your mouse is there, and so on with DIV 2...i hope i could helped you...

How to move div upward while scrolling downward

I am creating a small html file for myself just to try some new things. so far, I have a header, a background, and a center area for content. it is in the center and the position is set as fixed.
I want to make it so when someone scrolls down, the center area will move up. So there wont be large white-space at the top. Also, when they scroll up, so the center is near the top, it wont go over the header.
I"m sure this can be done with JavaScript. But, I'm not too sure how.
I'm sorry if this is unclear.
I recommend using jquery to accomplish this.
You can bind an event listener to the scroll event, the handler is passed an event object with all the information you need to achieve your desired result (scrolltop, pageX, pageY, etc....)
Once you have captured the scroll event, you can tell where the user scrolled to (how far down), and position your div accordingly.
http://api.jquery.com/scroll/
This could be achieved using javascript or Jquery (Jquery being the easiest of the two).
1.) Use arbitrary pixels to define when the div should move.
function scrolling() {
if ($(body).scrollTop() > 120px)
{
....perform div transition...
}
}
OR
2.) Use the position of the target div to define when the div should move.
function scrolling() {
if ($(body).scrollTop() > $("#TargetDiv").offset().top;)
{
....perform div transition...
}
}
If you use the second solution, be sure that you call Jquery and this script after the DOM is loaded i.e. after </body>. Otherwise it won't be able to define the #TargetDiv.
This can be done without use of jquery or javascript, if you are looking to do what I think you are.
http://jsfiddle.net/wN8c8/
by setting your content to a fixed size and setting the content to overflow:auto;
likewise, you could also set your page background-attachment to fixed, and create the illusion that the text is 'appearing' without the page moving. You can certainly go more in-depth with it using scripting, but it really depends on your intention.
z-index will also allow you to build your page in layers, so that you can determine what shows and what is hidden behind other page elements.
body {
background-color:yellow;
}
#header{
position:fixed;
width: 100%;
height:20px;
background-color:red;
z-index:2;
}
#content{
position:fixed;
width:80%;
height:60%;
background-color:#ddd;
overflow:auto;
margin:0px 10%;
z-index:1;
}
<div id="header"></div>
<div id="content">
This is some content.<br/>
This is some content.<br/>
This is some content.<br/>
</div>

Interactive HTML webpage

EDIT: Thanks for a lot of great examples on how to solve these. I cant decide between who to accept yet, but I will go though all examples and see which I like the most. Great feedback guys! =D
I normally do these kind of things in flash, but this time it has to be compatible with mac, iPads and all those units too.
So, what do I need help with?
I've got a picture, with some "hotspots" on. I want to be able to click any of those hotspots to show some information.
This should be fairly basic and easy to achieve, but since I've never done this in html before I have to ask you guys =)
So, what would be the best way to do this? It have to be compatible with any browser and device, and it doesnt need to be very advanced. If it's possible to add effects to the box (sliding out, fading in, or anything like that) then thats a nice bonus, but not something I need.
Any help would be great!
BREAKDOWN:
I have a background image with some "hotspots" (numbers 1 and 2 in my example). The users should be able to either hover the mouse over any of these or click it to get more information, as seen in picture #2
This is that happens when you hover/click any of these hotspots.
Text and image is displayed inside a nice little info box.
If the user clicks "more information" it will open up even further to display more information if available. Like in this img:
I don't think the Javascript approach is really necessary here. I created a little CSS-only mock-up for you on JSBin.
Basically the point is that you enclose the image in a relatively positioned div, then absolute position the hotspots inside the same div. Inside the hotspots divs you will have the more info elements, showing only on :hover of their parents.
This makes it simple, and far more accessible.
Update: cropping the image equally from both sides
If you want to keep the image centered and still not use any javascript, you could set the required image as a background-image of the container, and setting its background-position parameters to center center.
You would have to make sure that the width of this div is set to the width of your image, and the max-width to 100%, so that when the window gets resized below the image width it stays at the center.
Now, a problem that I encountered here is how to make the hotspots stay center relatively to the image. I solved it this way:
I created a wrapper div for the hotspots with these characteristics:
margin: 0 auto;
position: relative;
width: 0px;
This basically makes sure that the wrapper div finds the center of our image. Then, you would position the hotspots relatively to the top-center position of the image, instead of the top-left as a starting point.
Then you have what you are looking for.
Working demo
Here's another approach, and in my opinion far superior to using a map or excessive JS. Place <div> elements on top of the element with the background-image and have HTML and CSS do the heavy lifting for you.
See it on JSFiddle
HTML
The HTML should seem pretty each enough to understand, we create <div>s with the class hotspot and rely on certain things being present. Namely .text (to show digit), .hover-popup (to show on hover) and .click-popup (which is inside .hover-popup and is shown when clicked).
<div id="hotspot1" class="hotspot">
<div class="text">1</div>
<div class="hover-popup">
I was hovered!
<div class="click-popup">
I was clicked on!
</div>
</div>
</div>
<div id="hotspot2" class="hotspot">
<div class="text">2</div>
<div class="hover-popup">
I was hovered!
<div class="click-popup">
I was clicked on!
</div>
</div>
</div>
CSS
This is where most of the magic happens, see the comments for further explanation.
/* These two position each hotspot */
#hotspot1 {
left:15%; /* we could use px or position right or bottom also */
top:20%;
}
#hotspot2 {
left:35%;
top:25%;
}
/* General styles on the hotspot */
.hotspot {
border-radius:50%;
width:40px;
height:40px;
line-height:40px;
text-align:center;
background-color:#CCC;
position:absolute;
}
.hotspot .text {
width:40px;
height:40px;
}
/* Show the pointer on hover to signify a click event */
.hotspot .text:hover {
cursor:pointer;
}
/* hide them by default and bring them to the front */
.hover-popup,
.click-popup {
display:none;
z-index:1;
}
/* show when clicked */
.hotspot.clicked .click-popup {
display:block;
}
/* show and position when clicked */
.hotspot:hover .hover-popup {
display:block;
position:absolute;
left:100%;
top:0;
width:300px;
background-color:#BBB;
border:1px solid #000;
}
JavaScript (with jQuery)
Unfortunately you're going to have to use some JavaScript for the clicking part as CSS doesn't have a 'clicked' state (outside of hacks with checkboxes). I'm using jQuery because it's dead easy to do what I want.
$(document).ready(function () {
$('.hotspot').click(function () {
$(this).toggleClass('clicked');
});
});
Creating the arrow
Over at css-tricks you can find a tutorial for attaching an arrow to a element using the :before and/or :after pseudo-elements. You can even 'simulate' a border around them by placing the :after element on top of the :before. But yea, lots of resources on how to do this.
You should be able to use the onclick or OnMouseOver event in the map area (define the href as "").
An example using OnMouseOver is here: http://www.omegagrafix.com/mouseover/mousimap.html
Give a class for that image in html (Ex: imgclass). And in javascript(using jquery), build that hover box in html format and bind it to 'mouseover' event of that image.
For example:
function bindhtmltoimage() {
myimg = $('body').find('.imgclass');
divSlot.each(function (index) {
$(this).bind('mouseover', function () {
try {
//position the hover box on image. you can customize the y and x axis to place it left or right.
var x = $(this).offset().left;
var y = $(this).offset().top;
var position = $(window).height() - ($("#divHover").height() + y);
var widthposition = $(window).width() - ($("#divHover").width() + x);
if (position < 0 || widthposition < 0) {
if (position < 0) {
$("#divHover").css({
position: 'absolute',
left: x + 20,
top: y - $("#divHover").height() - 20
});
}
if (widthposition < 0) {
$("#divHover").css({
position: 'absolute',
left: x - $("#divHover").width(),
top: y + 20
});
}
}
//build your html string for that hover box and apply to it.
$('#divHover').html("your Html content for that box goes here");
$('#divHover').show();
//if you want the box dynamically generated. create the html content and append to the dom.
}
catch (e) {
alert(e)
}
});
});
}
it will work fine in desktop and mobile. if you face any problem in touch devices, bind the function to click event instead of 'mouseover'.
Also, for map approach, i strongly recommend SVG instead of images.

Implementing a hover info box

I have a calendar, and when the user hovers over a cell, a large-ish info box appears with details for that date. I am having some trouble though making the info box disappear when the user moves away.
I basically want it so that when the mouse cursor moves out of the calendar cell which is hidden by the info box it will disappear. But I'm having trouble with this because mouseenter and mouseleave get messed up by having the info box as the top element.
So I tried to get around this by using "placeholder" divs that are transparent, have the same shape and location as the calendar cell beneath it, and have a z-index of 1000 so they are above the info box. I then apply the mouseenter and mouseleave events to these divs instead.
There's two problems with this though. One, I have now messed up my HTML semantically. The divs have no purpose but to get around what seems to be a limitation. And secondly, they mess up my jQuery UI selection (I've applied it to the calendar cells - a click no longer selects a cell).
Is there a clean way to handle displaying an info box? There will be no user interaction with the info box -- it's just to display information.
EDIT: Here is some code:
<li>
<div class="day-content">
</div>
<div class="day-content-placeholder">
</div>
</li>
and CSS
li
{ position: absolute; width: 15%; height: 20%; top: ... left: ... }
.day-content
{ position: absolute; width: 100%; height: 100%; }
.day-content-placeholder
{ position: absolute; width: 100%; height: 100%; z-index: 1000; }
.popup
{ position: absolute; width: 300%; height: 300%; left: -150%; top: -150%; z-index: 500; }
and Javascript
var popup;
$('.week-content-placeholder')
.mouseenter(function()
{
popup = $('<div class="popup">'+a_lot_of_text+'</div>').insertAfter(this);
})
.mouseleave(function()
{
popup.remove();
});
That's not the exact code, but you get the idea. This works okay, but like I said, since .week-content-placeholder is above .week-content, the selection capability with jQuery UI doesn't work properly on .week-content.
You could modify your solution with the transparent "placeholder" divs in the following way:
Have the "placeholder" dive underneath the "calendar cell", using {zIndex: -1}.
When you enter a calendar cell, unhide the large "content" div and set {zIndex: 1000} on the "placeholder" div to bring it to the top.
Have a "mouseout" event on the placeholder div that will hide the "content" div and set {zIndex: -1} for the the "placeholder" cell.
Rather than create the "placeholder" cells in the HTML, you could create one in the javascript and move it to the postion of each "calendar" cell as you "mouseIn" it. You could also duplicate any "click" events on the "calendar cell" onto this one as well.
Let me know if this works.
The trick here is to make the info box a child of the cell:
<div id='box'>
Normal content
<div id='inner'>
This big box obscures everything in the cell!
</div>
</div>
The inner box is hidden until the hover occurs. Notice how with CSS we can make the box bigger than the cell itself with negative margins.
#box
{
width:100px;
height:100px;
margin:100px;
border:solid 2px darkblue;
position:relative;
}
#box #inner
{
display:none;
position:absolute;
background-color:#eeee00;
top:-10px;
left:-10px;
width:120px;
height:120px;
}
And you can use normal jquery hover because the hover covers box the box and it's child:
$('#box').hover(function(){
$('#inner').show();
},function(){
$('#inner').hide();
});
Here's it running:
http://jsfiddle.net/RbqCT/
You can create the info box dynamically as you do in your code.
Here's 15 different plugins that let you do this with jquery:
http://www.webdesignbooth.com/15-jquery-plugins-to-create-an-user-friendly-tooltip/
You could track mousemouse and use the offsetLeft + width and offsetTop + height of your hover trigger against the event.pageX and event.pageY to compare.
If you make this work as you described a tiny mouse movement that remains within the calendar cell (which is not even visible) leaves the popup in place, but a slightly larger movement that exits the cell makes the popup disappear.
The user sees only movement within the popup itself — small movement within the popup leaves it in place; large movement makes it go away.
I suggest triggering the disappearance of the popup on exiting the popup div itself. Any movement that remains within the "tip" panel leaves it up. I think that (1) this is better usability and (2) it avoids the whole problem with the obscured calendar cell event handling.
You could do that by adding a .mouseleave() handler to the div when you create it.

Categories

Resources