Basic JS - Is this function okay? - javascript

I have a carousel (Owl Carousel) with vertically centered controls. Because of the structure, I have to absolutely position the previous and next arrow. Because the page is responsive, their position is dynamic. The size of the controls may also change.
I've written a function that runs on load and resize. It gets the height of the image and the height of the controls, subtracts the latter from the former, divides by two, and then uses that number as the controls' margin-top.
It works, but I'm questioning if I'm getting and using all the variables correctly. Does JavaScript read in order? Where it runs the first line, then the next, then the next... I'm strong in CSS but JS has always been a crutch.
Can I write this more efficiently?
function centerCarouselControls() {
var carouselImage = $('.carousel-card > img');
var carouselControls = $('.owl-nav > div');
var carouselHeight = carouselImage.outerHeight();
var controlHeight = carouselControls.outerHeight();
var controlMargin = (carouselHeight - controlHeight) / 2;
carouselControls.css('margin-top', controlMargin);
}
$('.carousel-card > img').load(centerCarouselControls);
$(window).on('resize', centerCarouselControls);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I feel like this might be the type of question that gets flagged on here for not being specific enough. If that's the case, could someone please point me to a community where this would be more appropriate? Thanks!

In some browsers your code works like firefox 51, but it is more complete code this:
carouselControls.css('margin-top', controlMargin + 'px');

Related

Text Not Ellipsis at certain point using jQuery Plugin

I currently have a 'widget' div which has a static height, within it is an image which also has a static height. The only thing that can have a dynamic height is the title which can change from 1-3 lines long.
What's happening is that I'm trying to make the description within the div (which can be quite long) ellipsis before the containing div ends, taking into account the title which can vary in height.
I'm using a jQuery plugin called dotdotdot which docs can be found here http://dotdotdot.frebsite.nl/
The plugin is working but I think my JS might be off a bit. Would love some help as I just can't get my brain around it.
Fiddle Here
You can see it clearly on the fiddle but JS below.
$(document).ready(function () {
$(".caption").each(function () {
var authorheight = $('.meta').height();
var h2height = $('h4').height();
$(".desc").height(250 - h2height - authorheight);
$(".desc").dotdotdot({
after: "a.readmore"
});
});
});
Any help would be brilliant!
Thanks
You were doing everything right except for calculating the Height.
var authorheight = $('.meta').innerHeight();
var h2height = $('h4').innerHeight();
the above help you get the height along with the padding and everything.
Then next id you left padding which you have applied to .caption so your
height for .desc becomes as below
$(".desc").height(250 - h2height - authorheight -40);
UpdatedFiddle

How to move absolutely position elements depending on screen size in Jquery

