Center text in link which is as block - html

Ill start with showing you my problem in an image:
So i want to make a design for slider, now i want to make buttons for next and previous.
yellow things in image are links with display: block. What do i need to do, to make text ( those arrows are unicode characters ) be positioned vertically and horizontally? Considering i still want whole yellow thing be clickable as a link.
here is how yellow thing looks in css
a.prev {
width: 40px;
height: 270px;
display:block;
float:left;
background: yellow;
-webkit-border-top-left-radius: 5px;
-webkit-border-bottom-left-radius: 55px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-bottomleft: 55px;
border-top-left-radius: 5px;
border-bottom-left-radius: 45px;
}

Since you have a fixed height you can use a top margin to push your arrows down to the vertical center.
text-align:center should center your arrow horizontally.
Set line-height equal to the height of the element to center vertically.

I know an answer was accepted already, but I am just giving an alternative and a method that should work on dynamic heights.
I was not sure whether the arrows were merely inside an a ← or inside a span <span>←</span>. When they are not inside a span, it should be added with jQuery.
Static width and height: FIDDLE.
// Add span-wrappers around controls
$("a.controls").each(function() {
$(this.firstChild).wrap("<span></span>");
});
// Position arrows vertically
$("a.controls > span").css("top", function() {
var thisH = $(this).height(),
parentH = $(this).parent().height(),
thisTop = (parentH/2) - (thisH/2);
return thisTop;
});
Now, when you are using a dynamic/fluid lay-out this will not work well because the top-value is only calculated once. We need to recalculate the value every time the window is resized. Take a look here.
// Keep aspect ratio of div
function slideHeight() {
$("#slide-container").height(function() {
var $this = $(this),
w = $this.width() / 2.133;
return w;
});
}
slideHeight();
// Add span-wrappers around controls
$("a.controls").each(function() {
$(this.firstChild).wrap("<span></span>");
});
// Position arrows vertically
function arrowPos() {
$("a.controls > span").css("top", function() {
var thisH = $(this).height(),
parentH = $(this).parent().height(),
thisTop = (parentH / 2) - (thisH / 2);
return thisTop;
});
}
arrowPos();
//Execute functions on resize
$(window).resize(function() {
slideHeight();
arrowPos();
});​
​There you go. :)

Related

Dynamic HTML <select> height [duplicate]

This question already has answers here:
Adjust a div's height/width by dragging its left/top border without jQuery draggable?
(2 answers)
Closed 7 years ago.
Is it possible to make <select>'s height adjustable by the user? Simply by dragging the bottom of the expanded list.
Cross browser, you can't drag native drop-down boxes, but here is one suggestion how one can do.
Edit: But when the size property is set (size="2") you can, kind of. By elaborating with the option height and the amount of item, you might achieve something useful.
The select has a invisible area outside its bottom which make it resizeable. You can also click inside the select and resize, though the list drops down every second time.
Resources:
Adjust a div's height/width by dragging its left/top border without jQuery draggable?
jQuery draggable option elements
$(document).ready(function(){
$('#drag').on('mousedown', function(e){
var $dragable = $(this),
start = $dragable.height(),
pY = e.pageY;
$(document).on('mouseup', function(e){
$(document).off('mouseup').off('mousemove');
});
$(document).on('mousemove', function(me){
var my = (me.pageY - pY);
$dragable.css({
height: start + my,
});
});
});
$('#drag2').on('mousedown', function(e){
var $dragable = $(this),
start = $dragable.height(),
pY = e.pageY;
$(document).on('mouseup', function(e){
$(document).off('mouseup').off('mousemove');
});
$(document).on('mousemove', function(me){
var my = (me.pageY - pY);
$dragable.css({
height: start + my,
});
});
});
});
body {
margin: 30px;
}
div{
position: relative;
display: inline-block;
cursor: row-resize;
height: 30px;
padding-bottom: 10px;
}
select{
position: relative;
height: 100%;
vertical-align: top;
}
option {
padding: 5px 15px;
height: 25%; /* sizable when size property is set to more than 1 */
}
#drag2 {
margin-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<div id="drag">
<select>
<option>nr1</option>
<option>nr2</option>
<option>nr3</option>
<option>nr4</option>
</select>
</div>
<div id="drag2">
<select size="2">
<option>nr1</option>
<option>nr2</option>
<option>nr3</option>
<option>nr4</option>
</select>
</div>
</div>
Many textarea resizer js pluggins should work with select too...

