So I would like to have a link that would point to the nearest element with the class ".example" on their screen. I know you can have links pointing to unique IDs on the page setting the href to #uniqueID I just want to know if that is possible with classes
You'd need to use JavaScript for this. Assuming that by 'nearest element... on their screen' you mean the element with the smallest vertical distance to the clicked link.
A quick way to do this would be looping through each element with the class example, finding the one with the smallest distance, and scrolling it into view:
<script>
function toNearestExample(clicked_element) {
// first we get all elements of 'example' class
var examples = document.getElementsByClassName("example");
// now we find the index of the element nearest to the clicked element
// to do this we go through each element in this list, and find the closest vertical distance from the clicked element
var smallest = Math.abs(clicked_element.getBoundingClientRect().top - examples[0].getBoundingClientRect().top);
var indexOfSmallest = 0;
for(var i=1;i<examples.length;i++) { // for each element with class 'example'
// calculate vertical distance
var verticalDistance = Math.abs(clicked_element.getBoundingClientRect().top - examples[i].getBoundingClientRect().top);
if (verticalDistance < smallest) {
smallest = verticalDistance;
indexOfSmallest = i;
}
}
// once we have that, we can scroll it into view
examples[indexOfSmallest].scrollIntoView();
}
</script>
Now all we have to do is call this function when your element is clicked, making sure to pass the element that clicked it:
<a onclick="toNearestExample(this);">click me!</a>
Of course, you could easily modify the code for elements with distances other than vertical.
An issue with this method is that it will get slow as you add more and more example elements onto the page. Unless your <a> tag will be moving around the page, it would be better to just hardcode this in for performance or to prevent issues with different window sizes.
Related
I need to dynamically create a ui widget with a parent div.id='myDivId', which is a google map control.
var centerControlDiv = document.createElement('div');
var centerControl = new CenterControl(centerControlDiv, map);
centerControlDiv.index = 1;
centerControlDiv.id = 'myDivId';
map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);
// $('#myDivId') causes exception as $('#myDivId') is not created on
// map as a DOM element yet.
var uiWidget = new uiWidget('myDivId');
// $(#myDivId) is used in class uiWidget().
class uiWidget {
constructor(divId) {
this.id = divId;
// It should fail here due to this.$div property, as
// div 'myDivId' is not a DOM element yet by google map
// controls API.
this.$div.click($.proxy(this.event_click, this));
}
get $div() {
return $(‘#’ + this.id);
}
event_click(eve) {
}
}
But, there is no event of when this parent div is created. Therefore, the child ui widget can't be created at correct time.
How to know parent div with id 'myDivId' is created?
You are trying to reference a DOM element by ID as a child of document when that element has only been created but not yet added to the document.
But you already have a reference to the #myDivId element in the centerControlDiv variable, so you don't need to use the ID to reference it. Just change this line:
$('#myDivId').append("<div>UI widget</div>");
to:
$(centerControlDiv).append("<div>UI widget</div>");
Put another way, to answer your question "How to know parent div with id 'myDivId' is created?", that div already is created - you created it in the document.createElement('div') call. It just isn't a child of document yet.
So when you use $('#myDivId'), or similar calls like document.getElementById('myDivId'), those calls can't see it. It's just a standalone element that you have a reference to, so you can access it through that element instead of looking it up in the document DOM.
Update based on your latest code:
To apply this principle to your uiWidget class, you can have the class work with the actual div element you created instead of accessing it by ID. Even better, since you're using jQuery, pass it a jQuery object from the beginning, like this:
var uiWidget = new UiWidget( $(centerControlDiv) );
class UiWidget {
constructor($div) {
this.$div = $div;
this.$div.click($.proxy(this.event_click, this));
}
// ...
}
As you can see, the code no longer requires the div ID at all, and it doesn't need the get $div() either. $div and this.$div are already a jQuery object wrapping your centerControlDiv.
I also changed the name of the class to UiWidget to follow recommended JavaScript style and avoid conflict with the uiWidget variable that holds an instance of the class.
How to trigger multiple mouse-click events on arbitrarily many HTML elements covering each other?
I know you can use pointer-events: none; to let your click pass through your elements, but what if I want to trigger the mouse-click event on an element AND the mouse-click event on arbitrarily many other elements beneath it?
but what if I want to trigger the mouse-click event on an element AND the mouse-click event on arbitrarily many other elements beneath it?
Events bubble. Which means and event fired on an inner element, will also be received by the parent elements until the top most parent.
<div id="topmost">
<div id="second">
<p id="firstp"></p>
</div>
</div>
Assume you are using jquery. Below is how you would listen to click events from all elements below div.id="topmost".
Since the normal flow of events is for any click event (could be any other type of event) that is fired by any element with in the topmost div element will be bubbled to the outermost element, I only list to topmost click event and then check which element fired that event by checking the id of the target element. e.target will be the actual element that the click was performed on. You can either switch target.attr('id') or run it through if else conditions.
$(function () {
$("#topmost").on("click", function (e) {
e.preventDefault();
var target = $(e.target);
if(target.attr('id') === "idOfElement"){
// code to handle the event
}else{
});
A solution could be to track mouse move using :
$( document ).mousemove();
Store coordinates to a global variable then check its position when your element is clicked. That would give something like :
var mousePos = [0,0];
$( document ).mousemove(function( event ) {
mousePos[0] = event.pageX
mousePos[1] = event.pageY
});
$("#target").click(function(){
// Compare mouse coordinates and your items ones using offset, height and width
if(mousePos[0] > $('#target2').offset.left){
// Do whatever you are willing to do
}
});
I'm working on a project for my UI design class and need help fixing an element to the top of a page on scroll.
Here's what I have so far: http://ieatthings.com/opinio/query.html
As you scroll, the search bar should move up, over the navbar, and fit nicely into place to let the user search while in the middle of a page. But the problem is that the search bar keeps going up!
I used the Javascript from this tutorial: Fix object to top of browser window when scrolling. I have tried all kinds of possibilities and combinations, but have unfortunately not gotten this damn thing to work.
Any suggestions?
You will have to use Javascript to test the position of your element ("myElement") on the page compared to how far the page has been scrolled. If the page has been scrolled up beyond your element then you alter your element's css to snap it to the top of the page. Note: mobile browsers don't like the "position: fixed;" style property.
Give your element the id of "myElement" and insert this into your tag.
<script type="text/javascript">
var yPosition; // save original y position of element here
window.onload = function(){ // once entire page is loaded this function is fired
// save original y position of element before it is scrolled
yPosition = document.getElementById("myElement").offsetTop;
}
window.onscroll = function(){ // scrolling fires this function
var myElement = document.getElementById("myElement"); // for cleaner code
// compare original y position of element to y position of page
if( yPosition <= window.pageYOffset ){
// snap element to the top by changing css values of element
myElement.style.position = "fixed";
myElement.style.top = "0px";
}else{
// re-position to original flow of content
myElement.style.position = "relative";
myElement.style.top = ""; // set to default
}
}
</script>
Hopefully this helps!
I have a toggle event on specific div witch works fine ,
here is the demo
http://jsfiddle.net/b5SVg/9/
the trouble is that I have the outside container that I need to hide on load and show/hide on toggle. CUrrently my container display block fires first and I need it to be sinced wht the toggle. I know you might think that i should put the container inside the toggle but i cant since the FX.slide adds div around toggle element which is overflow hidden and has position . my container must stay where it is. Please advise
Read the comments on the code below ;)
var container = $$('.container').setStyle('display','none'); //cache container (useful for the 'future' ;) )"
var mySlide= new Fx.Slide('hidden').hide();
$('toggle').addEvent('click', function(event){
event.stop();
container.setStyle('display','block'); //put it before the toggle
mySlide.toggle().chain(function(){ //at the end of the sliding, this callback will be called
if(!this.open){ //if it's closed
container.setStyle('display', 'none'); //hide the container
}
});
});
Demo: http://jsfiddle.net/amgyw/1/
..btw you also can use the element proper instance of 'slide', without declaring var mySlide = ... ..like i.e. $('hidden').get('slide').toggle()
Is there a way to make a display object always be at the top of the display list?
For example, I know you can set the childIndex, i.e:
setChildIndex(myDisplayObject, numChildren-1);
But is there a way that an object has sensed that something else has been added to the display list and restack themselves accordingly?
You can listen to the Event.ADDED event on the container. This event will bubble up, so you'll get called whenever a display object is added to the container or any of its children.
Here's an example of how you could do this. You'll see the black box always stays on top.
var container:DisplayObjectContainer = this; // this is a frame script but just change this line as necessary
container.addEventListener(Event.ADDED,handleAdded,true);
function handleAdded(e:Event):void {
// this if tries to cover some edge cases, unlikely to happen in your code, from your description
if(container == topElement.parent && container.numChildren > 0 && container.getChildIndex(topElement) != container.numChildren - 1) {
container.setChildIndex(topElement,numChildren - 1);
}
}
function getSprite(c:uint):Sprite {
var sp:Sprite = new Sprite();
sp.graphics.beginFill(c);
sp.graphics.drawRect(0,0,100,100);
sp.graphics.endFill();
return sp;
}
var topElement:Sprite = getSprite(0);
container.addChild(topElement);
var sp:Sprite = getSprite(0xff0000);
container.addChild(sp);
sp.addChild(getSprite(0xff00));
var sp2:Sprite = getSprite(0xff);
container.addChild(sp2);
However, I think it's much simpler and cleaner just to have 2 containers, say, top and bottom, kind of like layers. In top you'd add the element that always must be on top (or this could be your element as you probably don't need to have this extra container). In bottom you'd add and remove whatever you want. Then you can forget about manually restacking stuff (at least to keep the top element atop).
You can override the addChild() method in the parent object. In that method you can move your child to the top using
setChildIndex(myDisplayObject, numChildren-1);
In this way everytime an object is added to the parent, the parent moves your object to the top.