For fun, I am creating a widget that can be toggled to use vertical typing (e.g. for Japanese). The vertical part is being done with a div that is contenteditable. At the moment, you can see both the textarea and the div, and watch their content change in sync. The checkbox does nothing yet.
My problem is that the svg that is the "handle" to drag and resize was inside the editable div, and this would get messed up if the user cut from or pasted into the div. So that's the real problem I'm solving, and if there's a better fix, let me know. In an attempt to fix this, I am putting the editable div within another div that has the svg, in order that the internal editable div will not affect it.
After doing this, the resize functionality does not work correctly. After clicking down on the handle, the div resizes extremely fast downwards (it's height growing).
Here is what I was trying to do "working": https://jsfiddle.net/m4Ljuzyn/167/
And here is the one where the resize is broken after I changed the layout a bit: https://jsfiddle.net/m4Ljuzyn/190/
I am using pure JavaScript only.
The problem comes from the fact that offsetLeft and offsetTop are relative to the element's parent. You're using that relative value with the mouse event's clientX/Y value and it's producing undesired results.
Take advantage of getBoundingClientRect for proper coordinates in your mousemove handler.
var bounds = verticalTextarea.getBoundingClientRect();
verticalTextarea.style.width = (evt.clientX - bounds.left) + "px";
verticalTextarea.style.height = (evt.clientY - bounds.top) + "px";
Be warned: getBoundingClientRect is an expensive calculation, and may negatively affect performance.
Update: Added Forked JSFiddle
https://jsfiddle.net/csoh7xzv/
Related
I'm trying to create a spot the difference game with jQuery.
Basically, several images stacked, positioned absolutely in a container. Above the container there is the page header with a logo and a menu, which takes altogather about 120px above the images container.
When someone clicks an area inside the image, I put there a new div, with either a correct (V) mark, or a wrong (red X).
I'm trying to get the position of the click inside the element, using the following code (the following used event variable e is returned in the click event just to be clear):
var parentOffset = $(this).parent().offset();
var topOffset = e.clientY - offset.top;
My problem is that the offset from the top changes when I scroll the page down a little to the footer area, and then I do not position the new marker div in the correct height.
When I'm scrolled to the top of the page, the mark is position correctly.
I've created such a game before, but can't understand why suddenly the calculation is wrong :\
Seems that I get the distance minus the scroll height, but not sure.
Thanks for your insight,
Yanipan
I played around with Firebug a little and it looks like e.originalEvent.layerY is exactly what you're looking for.
It always shows the absolute coordinates of your click within the clicked object, no matter where the screen is scrolled.
I have a grid of elements (3 x 3) formation which toggle visibility on hover, easy.
However my next step is to grow said elements to fill their container when hovered upon, I'm assuming I would need to get current (x,y) values and then grow this to the (x,y) values of the parent container and use css positioning, however every approach I take is hitting a brick wall. I have a fiddle here which demonstrates the layout / intended functionality - http://jsfiddle.net/u2w7J/
Any help would be gratefully appreciated!
The way your HTML is set up currently, this is kind of hard to accomplish while having it look smooth. A first try is to use the .toggleClass function and toggle "box" and "miniBox" for the hovered element. See http://jsfiddle.net/u2w7J/6/ for a demo.
Positioning is harder since the miniBoxes are not positioned absolutely. Hence, adding animation is causing weird results (see above demo).
I would suggest to have the miniBoxes positioned absolutely. When hovering, get the parents div left and top values and animate the miniBox using these values. Additionally, raise z-index during or before the animation to prevent other miniBoxes being visible.
I'm trying to draw in a div that is a droppable element.
To be more precise, I'm drawing arrows using images in a div element.
You can see it here:
http://ekstrakt.selfip.com/coach/?cmp=articleedit
I tried every other way I could think of for drawing with Javascript, even used some libraries made for drawing (ex. draw2d.js), but this is the way it suits me most.
Now, the problem is, I'm placing them in a 900px wide div. When the total width of the added divs/images exceeds 900px, the browser is placing them in wrong places.
Part of the code:
el=document.createElement("div");
eli=document.createElement("img");
$(eli).attr("src", "docs/temp/"+data);
$(el).append(eli);
$(el).draggable();
$(el).draggable('destroy');
$(el).css("position", "relative");
$("#frame").append(el);
$(el).css("float", "left");
$(el).css("width", Math.abs(dot1.x-dot2.x));
$(el).css("height", Math.abs(dot1.y-dot2.y));
$(el).css("left", dot1.x-negativeDistance);
var tempPos=$(el).position();
console.log("position| "+tempPos.left+":"+tempPos.top);
$(el).css("top", dot1.y);
negativeDistance=negativeDistance+Math.abs(dot1.x-dot2.x);
if(negativeDistance>900){
negativeDistance=negativeDistance-900;
}
When you see the example, you'll see the problem. Just click on the green field twice on different places.
Or, if anyone has a solution for drawing in a div, please share.
Have you considered positioning the drawn divs inside div#frame absolutely as opposed to relatively? You may need to rework the math in your code a bit, but you should be able to avoid relatively-positioned floating elements affecting each other's positioning within the parent div (which seems to be the source of your problem) this way. Just a thought.
I have a <div> that displays a graph inside. Sometimes this graph gets too big for the <div>, so I need a way for users to grab the graph with their mouse and move it around. I found the jQuery UI Draggable interaction and thought this is what I need. It was easy enough to get the basics to work, however, I'm having trouble getting this right.
Ideally, the graph can only be dragged to reveal otherwise hidden parts. For example, if there's more graph hidden to the right, then you can drag it to the left and see that hidden part. But then you can't drag it to the left anymore once everything to the right is visible. How do I implement something like this with jQuery UI Draggable? Is it possible? Is jQuery UI the right tool for this?
Less than ideal, but still ok, is that you can drag the graph wherever you want even if the graph is small enough to fit in the parent <div> and nothing is hidden. I can't even get this to work right. What happens is I can just choose not to specify the containment option. Then the graph isn't constrained.. The problem now is the graph's <div> is only a certain size (100% width and height of parent <div>). The nodes are placed with absolute positioning outside this size. Then when you go to drag the graph to reveal those hidden nodes, you can no longer drag the graph... because you're now clicking outside the graph's <div>.
I can maybe have a graph container <div> that I mess with to get things right and dynamically resize that container div as nodes are added or removed.. Or I can implement this without jQuery UI, just using the mousemove event.. What's the best approach? Is there another good library for this?
I think this is what you are looking for - Your container should be overflow:hidden, your graph would be contained in some thing with a width and height, and beyond that you just need to calculate a "constraint" box, which is going to be the .offset() of the container, adding the "extra space" by the calculating "overflowed" portion I.E. only allow dragging the thing from offset.left + container.innerWidth() - draggable.width() -> offset.left
Now, if either of these contraints already "fits" you'll need to make sure to "zero" it to the offset, and if they both fit, skip adding draggable... Put it all together and you get:
var contain = $("#container"),
big = $("#bigthing"),
offset = contain.offset(),
// calculate the "constraints"
constraints = [
offset.left + contain.innerWidth() - big.width(),
offset.top + contain.innerHeight() - big.height(),
offset.left,
offset.top
],
// it "fits" if our left/top constraint is higher or equal to the right/bottom
fitsX = constraints[0] >= constraints[2],
fitsY = constraints[1] >= constraints[3];
if (!(fitsX && fitsY)) {
if (fitsX) {
constraints[0] = constraints[2];
}
if (fitsY) {
constraints[1] = constraints[3];
}
big.draggable({
containment: constraints
});
}
Fiddled: http://jsfiddle.net/gnarf/jqy2b/1/
If you need to dynamically resize the draggable thing, just recalculate the containment option!
I have a page with many divs and style, with my div buried somewhere inside.
I am trying to have a button that automatically makes my div, that includes a video player, resize and capture the whole browser.
In order to do that I am trying to get the current position of the div and then position it relatively so that it'll get to the top-left corner so I could then use document.body.clientHeight/clientWidth.
Can't get this to work.
I tried the approach of moving my div to the first div and then resizing however this messes up the flash player.
Any ideas? any different approaches?
Thanks,
Guy
Use one of the lightbox clones that can handle DIVs. They usually copy the DIV in question into their own view DIV, which helps with positioning issues and you don't have to do anything to the buried div.
I find Multi-Faceted lightbox to be very easy for customizations:
http://www.gregphoto.net/lightbox/
but there are lots of others around as well.
Why relative?
You should rather use fixed instead of relative. Then set positon to 0,0 and width and height to 100%.
Simple js can do this.
On click, just set the div's style to 'fixed', and position 0,0. Like:
var theDiv = document.getElementById('yourDivsId');
theDiv.style.position = 'fixed';
theDiv.style.top = 0;
theDiv.style.left = 0;
This should do the trick:
<div style="position:absolute;top:0;left:0;width:100%;height:100%">
some content here
</div>