How to make a fixed floating button to stop at footer in angularjs

I would like to create a button using that floats until footer and then stops
1) Button should be poisition: fixed; bottom: 0px when footer is not visible
2) When footer becomes visible, button should just sit on top of footer
The button should handle following cases.
when states change in angular, when we get data from server the footer is visible for a moment and then the page expands, what will happen then?
when the page has less content and footer is visible, button should sit on top of footer.
How can i do this?
Here is the plunker i started to play around with
http://plnkr.co/edit/SoCBjkUjFICiuTeTPxDB?p=preview
I came across this post when searching for a similar solution. Without a ready answer, this is what I ended up doing, based on this post https://ngmilk.rocks/2015/04/09/angularjs-sticky-navigation-directive/ .
Basicly you need a $scope.$watch to watch for scope change, and an event handler attached to the onscroll event.
angular.module('myApp')
.directive('stickyBottom', function($window) {
return {
restrict: 'A',
scope: {},
link: function (scope, elem, attrs) {
// the element box saved for later reference
var elemRect;
// element height
var height = elem[0].clientHeight;
// element top, will be changed as scope is updated
var top = 0;
// updates element's original position
scope.$watch(function(){
elemRect = elem[0].getBoundingClientRect();
return elemRect.top + $window.pageYOffset;
}, function(newVal, oldVal){
// this is the original element position, save it
if(!elem.hasClass('fixed-bottom')){
top = newVal;
}
// properly position the element even in `fixed` display
elem.css('width', elemRect.width);
elem.css('left', elemRect.left);
// check position
toggleClass();
});
// toggle `fixed-bottom` class based on element's position
var toggleClass = function() {
// the element is hidden
if (elem[0].getBoundingClientRect().top + height > $window.innerHeight) {
elem.addClass('fixed-bottom');
}
// the element is visible
else {
// the element is visible in its original position
if (top - $window.pageYOffset + height < $window.innerHeight && elem.hasClass('fixed-bottom')) {
elem.removeClass('fixed-bottom');
}
}
}
// bind to `onscroll` event
$window.onscroll = function() {
toggleClass();
};
}
};
})
;
And here's some css:
.fixed-bottom {
position: fixed;
top: auto;
bottom: 0;
}
You can accomplish this affect without using angular at all by modifying your style.css. The simplest solution in this case is just to set the bottom parameter of the #to-top element to be at minimum higher than the footer, for example:
#to-top {
position:fixed;
bottom: 60px;
right: 10px;
width: 100px;
padding: 5px;
border: 1px solid #ccc;
background: red;
color: white;
font-weight: bold;
text-align: center;
cursor: pointer;
}

How can I hide the extra list items that don't fit within a fixed-height box?

