Append a class to an editable div when it changes its height - javascript

I have editable div with overflow set to hidden, I'd like the div to expand as the user types (if needed). II'm using jquery to change the class of the div each time the height changes.
I cant seem to get to work at all, it chnages the class but nothing happens
Fiddle
HTML:
<div class="contanier">
<div class="1" id="msgWriteArea" contenteditable="true"></div>
</div>
CSS:
#msgWriteArea{
outline: 0;
border: none;
resize: none;
width: 100%;
height:20px;
line-height:20px;
font-size:18px;
border:solid 1px #000;
background:#FFF;
}
.contanier .1{
height:20px;
overflow:hidden;
}
.contanier .2{
height:40px;
overflow:hidden;
}
.contanier .3{
height:60px;
overflow:hidden;
}
.contanier .4{
height:80px;
overflow:hidden;
}
.contanier .5{
height:80px;
overflow-y:scroll;
}
Javascript:
var chatBoxSize = {
oldHeight : 0,
scrollHeight : 0,
lastClass : 1,
maxClass : 5
};
function updateChatSize() {
var id = '#msgWriteArea';
var element = document.querySelector(id);
if((element.offsetHeight < element.scrollHeight) || (element.offsetWidth < element.scrollWidth)){
if(chatBoxSize.lastClass == null){
//add size 1
console.log('ADD SIZE 1');
$(id).addClass('1');
chatBoxSize.lastClass = '1';
} else if(chatBoxSize.oldHeight != $(id)[0].scrollHeight){
//get the correct size to add
if(parseInt(current) >= parseInt(chatBoxSize.maxClass)){
var current = chatBoxSize.maxClass,
last = parseInt(chatBoxSize.maxClass) - 1;
chatBoxSize.lastClass = current;
console.log('IS AT MAX SIZE');
} else if(chatBoxSize.scrollHeight < $(id)[0].scrollHeight){
var current = parseInt(chatBoxSize.lastClass) + 1,
last = parseInt(chatBoxSize.lastClass);
chatBoxSize.lastClass = current;
} else if(chatBoxSize.scrollHeight > $(id)[0].scrollHeight) {
var current = parseInt(chatBoxSize.lastClass) - 1,
last = parseInt(chatBoxSize.lastClass);
chatBoxSize.lastClass = current;
} else {
//console.log('No Change in height');
}
if(last != undefined){
console.log('Add', current, 'Remove', last);
$('#msgWriteArea').addClass(current + "");
$('#msgWriteArea').removeClass(last + "");
$('#display').val('Add ' + current + ' Remove' + last);
}
}
chatBoxSize.oldHeight = element.offsetHeight;
chatBoxSize.scrollHeight = $(id)[0].scrollHeight;
chatBoxSize.oldHeight = element.offsetHeight;
}
};
$(function (){
$('#msgWriteArea').bind('change keydown input', function () {
if(event.type == 'keydown'){
updateChatSize();
}
});
});
This is part of a larger page. So would need to the class to change on other elements but just one for now to get the hang of how this works

You can do it by adding this CSS:
#msgWriteArea{
height: auto !important;
max-height: 80px; // Max Chat Box Size..
overflow-y: scroll;
}
See JsFiddle

if you set a fix height to contenteditable this won't expand vertically,
so to begin with remove height attribute;
then using line-height attribute instead of el.offsetHeight (in the evaluation for adding a class depending on height) should fix your fiddle;
fiddle

Related

How to add active class while scrolling in div?