Hi I am building a magnetic poetry game where you drag words together to form some phrases. I am Using jqueryui draggable and droppable with absolute positioned divs.
http://test-magnets.meteor.com/
I am also trying to make the game responsive as much as possible. I have a bank of words to the right of the fridge that have a class "not-in-play" once you drop on the fridge that class is removed. So when the screen size is smaller i just want to move the magnets that have the class "not-in-play".
i was thinking something like this
$(document).ready(function() {
var screenwidth = $(window).width()
if (screenwidth <= 800) {
$('magnet.not-in-play').each(function(){
var currentPosLeft = parseInt($(this).css('left'));
$(this).css('left', (currentPosLeft - 1000) + 'px');
});
}
});
I can get an alert to fire inside the if block but any css i try is not working. It works in the console fine hence my confusion. Any suggestions would be greatly appreciated. Thanks
this seems to work fine in a fiddle
http://jsfiddle.net/ff0ynexc/
just not in my app
-John
Using -= will not work (you're setting the properties directly), instead do something like
var currentPosLeft = parseInt($('.magnet.not-in-play').css('left'));
$('.magnet.not-in-play').css('left', (currentPosLeft - 600) + 'px');
(You'll probably have to do that in a loop)

change css on scroll event w/ requestAnimation Frame

I want to change the background color of in-viewport elements (using overflow: scroll)
So here was my first attempt:
http://jsfiddle.net/2YeZG/
As you see, there is a brief flicker of the previous color before the new color is painted. Others have had similar problems.
Following the HTML5 rocks instructions, I tried to introduce requestAnimationFrame to fix this problem to no avail:
http://jsfiddle.net/RETbF/
What am I doing wrong here?
Here is a simpler example showing the same problem: http://jsfiddle.net/HJ9ng/
Filed bug with Chromium here: http://code.google.com/p/chromium/issues/detail?id=151880
if it is only the background color, well why don't you just change the parent background color to red and once it scroll just change it to pink?
I change your CSS to that
#dad
{
overflow-y: scroll;
overflow-x: hidden;
width: 100px;
height: 600px;
background-color:red;
}​
I remove some of you Jquery and change it to this
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
});
And I remove this line
iChild.css('backgroundColor', 'red');
But is the Red color it is important that won't work for sure http://jsfiddle.net/2YeZG/5/
I like Manuel's Solution.
But even though I don't get what you're exactly trying to do, I want to point out a few things.
In your fiddle code, I saw that you included Paul Irish's Shim for requestAnimationFrame.
But you never use it.
(It's basically a reliable setTimeOut, nothing else) it's from frame based animations.)
So since you just want to change some CSS properties, I don't see why you would need it. Even if you want transitions, you should rely on CSS transitions.
Other than that your code could look something like
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
eachElemNameHere.css('background-color','randomColor');
});
Also you should ideally not use something like that if you can help it. You should just add and remove class names and add all these properties in your CSS. Makes it work faster.
Also, again I don't quite get it, but you could use the jQuery function to find out each elements' position from the top to have better control.
Your problem seems to be that you only change the background color of the elements which have already been scrolled into view. Your code expects that the browser waits for your code to handle the scroll event before the browser redraws its view. This is most probably not a guarantee given by the HTML spec. That's why it flickers.
What you should do instead is to change the elements which are going to be scrolled into view. This is related to off screen rendering or double buffering as it is called in computer games programming. You build your scene off screen and copy the finished scene to the visible frame buffer.
I modified your first JSFiddle to include a multiplier for the height of the scroll area: http://jsfiddle.net/2YeZG/13/.
dad.bind('scroll', function() {
// new: query multiplier from input field (for demonstration only) and print message
var multiplier = +($("#multiplier")[0].value);
$("#message")[0].innerHTML=(multiplier*100)-100 + "% of screen rendering";
// your original code
var newScrollY = newScrollY = dad.scrollTop();
var isForward = newScrollY > oldScrollY;
var minVal = bSearch(bots, newScrollY, true);
// new: expand covered height by the given multiplier
// multiplier = 1 is similar to your code
// multiplier = 2 would be complete off screen rendering
var newScrollYHt = newScrollY + multiplier * dadHeight;
// your original code (continued)
var maxVal;
for (maxVal = minVal; maxVal < botsLen; maxVal++) {
var nxtTopSide = tops[maxVal];
if (nxtTopSide >= newScrollYHt) {
break;
}
}
maxVal = Math.min(maxVal, botsLen);
$(dadKids.slice(minVal, maxVal)).css('background', 'pink');
});
Your code had a multiplier of 1, meaning that you update the elements which are currently visible (100% of scroll area height). If you set the multiplier to 2, you get complete off screen updates for all your elements. The browser updates enough elements to the new background color so that even a 100% scroll would show updated elements. Since the browser seldom scrolls 100% of the area in one step (depends of the operating system and the scroll method!), it may be sufficient to reduce the multiplier to e.g. 1.5 (meaning 50% off screen rendering). On my machine (Google Chrome, Mac OS X with touch pad) I cannot produce any flicker if the multiplier is 1.7 or above.
BTW: If you do something more complicated than just changing the background color, you should not do it again and again. Instead you should check whether the element has already been updated and perform the change only afterwards.

How to split html to full-screen height pages?

