Repositioning jQuery UI Autocomplete on browser resize - javascript

There is an issue if you open up an autocomplete drop down and also resize your browser window the autocomplete drop down does not reposition. Highlighted in this video: http://www.youtube.com/watch?v=d7rZYH0DgWE
I have looked at the documentation and cannot find a reposition method (in the jquery-ui documentation http://jqueryui.com/demos/autocomplete) that can be called within a $(window).resize() function call.
Is there an elegant soultion to this?

I would suggest just closing the results on a page resize.
$(window).resize(function() {
$(".ui-autocomplete").css('display', 'none');
});
When a use changes the width of the window it will disappear and if they type again it will re-appear as it should, positioned correctly.

Looking at this again one way to solve this problem is just to call the autocomplete field to search on resize:
e.g
$(window).resize(function() {
$( "#autocomplete-field" ).autocomplete( "search" );
});
This will reposition the autocomplete dropdown.
You may also wish to make sure autocomplete caches the results so it doesn't hit the database when searching again. And another thing to consider is calling autocomplete( "search" ) within a timeout function to improve ui responsiveness Cross-browser window resize event - JavaScript / jQuery

Here is another solution if you don't want to redo the search or close the window.
$(window).resize(function() {
var position = $("#autocompleteField").offset();
var properties = { left: position.left,
top: position.bottom };
$(".ui-autocomplete").css(properties);
});

Yes it is possible, but it's very tricky. You must alter both the css and plugin. It's default functionality sets the top and right attributes. You must alter the plugin to position the div ( or ul ) relatively to the document's width and height. (ie top:50%, right:50%; margin-left:-500px; margin-top:-100px).
You can also destroy the division on resize if you don't want to mess it up. It will reappear on change based on the document's new width and height

Calling the autocomplete field to search on resize works for me. One thing to add: Make sure that search is only performed on resize when a search result is visible. Otherwise, search is executed even after having selected one item from the result box.

Related

Force a refresh of masonry grid

I have a script that is creating a grid, and the grid elements are "re-positioned" every time the viewport width is changed. I don't have access to the script, nor did I write it. I think it's a Masonry grid.
I'm dynamically changing the content of the grid, so I need to somehow "refresh" (re-calculate) the grid without refreshing the page. On mobile I did this by changing the "initial-scale" meta tag (then resetting it) to force the grid to update. However the viewport tag is ignored on desktop, so I don't know how to actually make the browser think that page dimensions are changed and force a refresh on the grid.
Any ideas are appreciated, thanks.
Depending on how the script is setup you may be able to simply trigger the resize event causing it to recalculate based on the current size. If the script is actually tracking the size and checking for changes then you will need to find the best way to force the script to perform it's grid recalculation, which means examining the script. It might be as simple as changing the value of the variable where the script is storing the previously recorded viewport width right before you trigger the resize event.
FYI: If the script is loading on your page then you do have access to the script.
window.addEventListener("resize", function(){
// Resize event listener from masonry script
console.log("Masonry grid resized for width "+window.innerWidth);
});
// If using jQuery
$(window).trigger("resize");
// Plain JS version
window.dispatchEvent(new Event('resize'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
If the masonry script is good it may have an API feature to do what you need, however I think you'd explore that already.
Alternatively...
Option #1: Modify a parent container
See if you can force a refresh by simply temporarily modifying a parent container. For example, increase container width by 1 pixel for an instant, and return back to the original width.
Option #2: Find the existing listener; find the functions
The existing script probably has a listener + actions for when the viewport changes size (as you describe happening). Inspect the script and find that listener, and see what it's running inside. It'll have some function(s) to calculate and render the grid, and you'd want to call those same functions in your own data-update function.
To find that listener, do a find for "resize", see what comes up.
Here's how a vanilla JS resize listener may look like:
var screenWidth = document.documentElement.clientWidth;
resizeRefresh(screenWidth);
function resizeRefresh(width) {
window.addEventListener("resize", function(){
newWidth = document.documentElement.clientWidth;
if (newWidth != width) {
width = newWidth;
// do stuff
}
}, true);
}

jQuery scrolling out of view issue

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

JScrollPane Dynamic Height

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.

Trigger an event when user clicks on a divs horizontal scrollbar arrow

I have a div with a horizontal scroll.
Is there any way I can detect the click on the horizontal scrolls
arrow using jQuery ?
Note:
Actually I want the scroll to move a fixed no of pixels to the right when the user clicks the right scroll arrow and vice versa.
The event should not be triggered on scroll. It should be only triggered if user explicitly clicks the scrolls arrow.
There are multiple divs having scrollbars, having same class and no ids.
Would prefer to not use any plugins
Here is a demo for what you want
http://jsbin.com/opufow/4/edit
I hope this will help you?
you can use .scroll function of jquery.
Edit 2: Another suggestion is to do something like this depending on your implementation of scrolling areas (see working jsfiddle):
function CustomScrollArrow(elementToScroll) {
var $el = $(elementToScroll);
return $('<a>Click me to scroll</a>').css(/*...*/).click(function(){
$el.scrollLeft($el.scrollLeft()+10);
});
}
$('.ScrollAreaClass').each(function(){
// You could choose to append to your scrolling
// areas or their wrapper classes or whatever...
$('body').append(new CustomScrollArrow(this));
});​
Afterwards it's just a matter of styling your handmade arrows.
Edit 1: I've seen you updated your question, so here's an updated answer with an alternative solution.
You can try to circumvent the problem by using a customized scrollbars implementation, for example jScrollPane by Kelvin Luck or any other, whatever. If the solution offers click events on arrows - then you're set. Otherwise just do a bit of tinkering...
I maintain, however, my point of view that unless you are looking to perform an action before the browser executes the arrow click, I would recommend adding an event handler to the actual result of that click, i.e. the scroll.
Doing this will help to avoid inconsistencies across various implementations of scrolling in browsers; will keep working if scrolling is performed in another manner (i.e. swipe gesture); will still work if there's some javascript code that replaces the default browser implementation of scrollbars.
jQuery offers the .scroll handler to capture scrolling and .scrollLeft to determine the resulting position of the horizontally scrolled content.
Try a working jsfiddle or see the code below:
// Cache the initial scroll position:
var initialLeftScroll = $('#wrapper').scrollLeft();
// Bind event:
$('#wrapper').scroll(function (ev) {
// Get new horizontal scroll offset:
var currentLeftScroll = $('#wrapper').scrollLeft();
// Determine the difference
// (did the user scroll horizontally or just vertically?):
var leftScrollDifference = currentLeftScroll - initialLeftScroll;
// Now we can check
if (leftScrollDifference) {
/* Do something here */
}
// Reset the cache:
initialLeftScroll = currentLeftScroll;
});

Scrollto Jquery, continue to follow the element?

Is there a way to 'track' a moving element across a page, or continually scroll towards it, so that it never leaves the users view?
I've got an element which slowly moves across the page and eventually off screen, meaning the user has to scroll towards it to see it. This element continuously moves.
I'm using the ScrollTo Jquery plugin to guide the user towards this element, this works fine.
But, is there anyway to make it so the element is continually scrolled towards?
So that it is tracked across the page?
At the moment the user has to repeatedly click a button to ScrollTo the element since it quickly moves out of view.
Any help is much appreciated.
You could try using a css hook if you're using a recent (> 1.4.3) version of jQuery. It depends on the property you are using to scroll it, let's say top.
$.cssHooks["top"] = {
get: function(elem, computed, extra) {
return $.css(elem, 'top');
},
set: function(elem, value) {
// set it
$.css(elem, 'top');
$(document).scrollTo(value);
}
};
This means each time top is set, it would call the set function here.
You could detect the element's offset position and append another element to it.
If your query is just to keep the element in view of user : irrespective of his scrolling. Then why not just use simple " position: fixed" element.
Check out this link: http://www.w3.org/Style/Examples/007/menus.en.html

Categories