Could you please tell me how to add an active class while scrolling in a div? I have one container, in which there are four divs. In the footer I also have four li (first, second, third). I want to select the li when the user scrolls the div.
Example
When the code runs, the first li should be selected because the first div is in the view port. If the user scrolls and moves to the second div, the second li should be selected. And so on.
I tried like that
https://jsbin.com/giwizufotu/edit?html,css,js,output
(function(){
'use strict';
$(function(){
$( "#container" ).scroll(function() {
console.log('scrlling');
if (elementInViewport2($('#first'))) {
// The element is visible, do something
console.log('first visible')
} else {
console.log('second visible')
}
});
})
function elementInViewport2(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}
})()
I don't want to use plugin
I have tried to use almost all the code you have written with little modifications:
Here is the working example link: https://jsfiddle.net/almamun1996/21wc37sx/3/
CSS:
.item {
width:25%;
display:inline-block;
margin:0;
padding:0;
color:blue;
font-size:20px;
text-align: center;
}
.footer{
border:1px solid;
position:fixed;
width:100%;
bottom:0px;
}
#container {
border:1px solid red;
overflow:auto;
width:100%;
height:300px;
}
.fC{
background-color:yellow;
padding:0;
}
#first{
background-color:blue;
}
#second {
background-color:green;
}
#third {
background-color:pink;
}
#fourth {
background-color:red;
}
.active {
background-color : red;
}
JS:
(function(){
'use strict';
$(function(){
$('.fC li:eq(0)').css('background-color','red').css('color','#ffffff');
$( "#container" ).scroll(function() {
//console.log('scrlling');
if (elementInViewport($('#first'))) {
// The element is visible, do something
//console.log('first visible')
} else {
//console.log('second visible')
}
});
});
function elementInViewport(e) {
var winBottom = $(window).scrollTop() + $(window).height();
var visibleETop = e.offset().top - winBottom;
var first = parseInt($('#first').css('height'));
var second = parseInt($('#second').css('height'));
var third = parseInt($('#third').css('height'));
var fourth = parseInt($('#fourth').css('height'));
if(Math.abs(e.offset().top) > first - parseInt($('#container').css('height')) && Math.abs(e.offset().top) <= first+second - parseInt($('#container').css('height')))
{
$('.fC li:eq(0)').css('background-color','').css('color','');
$('.fC li:eq(2)').css('background-color','').css('color','');
$('.fC li:eq(3)').css('background-color','').css('color','');
$('.fC li:eq(1)').css('background-color','red').css('color','#ffffff');
}
else if(Math.abs(e.offset().top) > first+second - parseInt($('#container').css('height')) && Math.abs(e.offset().top) <= first+second+third - parseInt($('#container').css('height')))
{
$('.fC li:eq(0)').css('background-color','').css('color','');
$('.fC li:eq(1)').css('background-color','').css('color','');
$('.fC li:eq(3)').css('background-color','').css('color','');
$('.fC li:eq(2)').css('background-color','red').css('color','#ffffff');
}
else if(Math.abs(e.offset().top) > first+second+third - parseInt($('#container').css('height')) && Math.abs(e.offset().top) <= first+second+third+fourth - parseInt($('#container').css('height')))
{
$('.fC li:eq(0)').css('background-color','').css('color','');
$('.fC li:eq(1)').css('background-color','').css('color','');
$('.fC li:eq(2)').css('background-color','').css('color','');
$('.fC li:eq(3)').css('background-color','red').css('color','#ffffff');
}
else{
$('.fC li:eq(1)').css('background-color','').css('color','');
$('.fC li:eq(2)').css('background-color','').css('color','');
$('.fC li:eq(3)').css('background-color','').css('color','');
$('.fC li:eq(0)').css('background-color','red').css('color','#ffffff');
}
if(visibleETop < 0){
return false;
}else{
return true;
}
}
})();
HTML:
Just replace the id='three' to id='third' in third div from your html.
You should consider changing class based on one edge-
function elementInViewport(e) {
var winBottom = $(window).scrollTop() + $(window).height();
var visibleETop = e.offset().top - winBottom;
if(visibleETop < 0){
return false;
}else{
return true;
}
}

Background Image Shouldn't Appear In Header In Drop Down Menu

