Long-time lurker here. This is my first post (and I'm an electrical engineer, not a programmer).
I would like to have an element in HTML for which I can detect a click on its upper-half and its lower-half. Specifically, suppose I have a large numeric digit, and if you click above its "waist" it increments, and if you click below its waist it decrements. I then need to put several of these next to one another, like a "split-flap display" at a train station.
I already have all the javascript working for increment-only, but I want to make it easier to decrement instead of having to wrap all the way around with many clicks. I have so far avoided using jquery, so if you can think of an HTML-only way to do this I would love to hear about it.
I realize I will probably have to wrap two smaller containers (an upper and a lower one) into a larger container, but how do I get the text to cover the height of both internal containers? I probably want to avoid cutting a font in half and updating upper and lower separately.
Thanks,
Paul
This should work:
element.addEventListener('click',function(e){
//here's the bounding rect
var bound=element.getBoundingClientRect();
var height=bound.height;
var mid=bound.bottom-(height/2);
//if we're above the middle increment, below decrement
if(e.clientY<mid)
;//we're above the middle, so put some code here that increments
else
;//we're below the middle, so put some code here that decrements
},false);
element is the element that you wish to apply this effect on
Related
I need to make four rectangles and an arrow at the center that points toward the rectange that is hovered. See https://jsfiddle.net/Lvmf67rm/1/
$(document).ready(function(){
$('.quarter:nth-child(1)').mouseenter(function(){
$('.pointer').css('transform','rotate(-45deg)');
});
$('.quarter:nth-child(2)').mouseenter(function(){
$('.pointer').css('transform','rotate(45deg)');
});
$('.quarter:nth-child(3)').mouseenter(function(){
$('.pointer').css('transform','rotate(-135deg)');
});
$('.quarter:nth-child(4)').mouseenter(function(){
$('.pointer').css('transform','rotate(135deg)');
});
});
There are two issues with what I've made:
If there would be an element before or somewhere in-between the rectangle divs - the arrow would point in the wrong direction (this is because "nth-child()" selects the children regardless of class)
When hovering between 3rd and the 4th rectangles the arrow doesn't go straight to the next block but goes through the first and second first (quite obvious why this happens).
But how to make it right? I'm quite a noob with javascript so this is the best I could do and I ask for your guidance.
P.S. Sorry if I didn't explain it very good, english is not my native.
P.P.S. Sorry, I forgot to mention I can't edit HTML.
Regarding adding elements before or somewhere in-between the rectangle divs, here are some possible solutions:
Best option: Just don't do it. Add other elements outside the container and use CSS positioning to position.
Use :nth-of-type instead of :nth-child
Instead of :nth-child use classes q1, q2...
Regarding arrow direction: See how using -225deg in q4 changes the behaviour:
$('.quarter:nth-child(4)').mouseenter(function(){
console.log($('.pointer').css('transform')); // get prev value
$('.pointer').css('transform','rotate(-225deg)'); // instead of 135deg
});
You can check the previous value to change the degrees dynamically, selecting the best option of the 2 candidates (where the absolute value of previous degrees - new degrees is minimal, adding or subtracting 360 degrees).
So I have a "cursor" object created like so:
var cursor=document.createElement('span');
cursor.id="currentCursor";
cursor.innerHTML="|";
cursor.style.fontWeight="bold";
cursor.style.position = 'absolute';
cursor.style.marginLeft="-1px";
Then I add it to the page where someone clicks with this:
var selection = window.getSelection();
var currentRange = selection.getRangeAt(0);
currentRange.insertNode(cursor);
The problem I'm running into is in certain places (mainly end of lines) if the cursor object is added it creates a line break before the object. Using insertNode to move it to another area removes the line break. Also if I set the display to "none", wait for a few seconds and then set it back to "inline" the line break is removed.
This seems like maybe a browser bug in adding absolute elements, but I was wondering if someone had a workaround. I've tried setting the width to 0px but it has no effect.
Update
So if I change the cursor to
cursor.style.position = 'static';
It doesn't have random line breaks. However this causes space to be created around the element. Any way to not allow elements to create space around them?
Update 2
Added a fiddle to show the problem:
http://jsfiddle.net/Mctittles/pSg2D/1/
Original code is a bit large but I slimmed it down to highlight this problem.
If you click at the end of the smiley face and then type it causes line 33 to trigger creating a new text node. After typing a couple letters you'll see the cursor object is forced to the next line. Clicking somewhere else to move it makes the lines merge again.
If you un-comment lines 38 and 40 you'll see what I was talking about with making it initially display:none and changing it later. This time it doesn't cause a line break.
I took out some cross-browser code for fiddler, so this might only work in Chrome
However [position:static] causes space to be created around the element.
No, it doesn’t cause it – there is no actual space created “around it”, it’s just the display width of a character plus spacing in the used font, and that gives the span element itself a width that is more than the | character itself. But when you position the element absolutely, you don’t notice that, because it is taken out of the flow, so it doesn’t push the following characters to the right.
My workaround proposal: Don’t put | into the span as innerHTML, but leave it empty – and then implement the line by giving the element a border-left:1px solid. Remove position:absolute, so that it defaults to static.
Then you might probably not like the height your cursor is getting with that – but that can be fixed as well, by setting display to inline-block, and giving it a height as well.
Here, see how you like ’dem apples: http://jsfiddle.net/pSg2D/9/
You should use CSS instead. Using z-index and maybe even float would (atleast should) fix this.
Edit: Always make sure no other styles make it break line!
This is as simple as I can get.
I will have several spans randomly positioned on the screen through something like:
$(".hidden:first").css('-webkit-transform','rotate('+((0.5-Math.random())*40)+'deg)');
$(".hidden:first").animate({
left: '+=' + (((screen.width-800-224)/2) + Math.random()*800),
top: '+=' + (50+Math.random()*600)
} [...]
and later on I would like to iterate through every char of every of those elements (that are randomly position and have random rotation), and I would need to discover the (x,y) position of every character on the screen so I can colorize it, forming certain draws according to certain functions.
Is this easily achievable? Remembering that I want the (x,y) position of each -character- of a span, not (x,y) of the span itself. I am really inexperienced at javascript.
EDIT: Answering my own question:
I currently managed to do what I needed by wrapping every single letter inside a <span> and later accessing its .offset().left and .offset().top through jquery. Is it that bad? :P
Thanks.
Fernando.
Something like this might get you started http://jsfiddle.net/QgRWk/
I need some help...
How should I do the markup of a layout with two images and a block of text divided in 2 columns with different width, where the 2nd column starts lower than the first one because of one of those images? Here is a sketch of my layout:
I hope I described my problem explicitly enough.
P.S.: Is it possible actually?
CSS3 has a solution, but it is not standard yet and won't work in older browsers here is a link http://www.css3.info/preview/multi-column-layout/.
Possibly the best idea is to use javascript somehow. Put all the text in the first column and test the height then move portions of the text over to the next column until you have equal columns or until the first column is at a desired height.
Another method is to have predefined proportions eg(2/3 in the first column and 1/3 in the second). Then split the text based on the proportions using character count. This won't be exact and you could use a method similar to the one above to find exact width based on overflow properties, but the characters should average out to be the correct length.
This method is pretty simple and would look like
var txt='Column text...';
var len=txt.length;
var chars=Math.floor(len*.67);
//Assuming you want 2/3 of the text in the first column
document.getElementById('col1').innerHTML=txt.substring(0,chars);
document.getElementById('col2').innerHTML=txt.substring(chars);
//Notice that this could split in the middle of a word so you would need to do
//some checking for the nearest space and the change the break to there.
//Also you could then use the previous method to adjust it if you want something really accurate
I'm looking to build a page that has no scrolling, and will recognize where the main div's contents overflow. The code will remember that point and construct a separate page that starts at that word or element.
I've spent a few hours fiddling, and here's the approaches that past questions employ:
1. Clone the div, incrementally strip words out until the clone's height/width becomes less than the original's.
Too slow. I suppose I could speed it up by exponentially stripping words and then slowly filling it back up--running past the target then backtracking slowly till I hit it exactly--but the approach itself seems kind of brute force.
2. Do the math on the div's dimensions, calculate out how many ems will fit horizontally and vertically.
Would be good if all contents were uniform text, ala a book, but I'm expecting to deal with headlines and images and whatnot, which throws a monkey wrench in this one. Also complicated by browsers' different default font preferences (100%? 144%?)
3. Render items as tokens, stop when the element in question (i.e. one character) is no longer visible to the user onscreen.
This would be my preferred approach, since it'd just involve some sort of isVisible() check on rendered elements. I don't know if it's consistent with how browsers opt to render, though.
Any recommendations on how this might get done? Or are browsers designed to render the whole page length before deciding whether a scrollbar is needed?
Instead of cloning the div, you could just have an overflow:hidden div and set div.scrollTop += div.height each time you need to advance a 'page'. (Even though the browser will show no scrollbar, you can still programmatically cause the div to scroll.)
This way, you let the browser handle what it's designed to do (flow of content).
Here's a snippet that will automatically advance through the pages: (demo)
var div = $('#pages'), h = div.height(), len = div[0].scrollHeight, p = $('#p');
setInterval(function() {
var top = div[0].scrollTop += h;
if (top >= len) top = div[0].scrollTop = 0;
p.text(Math.floor(top/h)+1 + '/' + Math.ceil(len/h)); // Show 'page' number
}, 1000);
You could also do some fiddling to make sure that a 'page' does not start in the middle of a block-level element if you don't want (for example) headlines sliced in half. Unfortunately, it will be much harder (perhaps impossible) to ensure that a line of text isn't sliced in half.