I have boxes that contain <ul> list content. These boxes have a slightly variable width but have a fixed height. This list content is dynamically generated containing anywhere from 0 - 200 list elements. However, because of the box height, I usually can display only 3-5 at a time. This is OK.
However, I have been artificially restricting those lists by using ASP.NET MVC code to only display the first 4 elements. This works in about 90% of cases - some boxes will still have overflow if all of the list items have a lot of text (see below).
I was wondering if there was a way in CSS to use like the overflow property or something and hide the list elements that don't fit? I have tried overflow: hidden on the <ul> to no avail. I imagine this is because the list doesn't know the height of the box that is is in or something
Clarification: Ideally, you wouldn't see any part of the <li> that doesn't fit. See this fiddle
I don't know how long any of these items will be ahead of time or how many elements their might even be, and the width/height of the box are not modifiable. Any ideas?
Original Fiddle: http://jsfiddle.net/emowbngx/1/
Example of Box HTML:
<div class="box">
<ul>
<li>List item</li>
<li>these LI's are dynamically generated</li>
<li>I have no idea of their length ahead of time</li>
<li>Seth Rollins</li>
</ul>
</div>
Box CSS:
.box {
height: 110px;
width: 350px;
min-width: 350px;
float: left;
margin: 8px 16px 8px 0;
position: relative;
border: 1px solid black;
}
I may have found a way to do this using a pure CSS solution. It involves using flexbox and a bit of cheating to show the bullet using a :before pseudo element.
It even allows centering visible li elements vertically inside the container.
fiddle: https://jsfiddle.net/aq34sb17/2/
CSS
ul {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100px;
max-width: 180px;
overflow: hidden;
padding-left: 15px;
justify-content: space-around;
}
li {
display: block;
width: 100%;
padding-left: 10px;
position: relative;
}
li:before {
content: '\2022';
position: absolute;
left: -5px;
}
and here's the solution applied to your fiddle: http://jsfiddle.net/emowbngx/7/
Here's my solution :
http://jsfiddle.net/gc5un34j/3/
Using element.offsetHeight to get the height of each element of your list and then comparing it to the container;
JQuery:
var listItems = $('ul li'); //The list rows
var listContainer = $('ul'); //The list
var listHeight = 0; //Contains the height of the 4 elements together
for(var i = 0; i < listItems.length; i++) {
listHeight += listItems[i].offsetHeight;
//If the row is bigger than the container, hides it, [0] to access the DOM Element
if(listContainer[0].offsetHeight < listHeight) {
$(listItems[i]).hide();
}
}
Pure JS in browsers supporting QuerySelectors:
var listItems = document.querySelectorAll('ul li'); //The list rows
var listContainer = document.querySelector('ul'); //The list
var listHeight = 0; //Contains the height of the 4 elements together
for(var i = 0; i < listItems.length; i++) {
listHeight += listItems[i].offsetHeight;
//If the row is bigger than the container, hides it
if(listContainer.offsetHeight < listHeight) {
listItems[i].style.display = 'none';
}
}
Tested in Chrome 44 and Firefox
This will not remove (always!) last child, but, maybe it could be solution (even nicer, imho):
http://jsfiddle.net/emowbngx/6/
$('.box').each(function(i) {
if ($(this).children().height() > $(this).height())
{
//$(this).find('li:last-child').css('display','none');
$(this).find('li').each(function(j) {
if ($(this).position().top + $(this).height() > $('.box').height()) {
$(this).css('display', 'none');
}
});
}
});
Note: didn't test it too long, try to change text in li's, and see by your self...

Absolute div overlay iframe borders?

I'm wondering if there is a way to have a div, absolutely positioned, hover over the border of the iframe that div is in. Can this be done?
My case:
I have an iframe with a list of files in it, on the right end of each file there is a button. I want to have a div-popup with some functions like a contextmenu. But because this button is at the edge of the iframe the absolutely positioned div is put behind/outside the iframe viewport. I want it to overlay in the rest of my document, outside the iframe.
​<iframe width="100" height="100">
div would be in here, say 300 x 100 px.
</iframe>
overlayed div should be visible here as well, basically the div should overlay the iframe.​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
Well, technically you can't do that. However, if you hijack the events in the iframe, you can recreate the context menu in the main window and use the relative position of the div within the iframe + the absolute position of the iframe itself.
So, to sum up, the context menu can be outside the iframe, and manipulated by the events from within the iframe.
Let me show you how it can be done. I don't have your code, so I'm just making a very crude proof of concept. :)
Example | Code
HTML
<iframe id='my_frame'></iframe>
<div id='copy_to_frame'>
<ul id='files_list'>
<li>data.dat</li>
<li>manual.html</li>
<li>readme.txt</li>
<li>model1.obj</li>
<li>human_model.obj</li>
</ul>
</div>
<div class='context_menu'>
<ul>
<li>Delete</li><li>Open</li><li>Move</li><li>Copy</li>
</ul>
</div>
Javascript
//Declare the necessary variables, good practice
var frame = $("#my_frame"),
frame_contents = frame.contents(),
frame_body = frame_contents .find("body"),
copy_list = $("#copy_to_frame"),
context_menu = $(".context_menu");
var bInside = false;
//Fill the iframe with a list
frame_body.html(copy_list.html());
copy_list.hide();
paint();
//Attach event handler for context menu popup etc.
$("#files_list li", frame_body).click(function(e){
var $this = $(this);
var rel_x = $this.position().left + $this.outerWidth() + 5,
rel_y = $this.position().top + $this.outerHeight()/2 - context_menu.outerHeight()/2 - frame_body.scrollTop(),
abs_x = frame.offset().left,
abs_y = frame.offset().top;
e.stopPropagation();
context_menu.css({
top: rel_y + abs_y,
left: rel_x + abs_x
});
//Show the context menu in this window
context_menu.show();
paint($this);
});
//Hide when clicking outside the context menu
$(document).add(frame_body).click(function(){
if(!bInside){
context_menu.hide();
paint();
}
});
//Determine if mouse is inside context menu
context_menu.mouseenter(function(){
bInside = true;
}).mouseleave(function(){
bInside = false;
});
function paint(el){
$("#files_list li", frame_body).css({
"background-color": "white",
"border": "1px solid transparent"
});
if(el){
el.css({
"background-color": "#ddecfd",
"border": "1px solid #7da2ce"
});
}
}
CSS
#my_frame{
position: absolute;
border: 1px solid gray;
width: 200px;
height: 100px;
top: 50%; left: 50%;
margin-top: -62.5px;
margin-left: -100px;
z-index: 1;
}
.context_menu{
display: none;
position: absolute;
top: 0;
left: 0;
background-color: white;
z-index: 2;
}
.context_menu ul{
border: 1px solid black;
border-right: 0;
display: inline-block;
}
.context_menu li{
display: inline-block;
border-right: 1px solid black;
padding: 2px;
text-align: center;
margin: 0px;
cursor: default;
}
.context_menu li:hover{
background-color: lightgray;
}
This is a bit of a guess based on the minimal information that was provided, but...
You can manipulate the contents of an <iframe> from within the parent document using jQuery, like so:
$('#myFrame').contents().find('a').click(function() { /*...*/ });
This allows you to detect when the user has clicked inside the <iframe>. Then you can work out where to position your overlay <div>.
Your overlay <div> will need to have position: fixed set. You can use jQuery's .offset() method to get the coordinates of the <iframe> and the link that was clicked inside the <iframe>. You can use these two values to calculate where to position the overlay <div> in the parent document. For example, to position the overlay to the left of the <iframe> and on the same vertical level as the link that was clicked you can do this:
$('#overlayDiv')
.offset({
left: $('#myFrame').offset().left - $('#overlayDiv').width(),
top: $('#myFrame').offset().top + $(this).offset().top
})
See this fiddle for a basic example of how it could work: http://jsfiddle.net/Gxd3M/2/
(Note that this assumes that the contents of the parent document and the iframe both come from the same server, i.e. they have the same origin.)