I've made a JavaScript dropdown menu. Everything works fine, except the background image. I have the image set to change when the dropdown menu is expanded, which also works fine.
The issue is with the headers. Unless the header is set to display inline-block or inline, the menu won't expand. When set to inline-block or inline everything expands when you click on the box. But if you click on the header itself, it adds the padding and border around the header and ads in the background image from the div. How do you prevent this from happening?
<div class="panel">
<div class="collapse"><h2>Features</h2></div>
<div class="elements">
text<br>text<br>text
</div>
</div>
<style>
h2 {/*display: inline-block;*/
/*display: inline;*/
margin: 0px;
padding: 0px 0px 0px 0px;
color: #ffffff;
text-align: center;
text-transform: uppercase;}
.expand,
.collapse {cursor: pointer;
background-position: center right;
background-repeat: no-repeat;
background-color: #000033;
border: 2px solid #990044;
color: #ffffff;
padding: 10px 0px;
text-align: center;}
.collapse {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABHUlEQVRIS+3USw6CMBAA0BYNutOjcAQ9iXHjhoXhBt4AEmwwbvQm6g04ii4hCLaNNRUp/dDgQllRPvMy05lC0PMFe/bAH7Re8R8qaYySTZGPoyBYXm3WMQwP04Gbhfd8FJDYtKTxNjkCCBf4Ni3y0dwWSrChm51wXI/FhjHaRXix5rKygtYwGr4C1QUitPdKUJ7xemILbcJw7JsDnBktqU20DfP9VfoaCxuoDCPJvc1hF1QF+wBNy6uKNYK6qA4mBFVRXawVlKHkPTfUbKJo65NuFJ1W0sNb1EjPgOQEUcakGbJIApRPQpoZ+1iaoQKqjCln2IJqYdpgrZGArEGaGke5pPzPZE/Juq0bjbtU9KPpc6MMTTGjPeyCfQV8AK4c2lwJRjQ3AAAAAElFTkSuQmCC);}
.expand {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABD0lEQVRIS+3Wyw2CQBAG4F1Q8KadSAnYgR0YL164SCWYKDHxonZgB1ICdiI3QR6yCgSVXXaAkGDkwgXyZf6dYcCo5Qu37KFugIaxH5FkdH1+hSYErpBgPck9E8j35AkUBYE5TEkqs6EoN1iApWmCUC6QgYHRUpCCOYk0zDUNV6VMkIYJSFAJFKLQim8glAqyME1b2AQ0zZ0CRQtBHiyNEop+gRCsCvoGVsGgaAbWwSDoE2wC40VxkxgPiteb7QFhPMsNsEPmLG196DZgolF0fFXYd614M47jhxvBCtEIXfy7rGZnKEq3k4jEZd3KPhMhcxqgYBV4gylZZaXf0qqR0t77g00n2pG/tjpl/37TPACe/d8VUJ3+EgAAAABJRU5ErkJggg==);}
.elements {background-color: #ccd9ff;
overflow: hidden;}
</style>
<script>
function aaManageEvent (eventObj, event, eventHandler) {
if (eventObj.addEventListener) {eventObj.addEventListener (event, eventHandler, false);}
else if (eventObj.attachEvent) {event = "on" + event; eventObj.attachEvent (event, eventHandler);}
}
window.onload = function () {
var divs = document.getElementsByTagName ("div");
for (var i = 0; i < divs.length; i++) {
if (divs[i].className == "collapse") {
aaManageEvent (divs [i], "click", spring.expandOrCollapse);
}
else if (divs[i].className == "elements") {
var height = divs [i].offsetHeight;
divs [i] .height = height;
if (divs [i] .id == "") divs [i].id = "div" + i;
divs [i].style.height = "0";
}
}
}
var spring = {
// adjust height
adjustItem : function (val, newItem) {
document.getElementById (newItem).style.height = val + "px";
},
// check if expand or collapse
expandOrCollapse : function (evnt) {
evnt = evnt ? evnt : window.event;
var target = evnt.target ? evnt.target : evnt.srcElement;
if (target.className == "collapse") spring.expand (target);
else spring.collapse (target);
},
// Expand Panel
expand : function (target) {
target.className = 'expand';
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, incr = height / 20;
for (var i=0; i < 20; i++) {
var val = (i + 1) * incr;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
},
// Collapse Panel
collapse : function (target) {
target.className = "collapse";
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, decr = height / 20;
for (var i = 0; i < 20; i++) {
var val = height - (decr * (i + 1));;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
}
};
</script>
When I click on the div, the dropdown works. But when I click on the header, I see an error in the browser console.
I think because when clicking on the <h2>Features</h2> element, the click event bubbles up to the <div class="collapse">, making the var target in this line not the <div class="collapse"> but the <h2>:
var target = evnt.target ? evnt.target : evnt.srcElement;
A possible solution to fix this is for example to add an id to this line:
<div id="header" class="collapse"><h2>Features</h2></div>
Then you can directly get that div by id and change the classname.
I've adjusted your expandOrCollapse function to make it toggle based on the classname from the div with id="header".
For example:
function aaManageEvent (eventObj, event, eventHandler) {
if (eventObj.addEventListener) {eventObj.addEventListener (event, eventHandler, false);}
else if (eventObj.attachEvent) {event = "on" + event; eventObj.attachEvent (event, eventHandler);}
}
window.onload = function () {
var divs = document.getElementsByTagName ("div");
for (var i = 0; i < divs.length; i++) {
if (divs[i].className == "collapse") {
aaManageEvent (divs [i], "click", spring.expandOrCollapse);
}
else if (divs[i].className == "elements") {
var height = divs [i].offsetHeight;
divs [i] .height = height;
if (divs [i] .id == "") divs [i].id = "div" + i;
divs [i].style.height = "0";
}
}
}
var spring = {
// adjust height
adjustItem : function (val, newItem) {
document.getElementById (newItem).style.height = val + "px";
},
// check if expand or collapse
expandOrCollapse : function (evnt) {
var header = document.getElementById('header');
if (header.className === "collapse") {
spring.expand(header);
} else {
spring.collapse(header);
}
},
// Expand Panel
expand : function (target) {
target.className = 'expand';
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, incr = height / 20;
for (var i=0; i < 20; i++) {
var val = (i + 1) * incr;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
},
// Collapse Panel
collapse : function (target) {
target.className = "collapse";
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, decr = height / 20;
for (var i = 0; i < 20; i++) {
var val = height - (decr * (i + 1));;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
}
};
h2 {/*display: inline-block;*/
/*display: inline;*/
margin: 0px;
padding: 0px 0px 0px 0px;
color: #ffffff;
text-align: center;
text-transform: uppercase;}
.expand,
.collapse {cursor: pointer;
background-position: center right;
background-repeat: no-repeat;
background-color: #000033;
border: 2px solid #990044;
color: #ffffff;
padding: 10px 0px;
text-align: center;}
.collapse {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABHUlEQVRIS+3USw6CMBAA0BYNutOjcAQ9iXHjhoXhBt4AEmwwbvQm6g04ii4hCLaNNRUp/dDgQllRPvMy05lC0PMFe/bAH7Re8R8qaYySTZGPoyBYXm3WMQwP04Gbhfd8FJDYtKTxNjkCCBf4Ni3y0dwWSrChm51wXI/FhjHaRXix5rKygtYwGr4C1QUitPdKUJ7xemILbcJw7JsDnBktqU20DfP9VfoaCxuoDCPJvc1hF1QF+wBNy6uKNYK6qA4mBFVRXawVlKHkPTfUbKJo65NuFJ1W0sNb1EjPgOQEUcakGbJIApRPQpoZ+1iaoQKqjCln2IJqYdpgrZGArEGaGke5pPzPZE/Juq0bjbtU9KPpc6MMTTGjPeyCfQV8AK4c2lwJRjQ3AAAAAElFTkSuQmCC);}
.expand {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABD0lEQVRIS+3Wyw2CQBAG4F1Q8KadSAnYgR0YL164SCWYKDHxonZgB1ICdiI3QR6yCgSVXXaAkGDkwgXyZf6dYcCo5Qu37KFugIaxH5FkdH1+hSYErpBgPck9E8j35AkUBYE5TEkqs6EoN1iApWmCUC6QgYHRUpCCOYk0zDUNV6VMkIYJSFAJFKLQim8glAqyME1b2AQ0zZ0CRQtBHiyNEop+gRCsCvoGVsGgaAbWwSDoE2wC40VxkxgPiteb7QFhPMsNsEPmLG196DZgolF0fFXYd614M47jhxvBCtEIXfy7rGZnKEq3k4jEZd3KPhMhcxqgYBV4gylZZaXf0qqR0t77g00n2pG/tjpl/37TPACe/d8VUJ3+EgAAAABJRU5ErkJggg==);}
.elements {background-color: #ccd9ff;
overflow: hidden;}
<div class="panel">
<div id="header" class="collapse"><h2>Features</h2></div>
<div class="elements">
text<br>text<br>text
</div>
</div>
Edit your declaration block of h2 as shown below. This will solve your problem.
h2 {
display: inline-block;
margin: 0px;
padding: 0px 0px 0px 0px;
color: #ffffff;
text-align: center;
text-transform: uppercase;
pointer-events: none; // this line solves your problem.
}
CSS property pointer-events let you control under what circumstances an element can become the target of mouse events. when you set it to none, the element will never be the target of mouse events. So, the click event passed on to its descendant elements (here the box).

Adding paging controls to a full page touch swiper/slider - Hammer.js

CLICK FOR FIDDLE
Below is a fully functional full page touch slider I have created using hammer.js
You can drag, swipe or pan to navigate between pages.
The slider works as expected but I am now trying to create fallback navigation by adding two buttons so paging left and right can occur on click also.
QUESTION
How can the hammer swipe left or right be called on click? (Javascript or jQuery).
CURRENT ATTEMPT
$('#Left').on('click', function() {
HammerCarousel(document.querySelector('.Swiper'), 'Left');
});
FULL CODE
function swipe() {
var reqAnimationFrame = (function () {
return window[Hammer.prefixed(window, "requestAnimationFrame")] || function (callback) {
setTimeout(callback, 1000 / 60);
}
})();
function dirProp(direction, hProp, vProp) {
return (direction & Hammer.DIRECTION_HORIZONTAL) ? hProp : vProp
}
function HammerCarousel(container, direction) {
this.container = container;
this.direction = direction;
this.panes = Array.prototype.slice.call(this.container.children, 0);
this.containerSize = this.container[dirProp(direction, 'offsetWidth', 'offsetHeight')];
this.currentIndex = 0;
this.hammer = new Hammer.Manager(this.container);
this.hammer.add(new Hammer.Pan({ direction: this.direction, threshold: 10 }));
this.hammer.on("panstart panmove panend pancancel", Hammer.bindFn(this.onPan, this));
this.show(this.currentIndex);
}
HammerCarousel.prototype = {
show: function (showIndex, percent, animate) {
showIndex = Math.max(0, Math.min(showIndex, this.panes.length - 1));
percent = percent || 0;
var className = this.container.className;
if (animate) {
if (className.indexOf('animate') === -1) {
this.container.className += ' animate';
}
} else {
if (className.indexOf('animate') !== -1) {
this.container.className = className.replace('animate', '').trim();
}
}
var paneIndex, pos, translate;
for (paneIndex = 0; paneIndex < this.panes.length; paneIndex++) {
pos = (this.containerSize / 100) * (((paneIndex - showIndex) * 100) + percent);
translate = 'translate3d(' + pos + 'px, 0, 0)';
this.panes[paneIndex].style.transform = translate;
this.panes[paneIndex].style.mozTransform = translate;
this.panes[paneIndex].style.webkitTransform = translate;
}
this.currentIndex = showIndex;
},
onPan: function (ev) {
var delta = dirProp(this.direction, ev.deltaX, ev.deltaY),
percent = (100 / this.containerSize) * delta,
animate = false;
if (ev.type == 'panend' || ev.type == 'pancancel') {
if (Math.abs(percent) > 20 && ev.type == 'panend') {
this.currentIndex += (percent < 0) ? 1 : -1;
}
percent = 0;
animate = true;
}
this.show(this.currentIndex, percent, animate);
}
};
var outer = new HammerCarousel(document.querySelector('.Swiper'), Hammer.DIRECTION_HORIZONTAL);
};
$(swipe);
html,
body,
.Page,
.Swiper{
position:relative;
height:100%;
}
.Swiper{
background:#666;
overflow:hidden;
}
.Swiper.animate > .Page{
transition:all .3s;
-webkit-transition:all .3s;
}
.Page{
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
padding:0 10px;
font:42px Arial;
color:#fff;
padding-top:10%;
text-align:center;
}
.Page:nth-child(odd) {
background:#b00;
}
.Page:nth-child(even) {
background:#58c;
}
#Left,
#Right{
position:absolute;
top:0;
height:50px;
width:50px;
background:#fff;
text-align:center;
font:16px/3em Arial;
cursor:pointer;
}
#Left{
left:0;
}
#Right{
right:0;
}
<script src="http://hammerjs.github.io/dist/hammer.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Swiper">
<div class="Page">PAGE 1<br/>DRAG LEFT</div>
<div class="Page">PAGE 2<br/>SWIPE ME</div>
<div class="Page">PAGE 3<br/>HOLD TO PAN</div>
<div class="Page">PAGE 4<br/>FLICK TO GO BACK</div>
</div>
<div id="Left">Left</div>
<div id="Right">Right</div>
I have crafted a jQuery solution for this that should satisfy the fallback you are looking for.
Some things to consider, though. In your example as well, page re-size is not accounted for. I have not done so in this either to remain consistent and solve the immediate issue, but you will notice I am grabbing the $('.Page').width(); as a variable in this solution. I would recommend re-assigning this value if you do account for re-sizing. Also, a mix of swiping/clicking will throw this off. I assume since you indicated this will be a fallback, the user will receive one of the two experiences. If not, we'll need a way to update tracker on swipe events as well.
You'll notice var tracker = { 'R': 0 }. While naming may not be the best, 'R' will account for how many right "swipes" (navigation clicks) the user has performed in a plus/minus 1 manner
<div id="Left" direction="L">Left</div>
<div id="Right" direction="R">Right</div>
$(function() {
var width = $('.Page').width();
var pages = $('.Page').length;
var tracker = { 'R': 0 }
$('#Right, #Left').click(function() {
$(this).attr('direction') === 'R' ?
((tracker.R < (pages - 1) ? tracker.R += 1 : pages)) :
(tracker.R > 0) ? (tracker.R -= 1) : 0;
$('.Swiper').animate({ 'scrollLeft': $('.Page').width() * tracker.R }, 250)
});
});
JSFiddle Link

