I have a "menu bar" (for lack of a better term) which is basically a fixed width ul at 980px. The li elements are populated on page load, and contain an image, a span, and a divider (for the next li).
If there are too many li elements, they overflow onto the next line. I want to prepare for such an event by running some JS/jquery after the list is populated to move all of the overflow elements into another div, which will essentially be a css hover menu with the elements inside it (it will say '...view more' or similar).
My initial approach has been to check, after populating the menu, if the menu's total width exceeds a certain number, and if so, to append the last element to the new div for overflow. This function would either loop with a variable checking the width of the menu, or call itself recursively, whichever. I got the basic functionality working with an if statement, but it was a single iteration to test - the last element got moved to the div successfully. Unfortunately, when I tried to iterate it (loop or recursive) the browser seemed to go into an endless loop in the js and never loaded the page properly.
A version of my current attempt looks like this:
/**code for populating etc happens here ... then calls trimList(); */
function trimList(){
var menuWidth = $('#menu').width();
if(menuWidth > 700){
$('#menu li:last-child').appendTo('#overflowList');
trimList();
}
}
With this version or with a while loop the browser eventually crashes, but I'm not sure why. I'm sure it's something obvious.
I'd like to either fix my current implementation, or do it some other way (perhaps - if width is longer, grab ALL elements that push beyond that width, and throw them in the div. All at once, rather than iterating. But I'm not sure what the best way to grab the first offending (boundary pushing) element would be.)
I'm sure this is something simple, I'm just struggling to figure out what's causing the issue now.
Thanks
edit: see below - fixed my issue
Fixed it!
The issue was that the 'overflow' div was inside the menu div and my CSS selectors targeted all descendants. So, after the first iteration, every subsequent .appendTo targeted the one which had already been appended. The stopping condition would never be reached, and it iterated endlessly..stack overflow.
For clarification, my answer involved changing $('#menu li:last-child') to $('#menu > li:last-child). Works great now.
Related
I am working on building a schedule. So far it's pretty straight-forward. There is one bit of functionality I am having issues with.
I have an ul that has a fixed height to allow scrolling. There are "Labels" (li.dayLabel) withing the ul that separate the hours. What I am trying to do is to have it so that when a label is scrolled out of view it will change the text in the placeholder to it's text. Then once that works, I need it to work in reverse. So when they label scrolls back into view it updates the placeholder. Basically, I am trying to make the placeholder be a title for the available items until another label is then scrolled out of view. This is for scrolling from the top. So as you scroll down the list the placeholder is meant to be a title for the section you are viewing until you reach another section and it takes its place. Then when you scroll back down I need it to replace the text with the previous li.dayLabel so the sections stay organized. I hope this makes sense.
You can see what I am trying to do by looking at the original that I am basing this off of. Notice how the placeholder changes as you scroll down the list and changes back when you scroll back up.
Demo: jsFiddle // Note: line 54 is the part that is in question
I originally used:
$(".snlf-schedule-list li.dayLabel:visible:first").text();
as the :first selector is suppose to only match a single element.
I later tried:
$(".snlf-schedule-list li.dayLabel:visible").filter(":eq(0)")
as this is suppose to be the same thing.
It seems that when an element is out of view it still is considered :visible I believe this is my issue.
Am I doing this completely wrong? I was under the impression that when you scroll an element like this it should no longer be :visible. After reading the documentation I have learned that this is not the correct selector to use.
It would appear that scrollTop is how I should be doing this. Now I have used scrollTop for scrolling down pages to disable animations when not in view but I am not clear on how to untilize this for a ul with scrollbars.
I tried:
var _first = $('li.dayLabel:first'); // next element to scroll out of view?
if( $(this).scrollTop() > (_first.offset().top+_first.height())) {
// Out of view
console.log("out");
} else {
// in view
console.log("in");
}
Updated Demo: jsFiddle
But it seems to be redundant as it's already calculating the first element so I am not sure how to get the correct element (the next one that's about to scroll out of view.) Then I need this to work when they scroll back up...
Any insight on this is much appreciated. Hopefully it's something simple I am just over complicating or missing completely.
Thanks,
Jeremy
The solution for my case was:
// Set placeholder text on scroll
var _scrollCagePositionTop = $(".snlf-schedule-list").offset().top;
var _first = $('li.dayLabel:first'); // first dayLabel element
$(".snlf-schedule-list").scroll(function(){
var _lastOffText = $(_first).text();
$("li.dayLabel").each(function() {
if ($(this).offset().top < _scrollCagePositionTop) {
_lastOffText = $(this).text();
}
});
$("#schedule-placeholder").text(_lastOffText);
});
What I did was set the known position of the top of the scroll cage (_scrollCagePositionTop)
When the user scrolls I set a variable _lastOffText that keeps track of the last item text content when scrolled out of view (less offset top than the palceholder). I then set this value to the placeholder.
This method allows me to have the proper text in my placeholder when the user scrolls up or down.
To fix the issue of an empty placeholder when the user scrolls back to the top I just set the default of _lastOffText to be the text of the first label ($(_first).text())
Hope others find this useful.
Here is the working demo: jsFiddle Final
jsFiddle (Just an example to give you the idea of problem)
I am stuck at this stupid thing and would really appreciate any help I can get. I have an un-ordered list of fixed width with multiple list items inside. These list items are dynamically populated.
Due to users actions on the page some of these elements might be set to display:none to hide from view. Currently I am applying margin-right to elements except for every 4th element using li:not(:nth-child(4n)){} selector. Now the issue is that when some of these elements are hidden by setting display: none, the nth-child selector still considers the elements that are hidden, as they are still in the markup. This causes the styling to mess up a bit.
Increasing the width of the ul will not work as shown in the fiddle. Is there any way I can achieve what I want without having to remove those list items from the list.
Regards
Though it may be better to just iterate over the elements, here's an interesting approach:
function reMargin(){
$("li").css("margin-right", 10);
$("li:visible").filter(":odd:odd").css("margin-right", 0);
}
jQuery(document).ready(function(){
jQuery('#set-display').on('click', function(){
jQuery('#set-this').addClass('display-none');
reMargin();
});
reMargin();
});
http://jsfiddle.net/PrgTQ/2/
:odd:odd actually returns every 4th element.
The demo page referenced can be found here.
I'm trying to determine a way that on the click of a parent category (ex: Stone Tiles, Stone Sinks), that the JScrollPane would re-determine the current height and adjust as needed. Unfortunately, my attempts to do so have not worked yet.
I referenced the example here which provided the following function (to do a refresh)...
api.reinitialise();
I've tried to setup this function to be triggered by the category parents like so...
var pane = $('.menuwrap')
pane.jScrollPane();
var api = pane.data('jsp');
var i = 1;
$("li.expandable.parent").click(function() {
api.reinitialise();
});
Unfortunately, while I was able to verify the click is being rendered, the function (api.reinitialize) doesn't appear to be working. I'm hoping that a fresh pair of eyes could point me in the right direction. :-)
Thanks!
The problem is that api.reinitialise executes immediately after the click, and the li element will not have expanded yet so when jscroll pane goes to to recalculate the height it gets it wrong. You can try adding a delay but the best solution would be to bind api.reinitialise() to an event that's triggered once the your list has finished expanding. I'm not sure how you're expanding the div within the li but if for instance it's using .animate, you could bind the api.reinitialise to the animation complete event.
Also noted that not all the parent li's have the class parent associated it to them. I would expect you would want the pane to reinitialize on the expansion and collapsing of all the main li elements.
Hope that helps !
Cheers :)
What you can do is have your inner divs expanded by default, and then close them with jquery, rather than in the CSS directly.
So instead of doing this:
.mydiv.closed {display:none}
do this in your jquery after the elements are drawn to the page:
$('.mydiv.closed').hide();
This will load the jscrollpane at the necessary height, and then collapse what you want to be initially hidden.
I have a set of LI elements with overflow propety set to hidden by the
jCarouselLite plugin. What I would like to do
is to scroll the jCarouselLite'd element in order to scroll to the
LI element I want, since I have it configured to
show only 3 elements.
Looking at the html code generated by the plugin, I can see:
<ul ..>
<li ..style="..overflow:hidden">1</li>
<li ..style="..overflow:hidden">2</li>
<li ..style="..overflow:hidden">3</li>
<li ..style="..overflow:hidden">4</li>
</ul>
So, I have the first 3 LI elements shown by the plugin, but not the last one. What I would like to do is to scroll so that the 4th LI element is shown, or I can do that by myself if I manage to check if that last LI is within the overflow area, so I can see if it's necessary to scroll for it in order to show it or not.
Hope I'm not getting things confused to understand.
If I understand you correctly, you want to check if the last li in that group has the style overflow: hidden.
You can do this with a simple selector.
$(document).ready(function(){
tester = $('li').last().css('overflow');
alert (tester);
});
That will set the last li's overflow style to the variable "tester", and when it sends the alert box it will alert the current state of overflow. So if overflow is set to hidden, it will say "hidden", if overflow is set to scroll it will say "scroll".
Sorry if I didn't understand properly or answer your question.
I couldn't find an answer for my original question, but as for any jCarouselLite plugin users, what I did in order to make the carouselLite scroll to a particular item, was to modify just the declaration of the private method go of the plugin in order to make it public, as follows:
.. code ..
go = $.fn.jCarouselLite.go = function go(to) {
if(!running) {
.. code ..
}
.. code ..
I'm sure it's not the best, and more importantly, safer solution, but for now it works for me. Just have to call
$().jCarouselLite.go(position);
on my script, considering position as a number starting from 0 (the first position on the carouselLite).
I'm trying to make a webpage where it basically looks like a word document. There would be multiple boxes that would scroll down and the text would flow and page break from one page to the next.
Does anyone have any idea where I would even start? Thanks.
Edit: It should be right in the browser, looking similar to this:
(Ignore the columns)
CSS mostly applies styles to a full element due to its box model. Exceptions are pseudo elements. So to create an appropriate break after a fixed length you would have to separate your text into correctly sized different elements.
EDIT:
It would be possible using javascript. But even in the simplest case, where everything inside the pages delivered as just one text element with no sub elements (not even other text elements), the code will be a development nightmare and will run quite crappy. This is because there is no measure function in javascript. So you would be forced to do trail and error to find the correct position to break the element. Since the properties of the elements are live it means, that the viewer of the website will see a lot of flickering of your page just after loading. If you dare put other elements inside the html element to break into pages you get even more problems. More or less you get hundreds of special cases (break inside other elements, what if those elements are inside even other elements) to look out for.
Something like that sounds possible using javascript, but it depends a bit on the structure of your html and whether or not you want to break paragraphs or just move the next paragraph to the next page if it doesn´t fit
So the simplest example, not breaking paragraphs / html elements with a flat html structure (no nested divs, columns, etc) like:
<div class="document">
<h1>title</h1>
<p>texts</p>
<h2>subtitle</h2>
<p>texts</p>
...
<p>texts</p>
</div>
would be to do something like:
height = 0
loop through all direct child elements of .document
{
if ( (height + element_height) > page_height)
{
add page_break_element before current element
height = 0
}
height = height + element_height
}
I´d use jquery because it makes it easy to loop through the elements, measure heights, etc.
I guess breaking paragraphs would be possible as well, but a lot of extra work.
<p style="page-break-before: always">This would print on the next page</p>