Pop up div with absolute position next to click - javascript

I am trying to make a right click lead to a div pop up. However, the click will be inside a cesium window, which only lets a div show if it has absolute position. Is it possible to edit the pop up position of a div with absolute position?
Right now, my code looks like this:
var editHandler = newCesium.ScreenSpaceEventHandler(scene.canvas);
editHandlersetInputAction(function(e){
var shapeEditMenu = document.getElementById("shapeEditMenu");
shapeEditMenu.style.display = "block";
shapeEditMenu.style.left = e.clientX;
shapeEditMenu.style.top = e.clientY;
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
#shapeEditMenu {
position: absolute;
display: none:
top: 80px;
height: 50px;
width: 80px;
}
<div id="shapeEditMenu">
Line thickness:
<input type="number"> pt
</div>
It doesn't work here because there isn't cesium, but what happens in my actual code is that the div pops up on right click, but always is at the same position, not at the place where you right click.

As mentioned in the comments, there is some API confusion going on here. clientX is part of browser-native API, not Cesium's API. Since you're using Cesium's event handling system, you get events from that API. In this case, you would use e.position.x and follow that up with a + 'px' to indicate CSS-pixel units for the stylesheet.
Also you have a few typos here:
newCesium. should be new Cesium.
editHandlersetInputAction should be editHandler.setInputAction
display: none: should be display: none;
Here's a live Sandcastle demo that shows a right-click "Testing" menu show up at the mouse location.
var viewer = new Cesium.Viewer('cesiumContainer');
var editHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
editHandler.setInputAction(function(e) {
var shapeEditMenu = document.getElementById("toolbar");
shapeEditMenu.textContent = 'Testing';
shapeEditMenu.style.display = "block";
shapeEditMenu.style.left = e.position.x + 'px';
shapeEditMenu.style.top = e.position.y + 'px';
shapeEditMenu.style.background = 'rgba(42, 42, 42, 0.8)';
shapeEditMenu.style.border = '1px solid #888';
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
editHandler.setInputAction(function(e) {
var shapeEditMenu = document.getElementById("toolbar");
shapeEditMenu.style.display = "none";
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

Related

Open Safari context menu BELOW text selection

I need to show a toolbar ABOVE a text selection in an editor. That's easy.
Unfortunately Safari on iOS seems to prefer opening its copy/paste/formatting context menu above text selections as well. But Facebook seems to have figured out a way to avoid this:
But after spending almost two hours with a remote debugger trying to figure out how the heck they achieved this, I'm giving up. I just can't figure it out.
I have built a very barebone prototype which displays a toolbar above a text selection (attached below). This works fine on my MacBook (using Chrome in this case):
But as the next screenshot demonstrates, Safari's context menu on an iPad conflicts with my toolbar. They open in almost the same position, making it impossible to interact with my toolbar.
I'm really keen to know how Facebook solved it. Any help would be greatly appreciated. Thank you :-)
Barebone prototype:
var toolbar = document.querySelector("div.Toolbar");
toolbar.style.display = "none";
document.onselectionchange = function()
{
var sel = getSelection();
if (sel.rangeCount > 0)
{
var ran = sel.getRangeAt(0);
if (ran.collapsed === false)
{
var rect = ran.getBoundingClientRect();
var rectTop = rect.top;
var rectCenter = rect.left + (rect.width / 2);
toolbar.style.display = "";
toolbar.style.left = (rectCenter - (toolbar.offsetWidth / 2)) + "px";
toolbar.style.top = (rectTop - toolbar.offsetHeight) + "px";
if (parseFloat(toolbar.style.top) < 0)
{
toolbar.style.top = "0px";
}
if (parseFloat(toolbar.style.left) < 0)
{
toolbar.style.left = "0px";
}
}
else
{
toolbar.style.display = "none";
}
}
else
{
toolbar.style.display = "none";
}
}
body
{
padding: 2em;
}
div.Toolbar
{
display: inline-block;
position: fixed;
background: orange;
box-shadow: 0px 0px 0.2em #333;
padding: 0.3em;
}
div[contenteditable="true"]
{
width: 600px;
height: 300px;
border: 1px solid gray;
padding: 0.5em;
}
<div class="Toolbar">
Buttons go here
</div>
<div contenteditable="true">
Try selecting some of this text in the editor. The toolbar shows up above the text selection as intended. But on an iPad we also get Safari's context menu which opens on top of our custom toolbar. Facebook has successfully solved this somehow - but how the heck did they do it?
</div>
I found the solution.
Quick answer: Add a "button" with an onclick or onmousedown handler.
Expanding on the solution:
I decided to go ahead with my project and simply attach the toolbar at the top of the viewport instead. But as the project progressed, I wanted to take a second shot at this problem - and this time the Context Menu did not overlap with my custom toolbar. It turned out that the mere presence of an element (<div> element representing a button in this case) with an onclick or onmousedown handler registered, was enough to make Safari realize that this is probably something where UI collisions should be avoided. Quite frankly I'm not a fan of this kind of "A.I", but at least there is an explaination now.
var button = document.createElement("div");
button.className = "ToolbarButton ToolbarButtonBold";
button.onmousedown = function() { /* ... */ }; // This saves the day
toolbar.appendChild(button);

How to create a new element on cursor DOM

How would I be able to create a new element and have it placed right where the mouse/cursor is located?
I have some example code below:
<div id = "adivthing></div>
<script>
var newthing = document.createElement("input");
document.getElementById("adivthing").appendChild(newthing);
</script>
If you use either the position: fixed or position: absolute style properties on the newthing element, you can then use the left and top properties to move the element around the box.
If you get the mouse coordinates from your triggering event (e.g. click), you can add the appropriate left and top to your element.
Example below:
function createInput(event){
var newthing = document.createElement("input");
document.getElementById("adivthing").appendChild(newthing); // Your existing code
// get the coordinates of the mouse
var x = event.clientX; // get the horizontal coordinate
var y = event.clientY; // get the vertical coordinate
// position newthing using the coordinates
newthing.style.position = "fixed"; // fixes el relative to page. Could use absolute.
newthing.style.left = x + "px";
newthing.style.top = y + "px";
}
/* Optional - Making new things more obvious in the pen */
input{
height: 10px;
width: 50px;
background: red;
}
#adivthing{
height: 600px;
width: 600px;
background: blue;
}
<!-- Onclick event added to your existing markup -->
<div id="adivthing" onclick="createInput(event)"></div>

How to refresh offsetHeight of div after changing img src on child using pure javascript?

I need to change an image in a div and then immediately centre it on the screen by calculating its height and width and then setting its left and top values. But when I change the img src and then try to get the div's offsetHeight and clientHeight, both the values are wrong. Strangely the offsetWidth and clientWidth values are correct.
Is there a way to refresh the div and get the correct value?
Edit: It appears that changing the image src makes everything after that not work. The change to the onclick event imageObj.onclick = function() {contractImageView(imageId);}; isn't working now either. If I comment out the if statement it all starts working again.
Below is the code...
// Get the page dimensions
var pageBody = document.getElementById(currentBody);
// If you couldn't get the page body, abort.
if (!pageBody) {
return;
}
var pageBodyHeight = window.innerHeight;
var pageBodyWidth = pageBody.offsetWidth;
var imageDiv = document.getElementById(imageId);
var imageObj = imageDiv.children[0];
var paraObj = imageDiv.children[1];
// If you can't get the div or its image, then abort.
if (!imageDiv || !imageObj) {
return;
}
// Check whether the image has been loaded yet, and load if needed
if (imageObj.src.indexOf('lazy_placeholder.gif') !== -1) {
for (item in photoLazyData) {
if (item === imageDiv.parentElement.id) {
imageObj.src = photoLazyData[item][imageDiv.id];
}
}
}
// Change the images class.
imageDiv.className = 'active_design_div';
imageDiv.style.visibility = 'visible';
imageDiv.style.opacity = 1;
// Set the objects new onclick method to collapse the image
imageObj.onclick = function() {contractImageView(imageId);};
// Calculate the right size
imageDiv.style.maxHeight = pageBodyHeight + 'px';
imageDiv.style.maxWidth = pageBodyWidth + 'px';
imageObj.style.maxHeight = pageBodyHeight + 'px';
imageObj.style.maxWidth = pageBodyWidth + 'px';
// Calculate the margins.
var imageDivWidth = imageDiv.offsetWidth || imageDiv.clientWidth;
// ## THIS IS WRONG IF THE ABOVE IF STATEMENT CHANGES THE SRC ##
var imageDivHeight = imageDiv.offsetHeight || imageDiv.clientHeight;
console.log(imageDiv.offsetHeight + ' : ' + imageDiv.clientHeight);
console.log(imageDiv.offsetWidth + ' : ' + imageDiv.clientWidth);
var leftOffset = (pageBodyWidth - imageDivWidth) / 2;
var topOffset = (pageBodyHeight - imageDivHeight) /2;
// Adjust styling to make the div visible and centred.
imageDiv.style.left = String(leftOffset) + 'px';
imageDiv.style.top = String(topOffset) + 'px';
currentId = imageId;
toggleBlackDiv();
Edit: I got this working in the end using Joonas89's answer. I basically moved the if statement that changes the src value to another function that is called prior to the one above. This solved the onclick problem mentioned above. I then changed the divs left/top from calculated values to 50% as detailed by Joonas89 (but on the container div rather than the img element), along with the new transform property. The div and img already had a position value of fixed so didn't need to change that.
Are you sure u want to calculate top and left positions? Wouldent it be better to add a class like this, that always centers it
.parentDiv{
position: relative;
}
.imageElement{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

Adjustable page division boundary

I have two columns in my HTML page.
<div id="content">
<div id="left"></div>
<div id="right"></div>
</div>
Each of them occupies half of the page
#content {
height: 100%;
}
#left, #right {
float: left;
width: 50%;
height: 100%;
overflow: auto;
}
I'd like the boundary between left and right halves to be adjustable by the user. That is, the user can move the boundary to the left or to the right as he/she browses the page. Is it possible to do that somehow?
Yes, but it requires JavaScript. To apply it, you could of course just set the width of each of the sides:
var leftPercent = 50;
function updateDivision() {
document.getElementById('left').style.width = leftPercent + '%';
document.getElementById('right').style.width = (100 - leftPercent) + '%';
}
Now you can adjust the division with, say leftPercent = 50; updateDivision(), but the user isn't going to do that. There are multiple different ways you could present this to the user. Probably the best-suited way would be a little line in the middle they could drag. For this, you could use a little CSS for the positioning:
#content {
position: relative;
}
#divider {
position: absolute;
/* left to be set by JavaScript */
width: 1px;
top: 0;
bottom: 0;
background: black;
cursor: col-resize;
/* feel free to customize this, of course */
}
And then make sure you've got a div with an id of divider in content and update updateDivision to also update the left of divider:
document.getElementById('left').style.left = leftPercent + '%';
Then you just need a little logic to handle the dragging. (Here, I've put all of the elements into appropriately-named variables):
divider.addEventListener('mousedown', function(e) {
e.preventDefault();
var lastX = e.pageX;
document.documentElement.addEventListener('mousemove', moveHandler, true);
document.documentElement.addEventListener('mouseup', upHandler, true);
function moveHandler(e) {
e.preventDefault();
e.stopPropagation();
var deltaX = e.pageX - lastX;
lastX = e.pageX;
leftPercent += deltaX / parseFloat(document.defaultView.getComputedStyle(content).width) * 100;
updateDivision();
}
function upHandler(e) {
e.preventDefault();
e.stopPropagation();
document.documentElement.removeEventListener('mousemove', moveHandler, true);
document.documentElement.removeEventListener('mouseup', upHandler, true);
}
}, false);
You should be able to read it to see how it works, but in short: It listens for when someone presses on the divider. When they do, it'll attach listeners to the page for when they move their mouse. When they do, it updates the variable and calls updateDivision to update the styles. When eventually it gets a mouseup, it stops listening on the page.
As a further improvement, you could make every element have an appropriate cursor style while dragging so your cursor doesn't flash while dragging it.
Try it out.
There's nothing in the divisions so nothing will happen. It's like writing:
<h1></h1>
And changing the CSS for h1 and expecting something to be there

show div as popoup when clicking on image [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have an image.
I want to show different divs as popup when user clicks on particular area of the image.
I want to do it using jquery & html.
Can any one help me with this.
Here is an example of sample solution: http://jsfiddle.net/htEvT/2/
JavaScript
$('#rabbit').click(function (e) {
var offset = $(this).offset(),
left = e.pageX - offset.left,
top = e.pageY - offset.top;
if (top > $(this).height() / 2) {
alertDiv('You\'ve cliked under the middle.', 'alert-white');
} else {
alertDiv('You\'ve cliked above the middle.', 'alert-gray');
}
});
function alertDiv(text, cssClass) {
var alrt = $('<div class="alert ' + cssClass + '">' + text + '</div>');
$(document.body).append(alrt);
alrt.click(function () {
alrt.remove();
});
}
​
CSS
.alert {
position: absolute;
left: 30px;
top: 30px;
width: 300px;
height: 200px;
border: 1px solid black;
}
.alert-white {
background: white;
}
.alert-gray {
background: #ccc;
}
​
HTML
<img src="http://www.clermontanimal.net/images/lop_rabbit_easter.jpg" id="rabbit" alt="" />​
If there are any issues with my solution please let me know. :)
Use Image Map on image and attach fancy box on different sections of image. Since, you have not posted code so I can't provide coding solution for the same.
Something like below should give you an Idea how to do this:
$("img").click(function() {
$("body").append("<div class='newdiv'></div>")
})
.newdiv{width:100px; height:300px;border:1px solid red;}
My favorite is Fancybox.
I'm yet to see something it cannot do. Great documentation and widely used so if you need help there is a high chance somebody else has asked the same question, and can be resolved with a simple google.
Create a DIV named "imgbox" on the HTML page on which your thumbnail images will be shown. The DIV and the CSS element ID associated with the DIV is shown below
<div id="imgbox"></div>
the css
#imgbox
{
vertical-align : middle;
position : absolute;
border: 1px solid #999;
background : #FFFFFF;
filter: Alpha(Opacity=100);
visibility : hidden;
height : 200px;
width : 200px;
z-index : 50;
overflow : hidden;
text-align : center;
}
Here is the JavaScript code to show the popup image:
Get the left and top positions of the thumbnail image:
function getElementLeft(elm)
{
var x = 0;
//set x to elm’s offsetLeft
x = elm.offsetLeft;
//set elm to its offsetParent
elm = elm.offsetParent;
//use while loop to check if elm is null
// if not then add current elm’s offsetLeft to x
//offsetTop to y and set elm to its offsetParent
while(elm != null)
{
x = parseInt(x) + parseInt(elm.offsetLeft);
elm = elm.offsetParent;
}
return x;
}
function getElementTop(elm)
{
var y = 0;
//set x to elm’s offsetLeft
y = elm.offsetTop;
//set elm to its offsetParent
elm = elm.offsetParent;
//use while loop to check if elm is null
// if not then add current elm’s offsetLeft to x
//offsetTop to y and set elm to its offsetParent
while(elm != null)
{
y = parseInt(y) + parseInt(elm.offsetTop);
elm = elm.offsetParent;
}
return y;
}
Get the thumbnail image source, make the DIV visible, increase the height and width to the required size, and attach the image to the DIV.
function Large(obj)
{
var imgbox=document.getElementById("imgbox");
imgbox.style.visibility='visible';
var img = document.createElement("img");
img.src=obj.src;
img.style.width='200px';
img.style.height='200px';
if(img.addEventListener){
img.addEventListener('mouseout',Out,false);
} else {
img.attachEvent('onmouseout',Out);
}
imgbox.innerHTML='';
imgbox.appendChild(img);
imgbox.style.left=(getElementLeft(obj)-50) +'px';
imgbox.style.top=(getElementTop(obj)-50) + 'px';
}
Hide the DIV at mouse out.
function Out()
{
document.getElementById("imgbox").style.visibility='hidden';
}
Add a OnMouseOver client-side event call for the thumbnail images to show the popup image on mouse-over.
<img id='img1' src='images/Sample.jpg' onmouseover="Large(this)" />
If the area is square, you can place a transparent element over the desired area, and give it a simple onClick event.
Use SimpleModal
You can use the plugin SimpleModal to achieve what you wanna do.
SimpleModal is a lightweight jQuery Plugin which provides a powerful interface for modal dialog development. Think of it as a modal dialog framework. SimpleModal gives you the flexibility to build whatever you can envision, while shielding you from related cross-browser issues inherent with UI development.
Using that, you can either call an already existing div or create a modal on the fly.
Calling an existing div:
$("#element-id").modal();
Making a modal on the fly:
$.modal("<div><h1>SimpleModal</h1></div>");
Giving options:
$("#element-id").modal({options});
$.modal("<div><h1>SimpleModal</h1></div>", {options});
Demos:
More demos here: http://www.ericmmartin.com/projects/simplemodal-demos/

Categories

Resources