How to achieve image changing on hover?

So I am trying to achieve the effect as such on this website.
(Near the bottom where you can hover over the image and it shows another as you move over it)
Any ideas? I mean I know they are just overlaying the two images, but how they then display the far image using CSS/Javascript on hover? This is beyond me. I have tried reproducing it myself with no success.
Try this:
var main = document.querySelector('.main');
var one = document.querySelector('.one');
var two = document.querySelector('.two');
main.onmousemove = function (e) {
var width = e.pageX - e.currentTarget.offsetLeft;
one.style.width = width + "px";
two.style.left = width + "px";
}
.main {
width: 200px;
height: 200px;
overflow: hidden;
position: relative;
}
.one {
background-image: url('http://www.lorempixel.com/200/200');
width: 50%;
height: 100%;
}
.two {
background-image: url('http://www.lorempixel.com/200/200/sports');
position: absolute;
left: 50%;
right: 0px;
top: 0px;
bottom: 0px;
background-position: right;
}
<div class="main">
<div class="one"></div>
<div class="two"></div>
</div>
Working Fiddle
So what's happening is, as the mouse hovers over the line, the width changes dynamically, if you inspect the element, you can see this as well.
Now, in the DOM structure, the brown car, the one being hidden is before the top image. So to achieve this, you can position the brown car absolutely, so it goes right behind the next image, and with javascript or jQuery add a listener for hover, on the image or that middle line that is used on the site, that will change the width of the top image (the silver one) in respect to the position of the mouse in the block of the image.
Essentially, the width of the background image should change by percentage to how far the mouse is from the left of the DIV, by percent i.e. if the mouse is at the middle, the width should be 50%.
Here is the js they use to do it, right from their site (I uncompressed it)
var ImageSlider = ImageSlider || {};
ImageSlider.Public = function(t) {
"use strict";
var e = t(".image-compare-tool"),
i = t(".image-compare-images"),
o = t(".image-compare-top img"),
a = (t(".image-compare-bottom img"), function(e) {
e.preventDefault();
var i, o = t(this).find(".image-compare-top"),
a = t(this).find(".image-compare-bottom img")[0],
n = a.getBoundingClientRect();
i = "mousemove" == e.originalEvent.type ? (e.pageX - n.left) / a.offsetWidth * 100 : (e.originalEvent.touches[0].pageX - n.left) / a.offsetWidth * 100, 100 >= i && o.css({
width: i + "%"
})
}),
n = function() {
i.each(function() {
t(this).on("mousemove", a), t(this).on("touchstart", a), t(this).on("touchmove", a)
})
},
m = function() {
o.each(function() {
var e = t(this).attr("src"),
i = t(this).parent();
i.css("background-image", "url(" + e + ")")
})
},
c = function() {
n(), m()
},
r = function() {
e.length > 0 && c()
};
r()}(jQuery);
If you look at html sources (Ctr + Shift + I in Chrome) you can see this element
<div class="image-compare-tool ICT-theverge">
<div class="image-compare-images">
<div class="image-compare-bottom"><img src="http://cdn2.vox-cdn.com/uploads/chorus_asset/file/2455624/khyzyl-saleem-plain-copylow.0.jpg"></div>
<div class="image-compare-top" style="width: 6.158357771261%; background-image: url(http://cdn0.vox-cdn.com/uploads/chorus_asset/file/2455620/khyzyl-saleem-plain-copylow1.0.jpeg);"><img src="http://cdn0.vox-cdn.com/uploads/chorus_asset/file/2455620/khyzyl-saleem-plain-copylow1.0.jpeg"></div>
</div>
</div>
So here are images! So next you need to look at css.
.image-compare-tool
{
max-width:100%;
width:100%;
z-index:999;
margin:0 auto 1.5em 0;
}
.image-compare-images
{
font-size:0;
position:relative;
height:100%;
-ms-touch-action:none;
-webkit-touch-callout:none;
-webkit-user-select:none;
}
.image-compare-images:hover
{
cursor:col-resize;
}
.image-compare-images img
{
display:block;
height:auto;
width:100%;
}
.image-compare-top,.image-compare-bottom
{
z-index:0;
height:100%;
}
.image-compare-top
{
background-size:cover;
height:100%;
left:0;
position:absolute;
top:0;
width:50%;
}
.image-compare-top:after
{
background-color:#fff;
content:'';
height:50px;
left:calc(100%-5px);
top:calc(50%-25px);
position:absolute;
width:10px;
}
.image-compare-top img
{
display:none;
}
.ICT-SBNation .image-compare-top:after
{
background-color:#c52126;
}
.ICT-SBNation .image-compare-top:before
{
background-color:#c52126;
content:'';
height:100%;
left:calc(100%-2.5px);
top:0;
position:absolute;
width:5px;
}
.ICT-TheVerge .image-compare-top:after
{
background-color:#fa4b2a;
}
.ICT-TheVerge .image-compare-top:before
{
background-color:#fa4b2a;
content:'';
height:100%;
left:calc(100%-2.5px);
top:0;
position:absolute;
width:5px;
}
.ICT-Polygon .image-compare-top:after
{
background-color:#ff0052;
}
.ICT-Polygon .image-compare-top:before
{
background-color:#ff0052;
content:'';
height:100%;
left:calc(100%-2.5px);
top:0;
position:absolute;
width:5px;
}
.image-compare-top:before,.ICT-Vox .image-compare-top:before
{
background-color:#fff;
content:'';
height:100%;
left:calc(100%-2.5px);
top:0;
position:absolute;
width:5px;
}
Here wea! You can implement same stuff by just including css and making same html structure and classes with just changing img paths...
And finally the js that i brazenly stole from the answer above:
var ImageSlider = ImageSlider || {};
ImageSlider.Public = function (t) {
"use strict";
var e = t(".image-compare-tool"),
i = t(".image-compare-images"),
o = t(".image-compare-top img"),
a = (t(".image-compare-bottom img"), function (e) {
e.preventDefault();
var i, o = t(this).find(".image-compare-top"),
a = t(this).find(".image-compare-bottom img")[0],
n = a.getBoundingClientRect();
i = "mousemove" == e.originalEvent.type ? (e.pageX - n.left) / a.offsetWidth * 100 : (e.originalEvent.touches[0].pageX - n.left) / a.offsetWidth * 100, 100 >= i && o.css({
width: i + "%"
})
}),
n = function () {
i.each(function () {
t(this).on("mousemove", a), t(this).on("touchstart", a), t(this).on("touchmove", a)
})
},
m = function () {
o.each(function () {
var e = t(this).attr("src"),
i = t(this).parent();
i.css("background-image", "url(" + e + ")")
})
},
c = function () {
n(), m()
},
r = function () {
e.length > 0 && c()
};
r()
}(jQuery);
And the working JSFiddle: http://jsfiddle.net/9gf59k00/
And my good luck...
$('img').on('mousemove', function(){
var imgsrc = $(this).attr('src');
if(imgsrc == 'img1.png'){
$(this).attr('src','img2.png');
}else{
$(this).attr('src','img1.png');
}
});
You can do this without javascript,
JSfiddle - http://jsfiddle.net/k4915wwm/
Just…
div:hover {
background:url("newImage.jpg");
}