I need to split some html content to pages, so that each page would have height of the screen and some predefined width. Page split can happen in the middle of paragraph (or probably some other html element), so this situation should be handled somehow.
What I really want to achieve is the effect of reading the book, page by page. I assume there will be a need for some javascript, so I'd prefer to to this with jQuery, but if other framework is required, it's also okay.
I have to admit that I'm quite new to HTML and all, so sorry if my guess is stupid, but currently I'm considering the following approach: measure actual height of the visible area (need to figure out how yet), then take my html document and incrementally take tag after tag, put this into invisible div and calculate its resulting height. When I'll have its height more than page height, I'm done. However, this approach will not work in case of long tags, e.g. long paragraph.
Thanks in advance.
EDIT: thanks for your previous answers. I tried to use approach of manual calculating the size of the elements, and encountered one problem which I cannot solve in a good way. This is problem of collapsing margins. What I'm trying to do is to loop through all the paragraphs in my document and sum up results of .outerHeight(true) jQuery call. This should give me the full height of element, including padding, margin and border. And it actually does what it says, but the problem here is that it doesn't take collapsing margins into account. Because of that I end up with wrong overall size (bigger than real one), because browser throws away some of margins (of adjacent paragraphs in my case), but I take them into account.
Any ideas how to solve this other than introducing the algorithm deciding which margins are collapsed and which are not? I think it is ugly...
You could use CSS3 multi-column rules, example: http://www.quirksmode.org/css/multicolumn.html
Or for support in all browsers use a javascript plugin: http://welcome.totheinter.net/columnizer-jquery-plugin/
This plugin even has a multi-page multi-column example: http://welcome.totheinter.net/2009/06/18/dynamic-multi-page-multi-column-newsletter-layout-with-columnizer/
I can think of one framework which seems to do what you need (and a bit more): https://github.com/Treesaver/treesaver
jQuery will give you the height (in pixels) of an element with the height() function.
jQuery("BODY").height() will give you the maximum height of the view port (though only if your content height is >= the height of the BODY - otherwise it will give you the height of how much space the body is taking up in the view port.)
Counting the heights of the P tags (or other tags) seems like a good way to go. I suppose if you want to break up the content of a P tag for large paragraphs, you could define a maximum "breakage" height for the last P tag on a page. You can then break rest of the contents of the P tag by creating a new P tag with jQuery("#the-next-page-id).append(jQuery("<P>"+restOfTheParagraphContent+"</P>"))
Use your own logic to calculate the height of each element in the html body
using jQuery code
$('selector').height();
Using this, you can calculate the height of some html elements and decide how much
elements should be displayed on your device screen.
for more, please visit jQuery Height Documentation
In case anyone still looking for something like this I recently did it using JQuery. It also leaves the first page empty (for title and such):
https://jsfiddle.net/xs31xzvt/
It basically iterates over the movable items and insert them into a new div if the previous div is full.
(function($) {
$(document).ready(formatPages)
function formatPages() {
var container = $('.container');
var subPage = $('.subpage').get(0);
var subPageHeight = subPage.offsetHeight;
var subPageScrollHeight = subPage.scrollHeight;
// See how many pages we'll need
var pages = Math.floor(subPageScrollHeight / subPageHeight) + 1;
//add a new page
var pageCount = 2;
var pageDiv = createPageDiv(pageCount);
var subPageDiv = createSubPageDiv(pageCount);
var addPage = function (){
pageCount++;
pageDiv = createPageDiv(pageCount);
subPageDiv = createSubPageDiv(pageCount);
pageDiv.append(subPageDiv);
container.append(pageDiv);
pageContentHeight = 0;
}
addPage()
container.append(pageDiv);
$('.movable').each(function() {
var element = $(this);
//remove the element
element.detach();
//try to add the element to the current page
if (pageContentHeight + element.get(0).offsetHeight > subPageHeight) {
subPageDiv.append(getFooterDiv().show());
//add a new page
addPage();
}
subPageDiv.append(element);
pageContentHeight += element.get(0).offsetHeight;
});
}
function createPageDiv(pageNum) {
return $('<div/>', {
class: 'page',
id: 'page' + pageNum
});
}
function createSubPageDiv(pageNum) {
return $('<div/>', {
class: 'subpage',
id: 'subpage' + pageNum
});
}
function getFooterDiv() {
return $('.footer').first().clone();
}
}(jQuery));

jquery: calculating 'margin-left' or 'left' relative to $(window).scrollLeft() is really jagged in Firefox — using .animate() or .css()

I have a horizontally scrolling website, and I have a block that I want to stay in frame at all times as the user scrolls right. It looks perfectly smooth in webkit browsers, but is crazy jagged in Firefox and I don't really care about IEs.
function fixMyId(){
$('#myId').css({'margin-left': 150 + $(window).scrollLeft()});
}
function fixMyIdAlt(){
$('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
And then I have it triggered on window scroll.
What would be a best way to average out the scrolling, so that maybe every so many seconds or pixels of scrolling it fires the function, or upon stopping the scrolling it animates the block into place? I tried playing with delay() but that doesn't do anything. And this one just looks stupid (plus I have no idea what the overhead of this kind of crunching is):
function fixMyIdStupid(){
window.scrollCounter++;
if(window.scrollCounter % 20 == 0) $('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
So what do I do? setTimeout and setInterval may be required, but those always make my head hurt.
EDIT: Here's a jsfiddle of it in action: http://jsfiddle.net/xsxSq/
The #f0f square is the #myId.
I tried to do such things as well, problem is that the scroll event isn't fired as much as you want. A nice workaround was subscribing the calculation function to the mousemove event, so it triggers A LOT. But on the other hand, I came up with another solution.
Why not turn things around and ask yourself:
Lets make it a position:fixed object and calculate what happens on resize. Because you actually are trying to create a position-x:fixed; and a position-y:absolute;
I actually did the following for the opposite kind of thing. A block that has to be exactly in the middle of the x-document, but in the y it was fixed.
$(document).ready(function ()
{
replaceFixed();
$(window).resize(replaceFixed);
$('#content').ajaxSuccess(replaceFixed);
$(window).scroll(replaceFixed);
function replaceFixed()
{
var jEl = $('#centeredFixedContainer');
var winW = $(window).width();
var docW = $(document).width();
var scrL = $(window).scrollLeft();
var divW = jEl.width();
var result = 0;
// window bigger than the element
if(winW > divW)
{
result = -scrL + ((docW-winW)/2);
}
else
{
result = $('#mainContainer').offset().left - scrL;
}
jEl.css('left',result);
}
});
Copying this code will not give you the solution, but will indicate another way to look at your problem.

Categories