Div smart width

see fiddle
html
<div class="e" style="left:5px;top:5px;">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbb</div>
<div class="e" style="left:5px;top:100px;">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>​
css
.e {
font-size: 10px;
font-family: arial;
background-color: yellow;
position: absolute;
max-width: 300px;
}
you will notice the 2nd div fits the size of the content exactly, but on the first div there's a bunch of empty space to the right of the a's and b's. This is because the div hit its max width of 300px and then wrapped the b's to a 2nd line. The wrapping is good, but then I would expect the div to then shrink back down to the width of the a's so that there's no empty space to the right.
Is it possible to get it to do this?
Tested in Chrome and FF.
​
you may avoid handling the width, as my understanding is that you're looking for a way to break the text in a satisfying manner.
use word-break: break-all, to wrap the text whenever it hits the container's edge.
Example:
demo on jsFiddle
Reference:
the CSS3 word-break property on Mozilla Developer Network
To shrink a div (or any element) to the size of its text content, you can use JavaScript to get a range that contains its contents and get the size of the range using range.getBoundingClientRect():
function sizeElementToContents(el) {
var range = document.createRange();
range.selectNodeContents(el);
var textRect = range.getBoundingClientRect();
el.style.width = textRect.width + "px";
}
But, of course, that only works with Modern browsers. IE8 and IE7 have different methods for working with ranges. Actually, IE7 automatically handles max-width the way you want it to, but when our IE8 code is run to re-size the divs on IE7, it shrinks the divs to 0. To avoid writing code for specific browser versions, this code runs on IE7 and IE8, but includes a little extra logic so that it works on both browser versions:
function sizeElementToContents(el) {
var range, width;
if (document.createRange) {
range = document.createRange();
range.selectNodeContents(el);
width = range.getBoundingClientRect().width;
}
else {
range = document.body.createTextRange();
range.moveToElementText(el);
range.moveStart("character", 1);
width = range.boundingWidth;
var height = range.boundingHeight;
range.collapse();
range.moveEnd("character", 1);
if (range.boundingHeight == height) {
return; // text doesn't wrap, so don't resize
}
}
el.style.width = width + "px";
}
Working demo: http://jsfiddle.net/gilly3/HZRFb/
Forking from Biziclop's solution:
.e {
font-size: 10px;
font-family: arial;
background-color: yellow;
position: absolute;
max-width: 300px;
margin-right:100%;
}
Link to the Fiddle.
Don't ask me why it works, it might break tomorrow, but adding some extreme margin-right seems to solve the problem:
.e {
margin-right: 9999px;
}
See http://jsfiddle.net/2cTga/1/