Get only the ellipsis text using jquery

Nice code, just wondered if it is possible to query and get the ellipsis text (i.e. with the dots in and not the original text)?
If I add the text
This is a long sentence
and (using the relevant css for ellipsis) it gets shortened to
This is a long sen ...
Is there a way to get the text
"This is a long sen ..."
from the $("p") DOM object rather than the original text?
Try that:
function getEllipsis(command, characters) {
for (var i = command.length; i >= 0; i--) {
if (command.substring(0, i).length < characters) {
if (i < command.length) {
command = command.substring(0, i) + "...";
}
return command;
}
}
}
console.log(getEllipsis("I am a long sentence",16))
console.log(getEllipsis("But I am even longer",20))
I have a rough draft that needs some browser-specific tweaking.
JavaScript:
jQuery.fn.getShowingText = function () {
// Add temporary element for measuring character widths
$('body').append('<div id="Test" style="padding:0;border:0;height:auto;width:auto;position:absolute;display:none;"></div>');
var longString = $(this).text();
var eleWidth = $(this).innerWidth();
var totalWidth = 0;
var totalString = '';
var finished = false;
var ellipWidth = $('#Test').html('…').innerWidth();
var offset = 7; // seems to differ based on browser (6 for Chrome and 7 for Firefox?)
for (var i = 0;
(i < longString.length) && ((totalWidth) < (eleWidth-offset)); i++) {
$('#Test').text(longString.charAt(i));
totalWidth += $('#Test').innerWidth();
totalString += longString.charAt(i);
if(i+1 === longString.length)
{
finished = true;
}
}
$('body').remove('#Test'); // Clean up temporary element
if(finished === false)
{
return totalString.substring(0,totalString.length-3)+"…";
}
else
{
return longString;
}
}
console.log($('#ellDiv').getShowingText());
CSS:
#Test {
padding:0;
border:0;
height: auto;
width: auto;
position:absolute;
white-space: pre;
}
div {
width: 100px;
white-space: nowrap;
border: 1px solid #000;
overflow:hidden;
text-overflow:ellipsis;
padding:0;
}
With the caveat that the offset needs to change depending on the browser, unless someone can figure out what is causing it.
I suspect letter-spacing or similar?

Categories

Resources